Merge git://git.kernel.org/pub/scm/linux/kernel/git/joern/misc
authorDavid Woodhouse <dwmw2@infradead.org>
Fri, 23 Mar 2007 17:31:17 +0000 (17:31 +0000)
committerDavid Woodhouse <dwmw2@infradead.org>
Fri, 23 Mar 2007 17:31:17 +0000 (17:31 +0000)
1494 files changed:
CREDITS
Documentation/SubmitChecklist
Documentation/arm/Samsung-S3C24XX/Suspend.txt
Documentation/cpu-load.txt [new file with mode: 0644]
Documentation/feature-removal-schedule.txt
Documentation/filesystems/proc.txt
Documentation/filesystems/vfs.txt
Documentation/ide.txt
Documentation/kdump/kdump.txt
Documentation/kernel-parameters.txt
Documentation/magic-number.txt
Documentation/networking/ip-sysctl.txt
Documentation/oops-tracing.txt
Documentation/sound/alsa/ALSA-Configuration.txt
Documentation/sparse.txt
Documentation/video4linux/CARDLIST.bttv
Documentation/video4linux/CARDLIST.saa7134
Documentation/video4linux/CQcam.txt
Documentation/video4linux/Zoran
Documentation/video4linux/cx2341x/fw-decoder-api.txt
Documentation/video4linux/cx2341x/fw-decoder-regs.txt [new file with mode: 0644]
Documentation/video4linux/cx2341x/fw-dma.txt
Documentation/video4linux/cx2341x/fw-encoder-api.txt
Documentation/video4linux/cx2341x/fw-memory.txt
Documentation/video4linux/et61x251.txt
Documentation/video4linux/sn9c102.txt
Documentation/video4linux/zc0301.txt
MAINTAINERS
Makefile
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/common/sharpsl_pm.c
arch/arm/configs/s3c2410_defconfig
arch/arm/kernel/entry-armv.S
arch/arm/kernel/entry-common.S
arch/arm/kernel/head.S
arch/arm/kernel/vmlinux.lds.S
arch/arm/mach-at91/at91sam9263.c
arch/arm/mach-at91/at91sam9263_devices.c
arch/arm/mach-at91/gpio.c
arch/arm/mach-iop13xx/Makefile
arch/arm/mach-iop13xx/iq81340mc.c
arch/arm/mach-iop13xx/iq81340sc.c
arch/arm/mach-iop13xx/irq.c
arch/arm/mach-iop13xx/setup.c
arch/arm/mach-iop13xx/time.c [deleted file]
arch/arm/mach-iop32x/glantank.c
arch/arm/mach-iop32x/iq31244.c
arch/arm/mach-iop32x/iq80321.c
arch/arm/mach-iop32x/irq.c
arch/arm/mach-iop32x/n2100.c
arch/arm/mach-iop33x/iq80331.c
arch/arm/mach-iop33x/iq80332.c
arch/arm/mach-iop33x/irq.c
arch/arm/mach-omap1/board-nokia770.c
arch/arm/mach-omap1/clock.c
arch/arm/mach-omap1/irq.c
arch/arm/mach-omap1/pm.c
arch/arm/mach-omap1/serial.c
arch/arm/mach-omap2/board-h4.c
arch/arm/mach-omap2/timer-gp.c
arch/arm/mach-pxa/corgi_pm.c
arch/arm/mach-pxa/generic.c
arch/arm/mach-pxa/sharpsl_pm.c
arch/arm/mach-pxa/spitz_pm.c
arch/arm/mach-sa1100/generic.c
arch/arm/mach-sa1100/jornada720.c
arch/arm/oprofile/common.c
arch/arm/plat-iop/Makefile
arch/arm/plat-iop/time.c
arch/arm/plat-omap/dma.c
arch/arm/plat-omap/dmtimer.c
arch/arm/plat-omap/gpio.c
arch/arm/plat-omap/mcbsp.c
arch/arm/plat-omap/mux.c
arch/arm/plat-s3c24xx/Kconfig
arch/arm26/kernel/entry.S
arch/avr32/Kconfig
arch/avr32/kernel/ptrace.c
arch/avr32/kernel/traps.c
arch/avr32/mach-at32ap/at32ap7000.c
arch/avr32/mm/cache.c
arch/cris/arch-v32/drivers/pci/dma.c
arch/frv/mm/init.c
arch/i386/Kconfig
arch/i386/Makefile
arch/i386/kernel/acpi/boot.c
arch/i386/kernel/acpi/earlyquirk.c
arch/i386/kernel/apic.c
arch/i386/kernel/cpu/cpufreq/Kconfig
arch/i386/kernel/cpu/cpufreq/longhaul.c
arch/i386/kernel/cpu/cpufreq/longhaul.h
arch/i386/kernel/cpu/cpufreq/powernow-k7.c
arch/i386/kernel/cpu/mcheck/p4.c
arch/i386/kernel/hpet.c
arch/i386/kernel/i8253.c
arch/i386/kernel/io_apic.c
arch/i386/kernel/irq.c
arch/i386/kernel/paravirt.c
arch/i386/kernel/pci-dma.c
arch/i386/kernel/process.c
arch/i386/kernel/setup.c
arch/i386/kernel/smp.c
arch/i386/kernel/smpboot.c
arch/i386/kernel/time.c
arch/i386/kernel/tsc.c
arch/i386/kernel/vmi.c
arch/i386/kernel/vmitime.c
arch/i386/lib/Makefile
arch/i386/lib/msr-on-cpu.c [new file with mode: 0644]
arch/ia64/configs/tiger_defconfig
arch/ia64/configs/zx1_defconfig
arch/ia64/defconfig
arch/ia64/ia32/sys_ia32.c
arch/ia64/kernel/asm-offsets.c
arch/ia64/kernel/crash.c
arch/ia64/kernel/efi.c
arch/ia64/kernel/fsys.S
arch/ia64/kernel/iosapic.c
arch/ia64/kernel/mca.c
arch/ia64/kernel/mca_drv.c
arch/ia64/kernel/msi_ia64.c
arch/ia64/kernel/perfmon.c
arch/ia64/kernel/ptrace.c
arch/ia64/kernel/setup.c
arch/ia64/lib/Makefile
arch/ia64/mm/contig.c
arch/ia64/mm/discontig.c
arch/ia64/sn/kernel/io_acpi_init.c
arch/ia64/sn/kernel/irq.c
arch/ia64/sn/kernel/msi_sn.c
arch/ia64/sn/kernel/setup.c
arch/m68knommu/kernel/setup.c
arch/m68knommu/platform/5307/ints.c
arch/m68knommu/platform/68328/ints.c
arch/m68knommu/platform/68328/timers.c
arch/m68knommu/platform/68360/config.c
arch/m68knommu/platform/68EZ328/config.c
arch/m68knommu/platform/68VZ328/config.c
arch/mips/Kconfig
arch/mips/Kconfig.debug
arch/mips/Makefile
arch/mips/arc/console.c
arch/mips/arc/init.c
arch/mips/arc/memory.c
arch/mips/arc/tree.c
arch/mips/au1000/mtx-1/board_setup.c
arch/mips/au1000/mtx-1/irqmap.c
arch/mips/basler/excite/excite_setup.c
arch/mips/cobalt/Kconfig [deleted file]
arch/mips/cobalt/Makefile
arch/mips/cobalt/console.c
arch/mips/cobalt/mtd.c [new file with mode: 0644]
arch/mips/cobalt/setup.c
arch/mips/configs/atlas_defconfig
arch/mips/configs/bigsur_defconfig
arch/mips/configs/capcella_defconfig
arch/mips/configs/cobalt_defconfig
arch/mips/configs/db1000_defconfig
arch/mips/configs/db1100_defconfig
arch/mips/configs/db1200_defconfig
arch/mips/configs/db1500_defconfig
arch/mips/configs/db1550_defconfig
arch/mips/configs/ddb5477_defconfig
arch/mips/configs/decstation_defconfig
arch/mips/configs/e55_defconfig
arch/mips/configs/emma2rh_defconfig
arch/mips/configs/ev64120_defconfig
arch/mips/configs/excite_defconfig
arch/mips/configs/ip22_defconfig
arch/mips/configs/ip27_defconfig
arch/mips/configs/ip32_defconfig
arch/mips/configs/jaguar-atx_defconfig
arch/mips/configs/jazz_defconfig
arch/mips/configs/jmr3927_defconfig
arch/mips/configs/lasat200_defconfig
arch/mips/configs/malta_defconfig
arch/mips/configs/mipssim_defconfig
arch/mips/configs/mpc30x_defconfig
arch/mips/configs/ocelot_3_defconfig
arch/mips/configs/ocelot_c_defconfig
arch/mips/configs/ocelot_defconfig
arch/mips/configs/ocelot_g_defconfig
arch/mips/configs/pb1100_defconfig
arch/mips/configs/pb1500_defconfig
arch/mips/configs/pb1550_defconfig
arch/mips/configs/pnx8550-jbs_defconfig
arch/mips/configs/pnx8550-stb810_defconfig
arch/mips/configs/pnx8550-v2pci_defconfig
arch/mips/configs/qemu_defconfig
arch/mips/configs/rbhma4500_defconfig
arch/mips/configs/rm200_defconfig
arch/mips/configs/sb1250-swarm_defconfig
arch/mips/configs/sead_defconfig
arch/mips/configs/tb0226_defconfig
arch/mips/configs/tb0229_defconfig
arch/mips/configs/tb0287_defconfig
arch/mips/configs/workpad_defconfig
arch/mips/configs/wrppmc_defconfig
arch/mips/configs/yosemite_defconfig
arch/mips/ddb5xxx/ddb5477/Makefile
arch/mips/dec/Makefile
arch/mips/dec/prom/Makefile
arch/mips/dec/prom/console.c
arch/mips/dec/prom/identify.c
arch/mips/dec/prom/init.c
arch/mips/defconfig
arch/mips/emma2rh/common/irq.c
arch/mips/emma2rh/markeins/irq.c
arch/mips/gt64120/ev64120/Makefile
arch/mips/gt64120/ev64120/promcon.c
arch/mips/gt64120/momenco_ocelot/Makefile
arch/mips/gt64120/wrppmc/Makefile
arch/mips/jazz/Makefile
arch/mips/jmr3927/common/Makefile
arch/mips/jmr3927/common/rtc_ds1742.c [deleted file]
arch/mips/jmr3927/rbhma3100/Makefile
arch/mips/jmr3927/rbhma3100/setup.c
arch/mips/kernel/Makefile
arch/mips/kernel/asm-offsets.c
arch/mips/kernel/early_printk.c [new file with mode: 0644]
arch/mips/kernel/i8259.c
arch/mips/kernel/linux32.c
arch/mips/kernel/mips_ksyms.c
arch/mips/kernel/process.c
arch/mips/kernel/ptrace.c
arch/mips/kernel/rtlx.c
arch/mips/kernel/scall32-o32.S
arch/mips/kernel/scall64-64.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/setup.c
arch/mips/kernel/signal.c
arch/mips/kernel/signal32.c
arch/mips/kernel/smp.c
arch/mips/kernel/smtc.c
arch/mips/kernel/traps.c
arch/mips/kernel/unaligned.c
arch/mips/kernel/vpe.c
arch/mips/lasat/lasat_board.c
arch/mips/lasat/prom.c
arch/mips/lasat/prom.h
arch/mips/lasat/setup.c
arch/mips/lib-32/Makefile
arch/mips/lib-64/Makefile
arch/mips/lib/Makefile
arch/mips/lib/promlib.c [deleted file]
arch/mips/mips-boards/generic/Makefile
arch/mips/mips-boards/generic/console.c [moved from arch/mips/mips-boards/generic/printf.c with 91% similarity]
arch/mips/mips-boards/generic/init.c
arch/mips/mips-boards/generic/memory.c
arch/mips/mips-boards/generic/time.c
arch/mips/mips-boards/malta/Makefile
arch/mips/mips-boards/malta/malta_smtc.c [moved from arch/mips/mips-boards/malta/malta_smp.c with 67% similarity]
arch/mips/mips-boards/sim/Makefile
arch/mips/mips-boards/sim/sim_console.c [moved from arch/mips/mips-boards/sim/sim_printf.c with 63% similarity]
arch/mips/mips-boards/sim/sim_mem.c
arch/mips/mips-boards/sim/sim_setup.c
arch/mips/mips-boards/sim/sim_time.c
arch/mips/mm/Makefile
arch/mips/mm/c-tx39.c
arch/mips/mm/cerr-sb1.c
arch/mips/mm/dma-default.c
arch/mips/mm/ioremap.c
arch/mips/momentum/jaguar_atx/ja-console.c
arch/mips/momentum/jaguar_atx/platform.c
arch/mips/momentum/ocelot_3/platform.c
arch/mips/momentum/ocelot_c/platform.c
arch/mips/momentum/ocelot_g/Makefile
arch/mips/oprofile/Kconfig
arch/mips/oprofile/op_model_mipsxx.c
arch/mips/pci/fixup-jmr3927.c
arch/mips/pci/fixup-sni.c
arch/mips/pci/ops-au1000.c
arch/mips/pci/pci.c
arch/mips/philips/pnx8550/common/prom.c
arch/mips/philips/pnx8550/common/setup.c
arch/mips/pmc-sierra/yosemite/py-console.c
arch/mips/sgi-ip22/Makefile
arch/mips/sgi-ip27/Makefile
arch/mips/sgi-ip27/ip27-console.c
arch/mips/sgi-ip27/ip27-init.c
arch/mips/sgi-ip32/Makefile
arch/mips/sibyte/Kconfig
arch/mips/sibyte/bcm1480/Makefile
arch/mips/sibyte/bcm1480/irq.c
arch/mips/sibyte/bcm1480/setup.c
arch/mips/sibyte/cfe/setup.c
arch/mips/sibyte/sb1250/Makefile
arch/mips/sibyte/sb1250/bcm1250_tbprof.c
arch/mips/sibyte/sb1250/setup.c
arch/mips/sni/Makefile
arch/mips/sni/pcimt.c
arch/mips/sni/pcit.c
arch/mips/sni/rm200.c
arch/mips/sni/sniprom.c
arch/mips/tx4927/common/tx4927_setup.c
arch/mips/tx4927/toshiba_rbtx4927/Makefile
arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
arch/mips/tx4938/common/setup.c
arch/mips/vr41xx/common/Makefile
arch/parisc/Kconfig
arch/parisc/Makefile
arch/parisc/hpux/entry_hpux.S
arch/parisc/hpux/fs.c
arch/parisc/hpux/gate.S
arch/parisc/hpux/sys_hpux.c
arch/parisc/hpux/wrappers.S
arch/parisc/kernel/asm-offsets.c
arch/parisc/kernel/cache.c
arch/parisc/kernel/drivers.c
arch/parisc/kernel/entry.S
arch/parisc/kernel/firmware.c
arch/parisc/kernel/head.S
arch/parisc/kernel/hpmc.S
arch/parisc/kernel/inventory.c
arch/parisc/kernel/irq.c
arch/parisc/kernel/module.c
arch/parisc/kernel/pacache.S
arch/parisc/kernel/parisc_ksyms.c
arch/parisc/kernel/pci-dma.c
arch/parisc/kernel/pci.c
arch/parisc/kernel/perf_asm.S
arch/parisc/kernel/process.c
arch/parisc/kernel/processor.c
arch/parisc/kernel/ptrace.c
arch/parisc/kernel/real2.S
arch/parisc/kernel/setup.c
arch/parisc/kernel/signal.c
arch/parisc/kernel/signal32.c
arch/parisc/kernel/smp.c
arch/parisc/kernel/syscall.S
arch/parisc/kernel/syscall_table.S
arch/parisc/kernel/time.c
arch/parisc/kernel/traps.c
arch/parisc/kernel/unaligned.c
arch/parisc/kernel/unwind.c
arch/parisc/kernel/vmlinux.lds.S
arch/parisc/lib/bitops.c
arch/parisc/lib/fixup.S
arch/parisc/lib/lusercopy.S
arch/parisc/lib/memcpy.c
arch/parisc/mm/fault.c
arch/parisc/mm/init.c
arch/parisc/mm/ioremap.c
arch/parisc/mm/kmap.c [deleted file]
arch/parisc/oprofile/init.c
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/prom_parse.c
arch/powerpc/kernel/traps.c
arch/powerpc/platforms/83xx/mpc834x_mds.c
arch/powerpc/platforms/85xx/Kconfig
arch/powerpc/platforms/celleb/scc_epci.c
arch/powerpc/platforms/chrp/pegasos_eth.c
arch/powerpc/platforms/embedded6xx/Kconfig
arch/powerpc/platforms/powermac/backlight.c
arch/powerpc/platforms/powermac/feature.c
arch/powerpc/platforms/powermac/pci.c
arch/powerpc/platforms/ps3/Kconfig
arch/powerpc/xmon/xmon.c
arch/ppc/Kconfig
arch/ppc/syslib/mv64x60.c
arch/s390/Kconfig
arch/s390/Makefile
arch/s390/defconfig
arch/s390/kernel/early.c
arch/s390/kernel/head31.S
arch/s390/kernel/head64.S
arch/s390/kernel/ipl.c
arch/s390/kernel/kprobes.c
arch/s390/kernel/machine_kexec.c
arch/s390/kernel/reipl.S
arch/s390/kernel/reipl64.S
arch/s390/kernel/setup.c
arch/s390/kernel/smp.c
arch/s390/kernel/time.c
arch/s390/lib/delay.c
arch/s390/mm/fault.c
arch/s390/mm/init.c
arch/sh/boards/renesas/r7780rp/Makefile
arch/sh/boards/renesas/r7780rp/io.c [deleted file]
arch/sh/boards/renesas/r7780rp/setup.c
arch/sh/boards/renesas/rts7751r2d/setup.c
arch/sh/configs/rts7751r2d_defconfig
arch/sh/kernel/entry-common.S
arch/sh/kernel/io_generic.c
arch/sh/kernel/process.c
arch/sh/kernel/ptrace.c
arch/sh/kernel/signal.c
arch/sh/kernel/vmlinux.lds.S
arch/sh/mm/cache-sh4.c
arch/sh/mm/cache-sh7705.c
arch/sh/mm/pg-sh4.c
arch/sh/mm/pg-sh7705.c
arch/sh/mm/tlb-flush.c
arch/sh/mm/tlb-sh3.c
arch/sh/mm/tlb-sh4.c
arch/sparc/kernel/of_device.c
arch/sparc/kernel/pcic.c
arch/sparc64/defconfig
arch/sparc64/kernel/irq.c
arch/sparc64/kernel/of_device.c
arch/sparc64/kernel/pci.c
arch/um/Kconfig.char
arch/um/drivers/daemon_user.c
arch/um/drivers/line.c
arch/um/drivers/mcast_user.c
arch/um/drivers/ssl.c
arch/um/drivers/stdio_console.c
arch/um/include/os.h
arch/um/kernel/irq.c
arch/um/kernel/signal.c
arch/um/os-Linux/elf_aux.c
arch/um/os-Linux/process.c
arch/um/os-Linux/sigio.c
arch/um/os-Linux/signal.c
arch/um/os-Linux/skas/process.c
arch/um/os-Linux/trap.c
arch/um/sys-i386/ldt.c
arch/um/sys-x86_64/syscalls.c
arch/x86_64/ia32/ptrace32.c
arch/x86_64/kernel/cpufreq/Kconfig
arch/x86_64/kernel/early-quirks.c
arch/x86_64/kernel/entry.S
arch/x86_64/kernel/hpet.c
arch/x86_64/kernel/i8259.c
arch/x86_64/kernel/io_apic.c
arch/x86_64/kernel/smpboot.c
arch/x86_64/kernel/time.c
arch/x86_64/kernel/tsc.c
arch/x86_64/lib/Makefile
arch/x86_64/lib/msr-on-cpu.c [new file with mode: 0644]
block/genhd.c
block/ioctl.c
drivers/acorn/char/Makefile
drivers/acorn/char/i2c.c [deleted file]
drivers/acorn/char/pcf8583.c [deleted file]
drivers/acorn/char/pcf8583.h [deleted file]
drivers/acpi/Kconfig
drivers/acpi/asus_acpi.c
drivers/acpi/blacklist.c
drivers/acpi/ec.c
drivers/acpi/events/evmisc.c
drivers/acpi/ibm_acpi.c
drivers/acpi/power.c
drivers/acpi/resources/rscreate.c
drivers/acpi/toshiba_acpi.c
drivers/acpi/video.c
drivers/ata/Kconfig
drivers/ata/Makefile
drivers/ata/ahci.c
drivers/ata/ata_generic.c
drivers/ata/ata_piix.c
drivers/ata/libata-acpi.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata-scsi.c
drivers/ata/libata-sff.c
drivers/ata/libata.h
drivers/ata/pata_ali.c
drivers/ata/pata_amd.c
drivers/ata/pata_atiixp.c
drivers/ata/pata_cmd64x.c
drivers/ata/pata_cs5520.c
drivers/ata/pata_cs5530.c
drivers/ata/pata_cs5535.c
drivers/ata/pata_cypress.c
drivers/ata/pata_efar.c
drivers/ata/pata_hpt366.c
drivers/ata/pata_hpt37x.c
drivers/ata/pata_hpt3x3.c
drivers/ata/pata_isapnp.c
drivers/ata/pata_it8213.c
drivers/ata/pata_it821x.c
drivers/ata/pata_ixp4xx_cf.c
drivers/ata/pata_jmicron.c
drivers/ata/pata_legacy.c
drivers/ata/pata_marvell.c
drivers/ata/pata_mpc52xx.c
drivers/ata/pata_mpiix.c
drivers/ata/pata_netcell.c
drivers/ata/pata_ns87410.c
drivers/ata/pata_oldpiix.c
drivers/ata/pata_opti.c
drivers/ata/pata_optidma.c
drivers/ata/pata_pcmcia.c
drivers/ata/pata_pdc2027x.c
drivers/ata/pata_pdc202xx_old.c
drivers/ata/pata_platform.c
drivers/ata/pata_qdi.c
drivers/ata/pata_radisys.c
drivers/ata/pata_rz1000.c
drivers/ata/pata_sc1200.c
drivers/ata/pata_scc.c [new file with mode: 0644]
drivers/ata/pata_serverworks.c
drivers/ata/pata_sil680.c
drivers/ata/pata_sis.c
drivers/ata/pata_sl82c105.c
drivers/ata/pata_triflex.c
drivers/ata/pata_via.c
drivers/ata/pata_winbond.c
drivers/ata/pdc_adma.c
drivers/ata/sata_inic162x.c
drivers/ata/sata_mv.c
drivers/ata/sata_nv.c
drivers/ata/sata_promise.c
drivers/ata/sata_qstor.c
drivers/ata/sata_sil.c
drivers/ata/sata_sil24.c
drivers/ata/sata_sis.c
drivers/ata/sata_svw.c
drivers/ata/sata_sx4.c
drivers/ata/sata_uli.c
drivers/ata/sata_via.c
drivers/ata/sata_vsc.c
drivers/ata/sis.h [new file with mode: 0644]
drivers/auxdisplay/cfag12864b.c
drivers/auxdisplay/cfag12864bfb.c
drivers/auxdisplay/ks0108.c
drivers/base/class.c
drivers/base/core.c
drivers/block/Kconfig
drivers/block/aoe/aoecmd.c
drivers/block/aoe/aoenet.c
drivers/block/cciss.c
drivers/block/floppy.c
drivers/block/pktcdvd.c
drivers/block/umem.c
drivers/bluetooth/bcm203x.c
drivers/bluetooth/bfusb.c
drivers/bluetooth/bt3c_cs.c
drivers/cdrom/viocd.c
drivers/char/Kconfig
drivers/char/agp/Makefile
drivers/char/agp/agp.h
drivers/char/agp/ali-agp.c
drivers/char/agp/amd-k7-agp.c
drivers/char/agp/amd64-agp.c
drivers/char/agp/ati-agp.c
drivers/char/agp/efficeon-agp.c
drivers/char/agp/generic.c
drivers/char/agp/hp-agp.c
drivers/char/agp/i460-agp.c
drivers/char/agp/intel-agp.c
drivers/char/agp/nvidia-agp.c
drivers/char/agp/parisc-agp.c
drivers/char/agp/sgi-agp.c
drivers/char/agp/sis-agp.c
drivers/char/agp/sworks-agp.c
drivers/char/agp/uninorth-agp.c
drivers/char/agp/via-agp.c
drivers/char/cyclades.c
drivers/char/ds1286.c
drivers/char/epca.c
drivers/char/hvc_console.c
drivers/char/ip2/i2lib.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/lcd.c
drivers/char/lcd.h
drivers/char/mwave/3780i.c
drivers/char/pcmcia/cm4040_cs.c
drivers/char/tty_io.c
drivers/clocksource/acpi_pm.c
drivers/clocksource/cyclone.c
drivers/connector/connector.c
drivers/cpufreq/cpufreq_ondemand.c
drivers/crypto/geode-aes.c
drivers/hid/hid-core.c
drivers/hid/hid-debug.c
drivers/hid/hid-input.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-acorn.c [new file with mode: 0644]
drivers/ide/Kconfig
drivers/ide/cris/ide-cris.c
drivers/ide/ide-disk.c
drivers/ide/ide-iops.c
drivers/ide/ide-lib.c
drivers/ide/ide-probe.c
drivers/ide/ide.c
drivers/ide/legacy/ali14xx.c
drivers/ide/legacy/dtc2278.c
drivers/ide/legacy/ht6560b.c
drivers/ide/legacy/ide-cs.c
drivers/ide/legacy/qd65xx.c
drivers/ide/legacy/umc8672.c
drivers/ide/mips/au1xxx-ide.c
drivers/ide/pci/alim15x3.c
drivers/ide/pci/cmd640.c
drivers/ide/pci/cmd64x.c
drivers/ide/pci/delkin_cb.c
drivers/ide/pci/generic.c
drivers/ide/pci/opti621.c
drivers/ide/pci/piix.c
drivers/ide/pci/rz1000.c
drivers/ide/pci/siimage.c
drivers/ide/pci/slc90e66.c
drivers/ide/ppc/pmac.c
drivers/ide/ppc/scc_pata.c
drivers/infiniband/core/cm.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/ucma.c
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/verbs.c
drivers/infiniband/hw/cxgb3/Makefile
drivers/infiniband/hw/cxgb3/cxio_hal.c
drivers/infiniband/hw/cxgb3/cxio_hal.h
drivers/infiniband/hw/cxgb3/cxio_resource.c
drivers/infiniband/hw/cxgb3/iwch_cm.c
drivers/infiniband/hw/cxgb3/iwch_ev.c
drivers/infiniband/hw/cxgb3/iwch_provider.c
drivers/infiniband/hw/cxgb3/iwch_provider.h
drivers/infiniband/hw/cxgb3/iwch_qp.c
drivers/infiniband/hw/ehca/ehca_classes.h
drivers/infiniband/hw/ehca/ehca_cq.c
drivers/infiniband/hw/ehca/ehca_irq.c
drivers/infiniband/hw/ehca/ehca_main.c
drivers/infiniband/hw/mthca/mthca_mr.c
drivers/infiniband/hw/mthca/mthca_qp.c
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_cm.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/infiniband/ulp/ipoib/ipoib_verbs.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/gpio_keys.c
drivers/input/serio/i8042.c
drivers/isdn/capi/Kconfig
drivers/isdn/capi/capidrv.c
drivers/isdn/capi/capiutil.c
drivers/isdn/capi/kcapi.c
drivers/isdn/gigaset/Makefile
drivers/isdn/gigaset/asyncdata.c
drivers/kvm/kvm.h
drivers/kvm/kvm_main.c
drivers/kvm/kvm_svm.h
drivers/kvm/mmu.c
drivers/kvm/paging_tmpl.h
drivers/kvm/svm.c
drivers/kvm/vmx.c
drivers/leds/Kconfig
drivers/leds/Makefile
drivers/leds/leds-cobalt.c [new file with mode: 0644]
drivers/leds/leds-h1940.c [new file with mode: 0644]
drivers/macintosh/via-pmu-backlight.c
drivers/md/md.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/md/raid6mmx.c
drivers/md/raid6sse1.c
drivers/md/raid6sse2.c
drivers/md/raid6x86.h
drivers/media/Kconfig
drivers/media/common/Kconfig
drivers/media/common/ir-functions.c
drivers/media/common/ir-keymaps.c
drivers/media/common/saa7146_fops.c
drivers/media/dvb/b2c2/flexcop-fe-tuner.c
drivers/media/dvb/bt8xx/bt878.c
drivers/media/dvb/bt8xx/dst.c
drivers/media/dvb/bt8xx/dvb-bt8xx.c
drivers/media/dvb/cinergyT2/cinergyT2.c
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-core/dvbdev.c
drivers/media/dvb/dvb-usb/Kconfig
drivers/media/dvb/dvb-usb/Makefile
drivers/media/dvb/dvb-usb/au6610.c [new file with mode: 0644]
drivers/media/dvb/dvb-usb/au6610.h [new file with mode: 0644]
drivers/media/dvb/dvb-usb/cxusb.c
drivers/media/dvb/dvb-usb/digitv.c
drivers/media/dvb/dvb-usb/dvb-usb-ids.h
drivers/media/dvb/dvb-usb/dvb-usb-remote.c
drivers/media/dvb/dvb-usb/gl861.c [new file with mode: 0644]
drivers/media/dvb/dvb-usb/gl861.h [new file with mode: 0644]
drivers/media/dvb/dvb-usb/m920x.c [new file with mode: 0644]
drivers/media/dvb/dvb-usb/m920x.h [new file with mode: 0644]
drivers/media/dvb/frontends/Kconfig
drivers/media/dvb/frontends/Makefile
drivers/media/dvb/frontends/cx24110.c
drivers/media/dvb/frontends/cx24123.c
drivers/media/dvb/frontends/dib3000mc.c
drivers/media/dvb/frontends/qt1010.c [new file with mode: 0644]
drivers/media/dvb/frontends/qt1010.h [new file with mode: 0644]
drivers/media/dvb/frontends/qt1010_priv.h [new file with mode: 0644]
drivers/media/dvb/frontends/stv0297.c
drivers/media/dvb/frontends/stv0299.c
drivers/media/dvb/frontends/tda10021.c
drivers/media/dvb/frontends/tda1004x.c
drivers/media/dvb/frontends/zl10353.c
drivers/media/dvb/frontends/zl10353.h
drivers/media/dvb/frontends/zl10353_priv.h
drivers/media/dvb/ttpci/av7110.c
drivers/media/dvb/ttpci/av7110.h
drivers/media/dvb/ttpci/av7110_av.c
drivers/media/dvb/ttpci/av7110_ca.c
drivers/media/dvb/ttpci/av7110_ir.c
drivers/media/dvb/ttpci/av7110_v4l.c
drivers/media/dvb/ttpci/budget-av.c
drivers/media/dvb/ttpci/budget-ci.c
drivers/media/dvb/ttusb-dec/ttusb_dec.c
drivers/media/radio/radio-aztech.c
drivers/media/radio/radio-gemtek-pci.c
drivers/media/radio/radio-maxiradio.c
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/bt8xx/bttv-cards.c
drivers/media/video/bt8xx/bttv-driver.c
drivers/media/video/bt8xx/bttv-input.c
drivers/media/video/bt8xx/bttv-risc.c
drivers/media/video/bt8xx/bttv-vbi.c
drivers/media/video/bt8xx/bttv.h
drivers/media/video/bt8xx/bttvp.h
drivers/media/video/cafe_ccic.c
drivers/media/video/cpia.c
drivers/media/video/cx2341x.c
drivers/media/video/cx25840/cx25840-core.c
drivers/media/video/cx25840/cx25840-firmware.c
drivers/media/video/cx88/Makefile
drivers/media/video/cx88/cx88-blackbird.c
drivers/media/video/cx88/cx88-cards.c
drivers/media/video/cx88/cx88-core.c
drivers/media/video/cx88/cx88-dvb.c
drivers/media/video/cx88/cx88-i2c.c
drivers/media/video/cx88/cx88-tvaudio.c
drivers/media/video/cx88/cx88-vbi.c
drivers/media/video/cx88/cx88-video.c
drivers/media/video/cx88/cx88.h
drivers/media/video/et61x251/et61x251.h
drivers/media/video/et61x251/et61x251_core.c
drivers/media/video/et61x251/et61x251_sensor.h
drivers/media/video/et61x251/et61x251_tas5130d1b.c
drivers/media/video/pvrusb2/pvrusb2-audio.c
drivers/media/video/pvrusb2/pvrusb2-context.c
drivers/media/video/pvrusb2/pvrusb2-ctrl.c
drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
drivers/media/video/pvrusb2/pvrusb2-debugifc.c
drivers/media/video/pvrusb2/pvrusb2-eeprom.c
drivers/media/video/pvrusb2/pvrusb2-encoder.c
drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
drivers/media/video/pvrusb2/pvrusb2-hdw.c
drivers/media/video/pvrusb2/pvrusb2-hdw.h
drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
drivers/media/video/pvrusb2/pvrusb2-i2c-core.h
drivers/media/video/pvrusb2/pvrusb2-io.c
drivers/media/video/pvrusb2/pvrusb2-ioread.c
drivers/media/video/pvrusb2/pvrusb2-std.c
drivers/media/video/pvrusb2/pvrusb2-sysfs.c
drivers/media/video/pvrusb2/pvrusb2-tuner.c
drivers/media/video/pvrusb2/pvrusb2-v4l2.c
drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
drivers/media/video/pvrusb2/pvrusb2-wm8775.c
drivers/media/video/pwc/Makefile
drivers/media/video/pwc/pwc-if.c
drivers/media/video/pwc/pwc-v4l.c
drivers/media/video/pwc/pwc.h
drivers/media/video/saa5246a.c
drivers/media/video/saa5246a.h
drivers/media/video/saa5249.c
drivers/media/video/saa7115.c
drivers/media/video/saa7127.c
drivers/media/video/saa7134/Makefile
drivers/media/video/saa7134/saa7134-cards.c
drivers/media/video/saa7134/saa7134-dvb.c
drivers/media/video/saa7134/saa7134-i2c.c
drivers/media/video/saa7134/saa7134-input.c
drivers/media/video/saa7134/saa7134.h
drivers/media/video/sn9c102/Kconfig
drivers/media/video/sn9c102/Makefile
drivers/media/video/sn9c102/sn9c102.h
drivers/media/video/sn9c102/sn9c102_config.h [new file with mode: 0644]
drivers/media/video/sn9c102/sn9c102_core.c
drivers/media/video/sn9c102/sn9c102_devtable.h [new file with mode: 0644]
drivers/media/video/sn9c102/sn9c102_hv7131d.c
drivers/media/video/sn9c102/sn9c102_mi0343.c
drivers/media/video/sn9c102/sn9c102_ov7630.c
drivers/media/video/sn9c102/sn9c102_ov7660.c [new file with mode: 0644]
drivers/media/video/sn9c102/sn9c102_pas106b.c
drivers/media/video/sn9c102/sn9c102_pas202bca.c [deleted file]
drivers/media/video/sn9c102/sn9c102_pas202bcb.c
drivers/media/video/sn9c102/sn9c102_sensor.h
drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
drivers/media/video/tvmixer.c
drivers/media/video/tvp5150.c
drivers/media/video/upd64031a.c
drivers/media/video/upd64083.c
drivers/media/video/usbvision/Kconfig
drivers/media/video/usbvision/usbvision-core.c
drivers/media/video/usbvision/usbvision-video.c
drivers/media/video/usbvision/usbvision.h
drivers/media/video/v4l1-compat.c
drivers/media/video/v4l2-common.c
drivers/media/video/video-buf.c
drivers/media/video/videodev.c
drivers/media/video/vivi.c
drivers/media/video/zc0301/zc0301.h
drivers/media/video/zc0301/zc0301_core.c
drivers/media/video/zc0301/zc0301_pas202bcb.c
drivers/media/video/zc0301/zc0301_pb0330.c
drivers/media/video/zc0301/zc0301_sensor.h
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/sm501.c [new file with mode: 0644]
drivers/misc/asus-laptop.c
drivers/misc/msi-laptop.c
drivers/misc/sony-laptop.c
drivers/mmc/mmc.c
drivers/mmc/sdhci.c
drivers/mtd/chips/cfi_cmdset_0002.c
drivers/mtd/chips/cfi_cmdset_0020.c
drivers/mtd/maps/dilnetpc.c
drivers/mtd/maps/esb2rom.c
drivers/mtd/mtdconcat.c
drivers/mtd/mtdpart.c
drivers/mtd/nand/cafe.c
drivers/mtd/nand/diskonchip.c
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/s3c2410.c
drivers/mtd/onenand/onenand_base.c
drivers/net/3c59x.c
drivers/net/8139cp.c
drivers/net/8139too.c
drivers/net/Kconfig
drivers/net/acenic.c
drivers/net/amd8111e.c
drivers/net/atl1/atl1_main.c
drivers/net/bnx2.c
drivers/net/bonding/bond_main.c
drivers/net/chelsio/cxgb2.c
drivers/net/chelsio/sge.c
drivers/net/cxgb3/adapter.h
drivers/net/cxgb3/cxgb3_ioctl.h
drivers/net/cxgb3/cxgb3_main.c
drivers/net/cxgb3/cxgb3_offload.c
drivers/net/cxgb3/sge.c
drivers/net/cxgb3/t3_hw.c
drivers/net/cxgb3/version.h
drivers/net/de600.c
drivers/net/e1000/e1000_main.c
drivers/net/ehea/ehea_main.c
drivers/net/forcedeth.c
drivers/net/gianfar.c
drivers/net/hamradio/baycom_epp.c
drivers/net/hamradio/hdlcdrv.c
drivers/net/hamradio/yam.c
drivers/net/ixgb/ixgb_main.c
drivers/net/lasi_82596.c
drivers/net/mv643xx_eth.c
drivers/net/mv643xx_eth.h
drivers/net/myri10ge/myri10ge.c
drivers/net/natsemi.c
drivers/net/netxen/netxen_nic.h
drivers/net/netxen/netxen_nic_ethtool.c
drivers/net/netxen/netxen_nic_hw.c
drivers/net/netxen/netxen_nic_init.c
drivers/net/netxen/netxen_nic_main.c
drivers/net/netxen/netxen_nic_phan_reg.h
drivers/net/ni52.c
drivers/net/ns83820.c
drivers/net/pcnet32.c
drivers/net/pppoe.c
drivers/net/qla3xxx.c
drivers/net/qla3xxx.h
drivers/net/r8169.c
drivers/net/s2io-regs.h
drivers/net/s2io.c
drivers/net/s2io.h
drivers/net/sgiseeq.c
drivers/net/sis190.c
drivers/net/sis900.c
drivers/net/skfp/cfm.c
drivers/net/skge.c
drivers/net/skge.h
drivers/net/sky2.c
drivers/net/spider_net.c
drivers/net/spider_net.h
drivers/net/starfire.c
drivers/net/sun3_82586.c
drivers/net/sungem_phy.c
drivers/net/sungem_phy.h
drivers/net/tc35815.c
drivers/net/tg3.c
drivers/net/tg3.h
drivers/net/tokenring/ibmtr.c
drivers/net/tulip/de2104x.c
drivers/net/tulip/dmfe.c
drivers/net/tulip/tulip_core.c
drivers/net/typhoon.c
drivers/net/ucc_geth.c
drivers/net/via-rhine.c
drivers/net/wan/cosa.c
drivers/net/wan/hdlc.c
drivers/net/wan/hdlc_cisco.c
drivers/net/wan/hdlc_fr.c
drivers/net/wan/hdlc_ppp.c
drivers/net/wan/hdlc_raw.c
drivers/net/wan/hdlc_x25.c
drivers/net/wan/z85230.c
drivers/net/wireless/airo.c
drivers/net/wireless/bcm43xx/bcm43xx.h
drivers/net/wireless/bcm43xx/bcm43xx_ilt.c
drivers/net/wireless/bcm43xx/bcm43xx_ilt.h
drivers/net/wireless/bcm43xx/bcm43xx_main.c
drivers/net/wireless/bcm43xx/bcm43xx_phy.c
drivers/net/wireless/bcm43xx/bcm43xx_radio.c
drivers/net/wireless/bcm43xx/bcm43xx_wx.c
drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
drivers/net/wireless/hostap/hostap.h
drivers/net/wireless/ipw2100.c
drivers/net/wireless/prism54/isl_ioctl.c
drivers/net/wireless/prism54/oid_mgt.c
drivers/net/wireless/wavelan.c
drivers/net/wireless/wavelan.p.h
drivers/net/wireless/wl3501_cs.c
drivers/net/wireless/zd1211rw/zd_chip.c
drivers/parisc/hppb.c
drivers/parisc/iosapic_private.h
drivers/parisc/lba_pci.c
drivers/parisc/led.c
drivers/parisc/power.c
drivers/parisc/sba_iommu.c
drivers/parport/parport_pc.c
drivers/pci/msi.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/aer/aerdrv.c
drivers/pci/pcie/portdrv_pci.c
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/search.c
drivers/pcmcia/hd64465_ss.c
drivers/pcmcia/m32r_cfc.c
drivers/pcmcia/m8xx_pcmcia.c
drivers/pcmcia/omap_cf.c
drivers/pcmcia/rsrc_mgr.c
drivers/pcmcia/vrc4171_card.c
drivers/pnp/pnpacpi/rsparser.c
drivers/rtc/Kconfig
drivers/rtc/class.c
drivers/rtc/interface.c
drivers/rtc/rtc-at91rm9200.c
drivers/rtc/rtc-pcf8583.c
drivers/rtc/rtc-sa1100.c
drivers/s390/block/dasd_eer.c
drivers/s390/char/sclp_quiesce.c
drivers/s390/char/tape_std.c
drivers/s390/cio/cio.c
drivers/s390/cio/device_fsm.c
drivers/s390/net/qeth_main.c
drivers/sbus/char/Kconfig
drivers/sbus/char/Makefile
drivers/sbus/char/aurora.c [deleted file]
drivers/sbus/char/aurora.h [deleted file]
drivers/sbus/char/bbc_i2c.c
drivers/sbus/char/cd180.h [deleted file]
drivers/sbus/char/uctrl.c
drivers/scsi/arm/cumana_2.c
drivers/scsi/arm/eesox.c
drivers/scsi/arm/fas216.c
drivers/scsi/arm/powertec.c
drivers/scsi/arm/scsi.h
drivers/serial/8250.c
drivers/serial/dz.c
drivers/serial/mcfserial.c
drivers/serial/mux.c
drivers/serial/serial_txx9.c
drivers/serial/sn_console.c
drivers/spi/atmel_spi.c
drivers/spi/omap_uwire.c
drivers/spi/spi_imx.c
drivers/spi/spi_s3c24xx_gpio.c
drivers/usb/class/cdc-acm.c
drivers/usb/core/Makefile
drivers/usb/core/devio.c
drivers/usb/core/driver.c
drivers/usb/core/hub.c
drivers/usb/core/message.c
drivers/usb/core/quirks.c [new file with mode: 0644]
drivers/usb/core/sysfs.c
drivers/usb/core/usb.c
drivers/usb/core/usb.h
drivers/usb/gadget/at91_udc.c
drivers/usb/gadget/goku_udc.c
drivers/usb/gadget/inode.c
drivers/usb/gadget/pxa2xx_udc.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/uhci-debug.c
drivers/usb/host/uhci-hcd.c
drivers/usb/host/uhci-hcd.h
drivers/usb/host/uhci-hub.c
drivers/usb/host/uhci-q.c
drivers/usb/input/hid-core.c
drivers/usb/input/usbkbd.c
drivers/usb/input/usbmouse.c
drivers/usb/input/wacom_wac.c
drivers/usb/input/wacom_wac.h
drivers/usb/misc/Kconfig
drivers/usb/misc/Makefile
drivers/usb/misc/appledisplay.c
drivers/usb/misc/ftdi-elan.c
drivers/usb/misc/iowarrior.c [new file with mode: 0644]
drivers/usb/mon/mon_bin.c
drivers/usb/mon/mon_text.c
drivers/usb/mon/usb_mon.h
drivers/usb/net/Kconfig
drivers/usb/net/Makefile
drivers/usb/net/asix.c
drivers/usb/net/dm9601.c [new file with mode: 0644]
drivers/usb/serial/airprime.c
drivers/usb/serial/cp2101.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio.h
drivers/usb/serial/ipaq.c
drivers/usb/serial/option.c
drivers/usb/serial/usb-serial.c
drivers/usb/storage/unusual_devs.h
drivers/usb/storage/usb.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/aty/aty128fb.c
drivers/video/aty/atyfb.h
drivers/video/aty/atyfb_base.c
drivers/video/aty/mach64_ct.c
drivers/video/aty/radeon_backlight.c
drivers/video/aty/radeon_base.c
drivers/video/backlight/Kconfig
drivers/video/backlight/Makefile
drivers/video/backlight/backlight.c
drivers/video/backlight/corgi_bl.c
drivers/video/backlight/hp680_bl.c
drivers/video/backlight/lcd.c
drivers/video/backlight/locomolcd.c
drivers/video/backlight/progear_bl.c [new file with mode: 0644]
drivers/video/chipsfb.c
drivers/video/console/fbcon.c
drivers/video/fbsysfs.c
drivers/video/i810/i810_main.c
drivers/video/nvidia/nv_backlight.c
drivers/video/nvidia/nv_proto.h
drivers/video/nvidia/nvidia.c
drivers/video/riva/fbdev.c
drivers/video/s3fb.c
drivers/video/sm501fb.c [new file with mode: 0644]
fs/affs/affs.h
fs/affs/inode.c
fs/affs/super.c
fs/autofs4/autofs_i.h
fs/autofs4/inode.c
fs/autofs4/root.c
fs/autofs4/waitq.c
fs/block_dev.c
fs/buffer.c
fs/char_dev.c
fs/cifs/CHANGES
fs/cifs/Makefile
fs/cifs/TODO
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/cifsglob.h
fs/cifs/cifspdu.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/dir.c
fs/cifs/export.c [new file with mode: 0644]
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/link.c
fs/cifs/readdir.c
fs/cifs/transport.c
fs/compat.c
fs/dlm/user.c
fs/ecryptfs/file.c
fs/ecryptfs/inode.c
fs/ecryptfs/main.c
fs/ecryptfs/mmap.c
fs/ext2/balloc.c
fs/ext3/balloc.c
fs/ext3/xattr.c
fs/ext4/balloc.c
fs/ext4/xattr.c
fs/fat/inode.c
fs/gfs2/glock.c
fs/gfs2/glops.c
fs/gfs2/incore.h
fs/gfs2/inode.c
fs/gfs2/ops_address.c
fs/gfs2/ops_export.c
fs/gfs2/ops_fstype.c
fs/gfs2/quota.c
fs/gfs2/super.c
fs/hostfs/hostfs_kern.c
fs/jffs2/background.c
fs/jffs2/comprtest.c [deleted file]
fs/jffs2/readinode.c
fs/jffs2/scan.c
fs/jffs2/wbuf.c
fs/jfs/jfs_txnmgr.c
fs/libfs.c
fs/ncpfs/inode.c
fs/ncpfs/sock.c
fs/partitions/check.c
fs/proc/base.c
fs/sysfs/dir.c
fs/sysfs/file.c
fs/sysfs/inode.c
fs/sysfs/sysfs.h
fs/xfs/linux-2.6/xfs_super.c
include/asm-arm/arch-aaec2000/entry-macro.S
include/asm-arm/arch-at91/entry-macro.S
include/asm-arm/arch-at91/hardware.h
include/asm-arm/arch-cl7500/entry-macro.S
include/asm-arm/arch-clps711x/entry-macro.S
include/asm-arm/arch-ebsa110/entry-macro.S
include/asm-arm/arch-ebsa285/entry-macro.S
include/asm-arm/arch-ep93xx/entry-macro.S
include/asm-arm/arch-h720x/entry-macro.S
include/asm-arm/arch-imx/entry-macro.S
include/asm-arm/arch-integrator/entry-macro.S
include/asm-arm/arch-iop13xx/entry-macro.S
include/asm-arm/arch-iop13xx/iop13xx.h
include/asm-arm/arch-iop13xx/irqs.h
include/asm-arm/arch-iop13xx/system.h
include/asm-arm/arch-iop13xx/time.h [new file with mode: 0644]
include/asm-arm/arch-iop32x/entry-macro.S
include/asm-arm/arch-iop32x/time.h [new file with mode: 0644]
include/asm-arm/arch-iop33x/entry-macro.S
include/asm-arm/arch-iop33x/time.h [new file with mode: 0644]
include/asm-arm/arch-ixp2000/entry-macro.S
include/asm-arm/arch-ixp23xx/entry-macro.S
include/asm-arm/arch-ixp23xx/ixdp2351.h
include/asm-arm/arch-ixp4xx/entry-macro.S
include/asm-arm/arch-l7200/entry-macro.S
include/asm-arm/arch-lh7a40x/entry-macro.S
include/asm-arm/arch-netx/entry-macro.S
include/asm-arm/arch-ns9xxx/entry-macro.S
include/asm-arm/arch-omap/entry-macro.S
include/asm-arm/arch-omap/memory.h
include/asm-arm/arch-omap/omap-alsa.h
include/asm-arm/arch-pnx4008/entry-macro.S
include/asm-arm/arch-pxa/entry-macro.S
include/asm-arm/arch-pxa/gpio.h
include/asm-arm/arch-pxa/hardware.h
include/asm-arm/arch-realview/entry-macro.S
include/asm-arm/arch-rpc/entry-macro.S
include/asm-arm/arch-s3c2410/audio.h
include/asm-arm/arch-s3c2410/entry-macro.S
include/asm-arm/arch-s3c2410/gpio.h
include/asm-arm/arch-sa1100/entry-macro.S
include/asm-arm/arch-sa1100/gpio.h
include/asm-arm/arch-shark/entry-macro.S
include/asm-arm/arch-versatile/entry-macro.S
include/asm-arm/hardware/iop3xx.h
include/asm-arm/system.h
include/asm-avr32/Kbuild
include/asm-avr32/dma-mapping.h
include/asm-frv/pgtable.h
include/asm-generic/page.h
include/asm-i386/delay.h
include/asm-i386/idle.h [deleted file]
include/asm-i386/io_apic.h
include/asm-i386/msr.h
include/asm-i386/nmi.h
include/asm-i386/paravirt.h
include/asm-i386/pgtable.h
include/asm-i386/processor.h
include/asm-i386/time.h
include/asm-i386/timer.h
include/asm-i386/topology.h
include/asm-i386/tsc.h
include/asm-i386/vmi.h
include/asm-i386/vmi_time.h
include/asm-ia64/kexec.h
include/asm-ia64/mca.h
include/asm-ia64/meminit.h
include/asm-ia64/pal.h
include/asm-ia64/pci.h
include/asm-ia64/resource.h
include/asm-ia64/sal.h
include/asm-ia64/swiotlb.h [deleted file]
include/asm-ia64/topology.h
include/asm-ia64/unwind.h
include/asm-m68knommu/m528xsim.h
include/asm-mips/bitops.h
include/asm-mips/dma.h
include/asm-mips/ds1742.h [deleted file]
include/asm-mips/ioctl.h
include/asm-mips/jmr3927/jmr3927.h
include/asm-mips/lasat/lasat.h
include/asm-mips/mach-atlas/mc146818rtc.h
include/asm-mips/mach-generic/dma-coherence.h
include/asm-mips/mach-generic/mc146818rtc.h
include/asm-mips/mach-ip27/topology.h
include/asm-mips/mach-jmr3927/ds1742.h [deleted file]
include/asm-mips/mach-jmr3927/mangle-port.h [new file with mode: 0644]
include/asm-mips/mach-mips/mc146818rtc.h
include/asm-mips/mach-rm/mc146818rtc.h
include/asm-mips/mips-boards/prom.h
include/asm-mips/mips_mt.h
include/asm-mips/ptrace.h
include/asm-mips/sgialib.h
include/asm-mips/sibyte/sb1250.h
include/asm-mips/sibyte/trace_prof.h [deleted file]
include/asm-mips/sigcontext.h
include/asm-mips/smtc.h
include/asm-mips/smtc_ipi.h
include/asm-mips/sni.h
include/asm-mips/spinlock.h
include/asm-mips/stackframe.h
include/asm-mips/uaccess.h
include/asm-mips/unistd.h
include/asm-parisc/assembly.h
include/asm-parisc/atomic.h
include/asm-parisc/bitops.h
include/asm-parisc/bug.h
include/asm-parisc/cache.h
include/asm-parisc/cacheflush.h
include/asm-parisc/dma-mapping.h
include/asm-parisc/elf.h
include/asm-parisc/hardware.h
include/asm-parisc/io.h
include/asm-parisc/led.h
include/asm-parisc/linkage.h
include/asm-parisc/mmzone.h
include/asm-parisc/module.h
include/asm-parisc/msgbuf.h
include/asm-parisc/page.h
include/asm-parisc/parisc-device.h
include/asm-parisc/pdc.h
include/asm-parisc/pdcpat.h
include/asm-parisc/pgalloc.h
include/asm-parisc/pgtable.h
include/asm-parisc/posix_types.h
include/asm-parisc/processor.h
include/asm-parisc/sembuf.h
include/asm-parisc/shmbuf.h
include/asm-parisc/signal.h
include/asm-parisc/smp.h
include/asm-parisc/spinlock_types.h
include/asm-parisc/statfs.h
include/asm-parisc/system.h
include/asm-parisc/thread_info.h
include/asm-parisc/tlbflush.h
include/asm-parisc/types.h
include/asm-parisc/uaccess.h
include/asm-parisc/unistd.h
include/asm-powerpc/topology.h
include/asm-s390/atomic.h
include/asm-s390/bugs.h
include/asm-s390/ipl.h [new file with mode: 0644]
include/asm-s390/local.h
include/asm-s390/processor.h
include/asm-s390/sections.h
include/asm-s390/setup.h
include/asm-sh/cache.h
include/asm-sh/cacheflush.h
include/asm-sh/cpu-sh3/cacheflush.h
include/asm-sh/cpu-sh4/cacheflush.h
include/asm-sh/pgtable.h
include/asm-sh/thread_info.h
include/asm-sparc/pci.h
include/asm-sparc/prom.h
include/asm-sparc64/dma.h
include/asm-sparc64/floppy.h
include/asm-sparc64/parport.h
include/asm-sparc64/pci.h
include/asm-sparc64/prom.h
include/asm-um/pgtable.h
include/asm-x86_64/hw_irq.h
include/asm-x86_64/io_apic.h
include/asm-x86_64/msr.h
include/asm-x86_64/nmi.h
include/asm-x86_64/swiotlb.h
include/asm-x86_64/topology.h
include/asm-x86_64/tsc.h
include/linux/ata.h
include/linux/audit.h
include/linux/auto_fs4.h
include/linux/backlight.h
include/linux/cdrom.h
include/linux/cfag12864b.h
include/linux/compat.h
include/linux/cpumask.h
include/linux/device.h
include/linux/ds1742rtc.h [deleted file]
include/linux/fb.h
include/linux/gpio_keys.h [moved from include/asm-arm/hardware/gpio_keys.h with 100% similarity]
include/linux/hid.h
include/linux/hrtimer.h
include/linux/hugetlb.h
include/linux/ide.h
include/linux/if_pppox.h
include/linux/if_vlan.h
include/linux/igmp.h
include/linux/irq.h
include/linux/isdn/capiutil.h
include/linux/kdev_t.h
include/linux/kmod.h
include/linux/ks0108.h
include/linux/kvm.h
include/linux/kvm_para.h [new file with mode: 0644]
include/linux/lcd.h
include/linux/libata.h
include/linux/magic.h
include/linux/migrate.h
include/linux/minix_fs.h
include/linux/mm.h
include/linux/mmc/host.h
include/linux/mod_devicetable.h
include/linux/mtd/iflash.h [deleted file]
include/linux/mtd/mtd.h
include/linux/mtd/onenand.h
include/linux/mv643xx.h
include/linux/ncp_fs_sb.h
include/linux/netfilter_ipv4/ip_conntrack_core.h
include/linux/nodemask.h
include/linux/page-flags.h
include/linux/pci.h
include/linux/pci_regs.h
include/linux/pm.h
include/linux/sched.h
include/linux/shm.h
include/linux/sm501-regs.h [new file with mode: 0644]
include/linux/sm501.h [new file with mode: 0644]
include/linux/socket.h
include/linux/spinlock.h
include/linux/stat.h
include/linux/sunrpc/sched.h
include/linux/sunrpc/svc.h
include/linux/sunrpc/svcsock.h
include/linux/swapops.h
include/linux/sysfs.h
include/linux/topology.h
include/linux/usb.h
include/linux/usb/ch9.h
include/linux/usb/iowarrior.h [new file with mode: 0644]
include/linux/usb/quirks.h [new file with mode: 0644]
include/linux/videodev2.h
include/linux/wireless.h
include/linux/writeback.h
include/media/cx2341x.h
include/media/ir-common.h
include/media/saa7115.h
include/media/v4l2-common.h
include/media/v4l2-dev.h
include/media/video-buf.h
include/net/inet_timewait_sock.h
include/net/irda/irda.h
include/net/netfilter/nf_conntrack_core.h
include/net/sock.h
include/net/xfrm.h
include/sound/version.h
init/Kconfig
init/main.c
ipc/mqueue.c
ipc/shm.c
kernel/hrtimer.c
kernel/irq/migration.c
kernel/kmod.c
kernel/kprobes.c
kernel/lockdep.c
kernel/module.c
kernel/params.c
kernel/power/Kconfig
kernel/power/main.c
kernel/rcutorture.c
kernel/relay.c
kernel/sched.c
kernel/signal.c
kernel/sysctl.c
kernel/time/clocksource.c
kernel/time/tick-broadcast.c
kernel/time/tick-common.c
kernel/time/tick-internal.h
kernel/time/tick-sched.c
kernel/timer.c
lib/Kconfig.debug
lib/bitmap.c
lib/cpumask.c
lib/fault-inject.c
lib/genalloc.c
lib/kobject.c
lib/swiotlb.c
mm/mempolicy.c
mm/migrate.c
mm/mmap.c
mm/page-writeback.c
mm/page_alloc.c
mm/rmap.c
mm/shmem.c
mm/slab.c
mm/tiny-shmem.c
mm/truncate.c
mm/vmscan.c
net/8021q/vlan.c
net/bluetooth/hci_sock.c
net/bluetooth/hidp/Kconfig
net/bluetooth/hidp/core.c
net/bluetooth/hidp/hidp.h
net/bluetooth/hidp/sock.c
net/bluetooth/rfcomm/tty.c
net/bridge/br_if.c
net/bridge/br_ioctl.c
net/bridge/br_notify.c
net/bridge/br_private.h
net/bridge/netfilter/ebtables.c
net/core/skbuff.c
net/core/sock.c
net/dccp/ccids/ccid3.c
net/dccp/dccp.h
net/dccp/input.c
net/dccp/minisocks.c
net/dccp/output.c
net/dccp/timer.c
net/ieee80211/softmac/ieee80211softmac_module.c
net/ieee80211/softmac/ieee80211softmac_wx.c
net/ipv4/Kconfig
net/ipv4/cipso_ipv4.c
net/ipv4/devinet.c
net/ipv4/igmp.c
net/ipv4/multipath_random.c
net/ipv4/multipath_wrandom.c
net/ipv4/netfilter/ip_conntrack_core.c
net/ipv4/netfilter/ip_conntrack_proto_tcp.c
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
net/ipv4/netfilter/nf_conntrack_proto_icmp.c
net/ipv4/netfilter/nf_nat_core.c
net/ipv4/netfilter/nf_nat_proto_gre.c
net/ipv4/netfilter/nf_nat_proto_icmp.c
net/ipv4/netfilter/nf_nat_proto_tcp.c
net/ipv4/netfilter/nf_nat_proto_udp.c
net/ipv4/tcp.c
net/ipv4/tcp_minisocks.c
net/ipv4/udp.c
net/ipv4/xfrm4_mode_tunnel.c
net/ipv4/xfrm4_policy.c
net/ipv6/Makefile
net/ipv6/addrconf.c
net/ipv6/addrconf_core.c [new file with mode: 0644]
net/ipv6/af_inet6.c
net/ipv6/anycast.c
net/ipv6/ip6_tunnel.c
net/ipv6/ipv6_sockglue.c
net/ipv6/ipv6_syms.c
net/ipv6/netfilter.c
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
net/ipv6/xfrm6_policy.c
net/ipx/ChangeLog [deleted file]
net/ipx/Kconfig
net/irda/irmod.c
net/key/af_key.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_proto_gre.c
net/netfilter/nf_conntrack_proto_tcp.c
net/netfilter/nf_conntrack_proto_udp.c
net/netfilter/nfnetlink.c
net/netfilter/nfnetlink_log.c
net/netlabel/netlabel_unlabeled.c
net/packet/af_packet.c
net/sctp/ipv6.c
net/sctp/outqueue.c
net/sctp/sm_statefuns.c
net/sunrpc/svc.c
net/sunrpc/svcsock.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_user.c
scripts/kernel-doc
scripts/mod/file2alias.c
scripts/mod/modpost.c
security/selinux/hooks.c
security/selinux/ss/avtab.c
security/selinux/ss/policydb.c
security/selinux/ss/services.c
security/selinux/ss/sidtab.c
sound/arm/aaci.c
sound/parisc/harmony.c
sound/pci/ac97/ac97_patch.c
sound/pci/ali5451/ali5451.c
sound/pci/bt87x.c
sound/pci/cmipci.c
sound/pci/echoaudio/echoaudio.c
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/riptide/riptide.c
sound/pci/rme9652/hdspm.c
sound/soc/codecs/wm9712.c

diff --git a/CREDITS b/CREDITS
index a4e5599003b28d5c5e7f74f08d24d1c2dba718c3..6bd8ab86b5bd1b80f2df2ceaf0a4f8d7634639a0 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -2678,7 +2678,7 @@ S: Ottawa, Ontario
 S: Canada K2P 0X8
 
 N: Mikael Pettersson
-E: mikpe@csd.uu.se
+E: mikpe@it.uu.se
 W: http://www.csd.uu.se/~mikpe/
 D: Miscellaneous fixes
 
index bfbb2718a2799b972fa6663ffbc0b34a7b88b999..bd23dc0bc0c7c9ced4323b761396377d700fad83 100644 (file)
@@ -76,3 +76,7 @@ kernel patches.
 22: Newly-added code has been compiled with `gcc -W'.  This will generate
     lots of noise, but is good for finding bugs like "warning: comparison
     between signed and unsigned".
+
+23: Tested after it has been merged into the -mm patchset to make sure
+    that it still works with all of the other queued patches and various
+    changes in the VM, VFS, and other subsystems.
index e12bc3284a272eae2c23999c30db92fdc47bfa5a..0dab6e32c130a2fc61192fd99cf95a963648beea 100644 (file)
@@ -5,10 +5,10 @@
 Introduction
 ------------
 
-  The S3C2410 supports a low-power suspend mode, where the SDRAM is kept
+  The S3C24XX supports a low-power suspend mode, where the SDRAM is kept
   in Self-Refresh mode, and all but the essential peripheral blocks are
   powered down. For more information on how this works, please look
-  at the S3C2410 datasheets from Samsung.
+  at the relevant CPU datasheet from Samsung.
 
 
 Requirements
@@ -56,6 +56,27 @@ Machine Support
   Note, the original method of adding an late_initcall() is wrong,
   and will end up initialising all compiled machines' pm init!
 
+  The following is an example of code used for testing wakeup from
+  an falling edge on IRQ_EINT0:
+
+
+static irqreturn_t button_irq(int irq, void *pw)
+{
+       return IRQ_HANDLED;
+}
+
+statuc void __init machine_init(void)
+{
+       ...
+
+       request_irq(IRQ_EINT0, button_irq, IRQF_TRIGGER_FALLING,
+                  "button-irq-eint0", NULL);
+
+       enable_irq_wake(IRQ_EINT0);
+
+       s3c2410_pm_init();
+}
+
 
 Debugging
 ---------
@@ -70,6 +91,12 @@ Debugging
      care should be taken that any external clock sources that the UARTs
      rely on are still enabled at that point.
 
+  3) If any debugging is placed in the resume path, then it must have the
+     relevant clocks and peripherals setup before use (ie, bootloader).
+
+     For example, if you transmit a character from the UART, the baud
+     rate and uart controls must be setup beforehand.
+
 
 Configuration
 -------------
@@ -89,6 +116,10 @@ Configuration
     Allows the entire memory to be checksummed before and after the
     suspend to see if there has been any corruption of the contents.
 
+    Note, the time to calculate the CRC is dependant on the CPU speed
+    and the size of memory. For an 64Mbyte RAM area on an 200MHz
+    S3C2410, this can take approximately 4 seconds to complete.
+
     This support requires the CRC32 function to be enabled.
 
 
diff --git a/Documentation/cpu-load.txt b/Documentation/cpu-load.txt
new file mode 100644 (file)
index 0000000..287224e
--- /dev/null
@@ -0,0 +1,113 @@
+CPU load
+--------
+
+Linux exports various bits of information via `/proc/stat' and
+`/proc/uptime' that userland tools, such as top(1), use to calculate
+the average time system spent in a particular state, for example:
+
+    $ iostat
+    Linux 2.6.18.3-exp (linmac)     02/20/2007
+
+    avg-cpu:  %user   %nice %system %iowait  %steal   %idle
+              10.01    0.00    2.92    5.44    0.00   81.63
+
+    ...
+
+Here the system thinks that over the default sampling period the
+system spent 10.01% of the time doing work in user space, 2.92% in the
+kernel, and was overall 81.63% of the time idle.
+
+In most cases the `/proc/stat' information reflects the reality quite
+closely, however due to the nature of how/when the kernel collects
+this data sometimes it can not be trusted at all.
+
+So how is this information collected?  Whenever timer interrupt is
+signalled the kernel looks what kind of task was running at this
+moment and increments the counter that corresponds to this tasks
+kind/state.  The problem with this is that the system could have
+switched between various states multiple times between two timer
+interrupts yet the counter is incremented only for the last state.
+
+
+Example
+-------
+
+If we imagine the system with one task that periodically burns cycles
+in the following manner:
+
+ time line between two timer interrupts
+|--------------------------------------|
+ ^                                    ^
+ |_ something begins working          |
+                                      |_ something goes to sleep
+                                     (only to be awaken quite soon)
+
+In the above situation the system will be 0% loaded according to the
+`/proc/stat' (since the timer interrupt will always happen when the
+system is executing the idle handler), but in reality the load is
+closer to 99%.
+
+One can imagine many more situations where this behavior of the kernel
+will lead to quite erratic information inside `/proc/stat'.
+
+
+/* gcc -o hog smallhog.c */
+#include <time.h>
+#include <limits.h>
+#include <signal.h>
+#include <sys/time.h>
+#define HIST 10
+
+static volatile sig_atomic_t stop;
+
+static void sighandler (int signr)
+{
+     (void) signr;
+     stop = 1;
+}
+static unsigned long hog (unsigned long niters)
+{
+     stop = 0;
+     while (!stop && --niters);
+     return niters;
+}
+int main (void)
+{
+     int i;
+     struct itimerval it = { .it_interval = { .tv_sec = 0, .tv_usec = 1 },
+                             .it_value = { .tv_sec = 0, .tv_usec = 1 } };
+     sigset_t set;
+     unsigned long v[HIST];
+     double tmp = 0.0;
+     unsigned long n;
+     signal (SIGALRM, &sighandler);
+     setitimer (ITIMER_REAL, &it, NULL);
+
+     hog (ULONG_MAX);
+     for (i = 0; i < HIST; ++i) v[i] = ULONG_MAX - hog (ULONG_MAX);
+     for (i = 0; i < HIST; ++i) tmp += v[i];
+     tmp /= HIST;
+     n = tmp - (tmp / 3.0);
+
+     sigemptyset (&set);
+     sigaddset (&set, SIGALRM);
+
+     for (;;) {
+         hog (n);
+         sigwait (&set, &i);
+     }
+     return 0;
+}
+
+
+References
+----------
+
+http://lkml.org/lkml/2007/2/12/6
+Documentation/filesystems/proc.txt (1.8)
+
+
+Thanks
+------
+
+Con Kolivas, Pavel Machek
index 6a451f47d40f3ede1ee6b726b5782d13ed145d6b..c3b1430cf603eafd2b51c2e43af55aec79a0fd40 100644 (file)
@@ -304,3 +304,15 @@ Why:       The code says it was obsolete when it was written in 2001.
 Who:   Richard Purdie <rpurdie@rpsys.net>
 
 ---------------------------
+
+What:  Wireless extensions over netlink (CONFIG_NET_WIRELESS_RTNETLINK)
+When:  with the merge of wireless-dev, 2.6.22 or later
+Why:   The option/code is
+        * not enabled on most kernels
+        * not required by any userspace tools (except an experimental one,
+          and even there only for some parts, others use ioctl)
+        * pointless since wext is no longer evolving and the ioctl
+          interface needs to be kept
+Who:   Johannes Berg <johannes@sipsolutions.net>
+
+---------------------------
index 72af5de1effb44a93d907ed4e0117ec403a8257e..5484ab5efd4f54433bc2a6f7c16c482cf8085001 100644 (file)
@@ -41,6 +41,7 @@ Table of Contents
   2.11 /proc/sys/fs/mqueue - POSIX message queues filesystem
   2.12 /proc/<pid>/oom_adj - Adjust the oom-killer score
   2.13 /proc/<pid>/oom_score - Display current oom-killer score
+  2.14 /proc/<pid>/io - Display the IO accounting fields
 
 ------------------------------------------------------------------------------
 Preface
@@ -1990,3 +1991,107 @@ need to  recompile  the kernel, or even to reboot the system. The files in the
 command to write value into these files, thereby changing the default settings
 of the kernel.
 ------------------------------------------------------------------------------
+
+2.14  /proc/<pid>/io - Display the IO accounting fields
+-------------------------------------------------------
+
+This file contains IO statistics for each running process
+
+Example
+-------
+
+test:/tmp # dd if=/dev/zero of=/tmp/test.dat &
+[1] 3828
+
+test:/tmp # cat /proc/3828/io
+rchar: 323934931
+wchar: 323929600
+syscr: 632687
+syscw: 632675
+read_bytes: 0
+write_bytes: 323932160
+cancelled_write_bytes: 0
+
+
+Description
+-----------
+
+rchar
+-----
+
+I/O counter: chars read
+The number of bytes which this task has caused to be read from storage. This
+is simply the sum of bytes which this process passed to read() and pread().
+It includes things like tty IO and it is unaffected by whether or not actual
+physical disk IO was required (the read might have been satisfied from
+pagecache)
+
+
+wchar
+-----
+
+I/O counter: chars written
+The number of bytes which this task has caused, or shall cause to be written
+to disk. Similar caveats apply here as with rchar.
+
+
+syscr
+-----
+
+I/O counter: read syscalls
+Attempt to count the number of read I/O operations, i.e. syscalls like read()
+and pread().
+
+
+syscw
+-----
+
+I/O counter: write syscalls
+Attempt to count the number of write I/O operations, i.e. syscalls like
+write() and pwrite().
+
+
+read_bytes
+----------
+
+I/O counter: bytes read
+Attempt to count the number of bytes which this process really did cause to
+be fetched from the storage layer. Done at the submit_bio() level, so it is
+accurate for block-backed filesystems. <please add status regarding NFS and
+CIFS at a later time>
+
+
+write_bytes
+-----------
+
+I/O counter: bytes written
+Attempt to count the number of bytes which this process caused to be sent to
+the storage layer. This is done at page-dirtying time.
+
+
+cancelled_write_bytes
+---------------------
+
+The big inaccuracy here is truncate. If a process writes 1MB to a file and
+then deletes the file, it will in fact perform no writeout. But it will have
+been accounted as having caused 1MB of write.
+In other words: The number of bytes which this process caused to not happen,
+by truncating pagecache. A task can cause "negative" IO too. If this task
+truncates some dirty pagecache, some IO which another task has been accounted
+for (in it's write_bytes) will not be happening. We _could_ just subtract that
+from the truncating task's write_bytes, but there is information loss in doing
+that.
+
+
+Note
+----
+
+At its current implementation state, this is a bit racy on 32-bit machines: if
+process A reads process B's /proc/pid/io while process B is updating one of
+those 64-bit counters, process A could see an intermediate result.
+
+
+More information about this can be found within the taskstats documentation in
+Documentation/accounting.
+
+------------------------------------------------------------------------------
index 7737bfd03cf8481e97717a849fc6c83887b7a94e..ea271f2d395400b82cd8023db74fed76d878ce06 100644 (file)
@@ -617,6 +617,11 @@ struct address_space_operations {
        In this case the prepare_write will be retried one the lock is
        regained.
 
+       Note: the page _must not_ be marked uptodate in this function
+       (or anywhere else) unless it actually is uptodate right now. As
+       soon as a page is marked uptodate, it is possible for a concurrent
+       read(2) to copy it to userspace.
+
   commit_write: If prepare_write succeeds, new data will be copied
         into the page and then commit_write will be called.  It will
         typically update the size of the file (if appropriate) and
index 786c3a766995f09ad8ad443c042be0af0a6484f3..3bb9f9c986113d4f2f31d1d56f461645bb84d917 100644 (file)
@@ -232,7 +232,9 @@ Summary of ide driver parameters for kernel command line
 
  "hdx=remap63"         : remap the drive: add 63 to all sector numbers
                          (for DM OnTrack)
+
+ "idex=noautotune"     : driver will NOT attempt to tune interface speed
+
  "hdx=autotune"                : driver will attempt to tune interface speed
                          to the fastest PIO mode supported,
                          if possible for this drive only.
@@ -267,17 +269,6 @@ Summary of ide driver parameters for kernel command line
  "idex=base,ctl"       : specify both base and ctl
 
  "idex=base,ctl,irq"   : specify base, ctl, and irq number
- "idex=autotune"       : driver will attempt to tune interface speed
-                         to the fastest PIO mode supported,
-                         for all drives on this interface.
-                         Not fully supported by all chipset types,
-                         and quite likely to cause trouble with
-                         older/odd IDE drives.
-
- "idex=noautotune"     : driver will NOT attempt to tune interface speed 
-                         This is the default for most chipsets,
-                         except the cmd640.
 
  "idex=serialize"      : do not overlap operations on idex. Please note
                          that you will have to specify this option for
@@ -303,13 +294,8 @@ The following are valid ONLY on ide0, which usually corresponds
 to the first ATA interface found on the particular host, and the defaults for
 the base,ctl ports must not be altered.
 
- "ide0=dtc2278"                : probe/support DTC2278 interface
- "ide0=ht6560b"                : probe/support HT6560B interface
  "ide0=cmd640_vlb"     : *REQUIRED* for VLB cards with the CMD640 chip
                          (not for PCI -- automatically detected)
- "ide0=qd65xx"         : probe/support qd65xx interface
- "ide0=ali14xx"                : probe/support ali14xx chipsets (ALI M1439/M1443/M1445)
- "ide0=umc8672"                : probe/support umc8672 chipsets
 
  "ide=doubler"         : probe/support IDE doublers on Amiga
 
@@ -317,6 +303,15 @@ There may be more options than shown -- use the source, Luke!
 
 Everything else is rejected with a "BAD OPTION" message.
 
+For legacy IDE VLB host drivers (ali14xx/dtc2278/ht6560b/qd65xx/umc8672)
+you need to explicitly enable probing by using "probe" kernel parameter,
+i.e. to enable probing for ALI M14xx chipsets (ali14xx host driver) use:
+
+* "ali14xx.probe" boot option when ali14xx driver is built-in the kernel
+
+* "probe" module parameter when ali14xx driver is compiled as module
+  ("modprobe ali14xx probe")
+
 ================================================================================
 
 IDE ATAPI streaming tape driver
index 79775a4130b5e1992d8ed8ca82d3056d0263e0bc..2fedc081b4c8533e2897f1b456b406a0f2555c4b 100644 (file)
@@ -30,6 +30,10 @@ On x86 machines, the first 640 KB of physical memory is needed to boot,
 regardless of where the kernel loads. Therefore, kexec backs up this
 region just before rebooting into the dump-capture kernel.
 
+Similarly on PPC64 machines first 32KB of physical memory is needed for
+booting regardless of where the kernel is loaded and to support 64K page
+size kexec backs up the first 64KB memory.
+
 All of the necessary information about the system kernel's core image is
 encoded in the ELF format, and stored in a reserved area of memory
 before a crash. The physical address of the start of the ELF header is
@@ -224,7 +228,7 @@ Dump-capture kernel config options (Arch Dependent, x86_64)
 Dump-capture kernel config options (Arch Dependent, ppc64)
 ----------------------------------------------------------
 
--  Make and install the kernel and its modules. DO NOT add this kernel
+*  Make and install the kernel and its modules. DO NOT add this kernel
    to the boot loader configuration files.
 
 Dump-capture kernel config options (Arch Dependent, ia64)
@@ -251,8 +255,8 @@ Dump-capture kernel config options (Arch Dependent, ia64)
 Boot into System Kernel
 =======================
 
-1) Make and install the kernel and its modules. Update the boot loader
-   (such as grub, yaboot, or lilo) configuration files as necessary.
+1) Update the boot loader (such as grub, yaboot, or lilo) configuration
+   files as necessary.
 
 2) Boot the system kernel with the boot parameter "crashkernel=Y@X",
    where Y specifies how much memory to reserve for the dump-capture kernel
@@ -356,10 +360,11 @@ If die() is called, and it happens to be a thread with pid 0 or 1, or die()
 is called inside interrupt context or die() is called and panic_on_oops is set,
 the system will boot into the dump-capture kernel.
 
-On powererpc systems when a soft-reset is generated, die() is called by all cpus and the system will boot into the dump-capture kernel.
+On powererpc systems when a soft-reset is generated, die() is called by all cpus
+and the system will boot into the dump-capture kernel.
 
 For testing purposes, you can trigger a crash by using "ALT-SysRq-c",
-"echo c > /proc/sysrq-trigger or write a module to force the panic.
+"echo c > /proc/sysrq-trigger" or write a module to force the panic.
 
 Write Out the Dump File
 =======================
@@ -410,12 +415,9 @@ format. Crash is available on Dave Anderson's site at the following URL:
 To Do
 =====
 
-1) Provide a kernel pages filtering mechanism, so core file size is not
-   extreme on systems with huge memory banks.
-
-2) Relocatable kernel can help in maintaining multiple kernels for
-   crash_dump, and the same kernel as the system kernel can be used to
-   capture the dump.
+1) Provide relocatable kernels for all architectures to help in maintaining
+   multiple kernels for crash_dump, and the same kernel as the system kernel
+   can be used to capture the dump.
 
 
 Contact
index c479d30eeaa384c019550194d12c94c10bf1e948..856c8b114e71698731c93503f19a32bd1b10c481 100644 (file)
@@ -79,6 +79,7 @@ parameter is applicable:
                        Documentation/scsi/.
        SELINUX SELinux support is enabled.
        SERIAL  Serial support is enabled.
+       SH      SuperH architecture is enabled.
        SMP     The kernel is an SMP kernel.
        SPARC   Sparc architecture is enabled.
        SWSUSP  Software suspend is enabled.
@@ -125,7 +126,8 @@ and is between 256 and 4096 characters. It is defined in the file
                        See header of drivers/scsi/53c7xx.c.
                        See also Documentation/scsi/ncr53c7xx.txt.
 
-       acpi=           [HW,ACPI] Advanced Configuration and Power Interface
+       acpi=           [HW,ACPI,X86-64,i386]
+                       Advanced Configuration and Power Interface
                        Format: { force | off | ht | strict | noirq }
                        force -- enable ACPI if default was off
                        off -- disable ACPI if default was on
@@ -485,7 +487,7 @@ and is between 256 and 4096 characters. It is defined in the file
 
        dtc3181e=       [HW,SCSI]
 
-       earlyprintk=    [IA-32,X86-64]
+       earlyprintk=    [IA-32,X86-64,SH]
                        earlyprintk=vga
                        earlyprintk=serial[,ttySn[,baudrate]]
 
@@ -1685,6 +1687,22 @@ and is between 256 and 4096 characters. It is defined in the file
        stifb=          [HW]
                        Format: bpp:<bpp1>[:<bpp2>[:<bpp3>...]]
 
+       sunrpc.pool_mode=
+                       [NFS]
+                       Control how the NFS server code allocates CPUs to
+                       service thread pools.  Depending on how many NICs
+                       you have and where their interrupts are bound, this
+                       option will affect which CPUs will do NFS serving.
+                       Note: this parameter cannot be changed while the
+                       NFS server is running.
+
+                       auto        the server chooses an appropriate mode
+                                   automatically using heuristics
+                       global      a single global pool contains all CPUs
+                       percpu      one pool for each CPU
+                       pernode     one pool for each NUMA node (equivalent
+                                   to global on non-NUMA machines)
+
        swiotlb=        [IA-64] Number of I/O TLB slabs
 
        switches=       [HW,M68k]
@@ -1758,10 +1776,17 @@ and is between 256 and 4096 characters. It is defined in the file
                        Note that genuine overcurrent events won't be
                        reported either.
 
+       usbcore.autosuspend=
+                       [USB] The autosuspend time delay (in seconds) used
+                       for newly-detected USB devices (default 2).  This
+                       is the time required before an idle device will be
+                       autosuspended.  Devices for which the delay is set
+                       to 0 won't be autosuspended at all.
+
        usbhid.mousepoll=
                        [USBHID] The interval which mice are to be polled at.
 
-       vdso=           [IA-32]
+       vdso=           [IA-32,SH]
                        vdso=1: enable VDSO (default)
                        vdso=0: disable VDSO mapping
 
index af67faccf4de991f75ef5bcc387095dceaa21926..0e740c812d12e4dc3ea77c67601a3937c26b26cb 100644 (file)
@@ -65,7 +65,6 @@ CMAGIC                0x0111      user              include/linux/a.out.h
 MKISS_DRIVER_MAGIC    0x04bf      mkiss_channel     drivers/net/mkiss.h
 RISCOM8_MAGIC         0x0907      riscom_port       drivers/char/riscom8.h
 SPECIALIX_MAGIC       0x0907      specialix_port    drivers/char/specialix_io8.h
-AURORA_MAGIC          0x0A18      Aurora_port       drivers/sbus/char/aurora.h
 HDLC_MAGIC            0x239e      n_hdlc            drivers/char/n_hdlc.c
 APM_BIOS_MAGIC        0x4101      apm_user          arch/i386/kernel/apm.c
 CYCLADES_MAGIC        0x4359      cyclades_port     include/linux/cyclades.h
index a0f6842368c37b77b571c5817029adaf45db1769..d3aae1f9b4c1970f5d119be92e54549d19640be3 100644 (file)
@@ -147,6 +147,11 @@ tcp_available_congestion_control - STRING
        More congestion control algorithms may be available as modules,
        but not loaded.
 
+tcp_base_mss - INTEGER
+       The initial value of search_low to be used by Packetization Layer
+       Path MTU Discovery (MTU probing).  If MTU probing is enabled,
+       this is the inital MSS used by the connection.
+
 tcp_congestion_control - STRING
        Set the congestion control algorithm to be used for new
        connections. The algorithm "reno" is always available, but
@@ -243,6 +248,27 @@ tcp_mem - vector of 3 INTEGERs: min, pressure, max
        Defaults are calculated at boot time from amount of available
        memory.
 
+tcp_moderate_rcvbuf - BOOLEAN
+       If set, TCP performs receive buffer autotuning, attempting to
+       automatically size the buffer (no greater than tcp_rmem[2]) to
+       match the size required by the path for full throughput.  Enabled by
+       default.
+
+tcp_mtu_probing - INTEGER
+       Controls TCP Packetization-Layer Path MTU Discovery.  Takes three
+       values:
+         0 - Disabled
+         1 - Disabled by default, enabled when an ICMP black hole detected
+         2 - Always enabled, use initial MSS of tcp_base_mss.
+
+tcp_no_metrics_save - BOOLEAN
+       By default, TCP saves various connection metrics in the route cache
+       when the connection closes, so that connections established in the
+       near future can use these to set initial conditions.  Usually, this
+       increases overall performance, but may sometimes cause performance
+       degredation.  If set, TCP will not cache metrics on closing
+       connections.
+
 tcp_orphan_retries - INTEGER
        How may times to retry before killing TCP connection, closed
        by our side. Default value 7 corresponds to ~50sec-16min
index 2503404ae5c26bce481d56daecb008588e86102e..ea55ea8bc8ef0c32de234e612adf742d72214167 100644 (file)
@@ -234,6 +234,12 @@ characters, each representing a particular tainted value.
   6: 'B' if a page-release function has found a bad page reference or
      some unexpected page flags.
 
+  7: 'U' if a user specifically requested that the Tainted flag be set,
+     ' ' otherwise.
+
+  7: 'U' if a user or user application specifically requested that the
+     Tainted flag be set, ' ' otherwise.
+
 The primary reason for the 'Tainted: ' string is to tell kernel
 debuggers if this is a clean kernel or if anything unusual has
 occurred.  Tainting is permanent: even if an offending module is
index c30ff1bb2d1019aedfb8d96d97cd248b9e711b93..db398a6441c1b110c94b1f32b2038926b728e028 100644 (file)
@@ -370,7 +370,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
     mpu_port   - 0x300,0x310,0x320,0x330 = legacy port,
                  1 = integrated PCI port,
                  0 = disable (default)
-    fm_port     - 0x388 (default), 0 = disable (default)
+    fm_port     - 0x388 = legacy port,
+                 1 = integrated PCI port (default),
+                 0 = disable
     soft_ac3    - Software-conversion of raw SPDIF packets (model 033 only)
                   (default = 1)
     joystick_port - Joystick port address (0 = disable, 1 = auto-detect)
@@ -895,10 +897,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
                        can be adjusted.  Appearing only when compiled with
                        $CONFIG_SND_DEBUG=y
 
-       STAC9200/9205/9220/9221/9254
+       STAC9200/9205/9254
+         ref           Reference board
+
+       STAC9220/9221
          ref           Reference board
          3stack        D945 3stack
          5stack        D945 5stack + SPDIF
+         macmini       Intel Mac Mini
+         macbook       Intel Mac Book
+         macbook-pro   Intel Mac Book Pro
 
        STAC9202/9250/9251
          ref           Reference board, base config
index f9c99c9a54f937616903a5fa5d0b8fee2fd020ae..1a3bdc27d95e98ce49c07791b02515e38ef678a5 100644 (file)
@@ -45,11 +45,15 @@ special.
 Getting sparse
 ~~~~~~~~~~~~~~
 
-With git, you can just get it from
+You can get latest released versions from the Sparse homepage at
+http://www.kernel.org/pub/linux/kernel/people/josh/sparse/
 
-        rsync://rsync.kernel.org/pub/scm/devel/sparse/sparse.git
+Alternatively, you can get snapshots of the latest development version
+of sparse using git to clone..
 
-and DaveJ has tar-balls at
+        git://git.kernel.org/pub/scm/linux/kernel/git/josh/sparse.git
+
+DaveJ has hourly generated tarballs of the git tree available at..
 
         http://www.codemonkey.org.uk/projects/git-snapshots/sparse/
 
index 4efa4645885f451e834a39908c4d8e1a26bf6faf..fc2fe9bc6713ff013ab0a93299975ca6d7e45ad3 100644 (file)
 125 -> MATRIX Vision Sigma-SQ
 126 -> MATRIX Vision Sigma-SLC
 127 -> APAC Viewcomp 878(AMAX)
-128 -> DViCO FusionHDTV DVB-T Lite                         [18ac:db10]
+128 -> DViCO FusionHDTV DVB-T Lite                         [18ac:db10,18ac:db11]
 129 -> V-Gear MyVCD
 130 -> Super TV Tuner
 131 -> Tibet Systems 'Progress DVR' CS16
index f6201cc37ec5fb608418b2e8b0cf64aeb33911ad..a12246a9bf23ff88b750874967842d8ec7ec8c9a 100644 (file)
 103 -> Compro Videomate DVB-T200A
 104 -> Hauppauge WinTV-HVR1110 DVB-T/Hybrid     [0070:6701]
 105 -> Terratec Cinergy HT PCMCIA               [153b:1172]
+106 -> Encore ENLTV                             [1131:2342,1131:2341,3016:2344]
+107 -> Encore ENLTV-FM                          [1131:230f]
+108 -> Terratec Cinergy HT PCI                  [153b:1175]
index ade8651e24432f879f6e3df5700b2761a9b807bd..04986efb731c443fcd16457d8e3638c8c15e9f81 100644 (file)
@@ -197,10 +197,10 @@ Use the ../../Maintainers file, particularly the  VIDEO FOR LINUX and PARALLEL
 PORT SUPPORT sections
 
 The video4linux page:
-  http://roadrunner.swansea.linux.org.uk/v4l.shtml
+  http://linuxtv.org
 
-The video4linux2 page:
-  http://millennium.diads.com/bdirks/v4l2.htm
+The V4L2 API spec:
+  http://v4l2spec.bytesex.org/
 
 Some web pages about the quickcams:
    http://www.dkfz-heidelberg.de/Macromol/wedemann/mini-HOWTO-cqcam.html
index deb218f77adb05f427aa1b5a2437fc3ca010eb4b..85c575ac4fb982dfbfe16e7258c4b7f0909633cb 100644 (file)
@@ -339,9 +339,9 @@ Information - video4linux/mjpeg extensions:
 (also see below)
 
 Information - video4linux2:
-http://www.thedirks.org/v4l2/
+http://linuxtv.org
+http://v4l2spec.bytesex.org/
 /usr/include/linux/videodev2.h
-http://www.bytesex.org/v4l/
 
 More information on the video4linux/mjpeg extensions, by Serguei
 Miridonovi and Rainer Johanni:
index 78bf5f21e513333e6c04b4369d9f6a1d9107fe0a..8c317b7a4fc9fc64bced2d0b87c75c8db0ab592b 100644 (file)
@@ -21,7 +21,7 @@ Param[0]
        0 based frame number in GOP to begin playback from.
 Param[1]
        Specifies the number of muted audio frames to play before normal
-       audio resumes.
+       audio resumes. (This is not implemented in the firmware, leave at 0)
 
 -------------------------------------------------------------------------------
 
@@ -32,6 +32,10 @@ Description
        playback stops at specified PTS.
 Param[0]
        Display 0=last frame, 1=black
+       Note: this takes effect immediately, so if you want to wait for a PTS,
+       then use '0', otherwise the screen goes to black at once.
+       You can call this later (even if there is no playback) with a 1 value
+       to set the screen to black.
 Param[1]
        PTS low
 Param[2]
@@ -60,8 +64,12 @@ Param[0]
            31   Speed:
                     '0' slow
                     '1' fast
+       Note: n is limited to 2. Anything higher does not result in
+       faster playback. Instead the host should start dropping frames.
 Param[1]
        Direction: 0=forward, 1=reverse
+       Note: to make reverse playback work you have to write full GOPs in
+       reverse order.
 Param[2]
        Picture mask:
            1=I frames
@@ -69,13 +77,16 @@ Param[2]
            7=I, P, B frames
 Param[3]
        B frames per GOP (for reverse play only)
+       Note: for reverse playback the Picture Mask should be set to I or I, P.
+       Adding B frames to the mask will result in corrupt video. This field
+       has to be set to the correct value in order to keep the timing correct.
 Param[4]
        Mute audio: 0=disable, 1=enable
 Param[5]
        Display 0=frame, 1=field
 Param[6]
        Specifies the number of muted audio frames to play before normal audio
-       resumes.
+       resumes. (Not implemented in the firmware, leave at 0)
 
 -------------------------------------------------------------------------------
 
@@ -212,6 +223,7 @@ Description
        Select audio mode
 Param[0]
        Dual mono mode action
+           0=Stereo, 1=Left, 2=Right, 3=Mono, 4=Swap, -1=Unchanged
 Param[1]
        Stereo mode action:
            0=Stereo, 1=Left, 2=Right, 3=Mono, 4=Swap, -1=Unchanged
@@ -224,7 +236,10 @@ Description
        Setup firmware to notify the host about a particular event.
        Counterpart to API 0xD5
 Param[0]
-       Event: 0=Audio mode change between stereo and dual channel
+       Event: 0=Audio mode change between mono, (joint) stereo and dual channel.
+       Event: 3=Decoder started
+       Event: 4=Unknown: goes off 10-15 times per second while decoding.
+       Event: 5=Some sync event: goes off once per frame.
 Param[1]
        Notification 0=disabled, 1=enabled
 Param[2]
@@ -273,43 +288,6 @@ Param[3]
 
 -------------------------------------------------------------------------------
 
-Name   CX2341X_DEC_SET_AUDIO_OUTPUT
-Enum   27/0x1B
-Description
-       Select audio output format
-Param[0]
-       Bitmask:
-            0:1  Data size:
-                     '00' 16 bit
-                     '01' 20 bit
-                     '10' 24 bit
-            2:7  Unused
-            8:9  Mode:
-                     '00' 2 channels
-                     '01' 4 channels
-                     '10' 6 channels
-                     '11' 6 channels with one line data mode
-                          (for left justified MSB first mode, 20 bit only)
-           10:11 Unused
-           12:13 Channel format:
-                     '00' right justified MSB first mode
-                     '01' left justified MSB first mode
-                     '10' I2S mode
-           14:15 Unused
-           16:21 Right justify bit count
-           22:31 Unused
-
--------------------------------------------------------------------------------
-
-Name   CX2341X_DEC_SET_AV_DELAY
-Enum   28/0x1C
-Description
-       Set audio/video delay in 90Khz ticks
-Param[0]
-       0=A/V in sync, negative=audio lags, positive=video lags
-
--------------------------------------------------------------------------------
-
 Name   CX2341X_DEC_SET_PREBUFFERING
 Enum   30/0x1E
 Description
diff --git a/Documentation/video4linux/cx2341x/fw-decoder-regs.txt b/Documentation/video4linux/cx2341x/fw-decoder-regs.txt
new file mode 100644 (file)
index 0000000..db2366c
--- /dev/null
@@ -0,0 +1,815 @@
+PVR350 Video decoder registers 0x02002800 -> 0x02002B00
+=======================================================
+
+This list has been worked out through trial and error. There will be mistakes
+and omissions. Some registers have no obvious effect so it's hard to say what
+they do, while others interact with each other, or require a certain load
+sequence. Horizontal filter setup is one example, with six registers working
+in unison and requiring a certain load sequence to correctly configure. The
+indexed colour palette is much easier to set at just two registers, but again
+it requires a certain load sequence.
+
+Some registers are fussy about what they are set to. Load in a bad value & the
+decoder will fail. A firmware reload will often recover, but sometimes a reset
+is required. For registers containing size information, setting them to 0 is
+generally a bad idea. For other control registers i.e. 2878, you'll only find
+out what values are bad when it hangs.
+
+--------------------------------------------------------------------------------
+2800
+      bit 0
+       Decoder enable
+         0 = disable
+         1 = enable
+--------------------------------------------------------------------------------
+2804
+      bits 0:31
+       Decoder horizontal Y alias register 1
+---------------
+2808
+      bits 0:31
+       Decoder horizontal Y alias register 2
+---------------
+280C
+      bits 0:31
+       Decoder horizontal Y alias register 3
+---------------
+2810
+      bits 0:31
+       Decoder horizontal Y alias register 4
+---------------
+2814
+      bits 0:31
+       Decoder horizontal Y alias register 5
+---------------
+2818
+      bits 0:31
+       Decoder horizontal Y alias trigger
+
+     These six registers control the horizontal aliasing filter for the Y plane.
+     The first five registers must all be loaded before accessing the trigger
+     (2818), as this register actually clocks the data through for the first
+     five.
+
+     To correctly program set the filter, this whole procedure must be done 16
+     times. The actual register contents are copied from a lookup-table in the
+     firmware which contains 4 different filter settings.
+
+--------------------------------------------------------------------------------
+281C
+      bits 0:31
+       Decoder horizontal UV alias register 1
+---------------
+2820
+      bits 0:31
+       Decoder horizontal UV alias register 2
+---------------
+2824
+      bits 0:31
+       Decoder horizontal UV alias register 3
+---------------
+2828
+      bits 0:31
+       Decoder horizontal UV alias register 4
+---------------
+282C
+      bits 0:31
+       Decoder horizontal UV alias register 5
+---------------
+2830
+      bits 0:31
+       Decoder horizontal UV alias trigger
+
+     These six registers control the horizontal aliasing for the UV plane.
+     Operation is the same as the Y filter, with 2830 being the trigger
+     register.
+
+--------------------------------------------------------------------------------
+2834
+      bits 0:15
+       Decoder Y source width in pixels
+
+      bits 16:31
+       Decoder Y destination width in pixels
+---------------
+2838
+      bits 0:15
+       Decoder UV source width in pixels
+
+      bits 16:31
+       Decoder UV destination width in pixels
+
+     NOTE: For both registers, the resulting image must be fully visible on
+     screen. If the image exceeds the right edge both the source and destination
+     size must be adjusted to reflect the visible portion. For the source width,
+     you must take into account the scaling when calculating the new value.
+--------------------------------------------------------------------------------
+
+283C
+      bits 0:31
+       Decoder Y horizontal scaling
+                   Normally = Reg 2854 >> 2
+---------------
+2840
+      bits 0:31
+       Decoder ?? unknown - horizontal scaling
+         Usually 0x00080514
+---------------
+2844
+      bits 0:31
+       Decoder UV horizontal scaling
+         Normally = Reg 2854 >> 2
+---------------
+2848
+      bits 0:31
+       Decoder ?? unknown - horizontal scaling
+         Usually 0x00100514
+---------------
+284C
+      bits 0:31
+       Decoder ?? unknown - Y plane
+         Usually 0x00200020
+---------------
+2850
+      bits 0:31
+       Decoder ?? unknown - UV plane
+         Usually 0x00200020
+---------------
+2854
+      bits 0:31
+       Decoder 'master' value for horizontal scaling
+---------------
+2858
+      bits 0:31
+       Decoder ?? unknown
+         Usually 0
+---------------
+285C
+      bits 0:31
+       Decoder ?? unknown
+         Normally = Reg 2854 >> 1
+---------------
+2860
+      bits 0:31
+       Decoder ?? unknown
+         Usually 0
+---------------
+2864
+      bits 0:31
+       Decoder ?? unknown
+         Normally = Reg 2854 >> 1
+---------------
+2868
+      bits 0:31
+       Decoder ?? unknown
+         Usually 0
+
+     Most of these registers either control horizontal scaling, or appear linked
+     to it in some way. Register 2854 contains the 'master' value & the other
+     registers can be calculated from that one. You must also remember to
+     correctly set the divider in Reg 2874.
+
+     To enlarge:
+            Reg 2854 = (source_width * 0x00200000) / destination_width
+            Reg 2874 = No divide
+
+     To reduce from full size down to half size:
+            Reg 2854 = (source_width/2 * 0x00200000) / destination width
+            Reg 2874 = Divide by 2
+
+     To reduce from half size down to quarter size:
+            Reg 2854 = (source_width/4 * 0x00200000) / destination width
+            Reg 2874 = Divide by 4
+
+     The result is always rounded up.
+
+--------------------------------------------------------------------------------
+286C
+      bits 0:15
+       Decoder horizontal Y buffer offset
+
+      bits 15:31
+       Decoder horizontal UV buffer offset
+
+     Offset into the video image buffer. If the offset is gradually incremented,
+     the on screen image will move left & wrap around higher up on the right.
+
+--------------------------------------------------------------------------------
+2870
+      bits 0:15
+       Decoder horizontal Y output offset
+
+      bits 16:31
+       Decoder horizontal UV output offset
+
+     Offsets the actual video output. Controls output alignment of the Y & UV
+     planes. The higher the value, the greater the shift to the left. Use
+     reg 2890 to move the image right.
+
+--------------------------------------------------------------------------------
+2874
+      bits 0:1
+       Decoder horizontal Y output size divider
+         00 = No divide
+         01 = Divide by 2
+         10 = Divide by 3
+
+      bits 4:5
+       Decoder horizontal UV output size divider
+         00 = No divide
+         01 = Divide by 2
+         10 = Divide by 3
+
+      bit 8
+       Decoder ?? unknown
+         0 = Normal
+         1 = Affects video output levels
+
+      bit 16
+       Decoder ?? unknown
+         0 = Normal
+         1 = Disable horizontal filter
+
+--------------------------------------------------------------------------------
+2878
+      bit 0
+       ?? unknown
+
+      bit 1
+       osd on/off
+         0 = osd off
+         1 = osd on
+
+      bit 2
+       Decoder + osd video timing
+         0 = NTSC
+         1 = PAL
+
+      bits 3:4
+       ?? unknown
+
+      bit 5
+       Decoder + osd
+         Swaps upper & lower fields
+
+--------------------------------------------------------------------------------
+287C
+      bits 0:10
+       Decoder & osd ?? unknown
+         Moves entire screen horizontally. Starts at 0x005 with the screen
+         shifted heavily to the right. Incrementing in steps of 0x004 will
+         gradually shift the screen to the left.
+
+      bits 11:31
+       ?? unknown
+
+     Normally contents are 0x00101111 (NTSC) or 0x1010111d (PAL)
+
+--------------------------------------------------------------------------------
+2880  --------    ?? unknown
+2884  --------    ?? unknown
+--------------------------------------------------------------------------------
+2888
+      bit 0
+       Decoder + osd ?? unknown
+         0 = Normal
+         1 = Misaligned fields (Correctable through 289C & 28A4)
+
+      bit 4
+       ?? unknown
+
+      bit 8
+       ?? unknown
+
+     Warning: Bad values will require a firmware reload to recover.
+                Known to be bad are 0x000,0x011,0x100,0x111
+--------------------------------------------------------------------------------
+288C
+      bits 0:15
+       osd ?? unknown
+         Appears to affect the osd position stability. The higher the value the
+         more unstable it becomes. Decoder output remains stable.
+
+      bits 16:31
+       osd ?? unknown
+         Same as bits 0:15
+
+--------------------------------------------------------------------------------
+2890
+      bits 0:11
+       Decoder output horizontal offset.
+
+     Horizontal offset moves the video image right. A small left shift is
+     possible, but it's better to use reg 2870 for that due to its greater
+     range.
+
+     NOTE: Video corruption will occur if video window is shifted off the right
+     edge. To avoid this read the notes for 2834 & 2838.
+--------------------------------------------------------------------------------
+2894
+      bits 0:23
+       Decoder output video surround colour.
+
+     Contains the colour (in yuv) used to fill the screen when the video is
+     running in a window.
+--------------------------------------------------------------------------------
+2898
+      bits 0:23
+       Decoder video window colour
+         Contains the colour (in yuv) used to fill the video window when the
+         video is turned off.
+
+      bit 24
+       Decoder video output
+         0 = Video on
+         1 = Video off
+
+      bit 28
+       Decoder plane order
+         0 = Y,UV
+         1 = UV,Y
+
+      bit 29
+       Decoder second plane byte order
+         0 = Normal (UV)
+         1 = Swapped (VU)
+
+     In normal usage, the first plane is Y & the second plane is UV. Though the
+     order of the planes can be swapped, only the byte order of the second plane
+     can be swapped. This isn't much use for the Y plane, but can be useful for
+     the UV plane.
+
+--------------------------------------------------------------------------------
+289C
+      bits 0:15
+       Decoder vertical field offset 1
+
+      bits 16:31
+       Decoder vertical field offset 2
+
+     Controls field output vertical alignment. The higher the number, the lower
+     the image on screen. Known starting values are 0x011E0017 (NTSC) &
+     0x01500017 (PAL)
+--------------------------------------------------------------------------------
+28A0
+      bits 0:15
+       Decoder & osd width in pixels
+
+      bits 16:31
+       Decoder & osd height in pixels
+
+     All output from the decoder & osd are disabled beyond this area. Decoder
+     output will simply go black outside of this region. If the osd tries to
+     exceed this area it will become corrupt.
+--------------------------------------------------------------------------------
+28A4
+      bits 0:11
+       osd left shift.
+
+     Has a range of 0x770->0x7FF. With the exception of 0, any value outside of
+     this range corrupts the osd.
+--------------------------------------------------------------------------------
+28A8
+      bits 0:15
+       osd vertical field offset 1
+
+      bits 16:31
+       osd vertical field offset 2
+
+     Controls field output vertical alignment. The higher the number, the lower
+     the image on screen. Known starting values are 0x011E0017 (NTSC) &
+     0x01500017 (PAL)
+--------------------------------------------------------------------------------
+28AC  --------    ?? unknown
+ |
+ V
+28BC  --------    ?? unknown
+--------------------------------------------------------------------------------
+28C0
+      bit 0
+       Current output field
+         0 = first field
+         1 = second field
+
+      bits 16:31
+       Current scanline
+         The scanline counts from the top line of the first field
+         through to the last line of the second field.
+--------------------------------------------------------------------------------
+28C4  --------    ?? unknown
+ |
+ V
+28F8  --------    ?? unknown
+--------------------------------------------------------------------------------
+28FC
+      bit 0
+       ?? unknown
+         0 = Normal
+         1 = Breaks decoder & osd output
+--------------------------------------------------------------------------------
+2900
+      bits 0:31
+       Decoder vertical Y alias register 1
+---------------
+2904
+      bits 0:31
+       Decoder vertical Y alias register 2
+---------------
+2908
+      bits 0:31
+       Decoder vertical Y alias trigger
+
+     These three registers control the vertical aliasing filter for the Y plane.
+     Operation is similar to the horizontal Y filter (2804). The only real
+     difference is that there are only two registers to set before accessing
+     the trigger register (2908). As for the horizontal filter, the values are
+     taken from a lookup table in the firmware, and the procedure must be
+     repeated 16 times to fully program the filter.
+--------------------------------------------------------------------------------
+290C
+      bits 0:31
+       Decoder vertical UV alias register 1
+---------------
+2910
+      bits 0:31
+       Decoder vertical UV alias register 2
+---------------
+2914
+      bits 0:31
+       Decoder vertical UV alias trigger
+
+     These three registers control the vertical aliasing filter for the UV
+     plane. Operation is the same as the Y filter, with 2914 being the trigger.
+--------------------------------------------------------------------------------
+2918
+      bits 0:15
+       Decoder Y source height in pixels
+
+      bits 16:31
+       Decoder Y destination height in pixels
+---------------
+291C
+      bits 0:15
+       Decoder UV source height in pixels divided by 2
+
+      bits 16:31
+       Decoder UV destination height in pixels
+
+     NOTE: For both registers, the resulting image must be fully visible on
+     screen. If the image exceeds the bottom edge both the source and
+     destination size must be adjusted to reflect the visible portion. For the
+     source height, you must take into account the scaling when calculating the
+     new value.
+--------------------------------------------------------------------------------
+2920
+      bits 0:31
+       Decoder Y vertical scaling
+         Normally = Reg 2930 >> 2
+---------------
+2924
+      bits 0:31
+       Decoder Y vertical scaling
+         Normally = Reg 2920 + 0x514
+---------------
+2928
+      bits 0:31
+       Decoder UV vertical scaling
+         When enlarging = Reg 2930 >> 2
+         When reducing = Reg 2930 >> 3
+---------------
+292C
+      bits 0:31
+       Decoder UV vertical scaling
+         Normally = Reg 2928 + 0x514
+---------------
+2930
+      bits 0:31
+       Decoder 'master' value for vertical scaling
+---------------
+2934
+      bits 0:31
+       Decoder ?? unknown - Y vertical scaling
+---------------
+2938
+      bits 0:31
+       Decoder Y vertical scaling
+         Normally = Reg 2930
+---------------
+293C
+      bits 0:31
+       Decoder ?? unknown - Y vertical scaling
+---------------
+2940
+      bits 0:31
+       Decoder UV vertical scaling
+         When enlarging = Reg 2930 >> 1
+         When reducing = Reg 2930
+---------------
+2944
+      bits 0:31
+       Decoder ?? unknown - UV vertical scaling
+---------------
+2948
+      bits 0:31
+       Decoder UV vertical scaling
+         Normally = Reg 2940
+---------------
+294C
+      bits 0:31
+       Decoder ?? unknown - UV vertical scaling
+
+     Most of these registers either control vertical scaling, or appear linked
+     to it in some way. Register 2930 contains the 'master' value & all other
+     registers can be calculated from that one. You must also remember to
+     correctly set the divider in Reg 296C
+
+     To enlarge:
+            Reg 2930 = (source_height * 0x00200000) / destination_height
+            Reg 296C = No divide
+
+     To reduce from full size down to half size:
+            Reg 2930 = (source_height/2 * 0x00200000) / destination height
+            Reg 296C = Divide by 2
+
+      To reduce from half down to quarter.
+            Reg 2930 = (source_height/4 * 0x00200000) / destination height
+            Reg 296C = Divide by 4
+
+--------------------------------------------------------------------------------
+2950
+      bits 0:15
+       Decoder Y line index into display buffer, first field
+
+      bits 16:31
+       Decoder Y vertical line skip, first field
+--------------------------------------------------------------------------------
+2954
+      bits 0:15
+       Decoder Y line index into display buffer, second field
+
+      bits 16:31
+       Decoder Y vertical line skip, second field
+--------------------------------------------------------------------------------
+2958
+      bits 0:15
+       Decoder UV line index into display buffer, first field
+
+      bits 16:31
+       Decoder UV vertical line skip, first field
+--------------------------------------------------------------------------------
+295C
+      bits 0:15
+       Decoder UV line index into display buffer, second field
+
+      bits 16:31
+       Decoder UV vertical line skip, second field
+--------------------------------------------------------------------------------
+2960
+      bits 0:15
+       Decoder destination height minus 1
+
+      bits 16:31
+       Decoder destination height divided by 2
+--------------------------------------------------------------------------------
+2964
+      bits 0:15
+       Decoder Y vertical offset, second field
+
+      bits 16:31
+       Decoder Y vertical offset, first field
+
+     These two registers shift the Y plane up. The higher the number, the
+     greater the shift.
+--------------------------------------------------------------------------------
+2968
+      bits 0:15
+       Decoder UV vertical offset, second field
+
+      bits 16:31
+       Decoder UV vertical offset, first field
+
+     These two registers shift the UV plane up. The higher the number, the
+     greater the shift.
+--------------------------------------------------------------------------------
+296C
+      bits 0:1
+       Decoder vertical Y output size divider
+         00 = No divide
+         01 = Divide by 2
+         10 = Divide by 4
+
+      bits 8:9
+       Decoder vertical UV output size divider
+         00 = No divide
+         01 = Divide by 2
+         10 = Divide by 4
+--------------------------------------------------------------------------------
+2970
+      bit 0
+       Decoder ?? unknown
+         0 = Normal
+         1 = Affect video output levels
+
+      bit 16
+       Decoder ?? unknown
+         0 = Normal
+         1 = Disable vertical filter
+
+--------------------------------------------------------------------------------
+2974  --------   ?? unknown
+ |
+ V
+29EF  --------   ?? unknown
+--------------------------------------------------------------------------------
+2A00
+      bits 0:2
+       osd colour mode
+         001 = 16 bit (565)
+         010 = 15 bit (555)
+         011 = 12 bit (444)
+         100 = 32 bit (8888)
+         101 = 8 bit indexed
+
+      bits 4:5
+       osd display bpp
+         01 = 8 bit
+         10 = 16 bit
+         11 = 32 bit
+
+      bit 8
+       osd global alpha
+         0 = Off
+         1 = On
+
+      bit 9
+       osd local alpha
+         0 = Off
+         1 = On
+
+      bit 10
+       osd colour key
+         0 = Off
+         1 = On
+
+      bit 11
+       osd ?? unknown
+         Must be 1
+
+      bit 13
+       osd colour space
+         0 = ARGB
+         1 = AYVU
+
+      bits 16:31
+       osd ?? unknown
+         Must be 0x001B (some kind of buffer pointer ?)
+
+     When the bits-per-pixel is set to 8, the colour mode is ignored and
+     assumed to be 8 bit indexed. For 16 & 32 bits-per-pixel the colour depth
+     is honoured, and when using a colour depth that requires fewer bytes than
+     allocated the extra bytes are used as padding. So for a 32 bpp with 8 bit
+     index colour, there are 3 padding bytes per pixel. It's also possible to
+     select 16bpp with a 32 bit colour mode. This results in the pixel width
+     being doubled, but the color key will not work as expected in this mode.
+
+     Colour key is as it suggests. You designate a colour which will become
+     completely transparent. When using 565, 555 or 444 colour modes, the
+     colour key is always 16 bits wide. The colour to key on is set in Reg 2A18.
+
+     Local alpha is a per-pixel 256 step transparency, with 0 being transparent
+     and 255 being solid. This is only available in 32 bit & 8 bit indexed
+     colour modes.
+
+     Global alpha is a 256 step transparency that applies to the entire osd,
+     with 0 being transparent & 255 being solid.
+
+     It's possible to combine colour key, local alpha & global alpha.
+--------------------------------------------------------------------------------
+2A04
+      bits 0:15
+       osd x coord for left edge
+
+      bits 16:31
+       osd y coord for top edge
+---------------
+2A08
+      bits 0:15
+       osd x coord for right edge
+
+      bits 16:31
+       osd y coord for bottom edge
+
+     For both registers, (0,0) = top left corner of the display area. These
+     registers do not control the osd size, only where it's positioned & how
+     much is visible. The visible osd area cannot exceed the right edge of the
+     display, otherwise the osd will become corrupt. See reg 2A10 for
+     setting osd width.
+--------------------------------------------------------------------------------
+2A0C
+      bits 0:31
+       osd buffer index
+
+     An index into the osd buffer. Slowly incrementing this moves the osd left,
+     wrapping around onto the right edge
+--------------------------------------------------------------------------------
+2A10
+      bits 0:11
+       osd buffer 32 bit word width
+
+     Contains the width of the osd measured in 32 bit words. This means that all
+     colour modes are restricted to a byte width which is divisible by 4.
+--------------------------------------------------------------------------------
+2A14
+      bits 0:15
+       osd height in pixels
+
+      bits 16:32
+       osd line index into buffer
+         osd will start displaying from this line.
+--------------------------------------------------------------------------------
+2A18
+      bits 0:31
+       osd colour key
+
+     Contains the colour value which will be transparent.
+--------------------------------------------------------------------------------
+2A1C
+      bits 0:7
+       osd global alpha
+
+     Contains the global alpha value (equiv ivtvfbctl --alpha XX)
+--------------------------------------------------------------------------------
+2A20  --------    ?? unknown
+ |
+ V
+2A2C  --------    ?? unknown
+--------------------------------------------------------------------------------
+2A30
+      bits 0:7
+       osd colour to change in indexed palette
+---------------
+2A34
+      bits 0:31
+       osd colour for indexed palette
+
+     To set the new palette, first load the index of the colour to change into
+     2A30, then load the new colour into 2A34. The full palette is 256 colours,
+     so the index range is 0x00-0xFF
+--------------------------------------------------------------------------------
+2A38  --------    ?? unknown
+2A3C  --------    ?? unknown
+--------------------------------------------------------------------------------
+2A40
+      bits 0:31
+       osd ?? unknown
+
+     Affects overall brightness, wrapping around to black
+--------------------------------------------------------------------------------
+2A44
+      bits 0:31
+       osd ?? unknown
+
+     Green tint
+--------------------------------------------------------------------------------
+2A48
+      bits 0:31
+       osd ?? unknown
+
+     Red tint
+--------------------------------------------------------------------------------
+2A4C
+      bits 0:31
+       osd ?? unknown
+
+     Affects overall brightness, wrapping around to black
+--------------------------------------------------------------------------------
+2A50
+      bits 0:31
+       osd ?? unknown
+
+     Colour shift
+--------------------------------------------------------------------------------
+2A54
+      bits 0:31
+       osd ?? unknown
+
+     Colour shift
+--------------------------------------------------------------------------------
+2A58  --------    ?? unknown
+ |
+ V
+2AFC  --------    ?? unknown
+--------------------------------------------------------------------------------
+2B00
+      bit 0
+       osd filter control
+         0 = filter off
+         1 = filter on
+
+      bits 1:4
+       osd ?? unknown
+
+--------------------------------------------------------------------------------
+
+v0.3 - 2 February 2007 - Ian Armstrong (ian@iarmst.demon.co.uk)
+
index 8123e262d5b6645acfbce7e3b3630a142b563c30..be52b6fd1e9ad78421cef1eed020d7eaae41305e 100644 (file)
@@ -22,6 +22,8 @@ urged to choose a smaller block size and learn the scatter-gather technique.
 
 Mailbox #10 is reserved for DMA transfer information.
 
+Note: the hardware expects little-endian data ('intel format').
+
 Flow
 ====
 
@@ -64,7 +66,7 @@ addresses are the physical memory location of the target DMA buffer.
 
 Each S-G array element is a struct of three 32-bit words. The first word is
 the source address, the second is the destination address. Both take up the
-entire 32 bits. The lowest 16 bits of the third word is the transfer byte
+entire 32 bits. The lowest 18 bits of the third word is the transfer byte
 count. The high-bit of the third word is the "last" flag. The last-flag tells
 the card to raise the DMA_DONE interrupt. From hard personal experience, if
 you forget to set this bit, the card will still "work" but the stream will
@@ -78,8 +80,8 @@ Array Element:
 
 - 32-bit Source Address
 - 32-bit Destination Address
-- 16-bit reserved (high bit is the last flag)
-- 16-bit byte count
+- 14-bit reserved (high bit is the last flag)
+- 18-bit byte count
 
 DMA Transfer Status
 ===================
@@ -87,8 +89,8 @@ DMA Transfer Status
 Register 0x0004 holds the DMA Transfer Status:
 
 Bit
-4   Scatter-Gather array error
-3   DMA write error
-2   DMA read error
-1   write completed
 0   read completed
+1   write completed
+2   DMA read error
+3   DMA write error
+4   Scatter-Gather array error
index 15df0df57dddb284974180e92d3b864b0f5661e1..242104ce5b61b09a82e20c24bbf44339f722d6ac 100644 (file)
@@ -213,16 +213,6 @@ Param[1]
 
 -------------------------------------------------------------------------------
 
-Name   CX2341X_ENC_SET_3_2_PULLDOWN
-Enum   177/0xB1
-Description
-       3:2 pulldown properties
-Param[0]
-       0=enabled
-       1=disabled
-
--------------------------------------------------------------------------------
-
 Name   CX2341X_ENC_SET_VBI_LINE
 Enum   183/0xB7
 Description
@@ -332,9 +322,7 @@ Param[0]
                '01'=JointStereo
                '10'=Dual
                '11'=Mono
-               Note: testing seems to indicate that Mono and possibly
-               JointStereo are not working (default to stereo).
-               Dual does work, though.
+               Note: the cx23415 cannot decode Joint Stereo properly.
 
          10:11 Mode Extension used in joint_stereo mode.
                In Layer I and II they indicate which subbands are in
@@ -413,16 +401,34 @@ Name      CX2341X_ENC_SET_PGM_INDEX_INFO
 Enum   199/0xC7
 Description
        Sets the Program Index Information.
+       The information is stored as follows:
+
+       struct info {
+               u32 length;             // Length of this frame
+               u32 offset_low;         // Offset in the file of the
+               u32 offset_high;        // start of this frame
+               u32 mask1;              // Bits 0-1 are the type mask:
+                                       // 1=I, 2=P, 4=B
+               u32 pts;                // The PTS of the frame
+               u32 mask2;              // Bit 0 is bit 32 of the pts.
+       };
+       u32 table_ptr;
+       struct info index[400];
+
+       The table_ptr is the encoder memory address in the table were
+       *new* entries will be written. Note that this is a ringbuffer,
+       so the table_ptr will wraparound.
 Param[0]
        Picture Mask:
            0=No index capture
            1=I frames
            3=I,P frames
            7=I,P,B frames
+       (Seems to be ignored, it always indexes I, P and B frames)
 Param[1]
        Elements requested (up to 400)
 Result[0]
-       Offset in SDF memory of the table.
+       Offset in the encoder memory of the start of the table.
 Result[1]
        Number of allocated elements up to a maximum of Param[1]
 
@@ -492,12 +498,14 @@ Name      CX2341X_ENC_GET_PREV_DMA_INFO_MB_9
 Enum   203/0xCB
 Description
        Returns information on the previous DMA transfer in conjunction with
-       bit 27 of the interrupt mask. Uses mailbox 9.
+       bit 27 or 18 of the interrupt mask. Uses mailbox 9.
 Result[0]
        Status bits:
-           Bit 0 set indicates transfer complete
-           Bit 2 set indicates transfer error
-           Bit 4 set indicates linked list error
+               0   read completed
+               1   write completed
+               2   DMA read error
+               3   DMA write error
+               4   Scatter-Gather array error
 Result[1]
        DMA type
 Result[2]
@@ -672,7 +680,7 @@ Description
        the value.
 Param[0]
        Command number:
-        1=set initial SCR value when starting encoding.
+        1=set initial SCR value when starting encoding (works).
         2=set quality mode (apparently some test setting).
         3=setup advanced VIM protection handling (supposedly only for the cx23416
           for raw YUV).
@@ -681,7 +689,11 @@ Param[0]
         4=generate artificial PTS timestamps
         5=USB flush mode
         6=something to do with the quantization matrix
-        7=set navigation pack insertion for DVD
+        7=set navigation pack insertion for DVD: adds 0xbf (private stream 2)
+          packets to the MPEG. The size of these packets is 2048 bytes (including
+          the header of 6 bytes: 0x000001bf + length). The payload is zeroed and
+          it is up to the application to fill them in. These packets are apparently
+          inserted every four frames.
         8=enable scene change detection (seems to be a failure)
         9=set history parameters of the video input module
        10=set input field order of VIM
index ef0aad3f88fc3ce20da0f6cd7177dfab4ac5ed12..9d736fe8de666cc585b26a3e37788c291fe2c40b 100644 (file)
@@ -1,6 +1,8 @@
 This document describes the cx2341x memory map and documents some of the register
 space.
 
+Note: the memory long words are little-endian ('intel format').
+
 Warning! This information was figured out from searching through the memory and
 registers, this information may not be correct and is certainly not complete, and
 was not derived from anything more than searching through the memory space with
@@ -67,7 +69,7 @@ DMA Registers 0x000-0xff:
  0x84 - first write linked list reg, for pci memory addr
  0x88 - first write linked list reg, for length of buffer in memory addr
        (|0x80000000 or this for last link)
- 0x8c-0xcc - rest of write linked list reg, 8 sets of 3 total, DMA goes here
+ 0x8c-0xdc - rest of write linked list reg, 8 sets of 3 total, DMA goes here
        from linked list addr in reg 0x0c, firmware must push through or
        something.
  0xe0 - first (and only) read linked list reg, for pci memory addr
@@ -123,12 +125,8 @@ Bit
 29 Encoder VBI capture
 28 Encoder Video Input Module reset event
 27 Encoder DMA complete
-26
-25 Decoder copy protect detection event
-24 Decoder audio mode change detection event
-23
+24 Decoder audio mode change detection event (through event notification)
 22 Decoder data request
-21 Decoder I-Frame? done
 20 Decoder DMA complete
 19 Decoder VBI re-insertion
 18 Decoder DMA err (linked-list bad)
index 1bdee8f85b9aa2ac2fe5e56fd8c3a2b4c64525f3..1247566c4de38211458144eb206432db0a8698d0 100644 (file)
@@ -23,7 +23,7 @@ Index
 
 1. Copyright
 ============
-Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>
+Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>
 
 
 2. Disclaimer
@@ -135,8 +135,9 @@ And finally:
 6. Module loading
 =================
 To use the driver, it is necessary to load the "et61x251" module into memory
-after every other module required: "videodev", "usbcore" and, depending on
-the USB host controller you have, "ehci-hcd", "uhci-hcd" or "ohci-hcd".
+after every other module required: "videodev", "v4l2_common", "compat_ioctl32",
+"usbcore" and, depending on the USB host controller you have, "ehci-hcd",
+"uhci-hcd" or "ohci-hcd".
 
 Loading can be done as shown below:
 
index 8cda472db36db5241447bb8ac9f794c076d17a79..2913da3d087896436247358da11d15aec25d9414 100644 (file)
@@ -1,5 +1,5 @@
 
-                        SN9C10x PC Camera Controllers
+                        SN9C1xx PC Camera Controllers
                                Driver for Linux
                         =============================
 
@@ -53,20 +53,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
 4. Overview and features
 ========================
-This driver attempts to support the video interface of the devices mounting the
-SONiX SN9C101, SN9C102 and SN9C103 PC Camera Controllers.
-
-It's worth to note that SONiX has never collaborated with the author during the
-development of this project, despite several requests for enough detailed
-specifications of the register tables, compression engine and video data format
-of the above chips. Nevertheless, these informations are no longer necessary,
-because all the aspects related to these chips are known and have been
-described in detail in this documentation.
+This driver attempts to support the video interface of the devices assembling
+the SONiX SN9C101, SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers
+("SN9C1xx" from now on).
 
 The driver relies on the Video4Linux2 and USB core modules. It has been
 designed to run properly on SMP systems as well.
 
-The latest version of the SN9C10x driver can be found at the following URL:
+The latest version of the SN9C1xx driver can be found at the following URL:
 http://www.linux-projects.org/
 
 Some of the features of the driver are:
@@ -85,11 +79,11 @@ Some of the features of the driver are:
   high compression quality (see also "Notes for V4L2 application developers"
   and "Video frame formats" paragraphs);
 - full support for the capabilities of many of the possible image sensors that
-  can be connected to the SN9C10x bridges, including, for instance, red, green,
+  can be connected to the SN9C1xx bridges, including, for instance, red, green,
   blue and global gain adjustments and exposure (see "Supported devices"
   paragraph for details);
 - use of default color settings for sunlight conditions;
-- dynamic I/O interface for both SN9C10x and image sensor control and
+- dynamic I/O interface for both SN9C1xx and image sensor control and
   monitoring (see "Optional device control through 'sysfs'" paragraph);
 - dynamic driver control thanks to various module parameters (see "Module
   parameters" paragraph);
@@ -130,8 +124,8 @@ necessary:
        CONFIG_USB_UHCI_HCD=m
        CONFIG_USB_OHCI_HCD=m
 
-The SN9C103 controller also provides a built-in microphone interface. It is
-supported by the USB Audio driver thanks to the ALSA API:
+The SN9C103, SN9c105 and SN9C120 controllers also provide a built-in microphone
+interface. It is supported by the USB Audio driver thanks to the ALSA API:
 
        # Sound
        #
@@ -155,18 +149,27 @@ And finally:
 6. Module loading
 =================
 To use the driver, it is necessary to load the "sn9c102" module into memory
-after every other module required: "videodev", "usbcore" and, depending on
-the USB host controller you have, "ehci-hcd", "uhci-hcd" or "ohci-hcd".
+after every other module required: "videodev", "v4l2_common", "compat_ioctl32",
+"usbcore" and, depending on the USB host controller you have, "ehci-hcd",
+"uhci-hcd" or "ohci-hcd".
 
 Loading can be done as shown below:
 
        [root@localhost home]# modprobe sn9c102
 
-At this point the devices should be recognized. You can invoke "dmesg" to
-analyze kernel messages and verify that the loading process has gone well:
+Note that the module is called "sn9c102" for historic reasons, althought it
+does not just support the SN9C102.
+
+At this point all the devices supported by the driver and connected to the USB
+ports should be recognized. You can invoke "dmesg" to analyze kernel messages
+and verify that the loading process has gone well:
 
        [user@localhost home]$ dmesg
 
+or, to isolate all the kernel messages generated by the driver:
+
+       [user@localhost home]$ dmesg | grep sn9c102
+
 
 7. Module parameters
 ====================
@@ -198,10 +201,11 @@ Default:        0
 -------------------------------------------------------------------------------
 Name:           frame_timeout
 Type:           uint array (min = 0, max = 64)
-Syntax:         <n[,...]>
-Description:    Timeout for a video frame in seconds. This parameter is
-               specific for each detected camera. This parameter can be
-               changed at runtime thanks to the /sys filesystem interface.
+Syntax:         <0|n[,...]>
+Description:    Timeout for a video frame in seconds before returning an I/O
+               error; 0 for infinity. This parameter is specific for each
+               detected camera and can be changed at runtime thanks to the
+               /sys filesystem interface.
 Default:        2
 -------------------------------------------------------------------------------
 Name:           debug
@@ -223,20 +227,21 @@ Default:        2
 8. Optional device control through "sysfs" [1]
 ==========================================
 If the kernel has been compiled with the CONFIG_VIDEO_ADV_DEBUG option enabled,
-it is possible to read and write both the SN9C10x and the image sensor
+it is possible to read and write both the SN9C1xx and the image sensor
 registers by using the "sysfs" filesystem interface.
 
 Every time a supported device is recognized, a write-only file named "green" is
 created in the /sys/class/video4linux/videoX directory. You can set the green
 channel's gain by writing the desired value to it. The value may range from 0
-to 15 for SN9C101 or SN9C102 bridges, from 0 to 127 for SN9C103 bridges.
-Similarly, only for SN9C103 controllers, blue and red gain control files are
-available in the same directory, for which accepted values may range from 0 to
-127.
+to 15 for the SN9C101 or SN9C102 bridges, from 0 to 127 for the SN9C103,
+SN9C105 and SN9C120 bridges.
+Similarly, only for the SN9C103, SN9C105 and SN9120 controllers, blue and red
+gain control files are available in the same directory, for which accepted
+values may range from 0 to 127.
 
 There are other four entries in the directory above for each registered camera:
 "reg", "val", "i2c_reg" and "i2c_val". The first two files control the
-SN9C10x bridge, while the other two control the sensor chip. "reg" and
+SN9C1xx bridge, while the other two control the sensor chip. "reg" and
 "i2c_reg" hold the values of the current register index where the following
 reading/writing operations are addressed at through "val" and "i2c_val". Their
 use is not intended for end-users. Note that "i2c_reg" and "i2c_val" will not
@@ -259,61 +264,84 @@ Now let's set the green gain's register of the SN9C101 or SN9C102 chips to 2:
        [root@localhost #] echo 0x11 > reg
        [root@localhost #] echo 2 > val
 
-Note that the SN9C10x always returns 0 when some of its registers are read.
+Note that the SN9C1xx always returns 0 when some of its registers are read.
 To avoid race conditions, all the I/O accesses to the above files are
 serialized.
-
 The sysfs interface also provides the "frame_header" entry, which exports the
 frame header of the most recent requested and captured video frame. The header
-is always 18-bytes long and is appended to every video frame by the SN9C10x
+is always 18-bytes long and is appended to every video frame by the SN9C1xx
 controllers. As an example, this additional information can be used by the user
 application for implementing auto-exposure features via software.
 
-The following table describes the frame header:
-
-Byte #  Value         Description
-------  -----         -----------
-0x00    0xFF          Frame synchronisation pattern.
-0x01    0xFF          Frame synchronisation pattern.
-0x02    0x00          Frame synchronisation pattern.
-0x03    0xC4          Frame synchronisation pattern.
-0x04    0xC4          Frame synchronisation pattern.
-0x05    0x96          Frame synchronisation pattern.
-0x06    0xXX          Unknown meaning. The exact value depends on the chip;
-                     possible values are 0x00, 0x01 and 0x20.
-0x07    0xXX          Variable value, whose bits are ff00uzzc, where ff is a
-                     frame counter, u is unknown, zz is a size indicator
-                     (00 = VGA, 01 = SIF, 10 = QSIF) and c stands for
-                     "compression enabled" (1 = yes, 0 = no).
-0x08    0xXX          Brightness sum inside Auto-Exposure area (low-byte).
-0x09    0xXX          Brightness sum inside Auto-Exposure area (high-byte).
-                     For a pure white image, this number will be equal to 500
-                     times the area of the specified AE area. For images
-                     that are not pure white, the value scales down according
-                     to relative whiteness.
-0x0A    0xXX          Brightness sum outside Auto-Exposure area (low-byte).
-0x0B    0xXX          Brightness sum outside Auto-Exposure area (high-byte).
-                     For a pure white image, this number will be equal to 125
-                     times the area outside of the specified AE area. For
-                     images that are not pure white, the value scales down
-                     according to relative whiteness.
-                     according to relative whiteness.
-
-The following bytes are used by the SN9C103 bridge only:
-
-0x0C    0xXX          Unknown meaning
-0x0D    0xXX          Unknown meaning
-0x0E    0xXX          Unknown meaning
-0x0F    0xXX          Unknown meaning
-0x10    0xXX          Unknown meaning
-0x11    0xXX          Unknown meaning
+The following table describes the frame header exported by the SN9C101 and
+SN9C102:
+
+Byte #  Value or bits Description
+------  ------------- -----------
+0x00    0xFF          Frame synchronisation pattern
+0x01    0xFF          Frame synchronisation pattern
+0x02    0x00          Frame synchronisation pattern
+0x03    0xC4          Frame synchronisation pattern
+0x04    0xC4          Frame synchronisation pattern
+0x05    0x96          Frame synchronisation pattern
+0x06    [3:0]         Read channel gain control = (1+R_GAIN/8)
+       [7:4]         Blue channel gain control = (1+B_GAIN/8)
+0x07    [ 0 ]         Compression mode. 0=No compression, 1=Compression enabled
+       [2:1]         Maximum scale factor for compression
+       [ 3 ]         1 = USB fifo(2K bytes) is full
+       [ 4 ]         1 = Digital gain is finish
+       [ 5 ]         1 = Exposure is finish
+       [7:6]         Frame index
+0x08    [7:0]         Y sum inside Auto-Exposure area (low-byte)
+0x09    [7:0]         Y sum inside Auto-Exposure area (high-byte)
+                     where Y sum = (R/4 + 5G/16 + B/8) / 32
+0x0A    [7:0]         Y sum outside Auto-Exposure area (low-byte)
+0x0B    [7:0]         Y sum outside Auto-Exposure area (high-byte)
+                     where Y sum = (R/4 + 5G/16 + B/8) / 128
+0x0C    0xXX          Not used
+0x0D    0xXX          Not used
+0x0E    0xXX          Not used
+0x0F    0xXX          Not used
+0x10    0xXX          Not used
+0x11    0xXX          Not used
+
+The following table describes the frame header exported by the SN9C103:
+
+Byte #  Value or bits Description
+------  ------------- -----------
+0x00    0xFF          Frame synchronisation pattern
+0x01    0xFF          Frame synchronisation pattern
+0x02    0x00          Frame synchronisation pattern
+0x03    0xC4          Frame synchronisation pattern
+0x04    0xC4          Frame synchronisation pattern
+0x05    0x96          Frame synchronisation pattern
+0x06    [6:0]         Read channel gain control = (1/2+R_GAIN/64)
+0x07    [6:0]         Blue channel gain control = (1/2+B_GAIN/64)
+       [7:4]
+0x08    [ 0 ]         Compression mode. 0=No compression, 1=Compression enabled
+       [2:1]         Maximum scale factor for compression
+       [ 3 ]         1 = USB fifo(2K bytes) is full
+       [ 4 ]         1 = Digital gain is finish
+       [ 5 ]         1 = Exposure is finish
+       [7:6]         Frame index
+0x09    [7:0]         Y sum inside Auto-Exposure area (low-byte)
+0x0A    [7:0]         Y sum inside Auto-Exposure area (high-byte)
+                     where Y sum = (R/4 + 5G/16 + B/8) / 32
+0x0B    [7:0]         Y sum outside Auto-Exposure area (low-byte)
+0x0C    [7:0]         Y sum outside Auto-Exposure area (high-byte)
+                     where Y sum = (R/4 + 5G/16 + B/8) / 128
+0x0D    [1:0]         Audio frame number
+       [ 2 ]         1 = Audio is recording
+0x0E    [7:0]         Audio summation (low-byte)
+0x0F    [7:0]         Audio summation (high-byte)
+0x10    [7:0]         Audio sample count
+0x11    [7:0]         Audio peak data in audio frame
 
 The AE area (sx, sy, ex, ey) in the active window can be set by programming the
-registers 0x1c, 0x1d, 0x1e and 0x1f of the SN9C10x controllers, where one unit
+registers 0x1c, 0x1d, 0x1e and 0x1f of the SN9C1xx controllers, where one unit
 corresponds to 32 pixels.
 
-[1] Part of the meaning of the frame header has been documented by Bertrik
-    Sikken.
+[1] The frame headers exported by the SN9C105 and SN9C120 are not described.
 
 
 9. Supported devices
@@ -323,15 +351,19 @@ here. They have never collaborated with the author, so no advertising.
 
 From the point of view of a driver, what unambiguously identify a device are
 its vendor and product USB identifiers. Below is a list of known identifiers of
-devices mounting the SN9C10x PC camera controllers:
+devices assembling the SN9C1xx PC camera controllers:
 
 Vendor ID  Product ID
 ---------  ----------
+0x0471     0x0327
+0x0471     0x0328
 0x0c45     0x6001
 0x0c45     0x6005
 0x0c45     0x6007
 0x0c45     0x6009
 0x0c45     0x600d
+0x0c45     0x6011
+0x0c45     0x6019
 0x0c45     0x6024
 0x0c45     0x6025
 0x0c45     0x6028
@@ -342,6 +374,7 @@ Vendor ID  Product ID
 0x0c45     0x602d
 0x0c45     0x602e
 0x0c45     0x6030
+0x0c45     0x603f
 0x0c45     0x6080
 0x0c45     0x6082
 0x0c45     0x6083
@@ -368,24 +401,40 @@ Vendor ID  Product ID
 0x0c45     0x60bb
 0x0c45     0x60bc
 0x0c45     0x60be
+0x0c45     0x60c0
+0x0c45     0x60c8
+0x0c45     0x60cc
+0x0c45     0x60ea
+0x0c45     0x60ec
+0x0c45     0x60fa
+0x0c45     0x60fb
+0x0c45     0x60fc
+0x0c45     0x60fe
+0x0c45     0x6130
+0x0c45     0x613a
+0x0c45     0x613b
+0x0c45     0x613c
+0x0c45     0x613e
 
 The list above does not imply that all those devices work with this driver: up
-until now only the ones that mount the following image sensors are supported;
-kernel messages will always tell you whether this is the case:
+until now only the ones that assemble the following image sensors are
+supported; kernel messages will always tell you whether this is the case (see
+"Module loading" paragraph):
 
 Model       Manufacturer
 -----       ------------
 HV7131D     Hynix Semiconductor, Inc.
 MI-0343     Micron Technology, Inc.
 OV7630      OmniVision Technologies, Inc.
+OV7660      OmniVision Technologies, Inc.
 PAS106B     PixArt Imaging, Inc.
 PAS202BCA   PixArt Imaging, Inc.
 PAS202BCB   PixArt Imaging, Inc.
 TAS5110C1B  Taiwan Advanced Sensor Corporation
 TAS5130D1B  Taiwan Advanced Sensor Corporation
 
-All the available control settings of each image sensor are supported through
-the V4L2 interface.
+Some of the available control settings of each image sensor are supported
+through the V4L2 interface.
 
 Donations of new models for further testing and support would be much
 appreciated. Non-available hardware will not be supported by the author of this
@@ -429,12 +478,15 @@ supplied by this driver).
 
 11. Video frame formats [1]
 =======================
-The SN9C10x PC Camera Controllers can send images in two possible video
-formats over the USB: either native "Sequential RGB Bayer" or Huffman
-compressed. The latter is used to achieve high frame rates. The current video
-format may be selected or queried from the user application by calling the
-VIDIOC_S_FMT or VIDIOC_G_FMT ioctl's, as described in the V4L2 API
-specifications.
+The SN9C1xx PC Camera Controllers can send images in two possible video
+formats over the USB: either native "Sequential RGB Bayer" or compressed.
+The compression is used to achieve high frame rates. With regard to the
+SN9C101, SN9C102 and SN9C103, the compression is based on the Huffman encoding
+algorithm described below, while the SN9C105 and SN9C120 the compression is
+based on the JPEG standard.
+The current video format may be selected or queried from the user application
+by calling the VIDIOC_S_FMT or VIDIOC_G_FMT ioctl's, as described in the V4L2
+API specifications.
 
 The name "Sequential Bayer" indicates the organization of the red, green and
 blue pixels in one video frame. Each pixel is associated with a 8-bit long
@@ -447,14 +499,14 @@ G[m]   R[m+1]  G[m+2]  R[m+2]  ...   G[2m-2]        R[2m-1]
 ...                                  G[n(m-2)]      R[n(m-1)]
 
 The above matrix also represents the sequential or progressive read-out mode of
-the (n, m) Bayer color filter array used in many CCD/CMOS image sensors.
+the (n, m) Bayer color filter array used in many CCD or CMOS image sensors.
 
-One compressed video frame consists of a bitstream that encodes for every R, G,
-or B pixel the difference between the value of the pixel itself and some
-reference pixel value. Pixels are organised in the Bayer pattern and the Bayer
-sub-pixels are tracked individually and alternatingly. For example, in the
-first line values for the B and G1 pixels are alternatingly encoded, while in
-the second line values for the G2 and R pixels are alternatingly encoded.
+The Huffman compressed video frame consists of a bitstream that encodes for
+every R, G, or B pixel the difference between the value of the pixel itself and
+some reference pixel value. Pixels are organised in the Bayer pattern and the
+Bayer sub-pixels are tracked individually and alternatingly. For example, in
+the first line values for the B and G1 pixels are alternatingly encoded, while
+in the second line values for the G2 and R pixels are alternatingly encoded.
 
 The pixel reference value is calculated as follows:
 - the 4 top left pixels are encoded in raw uncompressed 8-bit format;
@@ -470,8 +522,9 @@ The pixel reference value is calculated as follows:
   decoding.
 
 The algorithm purely describes the conversion from compressed Bayer code used
-in the SN9C10x chips to uncompressed Bayer. Additional steps are required to
-convert this to a color image (i.e. a color interpolation algorithm).
+in the SN9C101, SN9C102 and SN9C103 chips to uncompressed Bayer. Additional
+steps are required to convert this to a color image (i.e. a color interpolation
+algorithm).
 
 The following Huffman codes have been found:
 0: +0 (relative to reference pixel value)
@@ -506,13 +559,18 @@ order):
 - Philippe Coval for having helped testing the PAS202BCA image sensor;
 - Joao Rodrigo Fuzaro, Joao Limirio, Claudio Filho and Caio Begotti for the
   donation of a webcam;
+- Dennis Heitmann for the donation of a webcam;
 - Jon Hollstrom for the donation of a webcam;
+- Nick McGill for the donation of a webcam;
 - Carlos Eduardo Medaglia Dyonisio, who added the support for the PAS202BCB
   image sensor;
 - Stefano Mozzi, who donated 45 EU;
 - Andrew Pearce for the donation of a webcam;
+- John Pullan for the donation of a webcam;
 - Bertrik Sikken, who reverse-engineered and documented the Huffman compression
-  algorithm used in the SN9C10x controllers and implemented the first decoder;
+  algorithm used in the SN9C101, SN9C102 and SN9C103 controllers and
+  implemented the first decoder;
 - Mizuno Takafumi for the donation of a webcam;
 - an "anonymous" donator (who didn't want his name to be revealed) for the
   donation of a webcam.
+- an anonymous donator for the donation of four webcams.
index f406f5e800464dcd11315459575ad5fb141a752f..befdfdacdc5b36e7e63de4415666e37b60e5a686 100644 (file)
@@ -23,7 +23,7 @@ Index
 
 1. Copyright
 ============
-Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>
+Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>
 
 
 2. Disclaimer
@@ -125,8 +125,9 @@ And finally:
 6. Module loading
 =================
 To use the driver, it is necessary to load the "zc0301" module into memory
-after every other module required: "videodev", "usbcore" and, depending on
-the USB host controller you have, "ehci-hcd", "uhci-hcd" or "ohci-hcd".
+after every other module required: "videodev", "v4l2_common", "compat_ioctl32",
+"usbcore" and, depending on the USB host controller you have, "ehci-hcd",
+"uhci-hcd" or "ohci-hcd".
 
 Loading can be done as shown below:
 
@@ -211,12 +212,11 @@ Vendor ID  Product ID
 0x041e     0x4036
 0x041e     0x403a
 0x0458     0x7007
-0x0458     0x700C
+0x0458     0x700c
 0x0458     0x700f
 0x046d     0x08ae
 0x055f     0xd003
 0x055f     0xd004
-0x046d     0x08ae
 0x0ac8     0x0301
 0x0ac8     0x301b
 0x0ac8     0x303b
index 6261597a1bce3037b386628760f0821189c498a5..17555bba20af84bc071d7cd8d553d06b3598e4f3 100644 (file)
@@ -679,6 +679,11 @@ L: linux-hams@vger.kernel.org
 W:     http://www.linux-ax25.org/
 S:     Maintained
 
+BACKLIGHT CLASS/SUBSYSTEM
+P:     Richard Purdie
+M:     rpurdie@rpsys.net
+S:     Maintained
+
 BAYCOM/HDLCDRV DRIVERS FOR AX.25
 P:     Thomas Sailer
 M:     t.sailer@alumni.ethz.ch
@@ -1098,9 +1103,6 @@ W:        http://lanana.org/docs/device-list/index.html
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 
-DEVICE FILESYSTEM
-S:     Obsolete
-
 DIGI INTL. EPCA DRIVER
 P:     Digi International, Inc
 M:     Eng.Linux@digi.com
@@ -1301,7 +1303,7 @@ S:        Maintained
 ETHERNET BRIDGE
 P:     Stephen Hemminger
 M:     shemminger@linux-foundation.org
-L:     bridge@osdl.org
+L:     bridge@lists.osdl.org
 W:     http://bridge.sourceforge.net/
 S:     Maintained
 
@@ -1316,13 +1318,13 @@ S:      Maintained
 
 EXT3 FILE SYSTEM
 P:     Stephen Tweedie, Andrew Morton
-M:     sct@redhat.com, akpm@osdl.org, adilger@clusterfs.com
+M:     sct@redhat.com, akpm@linux-foundation.org, adilger@clusterfs.com
 L:     linux-ext4@vger.kernel.org
 S:     Maintained
 
 EXT4 FILE SYSTEM
 P:     Stephen Tweedie, Andrew Morton
-M:     sct@redhat.com, akpm@osdl.org, adilger@clusterfs.com
+M:     sct@redhat.com, akpm@linux-foundation.org, adilger@clusterfs.com
 L:     linux-ext4@vger.kernel.org
 S:     Maintained
 
@@ -1340,7 +1342,7 @@ S:        Supported
 
 FRAMEBUFFER LAYER
 P:     Antonino Daplas
-M:     adaplas@pol.net
+M:     adaplas@gmail.com
 L:     linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
 W:     http://linux-fbdev.sourceforge.net/
 S:     Maintained
@@ -1487,6 +1489,13 @@ HID CORE LAYER
 P:     Jiri Kosina
 M:     jkosina@suse.cz
 L:     linux-input@atrey.karlin.mff.cuni.cz
+T:     git kernel.org:/pub/scm/linux/kernel/git/jikos/hid.git
+S:     Maintained
+
+HIGH-RESOLUTION TIMERS, CLOCKEVENTS, DYNTICKS
+P:     Thomas Gleixner
+M:     tglx@linutronix.de
+L:     linux-kernel@vger.kernel.org
 S:     Maintained
 
 HIGH-SPEED SCC DRIVER FOR AX.25
@@ -1745,7 +1754,7 @@ S:        Maintained
 
 INTEL 810/815 FRAMEBUFFER DRIVER
 P:     Antonino Daplas
-M:     adaplas@pol.net
+M:     adaplas@gmail.com
 L:     linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
 S:     Maintained
 
@@ -1895,13 +1904,6 @@ L:       isdn4linux@listserv.isdn4linux.de
 W:     http://www.melware.de
 S:     Maintained
 
-JOURNALLING FLASH FILE SYSTEM (JFFS)
-P:     Axis Communications AB
-M:     jffs-dev@axis.com
-L:     jffs-dev@axis.com
-W:     http://www.developer.axis.com/software/jffs/
-S:     Maintained
-
 JOURNALLING FLASH FILE SYSTEM V2 (JFFS2)
 P:     David Woodhouse
 M:     dwmw2@infradead.org
@@ -1919,7 +1921,7 @@ S:        Supported
 
 JOURNALLING LAYER FOR BLOCK DEVICES (JBD)
 P:     Stephen Tweedie, Andrew Morton
-M:     sct@redhat.com, akpm@osdl.org
+M:     sct@redhat.com, akpm@linux-foundation.org
 L:     linux-ext4@vger.kernel.org
 S:     Maintained
 
@@ -1990,7 +1992,7 @@ P:        Eric Biederman
 M:     ebiederm@xmission.com
 W:     http://www.xmission.com/~ebiederm/files/kexec/
 L:     linux-kernel@vger.kernel.org
-L:     fastboot@osdl.org
+L:     fastboot@lists.osdl.org
 S:     Maintained
 
 KPROBES
@@ -2328,7 +2330,7 @@ S:        Maintained
 NETEM NETWORK EMULATOR
 P:     Stephen Hemminger
 M:     shemminger@linux-foundation.org
-L:     netem@osdl.org
+L:     netem@lists.osdl.org
 S:     Maintained
 
 NETFILTER/IPTABLES/IPCHAINS
@@ -2367,7 +2369,7 @@ S:        Maintained
 
 NETWORK DEVICE DRIVERS
 P:     Andrew Morton
-M:     akpm@osdl.org
+M:     akpm@linux-foundation.org
 P:     Jeff Garzik
 M:     jgarzik@pobox.com
 L:     netdev@vger.kernel.org
@@ -2467,7 +2469,7 @@ S:        Maintained
 
 NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER
 P:     Antonino Daplas
-M:     adaplas@pol.net
+M:     adaplas@gmail.com
 L:     linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
 S:     Maintained
 
@@ -2548,16 +2550,8 @@ L:       i2c@lm-sensors.org
 S:     Maintained
 
 PARALLEL PORT SUPPORT
-P:     Phil Blundell
-M:     philb@gnu.org
-P:     Tim Waugh
-M:     tim@cyberelk.net
-P:     David Campbell
-P:     Andrea Arcangeli
-M:     andrea@suse.de
 L:     linux-parport@lists.infradead.org
-W:     http://people.redhat.com/twaugh/parport/
-S:     Maintained
+S:     Orphan
 
 PARIDE DRIVERS FOR PARALLEL PORT IDE DEVICES
 P:     Tim Waugh
@@ -2743,7 +2737,7 @@ S:        Supported
 PVRUSB2 VIDEO4LINUX DRIVER
 P:     Mike Isely
 M:     isely@pobox.com
-L:     pvrusb2@isely.net
+L:     pvrusb2@isely.net       (subscribers-only)
 L:     video4linux-list@redhat.com
 W:     http://www.isely.net/pvrusb2/
 S:     Maintained
@@ -2851,7 +2845,7 @@ S:        Orphan
 
 S3 SAVAGE FRAMEBUFFER DRIVER
 P:     Antonino Daplas
-M:     adaplas@pol.net
+M:     adaplas@gmail.com
 L:     linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
 S:     Maintained
 
@@ -3062,7 +3056,7 @@ S:        Supported
 SOFTWARE SUSPEND:
 P:     Pavel Machek
 M:     pavel@suse.cz
-L:     linux-pm@osdl.org
+L:     linux-pm@lists.osdl.org
 S:     Maintained
 
 SONIC NETWORK DRIVER
@@ -3173,8 +3167,8 @@ L:        linux-kernel@vger.kernel.org ?
 S:     Supported
 
 SPIDERNET NETWORK DRIVER for CELL
-P:     Jim Lewis
-M:     jim@jklewis.com
+P:     Linas Vepstas
+M:     linas@austin.ibm.com
 L:     netdev@vger.kernel.org
 S:     Supported
 
@@ -3387,6 +3381,13 @@ L:       linux-usb-devel@lists.sourceforge.net
 S:     Maintained
 W:     http://www.kroah.com/linux-usb/
 
+USB DAVICOM DM9601 DRIVER
+P:     Peter Korsgaard
+M:     jacmet@sunsite.dk
+L:     linux-usb-devel@lists.sourceforge.net
+W:     http://www.linux-usb.org/usbnet
+S:     Maintained
+
 USB EHCI DRIVER
 P:     David Brownell
 M:     dbrownell@users.sourceforge.net
@@ -3412,6 +3413,7 @@ USB HID/HIDBP DRIVERS
 P:     Jiri Kosina
 M:     jkosina@suse.cz
 L:     linux-usb-devel@lists.sourceforge.net
+T:     git kernel.org:/pub/scm/linux/kernel/git/jikos/hid.git
 S:     Maintained
 
 USB HUB DRIVER
index b6c8790925bfe1f4c51442e06941f34207b0cc02..6393738fe968db56ded487cd5c4619c9d1ddb72c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
-SUBLEVEL = 20
-EXTRAVERSION =
+SUBLEVEL = 21
+EXTRAVERSION = -rc3
 NAME = Homicidal Dwarf Hamster
 
 # *DOCUMENTATION*
index 4409561ea32c44ed2e76d88a543cd9492a36380b..e7baca29f3fb47f59cab05cf016b3f5cf25ebb26 100644 (file)
@@ -21,6 +21,10 @@ config ARM
 config SYS_SUPPORTS_APM_EMULATION
        bool
 
+config GENERIC_GPIO
+       bool
+       default n
+
 config GENERIC_TIME
        bool
        default n
@@ -163,6 +167,7 @@ config ARCH_VERSATILE
 
 config ARCH_AT91
        bool "Atmel AT91"
+       select GENERIC_GPIO
        help
          This enables support for systems based on the Atmel AT91RM9200
          and AT91SAM9xxx processors.
@@ -171,6 +176,7 @@ config ARCH_CLPS7500
        bool "Cirrus CL-PS7500FE"
        select TIMER_ACORN
        select ISA
+       select NO_IOPORT
        help
          Support for the Cirrus Logic PS7500FE system-on-a-chip.
 
@@ -189,6 +195,7 @@ config ARCH_CO285
 config ARCH_EBSA110
        bool "EBSA-110"
        select ISA
+       select NO_IOPORT
        help
          This is an evaluation board for the StrongARM processor available
          from Digital. It has limited hardware on-board, including an
@@ -302,6 +309,7 @@ config ARCH_PXA
        bool "PXA2xx-based"
        depends on MMU
        select ARCH_MTD_XIP
+       select GENERIC_GPIO
        select GENERIC_TIME
        help
          Support for Intel's PXA2XX processor line.
@@ -323,11 +331,13 @@ config ARCH_SA1100
        select ISA
        select ARCH_DISCONTIGMEM_ENABLE
        select ARCH_MTD_XIP
+       select GENERIC_GPIO
        help
          Support for StrongARM 11x0 based boards.
 
 config ARCH_S3C2410
        bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443"
+       select GENERIC_GPIO
        help
          Samsung S3C2410X CPU based systems, such as the Simtec Electronics
          BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
@@ -352,6 +362,7 @@ config ARCH_LH7A40X
 
 config ARCH_OMAP
        bool "TI OMAP"
+       select GENERIC_GPIO
        help
          Support for TI's OMAP platform (OMAP1 and OMAP2).
 
index 1320418b5d6f7328a383d023bac7ac1daadfe1db..ab9f2d4bd04ed0a15b948381070c99eff7d7626b 100644 (file)
@@ -124,7 +124,7 @@ endif
  machine-$(CONFIG_ARCH_H720X)     := h720x
  machine-$(CONFIG_ARCH_AAEC2000)   := aaec2000
  machine-$(CONFIG_ARCH_REALVIEW)   := realview
- machine-$(CONFIG_ARCH_AT91)      := at91rm9200
+ machine-$(CONFIG_ARCH_AT91)      := at91
  machine-$(CONFIG_ARCH_EP93XX)    := ep93xx
  machine-$(CONFIG_ARCH_PNX4008)           := pnx4008
  machine-$(CONFIG_ARCH_NETX)      := netx
index a3b450f8ef17b94a32c83b9c92acbf2861019386..a9bc5b52218fe9513cda477860dd0a5f90aca20a 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/leds.h>
+#include <linux/apm-emulation.h>
 
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/irq.h>
-#include <asm/apm-emulation.h>
 #include <asm/arch/pm.h>
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/sharpsl.h>
index df19e3632038d8bc0d3252afa41a5fbd44cc7df0..d4ca0f06be5f53eca5ef1c52a241c71ff9b36658 100644 (file)
@@ -1,11 +1,13 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Thu Feb 15 11:26:24 2007
+# Linux kernel version: 2.6.21-rc1
+# Wed Feb 21 16:48:01 2007
 #
 CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
 # CONFIG_GENERIC_TIME is not set
 CONFIG_MMU=y
+CONFIG_NO_IOPORT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_HARDIRQS_SW_RESEND=y
@@ -15,6 +17,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA=y
 CONFIG_VECTORS_BASE=0xffff0000
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -33,6 +36,7 @@ CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
@@ -120,6 +124,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
 # CONFIG_ARCH_IXP2000 is not set
 # CONFIG_ARCH_IXP23XX is not set
 # CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_NS9XXX is not set
 # CONFIG_ARCH_PNX4008 is not set
 # CONFIG_ARCH_PXA is not set
 # CONFIG_ARCH_RPC is not set
@@ -161,6 +166,7 @@ CONFIG_MACH_OTOM=y
 CONFIG_MACH_AML_M5900=y
 CONFIG_BAST_PC104_IRQ=y
 CONFIG_MACH_VR1000=y
+CONFIG_MACH_QT2410=y
 CONFIG_CPU_S3C2412=y
 CONFIG_S3C2412_DMA=y
 CONFIG_S3C2412_PM=y
@@ -190,6 +196,7 @@ CONFIG_CPU_S3C2442=y
 #
 CONFIG_SMDK2440_CPU2442=y
 CONFIG_CPU_S3C2443=y
+CONFIG_S3C2443_DMA=y
 
 #
 # S3C2443 Machines
@@ -250,6 +257,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4096
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_ALIGNMENT_TRAP=y
 
 #
@@ -259,6 +267,7 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_CMDLINE="root=/dev/hda1 ro init=/bin/bash console=ttySAC0"
 # CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
 
 #
 # Floating point emulation
@@ -287,7 +296,7 @@ CONFIG_PM=y
 # CONFIG_PM_LEGACY is not set
 # CONFIG_PM_DEBUG is not set
 # CONFIG_PM_SYSFS_DEPRECATED is not set
-CONFIG_APM=y
+# CONFIG_APM_EMULATION is not set
 
 #
 # Networking
@@ -303,6 +312,7 @@ CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -387,6 +397,7 @@ CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -506,6 +517,7 @@ CONFIG_PARPORT_1284=y
 # Plug and Play support
 #
 # CONFIG_PNP is not set
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -680,6 +692,7 @@ CONFIG_KEYBOARD_ATKBD=y
 # CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
 # CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_GPIO is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 # CONFIG_MOUSE_SERIAL is not set
@@ -848,12 +861,13 @@ CONFIG_SPI_MASTER=y
 #
 CONFIG_SPI_BITBANG=m
 # CONFIG_SPI_BUTTERFLY is not set
-CONFIG_SPI_S3C24XX_GPIO=m
 CONFIG_SPI_S3C24XX=m
+CONFIG_SPI_S3C24XX_GPIO=m
 
 #
 # SPI Protocol Masters
 #
+# CONFIG_SPI_AT25 is not set
 
 #
 # Dallas's 1-wire bus
@@ -869,6 +883,7 @@ CONFIG_HWMON_VID=m
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ADM9240 is not set
 # CONFIG_SENSORS_ASB100 is not set
@@ -910,7 +925,11 @@ CONFIG_SENSORS_LM85=m
 #
 # Misc devices
 #
-# CONFIG_TIFM_CORE is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
 
 #
 # LED devices
@@ -945,16 +964,22 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=m
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB_DDC is not set
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
 CONFIG_FB_MODE_HELPERS=y
 # CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frambuffer hardware drivers
+#
 # CONFIG_FB_S1D13XXX is not set
 CONFIG_FB_S3C2410=y
 # CONFIG_FB_S3C2410_DEBUG is not set
@@ -976,7 +1001,6 @@ CONFIG_FONT_8x16=y
 # Logo configuration
 #
 # CONFIG_LOGO is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -987,6 +1011,7 @@ CONFIG_FONT_8x16=y
 # HID Devices
 #
 CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
 
 #
 # USB support
@@ -1001,7 +1026,6 @@ CONFIG_USB=y
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
@@ -1011,7 +1035,8 @@ CONFIG_USB_DEVICEFS=y
 #
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_SL811_HCD is not set
 
@@ -1052,6 +1077,7 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
 
 #
 # USB Imaging devices
@@ -1089,6 +1115,7 @@ CONFIG_USB_MON=y
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -1134,6 +1161,7 @@ CONFIG_RTC_INTF_DEV=y
 #
 # RTC drivers
 #
+# CONFIG_RTC_DRV_CMOS is not set
 # CONFIG_RTC_DRV_X1205 is not set
 # CONFIG_RTC_DRV_DS1307 is not set
 # CONFIG_RTC_DRV_DS1553 is not set
@@ -1339,15 +1367,16 @@ CONFIG_MAGIC_SYSRQ=y
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1358,6 +1387,7 @@ CONFIG_DEBUG_INFO=y
 CONFIG_FRAME_POINTER=y
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
 CONFIG_DEBUG_USER=y
 # CONFIG_DEBUG_ERRORS is not set
 CONFIG_DEBUG_LL=y
@@ -1387,4 +1417,4 @@ CONFIG_CRC32=y
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
index cc10a093a5455fa9f1b156b502c5346e64a985b6..d645897652c2d50a073bc529533127beff369c8d 100644 (file)
@@ -27,6 +27,7 @@
  * Interrupt handling.  Preserves r7, r8, r9
  */
        .macro  irq_handler
+       get_irqnr_preamble r5, lr
 1:     get_irqnr_and_base r0, r6, r5, lr
        movne   r1, sp
        @
index 6f5e7c50d42ff2d78bd9b29d050f9902904f1af7..c589dc3ecd1ac0fb48cc619496fd3456649cb0a6 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <asm/unistd.h>
+#include <asm/arch/entry-macro.S>
 
 #include "entry-header.S"
 
@@ -25,6 +26,9 @@ ret_fast_syscall:
        tst     r1, #_TIF_WORK_MASK
        bne     fast_work_pending
 
+       /* perform architecture specific actions before user return */
+       arch_ret_to_user r1, lr
+
        @ fast_restore_user_regs
        ldr     r1, [sp, #S_OFF + S_PSR]        @ get calling cpsr
        ldr     lr, [sp, #S_OFF + S_PC]!        @ get pc
@@ -61,6 +65,9 @@ ret_slow_syscall:
        tst     r1, #_TIF_WORK_MASK
        bne     work_pending
 no_work_pending:
+       /* perform architecture specific actions before user return */
+       arch_ret_to_user r1, lr
+
        @ slow_restore_user_regs
        ldr     r1, [sp, #S_PSR]                @ get calling cpsr
        ldr     lr, [sp, #S_PC]!                @ get pc
index cf495a3084b31f8a7ead7089508ff16096864ae9..66db0a9bf0bcfb40c6a4834721d2fc17f4872689 100644 (file)
        .endm
 
 #ifdef CONFIG_XIP_KERNEL
-#define TEXTADDR  XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR)
+#define KERNEL_START   XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR)
+#define KERNEL_END     _edata_loc
 #else
-#define TEXTADDR  KERNEL_RAM_VADDR
+#define KERNEL_START   KERNEL_RAM_VADDR
+#define KERNEL_END     _end
 #endif
 
 /*
@@ -240,16 +242,32 @@ __create_page_tables:
         * Now setup the pagetables for our kernel direct
         * mapped region.
         */
-       add     r0, r4,  #(TEXTADDR & 0xff000000) >> 18 @ start of kernel
-       str     r3, [r0, #(TEXTADDR & 0x00f00000) >> 18]!
-
-       ldr     r6, =(_end - PAGE_OFFSET - 1)   @ r6 = number of sections
-       mov     r6, r6, lsr #20                 @ needed for kernel minus 1
+       add     r0, r4,  #(KERNEL_START & 0xff000000) >> 18
+       str     r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]!
+       ldr     r6, =(KERNEL_END - 1)
+       add     r0, r0, #4
+       add     r6, r4, r6, lsr #18
+1:     cmp     r0, r6
+       add     r3, r3, #1 << 20
+       strls   r3, [r0], #4
+       bls     1b
 
-1:     add     r3, r3, #1 << 20
-       str     r3, [r0, #4]!
-       subs    r6, r6, #1
-       bgt     1b
+#ifdef CONFIG_XIP_KERNEL
+       /*
+        * Map some ram to cover our .data and .bss areas.
+        */
+       orr     r3, r7, #(KERNEL_RAM_PADDR & 0xff000000)
+       orr     r3, r3, #(KERNEL_RAM_PADDR & 0x00f00000)
+       add     r0, r4,  #(KERNEL_RAM_VADDR & 0xff000000) >> 18
+       str     r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> 18]!
+       ldr     r6, =(_end - 1)
+       add     r0, r0, #4
+       add     r6, r4, r6, lsr #18
+1:     cmp     r0, r6
+       add     r3, r3, #1 << 20
+       strls   r3, [r0], #4
+       bls     1b
+#endif
 
        /*
         * Then map first 1MB of ram in case it contains our boot params.
@@ -259,22 +277,6 @@ __create_page_tables:
        orr     r6, r6, #(PHYS_OFFSET & 0x00e00000)
        str     r6, [r0]
 
-#ifdef CONFIG_XIP_KERNEL
-       /*
-        * Map some ram to cover our .data and .bss areas.
-        * Mapping 3MB should be plenty.
-        */
-       sub     r3, r4, #PHYS_OFFSET
-       mov     r3, r3, lsr #20
-       add     r0, r0, r3, lsl #2
-       add     r6, r6, r3, lsl #20
-       str     r6, [r0], #4
-       add     r6, r6, #(1 << 20)
-       str     r6, [r0], #4
-       add     r6, r6, #(1 << 20)
-       str     r6, [r0]
-#endif
-
 #ifdef CONFIG_DEBUG_LL
        ldr     r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
        /*
index b929a60f7547cdde716dca1c18b06aafd92f8a22..ddbdad48f5b2636285c36d4836bb863f5b2e25f7 100644 (file)
@@ -156,6 +156,7 @@ SECTIONS
 
                _edata = .;
        }
+       _edata_loc = __data_loc + SIZEOF(.data);
 
        .bss : {
                __bss_start = .;        /* BSS                          */
index 6aa342e8f1b1fc6c67142aeac0c9c77774527b72..0e89a7fca3fa53df2bdbe2e799526903847d8477 100644 (file)
@@ -124,7 +124,7 @@ static struct clk isi_clk = {
 };
 static struct clk lcdc_clk = {
        .name           = "lcdc_clk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_ISI,
+       .pmc_mask       = 1 << AT91SAM9263_ID_LCDC,
        .type           = CLK_TYPE_PERIPHERAL,
 };
 static struct clk ohci_clk = {
index d9af7ca58bce9f9d160e32d1705adc96262479ec..b77121f27f34378f97d742ab5b9132269db8b9b8 100644 (file)
@@ -553,7 +553,7 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
        if (enable_spi0) {
                at91_set_B_periph(AT91_PIN_PA0, 0);     /* SPI0_MISO */
                at91_set_B_periph(AT91_PIN_PA1, 0);     /* SPI0_MOSI */
-               at91_set_B_periph(AT91_PIN_PA2, 0);     /* SPI1_SPCK */
+               at91_set_B_periph(AT91_PIN_PA2, 0);     /* SPI0_SPCK */
 
                at91_clock_associate("spi0_clk", &at91sam9263_spi0_device.dev, "spi_clk");
                platform_device_register(&at91sam9263_spi0_device);
index 7b87f3f101b7d324cdda7409ff4945e634ec4638..44211a0af19a805fd81a0d1a5783f07ed4db958f 100644 (file)
@@ -210,7 +210,7 @@ int gpio_direction_input(unsigned pin)
 
        if (!pio || !(__raw_readl(pio + PIO_PSR) & mask))
                return -EINVAL;
-       __raw_writel(mask, pio + PIO_OER);
+       __raw_writel(mask, pio + PIO_ODR);
        return 0;
 }
 EXPORT_SYMBOL(gpio_direction_input);
index c3d6c08f2d4cfbc3cb0d1ee960b8c101617a8636..4185e0586c33f18e2a7b729336a6b79f4f9650de 100644 (file)
@@ -5,7 +5,6 @@ obj-                    :=
 
 obj-$(CONFIG_ARCH_IOP13XX) += setup.o
 obj-$(CONFIG_ARCH_IOP13XX) += irq.o
-obj-$(CONFIG_ARCH_IOP13XX) += time.o
 obj-$(CONFIG_ARCH_IOP13XX) += pci.o
 obj-$(CONFIG_ARCH_IOP13XX) += io.o
 obj-$(CONFIG_MACH_IQ81340SC) += iq81340sc.o
index 2a1bbfe9896fcdf21c6183886176de0d7ea63cd9..a519d707571c81e678c81b0e2ed8d7a639943635 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/mach/arch.h>
 #include <asm/arch/pci.h>
 #include <asm/mach/time.h>
+#include <asm/arch/time.h>
 
 extern int init_atu; /* Flag to select which ATU(s) to initialize / disable */
 
@@ -78,12 +79,12 @@ static void __init iq81340mc_init(void)
 
 static void __init iq81340mc_timer_init(void)
 {
-       iop13xx_init_time(400000000);
+       iop_init_time(400000000);
 }
 
 static struct sys_timer iq81340mc_timer = {
        .init       = iq81340mc_timer_init,
-       .offset     = iop13xx_gettimeoffset,
+       .offset     = iop_gettimeoffset,
 };
 
 MACHINE_START(IQ81340MC, "Intel IQ81340MC")
index 5ad2b62c9bfde0582cc614f386f80591c7e82fe8..0e71fbcabe00a3dbafa3d85713a2182bf57fc10c 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/mach/arch.h>
 #include <asm/arch/pci.h>
 #include <asm/mach/time.h>
+#include <asm/arch/time.h>
 
 extern int init_atu;
 
@@ -80,12 +81,12 @@ static void __init iq81340sc_init(void)
 
 static void __init iq81340sc_timer_init(void)
 {
-       iop13xx_init_time(400000000);
+       iop_init_time(400000000);
 }
 
 static struct sys_timer iq81340sc_timer = {
        .init       = iq81340sc_timer_init,
-       .offset     = iop13xx_gettimeoffset,
+       .offset     = iop_gettimeoffset,
 };
 
 MACHINE_START(IQ81340SC, "Intel IQ81340SC")
index 162b93214965435d395a95b437162d49a49c935f..b2eb0b961031abcc64d4f73c68850c58eea129b7 100644 (file)
@@ -161,65 +161,49 @@ static void write_intsize(u32 val)
 static void
 iop13xx_irq_mask0 (unsigned int irq)
 {
-       u32 cp_flags = iop13xx_cp6_save();
        write_intctl_0(read_intctl_0() & ~(1 << (irq - 0)));
-       iop13xx_cp6_restore(cp_flags);
 }
 
 static void
 iop13xx_irq_mask1 (unsigned int irq)
 {
-       u32 cp_flags = iop13xx_cp6_save();
        write_intctl_1(read_intctl_1() & ~(1 << (irq - 32)));
-       iop13xx_cp6_restore(cp_flags);
 }
 
 static void
 iop13xx_irq_mask2 (unsigned int irq)
 {
-       u32 cp_flags = iop13xx_cp6_save();
        write_intctl_2(read_intctl_2() & ~(1 << (irq - 64)));
-       iop13xx_cp6_restore(cp_flags);
 }
 
 static void
 iop13xx_irq_mask3 (unsigned int irq)
 {
-       u32 cp_flags = iop13xx_cp6_save();
        write_intctl_3(read_intctl_3() & ~(1 << (irq - 96)));
-       iop13xx_cp6_restore(cp_flags);
 }
 
 static void
 iop13xx_irq_unmask0(unsigned int irq)
 {
-       u32 cp_flags = iop13xx_cp6_save();
        write_intctl_0(read_intctl_0() | (1 << (irq - 0)));
-       iop13xx_cp6_restore(cp_flags);
 }
 
 static void
 iop13xx_irq_unmask1(unsigned int irq)
 {
-       u32 cp_flags = iop13xx_cp6_save();
        write_intctl_1(read_intctl_1() | (1 << (irq - 32)));
-       iop13xx_cp6_restore(cp_flags);
 }
 
 static void
 iop13xx_irq_unmask2(unsigned int irq)
 {
-       u32 cp_flags = iop13xx_cp6_save();
        write_intctl_2(read_intctl_2() | (1 << (irq - 64)));
-       iop13xx_cp6_restore(cp_flags);
 }
 
 static void
 iop13xx_irq_unmask3(unsigned int irq)
 {
-       u32 cp_flags = iop13xx_cp6_save();
        write_intctl_3(read_intctl_3() | (1 << (irq - 96)));
-       iop13xx_cp6_restore(cp_flags);
 }
 
 static struct irq_chip iop13xx_irqchip1 = {
@@ -256,7 +240,6 @@ void __init iop13xx_init_irq(void)
 {
        unsigned int i;
 
-       u32 cp_flags = iop13xx_cp6_save();
        iop_init_cp6_handler();
 
        /* disable all interrupts */
@@ -288,6 +271,4 @@ void __init iop13xx_init_irq(void)
                set_irq_handler(i, handle_level_irq);
                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
        }
-
-       iop13xx_cp6_restore(cp_flags);
 }
index 5fbeb28d04bb6bcf67ceb976e3d2fae931f6b036..9a46bcd5f18e3992eaac306c62ba128fdf15d509 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/mach/map.h>
 #include <asm/hardware.h>
 #include <asm/irq.h>
+#include <asm/io.h>
 
 #define IOP13XX_UART_XTAL 33334000
 #define IOP13XX_SETUP_DEBUG 0
diff --git a/arch/arm/mach-iop13xx/time.c b/arch/arm/mach-iop13xx/time.c
deleted file mode 100644 (file)
index 8b21365..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * arch/arm/mach-iop13xx/time.c
- *
- * Timer code for IOP13xx (copied from IOP32x/IOP33x implementation)
- *
- * Author: Deepak Saxena <dsaxena@mvista.com>
- *
- * Copyright 2002-2003 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.
- */
-
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/timex.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/time.h>
-
-static unsigned long ticks_per_jiffy;
-static unsigned long ticks_per_usec;
-static unsigned long next_jiffy_time;
-
-static inline u32 read_tcr1(void)
-{
-       u32 val;
-       asm volatile("mrc p6, 0, %0, c3, c9, 0" : "=r" (val));
-       return val;
-}
-
-unsigned long iop13xx_gettimeoffset(void)
-{
-       unsigned long offset;
-       u32 cp_flags;
-
-       cp_flags = iop13xx_cp6_save();
-       offset = next_jiffy_time - read_tcr1();
-       iop13xx_cp6_restore(cp_flags);
-
-       return offset / ticks_per_usec;
-}
-
-static irqreturn_t
-iop13xx_timer_interrupt(int irq, void *dev_id)
-{
-       u32 cp_flags = iop13xx_cp6_save();
-
-       write_seqlock(&xtime_lock);
-
-       asm volatile("mcr p6, 0, %0, c6, c9, 0" : : "r" (1));
-
-       while ((signed long)(next_jiffy_time - read_tcr1())
-                                                       >= ticks_per_jiffy) {
-               timer_tick();
-               next_jiffy_time -= ticks_per_jiffy;
-       }
-
-       write_sequnlock(&xtime_lock);
-
-       iop13xx_cp6_restore(cp_flags);
-
-       return IRQ_HANDLED;
-}
-
-static struct irqaction iop13xx_timer_irq = {
-       .name           = "IOP13XX Timer Tick",
-       .handler        = iop13xx_timer_interrupt,
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
-};
-
-void __init iop13xx_init_time(unsigned long tick_rate)
-{
-       u32 timer_ctl;
-       u32 cp_flags;
-
-       ticks_per_jiffy = (tick_rate + HZ/2) / HZ;
-       ticks_per_usec = tick_rate / 1000000;
-       next_jiffy_time = 0xffffffff;
-
-       timer_ctl = IOP13XX_TMR_EN | IOP13XX_TMR_PRIVILEGED |
-                       IOP13XX_TMR_RELOAD | IOP13XX_TMR_RATIO_1_1;
-
-       /*
-        * We use timer 0 for our timer interrupt, and timer 1 as
-        * monotonic counter for tracking missed jiffies.
-        */
-       cp_flags = iop13xx_cp6_save();
-       asm volatile("mcr p6, 0, %0, c4, c9, 0" : : "r" (ticks_per_jiffy - 1));
-       asm volatile("mcr p6, 0, %0, c0, c9, 0" : : "r" (timer_ctl));
-       asm volatile("mcr p6, 0, %0, c5, c9, 0" : : "r" (0xffffffff));
-       asm volatile("mcr p6, 0, %0, c1, c9, 0" : : "r" (timer_ctl));
-       iop13xx_cp6_restore(cp_flags);
-
-       setup_irq(IRQ_IOP13XX_TIMER0, &iop13xx_timer_irq);
-}
index b9b765057dbecd8d2a74841bb5fd6ee2c28ce7a0..45f4f13ae11bc38d4634cd265e2d8a14435c1562 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/mach/time.h>
 #include <asm/mach-types.h>
 #include <asm/page.h>
+#include <asm/arch/time.h>
 
 /*
  * GLAN Tank timer tick configuration.
 static void __init glantank_timer_init(void)
 {
        /* 33.333 MHz crystal.  */
-       iop3xx_init_time(200000000);
+       iop_init_time(200000000);
 }
 
 static struct sys_timer glantank_timer = {
        .init           = glantank_timer_init,
-       .offset         = iop3xx_gettimeoffset,
+       .offset         = iop_gettimeoffset,
 };
 
 
index be4aedfa0de6abd0182202967a70f83867386cd0..571ac35bc2c75e482278c330a8f86fff754abbb2 100644 (file)
@@ -36,7 +36,7 @@
 #include <asm/mach-types.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-
+#include <asm/arch/time.h>
 
 /*
  * The EP80219 and IQ31244 use the same machine ID.  To find out
@@ -56,16 +56,16 @@ static void __init iq31244_timer_init(void)
 {
        if (is_80219()) {
                /* 33.333 MHz crystal.  */
-               iop3xx_init_time(200000000);
+               iop_init_time(200000000);
        } else {
                /* 33.000 MHz crystal.  */
-               iop3xx_init_time(198000000);
+               iop_init_time(198000000);
        }
 }
 
 static struct sys_timer iq31244_timer = {
        .init           = iq31244_timer_init,
-       .offset         = iop3xx_gettimeoffset,
+       .offset         = iop_gettimeoffset,
 };
 
 
index 1f37b550188840d6263c5275c52fb50e4e64b371..361c70c0f64cfba07ee39d37f35bfdffeb052c9c 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/mach-types.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <asm/arch/time.h>
 
 /*
  * IQ80321 timer tick configuration.
 static void __init iq80321_timer_init(void)
 {
        /* 33.333 MHz crystal.  */
-       iop3xx_init_time(200000000);
+       iop_init_time(200000000);
 }
 
 static struct sys_timer iq80321_timer = {
        .init           = iq80321_timer_init,
-       .offset         = iop3xx_gettimeoffset,
+       .offset         = iop_gettimeoffset,
 };
 
 
index 8b0ac5590ae4611ad2ac519b220dd75bde0b33fd..82598dc18d802b511666d1030af00434701026c6 100644 (file)
@@ -23,16 +23,12 @@ static u32 iop32x_mask;
 
 static inline void intctl_write(u32 val)
 {
-       iop3xx_cp6_enable();
        asm volatile("mcr p6, 0, %0, c0, c0, 0" : : "r" (val));
-       iop3xx_cp6_disable();
 }
 
 static inline void intstr_write(u32 val)
 {
-       iop3xx_cp6_enable();
        asm volatile("mcr p6, 0, %0, c4, c0, 0" : : "r" (val));
-       iop3xx_cp6_disable();
 }
 
 static void
index 966aa51aee09f2a2ae2f430357234d7e178bce85..5f07344d96f3dfa65a6ab33d01d9d6cde606e9b0 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/mach-types.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <asm/arch/time.h>
 
 /*
  * N2100 timer tick configuration.
 static void __init n2100_timer_init(void)
 {
        /* 33.000 MHz crystal.  */
-       iop3xx_init_time(198000000);
+       iop_init_time(198000000);
 }
 
 static struct sys_timer n2100_timer = {
        .init           = n2100_timer_init,
-       .offset         = iop3xx_gettimeoffset,
+       .offset         = iop_gettimeoffset,
 };
 
 
index 97a7b7488264ea8609fcd99461a9568b3f631d3c..1a9e36138d8046ff9a7ccbc427852141100f794c 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/mach-types.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <asm/arch/time.h>
 
 /*
  * IQ80331 timer tick configuration.
@@ -40,14 +41,14 @@ static void __init iq80331_timer_init(void)
 {
        /* D-Step parts run at a higher internal bus frequency */
        if (*IOP3XX_ATURID >= 0xa)
-               iop3xx_init_time(333000000);
+               iop_init_time(333000000);
        else
-               iop3xx_init_time(266000000);
+               iop_init_time(266000000);
 }
 
 static struct sys_timer iq80331_timer = {
        .init           = iq80331_timer_init,
-       .offset         = iop3xx_gettimeoffset,
+       .offset         = iop_gettimeoffset,
 };
 
 
index 9887bfc1c07861269dc08fec92a4546f584b5cd0..96d6f0f3cd215d384348fb18b4add2a66cdc8658 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/mach-types.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <asm/arch/time.h>
 
 /*
  * IQ80332 timer tick configuration.
@@ -40,14 +41,14 @@ static void __init iq80332_timer_init(void)
 {
        /* D-Step parts and the iop333 run at a higher internal bus frequency */
        if (*IOP3XX_ATURID >= 0xa || *IOP3XX_ATUDID == 0x374)
-               iop3xx_init_time(333000000);
+               iop_init_time(333000000);
        else
-               iop3xx_init_time(266000000);
+               iop_init_time(266000000);
 }
 
 static struct sys_timer iq80332_timer = {
        .init           = iq80332_timer_init,
-       .offset         = iop3xx_gettimeoffset,
+       .offset         = iop_gettimeoffset,
 };
 
 
index effbe6b782d04b2dc3d7f6f0abbc5839013ba044..c65ea78a2427eb4073ab73e29321e56fa312e3d9 100644 (file)
@@ -24,44 +24,32 @@ static u32 iop33x_mask1;
 
 static inline void intctl0_write(u32 val)
 {
-       iop3xx_cp6_enable();
        asm volatile("mcr p6, 0, %0, c0, c0, 0" : : "r" (val));
-       iop3xx_cp6_disable();
 }
 
 static inline void intctl1_write(u32 val)
 {
-       iop3xx_cp6_enable();
        asm volatile("mcr p6, 0, %0, c1, c0, 0" : : "r" (val));
-       iop3xx_cp6_disable();
 }
 
 static inline void intstr0_write(u32 val)
 {
-       iop3xx_cp6_enable();
        asm volatile("mcr p6, 0, %0, c2, c0, 0" : : "r" (val));
-       iop3xx_cp6_disable();
 }
 
 static inline void intstr1_write(u32 val)
 {
-       iop3xx_cp6_enable();
        asm volatile("mcr p6, 0, %0, c3, c0, 0" : : "r" (val));
-       iop3xx_cp6_disable();
 }
 
 static inline void intbase_write(u32 val)
 {
-       iop3xx_cp6_enable();
        asm volatile("mcr p6, 0, %0, c12, c0, 0" : : "r" (val));
-       iop3xx_cp6_disable();
 }
 
 static inline void intsize_write(u32 val)
 {
-       iop3xx_cp6_enable();
        asm volatile("mcr p6, 0, %0, c13, c0, 0" : : "r" (val));
-       iop3xx_cp6_disable();
 }
 
 static void
index cbe909bad79b3fde3e1b064b69bdb78e081b56f1..70014f751bc4baa7c70e06f15affa9e84a01d771 100644 (file)
@@ -16,6 +16,8 @@
 
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
 
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
@@ -103,7 +105,7 @@ static struct ads7846_platform_data nokia770_ads7846_platform_data __initdata =
 
 static struct spi_board_info nokia770_spi_board_info[] __initdata = {
        [0] = {
-               .modalias       = "lcd_lph8923",
+               .modalias               = "lcd_mipid",
                .bus_num        = 2,
                .chip_select    = 3,
                .max_speed_hz   = 12000000,
index 638490e62d5f5ebb7e07a21f586c521b9b2f2fe2..f625f6dd228a5187598d115b7293afdee924c755 100644 (file)
@@ -432,8 +432,7 @@ static int omap1_clk_enable(struct clk *clk)
                        }
 
                        if (clk->flags & CLOCK_NO_IDLE_PARENT)
-                               if (!cpu_is_omap24xx())
-                                       omap1_clk_deny_idle(clk->parent);
+                               omap1_clk_deny_idle(clk->parent);
                }
 
                ret = clk->enable(clk);
@@ -454,8 +453,7 @@ static void omap1_clk_disable(struct clk *clk)
                if (likely(clk->parent)) {
                        omap1_clk_disable(clk->parent);
                        if (clk->flags & CLOCK_NO_IDLE_PARENT)
-                               if (!cpu_is_omap24xx())
-                                       omap1_clk_allow_idle(clk->parent);
+                               omap1_clk_allow_idle(clk->parent);
                }
        }
 }
@@ -471,7 +469,7 @@ static int omap1_clk_enable_generic(struct clk *clk)
        if (unlikely(clk->enable_reg == 0)) {
                printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
                       clk->name);
-               return 0;
+               return -EINVAL;
        }
 
        if (clk->flags & ENABLE_REG_32BIT) {
@@ -651,10 +649,18 @@ int __init omap1_clk_init(void)
        int crystal_type = 0; /* Default 12 MHz */
        u32 reg;
 
+#ifdef CONFIG_DEBUG_LL
+       /* Resets some clocks that may be left on from bootloader,
+        * but leaves serial clocks on.
+        */
+       omap_writel(0x3 << 29, MOD_CONF_CTRL_0);
+#endif
+
        /* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */
        reg = omap_readw(SOFT_REQ_REG) & (1 << 4);
        omap_writew(reg, SOFT_REQ_REG);
-       omap_writew(0, SOFT_REQ_REG2);
+       if (!cpu_is_omap15xx())
+               omap_writew(0, SOFT_REQ_REG2);
 
        clk_init(&omap1_clk_functions);
 
@@ -685,7 +691,7 @@ int __init omap1_clk_init(void)
 
        info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config);
        if (info != NULL) {
-               if (!cpu_is_omap1510())
+               if (!cpu_is_omap15xx())
                        crystal_type = info->system_clock_type;
        }
 
index 6383a12ad970ffe275049d87237109ea80d13a5b..410d3e78dd0fd9911633c84657f23877792950c6 100644 (file)
@@ -238,7 +238,7 @@ void __init omap_init_irq(void)
 
        if (cpu_is_omap730())
                omap_unmask_irq(INT_730_IH2_IRQ);
-       else if (cpu_is_omap1510())
+       else if (cpu_is_omap15xx())
                omap_unmask_irq(INT_1510_IH2_IRQ);
        else if (cpu_is_omap16xx())
                omap_unmask_irq(INT_1610_IH2_IRQ);
index 4834758d340c60a9bdec5b349a780443d9893e52..49efe903dacda7c98e8b1043b7b761fa62c73298 100644 (file)
@@ -256,7 +256,8 @@ void omap_pm_suspend(void)
                tps65010_set_led(LED1, OFF);
        }
 
-       omap_writew(0xffff, ULPD_SOFT_DISABLE_REQ_REG);
+       if (!cpu_is_omap15xx())
+               omap_writew(0xffff, ULPD_SOFT_DISABLE_REQ_REG);
 
        /*
         * Step 1: turn off interrupts (FIXME: NOTE: already disabled)
@@ -434,7 +435,8 @@ void omap_pm_suspend(void)
                MPUI1610_RESTORE(OMAP_IH2_3_MIR);
        }
 
-       omap_writew(0, ULPD_SOFT_DISABLE_REQ_REG);
+       if (!cpu_is_omap15xx())
+               omap_writew(0, ULPD_SOFT_DISABLE_REQ_REG);
 
        /*
         * Reenable interrupts
@@ -704,6 +706,8 @@ static struct pm_ops omap_pm_ops ={
 
 static int __init omap_pm_init(void)
 {
+       int error;
+
        printk("Power Management for TI OMAP.\n");
 
        /*
@@ -760,7 +764,9 @@ static int __init omap_pm_init(void)
        omap_pm_init_proc();
 #endif
 
-       subsys_create_file(&power_subsys, &sleep_while_idle_attr);
+       error = subsys_create_file(&power_subsys, &sleep_while_idle_attr);
+       if (error)
+               printk(KERN_ERR "subsys_create_file failed: %d\n", error);
 
        if (cpu_is_omap16xx()) {
                /* configure LOW_PWR pin */
index 4cc98a578e4bf5ed98ac048f702f2c519ae7a22d..10a4fe88b2fd5993a9b8d262f63f9aea4dca5381 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * linux/arch/arm/mach-omap1/serial.c
  *
- * OMAP1 CPU identification code
+ * OMAP1 serial support.
  *
  * 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
@@ -59,7 +59,7 @@ static void __init omap_serial_reset(struct plat_serial8250_port *p)
        omap_serial_outp(p, UART_OMAP_SCR, 0x08);       /* TX watermark */
        omap_serial_outp(p, UART_OMAP_MDR1, 0x00);      /* enable UART */
 
-       if (!cpu_is_omap1510()) {
+       if (!cpu_is_omap15xx()) {
                omap_serial_outp(p, UART_OMAP_SYSC, 0x01);
                while (!(omap_serial_in(p, UART_OMAP_SYSC) & 0x01));
        }
@@ -121,7 +121,7 @@ void __init omap_serial_init(void)
                serial_platform_data[1].irq = INT_730_UART_MODEM_IRDA_2;
        }
 
-       if (cpu_is_omap1510()) {
+       if (cpu_is_omap15xx()) {
                serial_platform_data[0].uartclk = OMAP1510_BASE_BAUD * 16;
                serial_platform_data[1].uartclk = OMAP1510_BASE_BAUD * 16;
                serial_platform_data[2].uartclk = OMAP1510_BASE_BAUD * 16;
@@ -147,10 +147,10 @@ void __init omap_serial_init(void)
                                printk("Could not get uart1_ck\n");
                        else {
                                clk_enable(uart1_ck);
-                               if (cpu_is_omap1510())
+                               if (cpu_is_omap15xx())
                                        clk_set_rate(uart1_ck, 12000000);
                        }
-                       if (cpu_is_omap1510()) {
+                       if (cpu_is_omap15xx()) {
                                omap_cfg_reg(UART1_TX);
                                omap_cfg_reg(UART1_RTS);
                                if (machine_is_omap_innovator()) {
@@ -167,12 +167,12 @@ void __init omap_serial_init(void)
                                printk("Could not get uart2_ck\n");
                        else {
                                clk_enable(uart2_ck);
-                               if (cpu_is_omap1510())
+                               if (cpu_is_omap15xx())
                                        clk_set_rate(uart2_ck, 12000000);
                                else
                                        clk_set_rate(uart2_ck, 48000000);
                        }
-                       if (cpu_is_omap1510()) {
+                       if (cpu_is_omap15xx()) {
                                omap_cfg_reg(UART2_TX);
                                omap_cfg_reg(UART2_RTS);
                                if (machine_is_omap_innovator()) {
@@ -189,10 +189,10 @@ void __init omap_serial_init(void)
                                printk("Could not get uart3_ck\n");
                        else {
                                clk_enable(uart3_ck);
-                               if (cpu_is_omap1510())
+                               if (cpu_is_omap15xx())
                                        clk_set_rate(uart3_ck, 12000000);
                        }
-                       if (cpu_is_omap1510()) {
+                       if (cpu_is_omap15xx()) {
                                omap_cfg_reg(UART3_TX);
                                omap_cfg_reg(UART3_RX);
                        }
index 3b1ad1d981a359288dc67c84c6f5416e5b1042c7..1e7ed6d22ca98efc6614ff56071d91ac4679af6f 100644 (file)
@@ -39,7 +39,6 @@
 #include "prcm-regs.h"
 
 #include <asm/io.h>
-#include <asm/delay.h>
 
 static unsigned int row_gpios[6] = { 88, 89, 124, 11, 6, 96 };
 static unsigned int col_gpios[7] = { 90, 91, 100, 36, 12, 97, 98 };
@@ -179,9 +178,11 @@ static int h4_select_irda(struct device *dev, int state)
        return err;
 }
 
-static void set_trans_mode(void *data)
+static void set_trans_mode(struct work_struct *work)
 {
-       int *mode = data;
+       struct omap_irda_config *irda_config =
+               container_of(work, struct omap_irda_config, gpio_expa.work);
+       int mode = irda_config->mode;
        unsigned char expa;
        int err = 0;
 
@@ -191,7 +192,7 @@ static void set_trans_mode(void *data)
 
        expa &= ~0x01;
 
-       if (!(*mode & IR_SIRMODE)) { /* MIR/FIR */
+       if (!(mode & IR_SIRMODE)) { /* MIR/FIR */
                expa |= 0x01;
        }
 
@@ -204,9 +205,9 @@ static int h4_transceiver_mode(struct device *dev, int mode)
 {
        struct omap_irda_config *irda_config = dev->platform_data;
 
+       irda_config->mode = mode;
        cancel_delayed_work(&irda_config->gpio_expa);
-       PREPARE_WORK(&irda_config->gpio_expa, set_trans_mode, &mode);
-#error this is not permitted - mode is an argument variable
+       PREPARE_DELAYED_WORK(&irda_config->gpio_expa, set_trans_mode);
        schedule_delayed_work(&irda_config->gpio_expa, 0);
 
        return 0;
index 973189cd97665c7aee22f2a51439e5745eb4a630..45d1aaa51b576d47a3610d6c04c1d8b90691cee3 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/irq.h>
 
 #include <asm/mach/time.h>
 #include <asm/arch/dmtimer.h>
@@ -64,7 +65,7 @@ static void __init omap2_gp_timer_init(void)
        BUG_ON(gptimer == NULL);
 
        omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_SYS_CLK);
-       tick_period = clk_get_rate(omap_dm_timer_get_fclk(gptimer)) / 100;
+       tick_period = clk_get_rate(omap_dm_timer_get_fclk(gptimer)) / HZ;
        tick_period -= 1;
 
        setup_irq(omap_dm_timer_get_irq(gptimer), &omap2_gp_timer_irq);
index 165017de8d0d39e2e261c55d41af2ef01ffcdc20..392c38717362751b9614ae88e1db1abff6c229c7 100644 (file)
@@ -16,7 +16,8 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
-#include <asm/apm-emulation.h>
+#include <linux/apm-emulation.h>
+
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 #include <asm/hardware.h>
index 390524c4710f543384861206557a72cc514a1175..b8cb79f899d517004c95390044add5697a4a931e 100644 (file)
@@ -36,6 +36,7 @@
 #include <asm/mach/map.h>
 
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/gpio.h>
 #include <asm/arch/udc.h>
 #include <asm/arch/pxafb.h>
 #include <asm/arch/mmc.h>
@@ -106,13 +107,16 @@ unsigned long long sched_clock(void)
  * Handy function to set GPIO alternate functions
  */
 
-void pxa_gpio_mode(int gpio_mode)
+int pxa_gpio_mode(int gpio_mode)
 {
        unsigned long flags;
        int gpio = gpio_mode & GPIO_MD_MASK_NR;
        int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
        int gafr;
 
+       if (gpio > PXA_LAST_GPIO)
+               return -EINVAL;
+
        local_irq_save(flags);
        if (gpio_mode & GPIO_DFLT_LOW)
                GPCR(gpio) = GPIO_bit(gpio);
@@ -125,10 +129,32 @@ void pxa_gpio_mode(int gpio_mode)
        gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2));
        GAFR(gpio) = gafr |  (fn  << (((gpio) & 0xf)*2));
        local_irq_restore(flags);
+
+       return 0;
 }
 
 EXPORT_SYMBOL(pxa_gpio_mode);
 
+/*
+ * Return GPIO level
+ */
+int pxa_gpio_get_value(unsigned gpio)
+{
+       return __gpio_get_value(gpio);
+}
+
+EXPORT_SYMBOL(pxa_gpio_get_value);
+
+/*
+ * Set output GPIO level
+ */
+void pxa_gpio_set_value(unsigned gpio, int value)
+{
+       __gpio_set_value(gpio, value);
+}
+
+EXPORT_SYMBOL(pxa_gpio_set_value);
+
 /*
  * Routine to safely enable or disable a clock in the CKEN
  */
index b1d8cfca245a2dd18d582963cb2c04a267f19bea..f9d1b61e118523f70ef8422cc7dfcdd663592d96 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/platform_device.h>
+#include <linux/apm-emulation.h>
 
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
-#include <asm/apm-emulation.h>
 #include <asm/arch/pm.h>
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/sharpsl.h>
index b97d543d93640d6a4f1cb01efbd8e46fac9fe0f7..745a4dc7acdde6dc2fe4918c427178aac1a5f546 100644 (file)
@@ -16,7 +16,8 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
-#include <asm/apm-emulation.h>
+#include <linux/apm-emulation.h>
+
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 #include <asm/hardware.h>
index e510295c2580d89591eee0b4675f8d401f966540..192a5a26cf2b4c16ff5f9a5cd044c578468432dd 100644 (file)
@@ -138,6 +138,36 @@ unsigned long long sched_clock(void)
        return v;
 }
 
+int gpio_direction_input(unsigned gpio)
+{
+       unsigned long flags;
+
+       if (gpio > GPIO_MAX)
+               return -EINVAL;
+
+       local_irq_save(flags);
+       GPDR &= ~GPIO_GPIO(gpio);
+       local_irq_restore(flags);
+       return 0;
+}
+
+EXPORT_SYMBOL(gpio_direction_input);
+
+int gpio_direction_output(unsigned gpio)
+{
+       unsigned long flags;
+
+       if (gpio > GPIO_MAX)
+               return -EINVAL;
+
+       local_irq_save(flags);
+       GPDR |= GPIO_GPIO(gpio);
+       local_irq_restore(flags);
+       return 0;
+}
+
+EXPORT_SYMBOL(gpio_direction_output);
+
 /*
  * Default power-off for SA1100
  */
index 54ecdaa373d6d4b8feeff7a445783daeabc1793a..64067cd58d36e075cd7fede2ddbdb48e2d715f1e 100644 (file)
@@ -231,12 +231,6 @@ static struct platform_device *devices[] __initdata = {
        &s1d13xxxfb_device,
 };
 
-/* a stub for now, we theoretically cannot suspend without a flashboard */
-int pm_suspend(suspend_state_t state)
-{
-       return -1;
-}
-
 static int __init jornada720_init(void)
 {
        int ret = -ENODEV;
index 0a007b931f6368f8dcb8eb3dc4b47d4c5ae17b6d..a9de727c9327aa29eb266e45860a681e72f1d55c 100644 (file)
@@ -131,6 +131,8 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
        struct op_arm_model_spec *spec = NULL;
        int ret = -ENODEV;
 
+       ops->backtrace = arm_backtrace;
+
 #ifdef CONFIG_CPU_XSCALE
        spec = &op_xscale_spec;
 #endif
@@ -161,7 +163,6 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
                ops->start = op_arm_start;
                ops->stop = op_arm_stop;
                ops->cpu_type = op_arm_model->name;
-               ops->backtrace = arm_backtrace;
                printk(KERN_INFO "oprofile: using %s\n", spec->name);
        }
 
index 3250d732a17142fec31636d18a551df97b57e1ba..4d2b1da3cd82e6105fcc1269d71b82cf7488d265 100644 (file)
@@ -24,6 +24,7 @@ obj-$(CONFIG_ARCH_IOP33X) += cp6.o
 
 # IOP13XX
 obj-$(CONFIG_ARCH_IOP13XX) += cp6.o
+obj-$(CONFIG_ARCH_IOP13XX) += time.o
 
 obj-m                  :=
 obj-n                  :=
index f530abdaa7a1e7fb5bd16ea5e5a49263d39f8cad..16300adfb4de2af53a30ccf0ecf79aa9cbde3260 100644 (file)
 #include <asm/uaccess.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
-
-#ifdef CONFIG_ARCH_IOP32X
-#define IRQ_IOP3XX_TIMER0      IRQ_IOP32X_TIMER0
-#else
-#ifdef CONFIG_ARCH_IOP33X
-#define IRQ_IOP3XX_TIMER0      IRQ_IOP33X_TIMER0
-#endif
-#endif
+#include <asm/arch/time.h>
 
 static unsigned long ticks_per_jiffy;
 static unsigned long ticks_per_usec;
 static unsigned long next_jiffy_time;
 
-unsigned long iop3xx_gettimeoffset(void)
+unsigned long iop_gettimeoffset(void)
 {
-       unsigned long offset;
+       unsigned long offset, temp1, temp2;
 
-       offset = next_jiffy_time - *IOP3XX_TU_TCR1;
+       /* enable cp6, if necessary, to avoid taking the overhead of an
+        * undefined instruction trap
+        */
+       asm volatile (
+       "mrc    p15, 0, %0, c15, c1, 0\n\t"
+       "ands   %1, %0, #(1 << 6)\n\t"
+       "orreq  %0, %0, #(1 << 6)\n\t"
+       "mcreq  p15, 0, %0, c15, c1, 0\n\t"
+#ifdef CONFIG_XSCALE
+       "mrceq  p15, 0, %0, c15, c1, 0\n\t"
+       "moveq  %0, %0\n\t"
+       "subeq  pc, pc, #4\n\t"
+#endif
+       : "=r"(temp1), "=r"(temp2) : : "cc");
+
+       offset = next_jiffy_time - read_tcr1();
 
        return offset / ticks_per_usec;
 }
 
 static irqreturn_t
-iop3xx_timer_interrupt(int irq, void *dev_id)
+iop_timer_interrupt(int irq, void *dev_id)
 {
        write_seqlock(&xtime_lock);
 
-       iop3xx_cp6_enable();
-       asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (1));
-       iop3xx_cp6_disable();
+       write_tisr(1);
 
-       while ((signed long)(next_jiffy_time - *IOP3XX_TU_TCR1)
-                                                       >= ticks_per_jiffy) {
+       while ((signed long)(next_jiffy_time - read_tcr1())
+               >= ticks_per_jiffy) {
                timer_tick();
                next_jiffy_time -= ticks_per_jiffy;
        }
@@ -66,13 +72,13 @@ iop3xx_timer_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static struct irqaction iop3xx_timer_irq = {
-       .name           = "IOP3XX Timer Tick",
-       .handler        = iop3xx_timer_interrupt,
+static struct irqaction iop_timer_irq = {
+       .name           = "IOP Timer Tick",
+       .handler        = iop_timer_interrupt,
        .flags          = IRQF_DISABLED | IRQF_TIMER,
 };
 
-void __init iop3xx_init_time(unsigned long tick_rate)
+void __init iop_init_time(unsigned long tick_rate)
 {
        u32 timer_ctl;
 
@@ -80,19 +86,17 @@ void __init iop3xx_init_time(unsigned long tick_rate)
        ticks_per_usec = tick_rate / 1000000;
        next_jiffy_time = 0xffffffff;
 
-       timer_ctl = IOP3XX_TMR_EN | IOP3XX_TMR_PRIVILEGED |
-                       IOP3XX_TMR_RELOAD | IOP3XX_TMR_RATIO_1_1;
+       timer_ctl = IOP_TMR_EN | IOP_TMR_PRIVILEGED |
+                       IOP_TMR_RELOAD | IOP_TMR_RATIO_1_1;
 
        /*
         * We use timer 0 for our timer interrupt, and timer 1 as
         * monotonic counter for tracking missed jiffies.
         */
-       iop3xx_cp6_enable();
-       asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (ticks_per_jiffy - 1));
-       asm volatile("mcr p6, 0, %0, c0, c1, 0" : : "r" (timer_ctl));
-       asm volatile("mcr p6, 0, %0, c5, c1, 0" : : "r" (0xffffffff));
-       asm volatile("mcr p6, 0, %0, c1, c1, 0" : : "r" (timer_ctl));
-       iop3xx_cp6_disable();
-
-       setup_irq(IRQ_IOP3XX_TIMER0, &iop3xx_timer_irq);
+       write_trr0(ticks_per_jiffy - 1);
+       write_tmr0(timer_ctl);
+       write_trr1(0xffffffff);
+       write_tmr1(timer_ctl);
+
+       setup_irq(IRQ_IOP_TIMER0, &iop_timer_irq);
 }
index bb045e5ddbd837e3906a90415e5800b383c6dd08..f3f84fbf8b875da63e8cf10bf178745a2eff2a7d 100644 (file)
@@ -557,7 +557,7 @@ int omap_request_dma(int dev_id, const char *dev_name,
                omap_enable_channel_irq(free_ch);
                /* Clear the CSR register and IRQ status register */
                OMAP_DMA_CSR_REG(free_ch) = OMAP2_DMA_CSR_CLEAR_MASK;
-               omap_writel(~0x0, OMAP_DMA4_IRQSTATUS_L0);
+               omap_writel(1 << free_ch, OMAP_DMA4_IRQSTATUS_L0);
        }
 
        *dma_ch_out = free_ch;
@@ -597,10 +597,7 @@ void omap_free_dma(int lch)
 
                /* Clear the CSR register and IRQ status register */
                OMAP_DMA_CSR_REG(lch) = OMAP2_DMA_CSR_CLEAR_MASK;
-
-               val = omap_readl(OMAP_DMA4_IRQSTATUS_L0);
-               val |= 1 << lch;
-               omap_writel(val, OMAP_DMA4_IRQSTATUS_L0);
+               omap_writel(1 << lch, OMAP_DMA4_IRQSTATUS_L0);
 
                /* Disable all DMA interrupts for the channel. */
                OMAP_DMA_CICR_REG(lch) = 0;
@@ -927,7 +924,6 @@ static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id)
 static int omap2_dma_handle_ch(int ch)
 {
        u32 status = OMAP_DMA_CSR_REG(ch);
-       u32 val;
 
        if (!status)
                return 0;
@@ -948,11 +944,7 @@ static int omap2_dma_handle_ch(int ch)
                       dma_chan[ch].dev_id);
 
        OMAP_DMA_CSR_REG(ch) = OMAP2_DMA_CSR_CLEAR_MASK;
-
-       val = omap_readl(OMAP_DMA4_IRQSTATUS_L0);
-       /* ch in this function is from 0-31 while in register it is 1-32 */
-       val = 1 << (ch);
-       omap_writel(val, OMAP_DMA4_IRQSTATUS_L0);
+       omap_writel(1 << ch, OMAP_DMA4_IRQSTATUS_L0);
 
        if (likely(dma_chan[ch].callback != NULL))
                dma_chan[ch].callback(ch, status, dma_chan[ch].data);
index bcbb8d7392be6d5b5ca729b29a32439a1ba5331a..45f0439bffba6d81c946d7321dadb00b02254109 100644 (file)
@@ -90,8 +90,8 @@ static struct omap_dm_timer dm_timers[] = {
        { .phys_base = 0xfffb2c00, .irq = INT_1610_GPTIMER4 },
        { .phys_base = 0xfffb3400, .irq = INT_1610_GPTIMER5 },
        { .phys_base = 0xfffb3c00, .irq = INT_1610_GPTIMER6 },
-       { .phys_base = 0xfffb4400, .irq = INT_1610_GPTIMER7 },
-       { .phys_base = 0xfffb4c00, .irq = INT_1610_GPTIMER8 },
+       { .phys_base = 0xfffb7400, .irq = INT_1610_GPTIMER7 },
+       { .phys_base = 0xfffbd400, .irq = INT_1610_GPTIMER8 },
 };
 
 #elif defined(CONFIG_ARCH_OMAP2)
@@ -314,6 +314,8 @@ struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
 {
        BUG();
+
+       return 0;
 }
 
 #endif
index 4f2fd55913379a10b080412408f9d8e2a2b132c4..b8c01de208b4d0469dd0a9499e3109b1ec1fdd13 100644 (file)
@@ -974,10 +974,11 @@ static struct irq_chip gpio_irq_chip = {
 };
 
 static struct irq_chip mpuio_irq_chip = {
-       .name   = "MPUIO",
-       .ack    = mpuio_ack_irq,
-       .mask   = mpuio_mask_irq,
-       .unmask = mpuio_unmask_irq
+       .name     = "MPUIO",
+       .ack      = mpuio_ack_irq,
+       .mask     = mpuio_mask_irq,
+       .unmask   = mpuio_unmask_irq,
+       .set_type = gpio_irq_type,
 };
 
 static int initialized;
index ec50008a2df6421e46275d0ec022231bdf9a3b8f..b8d6f17ff58fc86e57301d64226a8ea87810a813 100644 (file)
@@ -20,8 +20,8 @@
 #include <linux/interrupt.h>
 #include <linux/err.h>
 #include <linux/clk.h>
+#include <linux/delay.h>
 
-#include <asm/delay.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
index 042105ac30b8ea5058861343058d62112e44b288..6c798d288688a8f3ef73ba39ce30106c3a1e1f9c 100644 (file)
@@ -116,7 +116,7 @@ int __init_or_module omap_cfg_reg(const unsigned long index)
        }
 
        /* Check for pull up or pull down selection on 1610 */
-       if (!cpu_is_omap1510()) {
+       if (!cpu_is_omap15xx()) {
                if (cfg->pu_pd_reg && cfg->pull_val) {
                        spin_lock_irqsave(&mux_spin_lock, flags);
                        pu_pd_orig = omap_readl(cfg->pu_pd_reg);
@@ -172,7 +172,7 @@ int __init_or_module omap_cfg_reg(const unsigned long index)
                printk("      %s (0x%08x) = 0x%08x -> 0x%08x\n",
                       cfg->mux_reg_name, cfg->mux_reg, reg_orig, reg);
 
-               if (!cpu_is_omap1510()) {
+               if (!cpu_is_omap15xx()) {
                        if (cfg->pu_pd_reg && cfg->pull_val) {
                                printk("      %s (0x%08x) = 0x%08x -> 0x%08x\n",
                                       cfg->pu_pd_name, cfg->pu_pd_reg,
index e223431606345d6d68f178d6f602bf3c24a020f1..b972f36d547ccd17190fd4cb698e1aa3e2656043 100644 (file)
@@ -8,6 +8,7 @@ config PLAT_S3C24XX
        bool
        depends on ARCH_S3C2410
        default y if ARCH_S3C2410
+       select NO_IOPORT
        help
          Base platform code for any Samsung S3C device
 
@@ -57,6 +58,11 @@ config S3C2410_PM_CHECK
          going to sleep. The blocks are then checked on resume for any
          errors.
 
+         Note, this can take several seconds depending on memory size
+         and CPU speed.
+
+         See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
+
 config S3C2410_PM_CHECK_CHUNKSIZE
        int "S3C2410 PM Suspend CRC Chunksize (KiB)"
        depends on ARCH_S3C2410 && PM && S3C2410_PM_CHECK
@@ -67,6 +73,8 @@ config S3C2410_PM_CHECK_CHUNKSIZE
          the CRC data block will take more memory, but wil identify any
          faults with better precision.
 
+         See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
+
 config S3C2410_LOWLEVEL_UART_PORT
        int "S3C2410 UART to use for low-level messages"
        default 0
index 6d910ea43d34dbc78b67be83e78822f9c3b34204..91496cc687b1d6831acbbd7bb82a861da12783da 100644 (file)
@@ -245,11 +245,6 @@ ENTRY(vector_swi)
        zero_fp
        get_scno
 
-#ifdef CONFIG_ALIGNMENT_TRAP
-       ldr     ip, __cr_alignment
-       ldr     ip, [ip]
-       mcr     p15, 0, ip, c1, c0              @ update control register
-#endif
        enable_irqs ip
 
        str     r4, [sp, #-S_OFF]!              @ push fifth arg
@@ -299,11 +294,6 @@ __sys_trace_return:
        b       ret_slow_syscall
 
        .align  5
-#ifdef CONFIG_ALIGNMENT_TRAP
-       .type   __cr_alignment, #object
-__cr_alignment:
-       .word   cr_alignment
-#endif
 
        .type   sys_call_table, #object
 ENTRY(sys_call_table)
index bb059a4e1df94a757eac011ad007552a8649be69..ce4013aee59bcd728ba24071e306040ae4e25a4d 100644 (file)
@@ -22,6 +22,10 @@ config AVR32
 config UID16
        bool
 
+config GENERIC_GPIO
+       bool
+       default y
+
 config GENERIC_HARDIRQS
        bool
        default y
index f2e81cd7900223cc3e112fa0b1c40eeb8319ff13..6f4388f7c20be5d57726dfcd01fe94fc962fda3b 100644 (file)
@@ -313,7 +313,7 @@ asmlinkage void do_debug_priv(struct pt_regs *regs)
                __mtdr(DBGREG_DC, dc);
 
                ti = current_thread_info();
-               ti->flags |= _TIF_BREAKPOINT;
+               set_ti_thread_flag(ti, TIF_BREAKPOINT);
 
                /* The TLB miss handlers don't check thread flags */
                if ((regs->pc >= (unsigned long)&itlb_miss)
@@ -328,7 +328,7 @@ asmlinkage void do_debug_priv(struct pt_regs *regs)
                 * single step.
                 */
                if ((regs->sr & MODE_MASK) != MODE_SUPERVISOR)
-                       ti->flags |= TIF_SINGLE_STEP;
+                       set_ti_thread_flag(ti, TIF_SINGLE_STEP);
        } else {
                panic("Unable to handle debug trap at pc = %08lx\n",
                      regs->pc);
index 7e803f4d7a12902972da2ce1325acd0bc43cafc2..adc01a12d15487ff8ae335f8352b9820d00b9395 100644 (file)
@@ -49,39 +49,45 @@ out:
        return;
 }
 
+static inline int valid_stack_ptr(struct thread_info *tinfo, unsigned long p)
+{
+       return (p > (unsigned long)tinfo)
+               && (p < (unsigned long)tinfo + THREAD_SIZE - 3);
+}
+
 #ifdef CONFIG_FRAME_POINTER
 static inline void __show_trace(struct task_struct *tsk, unsigned long *sp,
                                struct pt_regs *regs)
 {
-       unsigned long __user *fp;
-       unsigned long __user *last_fp = NULL;
-
-       if (regs) {
-               fp = (unsigned long __user *)regs->r7;
-       } else if (tsk == current) {
-               register unsigned long __user *real_fp __asm__("r7");
-               fp = real_fp;
-       } else {
-               fp = (unsigned long __user *)tsk->thread.cpu_context.r7;
-       }
+       unsigned long lr, fp;
+       struct thread_info *tinfo;
+
+       tinfo = (struct thread_info *)
+               ((unsigned long)sp & ~(THREAD_SIZE - 1));
+
+       if (regs)
+               fp = regs->r7;
+       else if (tsk == current)
+               asm("mov %0, r7" : "=r"(fp));
+       else
+               fp = tsk->thread.cpu_context.r7;
 
        /*
-        * Walk the stack until (a) we get an exception, (b) the frame
-        * pointer becomes zero, or (c) the frame pointer gets stuck
-        * at the same value.
+        * Walk the stack as long as the frame pointer (a) is within
+        * the kernel stack of the task, and (b) it doesn't move
+        * downwards.
         */
-       while (fp && fp != last_fp) {
-               unsigned long lr, new_fp = 0;
-
-               last_fp = fp;
-               if (__get_user(lr, fp))
-                       break;
-               if (fp && __get_user(new_fp, fp + 1))
-                       break;
-               fp = (unsigned long __user *)new_fp;
+       while (valid_stack_ptr(tinfo, fp)) {
+               unsigned long new_fp;
 
+               lr = *(unsigned long *)fp;
                printk(" [<%08lx>] ", lr);
                print_symbol("%s\n", lr);
+
+               new_fp = *(unsigned long *)(fp + 4);
+               if (new_fp <= fp)
+                       break;
+               fp = new_fp;
        }
        printk("\n");
 }
index bc235507c5c7508c28a79a6219079c95d349641b..472703f90c22cfceb918af4c3e1a26a8ca6e815b 100644 (file)
@@ -752,7 +752,7 @@ static struct resource atmel_spi1_resource[] = {
 DEFINE_DEV(atmel_spi, 1);
 DEV_CLK(spi_clk, atmel_spi1, pba, 1);
 
-static void
+static void __init
 at32_spi_setup_slaves(unsigned int bus_num, struct spi_board_info *b,
                      unsigned int n, const u8 *pins)
 {
index fb13f72e9a0290430a45db2ff6a65dafe9c114b4..8f7b1c3cd0f94658fec53cea41f81c856a90aa24 100644 (file)
@@ -121,9 +121,8 @@ void flush_icache_range(unsigned long start, unsigned long end)
 void flush_icache_page(struct vm_area_struct *vma, struct page *page)
 {
        if (vma->vm_flags & VM_EXEC) {
-               void *v = kmap(page);
+               void *v = page_address(page);
                __flush_icache_range((unsigned long)v, (unsigned long)v + PAGE_SIZE);
-               kunmap(v);
        }
 }
 
index 426b09878a05a5256c2fbc6ab3067a35c4726ccf..70d3bf0c92e8ebdda3c5d56bcb3663cfe6dc7ffc 100644 (file)
@@ -111,7 +111,7 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
        return DMA_MEMORY_IO;
 
  free1_out:
-       kfree(dev->dma_mem->bitmap);
+       kfree(dev->dma_mem);
  out:
        return 0;
 }
index 3f3a0ed3539bc514b7aa45f9f2b52fbfa42319b7..4103c2c487f3a114654f242f16b18d0e99281447 100644 (file)
@@ -126,8 +126,7 @@ void __init paging_init(void)
 
        /* distribute the allocatable pages across the various zones and pass them to the allocator
         */
-       zones_size[ZONE_DMA]     = max_low_pfn - min_low_pfn;
-       zones_size[ZONE_NORMAL]  = 0;
+       zones_size[ZONE_NORMAL]  = max_low_pfn - min_low_pfn;
 #ifdef CONFIG_HIGHMEM
        zones_size[ZONE_HIGHMEM] = num_physpages - num_mappedpages;
 #endif
index 2f7672545fe98ae0096d0249fefcf250dbdab5df..27e8453274e660b17c08d555aa4e394f7b01a548 100644 (file)
@@ -220,11 +220,11 @@ config PARAVIRT
 
 config VMI
        bool "VMI Paravirt-ops support"
-       depends on PARAVIRT && !NO_HZ
-       default y
+       depends on PARAVIRT
        help
-         VMI provides a paravirtualized interface to multiple hypervisors
-         include VMware ESX server and Xen by connecting to a ROM module
+         VMI provides a paravirtualized interface to the VMware ESX server
+         (it could be used by other hypervisors in theory too, but is not
+         at the moment), by linking the kernel to a GPL-ed ROM module
          provided by the hypervisor.
 
 config ACPI_SRAT
@@ -893,7 +893,6 @@ config HOTPLUG_CPU
 config COMPAT_VDSO
        bool "Compat VDSO support"
        default y
-       depends on !PARAVIRT
        help
          Map the VDSO to the predictable old-style address too.
        ---help---
@@ -1287,12 +1286,3 @@ config X86_TRAMPOLINE
 config KTIME_SCALAR
        bool
        default y
-
-config NO_IDLE_HZ
-       bool
-       depends on PARAVIRT
-       default y
-       help
-         Switches the regular HZ timer off when the system is going idle.
-         This helps a hypervisor detect that the Linux system is idle,
-         reducing the overhead of idle systems.
index f7ac1aea1d8a05e635828e1b8356da975123d3c3..bd28f9f9b4b7bfa020a2bb364561abb14db1a03e 100644 (file)
@@ -31,7 +31,7 @@ LDFLAGS_vmlinux := --emit-relocs
 endif
 CHECKFLAGS     += -D__i386__
 
-CFLAGS += -pipe -msoft-float -mregparm=3
+CFLAGS += -pipe -msoft-float -mregparm=3 -freg-struct-return
 
 # prevent gcc from keeping the stack 16 byte aligned
 CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2)
index e5eb97a910ed8d82f74fc67802e04321eacdc82c..9ea5b8ecc7e1d61918da7043a15b55400c121735 100644 (file)
@@ -1072,7 +1072,28 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = {
                               "ASUS A7V ACPI BIOS Revision 1007"),
                     },
         },
-
+       {
+               /*
+                * Latest BIOS for IBM 600E (1.16) has bad pcinum
+                * for LPC bridge, which is needed for the PCI
+                * interrupt links to work. DSDT fix is in bug 5966.
+                * 2645, 2646 model numbers are shared with 600/600E/600X
+                */
+        .callback = disable_acpi_irq,
+        .ident = "IBM Thinkpad 600 Series 2645",
+        .matches = {
+                    DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
+                    DMI_MATCH(DMI_BOARD_NAME, "2645"),
+                    },
+        },
+       {
+        .callback = disable_acpi_irq,
+        .ident = "IBM Thinkpad 600 Series 2646",
+        .matches = {
+                    DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
+                    DMI_MATCH(DMI_BOARD_NAME, "2646"),
+                    },
+        },
        /*
         * Boxes that need ACPI PCI IRQ routing and PCI scan disabled
         */
index bf86f7662d8b7a4c6210ff6e537502db624e27b6..a7d22d9f3d7e50d13ae2c4d6a43aba093a920b8a 100644 (file)
 
 #ifdef CONFIG_ACPI
 
-static int nvidia_hpet_detected __initdata;
-
 static int __init nvidia_hpet_check(struct acpi_table_header *header)
 {
-       nvidia_hpet_detected = 1;
        return 0;
 }
 #endif
@@ -29,9 +26,7 @@ static int __init check_bridge(int vendor, int device)
        /* According to Nvidia all timer overrides are bogus unless HPET
           is enabled. */
        if (!acpi_use_timer_override && vendor == PCI_VENDOR_ID_NVIDIA) {
-               nvidia_hpet_detected = 0;
-               acpi_table_parse(ACPI_SIG_HPET, nvidia_hpet_check);
-               if (nvidia_hpet_detected == 0) {
+               if (acpi_table_parse(ACPI_SIG_HPET, nvidia_hpet_check)) {
                        acpi_skip_timer_override = 1;
                          printk(KERN_INFO "Nvidia board "
                        "detected. Ignoring ACPI "
index 9655c233e6f144804c275f9b8eada53fb27f8f8a..2383bcf18c5d0c321712f854721441562d522025 100644 (file)
@@ -38,7 +38,6 @@
 #include <asm/hpet.h>
 #include <asm/i8253.h>
 #include <asm/nmi.h>
-#include <asm/idle.h>
 
 #include <mach_apic.h>
 #include <mach_apicdef.h>
@@ -494,8 +493,15 @@ void __init setup_boot_APIC_clock(void)
                /* No broadcast on UP ! */
                if (num_possible_cpus() == 1)
                        return;
-       } else
-               lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
+       } else {
+               /*
+                * If nmi_watchdog is set to IO_APIC, we need the
+                * PIT/HPET going.  Otherwise register lapic as a dummy
+                * device.
+                */
+               if (nmi_watchdog != NMI_IO_APIC)
+                       lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
+       }
 
        /* Setup the lapic or request the broadcast */
        setup_APIC_timer();
@@ -561,7 +567,6 @@ void fastcall smp_apic_timer_interrupt(struct pt_regs *regs)
         * Besides, if we don't timer interrupts ignore the global
         * interrupt lock, which is the WrongThing (tm) to do.
         */
-       exit_idle();
        irq_enter();
        local_apic_timer_interrupt();
        irq_exit();
@@ -1221,7 +1226,6 @@ void smp_spurious_interrupt(struct pt_regs *regs)
 {
        unsigned long v;
 
-       exit_idle();
        irq_enter();
        /*
         * Check if this really is a spurious interrupt and ACK it
@@ -1245,7 +1249,6 @@ void smp_error_interrupt(struct pt_regs *regs)
 {
        unsigned long v, v1;
 
-       exit_idle();
        irq_enter();
        /* First tickle the hardware, only then report what went on. -- REW */
        v = apic_read(APIC_ESR);
index 6c52182ca323c7e874a35f30092da909449f8b19..e912aae9473cb449480cde7a60e68b70347a6b71 100644 (file)
@@ -125,7 +125,6 @@ config X86_SPEEDSTEP_CENTRINO_ACPI
        bool "Use ACPI tables to decode valid frequency/voltage (deprecated)"
        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
index b59878a0d9b31a6f58b939f64bebadc656c55752..a1f1b715bcf8f0fd7cda241a05885c44f344f170 100644 (file)
@@ -61,8 +61,8 @@ static int cpu_model;
 static unsigned int numscales=16;
 static unsigned int fsb;
 
-static struct mV_pos *vrm_mV_table;
-static unsigned char *mV_vrm_table;
+static const struct mV_pos *vrm_mV_table;
+static const unsigned char *mV_vrm_table;
 struct f_msr {
        u8 vrm;
        u8 pos;
index bb0a04b1d1abe5af709ce624397c838013d0bd46..102548f128422ffba612cbc7d9ed5efe949f3cd0 100644 (file)
@@ -56,7 +56,7 @@ union msr_longhaul {
 /*
  * VIA C3 Samuel 1  & Samuel 2 (stepping 0)
  */
-static int __initdata samuel1_clock_ratio[16] = {
+static const int __initdata samuel1_clock_ratio[16] = {
        -1, /* 0000 -> RESERVED */
        30, /* 0001 ->  3.0x */
        40, /* 0010 ->  4.0x */
@@ -75,7 +75,7 @@ static int __initdata samuel1_clock_ratio[16] = {
        -1, /* 1111 -> RESERVED */
 };
 
-static int __initdata samuel1_eblcr[16] = {
+static const int __initdata samuel1_eblcr[16] = {
        50, /* 0000 -> RESERVED */
        30, /* 0001 ->  3.0x */
        40, /* 0010 ->  4.0x */
@@ -97,7 +97,7 @@ static int __initdata samuel1_eblcr[16] = {
 /*
  * VIA C3 Samuel2 Stepping 1->15
  */
-static int __initdata samuel2_eblcr[16] = {
+static const int __initdata samuel2_eblcr[16] = {
        50,  /* 0000 ->  5.0x */
        30,  /* 0001 ->  3.0x */
        40,  /* 0010 ->  4.0x */
@@ -119,7 +119,7 @@ static int __initdata samuel2_eblcr[16] = {
 /*
  * VIA C3 Ezra
  */
-static int __initdata ezra_clock_ratio[16] = {
+static const int __initdata ezra_clock_ratio[16] = {
        100, /* 0000 -> 10.0x */
        30,  /* 0001 ->  3.0x */
        40,  /* 0010 ->  4.0x */
@@ -138,7 +138,7 @@ static int __initdata ezra_clock_ratio[16] = {
        120, /* 1111 -> 12.0x */
 };
 
-static int __initdata ezra_eblcr[16] = {
+static const int __initdata ezra_eblcr[16] = {
        50,  /* 0000 ->  5.0x */
        30,  /* 0001 ->  3.0x */
        40,  /* 0010 ->  4.0x */
@@ -160,7 +160,7 @@ static int __initdata ezra_eblcr[16] = {
 /*
  * VIA C3 (Ezra-T) [C5M].
  */
-static int __initdata ezrat_clock_ratio[32] = {
+static const int __initdata ezrat_clock_ratio[32] = {
        100, /* 0000 -> 10.0x */
        30,  /* 0001 ->  3.0x */
        40,  /* 0010 ->  4.0x */
@@ -196,7 +196,7 @@ static int __initdata ezrat_clock_ratio[32] = {
        -1,  /* 1111 -> RESERVED (12.0x) */
 };
 
-static int __initdata ezrat_eblcr[32] = {
+static const int __initdata ezrat_eblcr[32] = {
        50,  /* 0000 ->  5.0x */
        30,  /* 0001 ->  3.0x */
        40,  /* 0010 ->  4.0x */
@@ -235,7 +235,7 @@ static int __initdata ezrat_eblcr[32] = {
 /*
  * VIA C3 Nehemiah */
 
-static int __initdata  nehemiah_clock_ratio[32] = {
+static const int __initdata  nehemiah_clock_ratio[32] = {
        100, /* 0000 -> 10.0x */
        160, /* 0001 -> 16.0x */
        40,  /* 0010 ->  4.0x */
@@ -270,7 +270,7 @@ static int __initdata  nehemiah_clock_ratio[32] = {
        120, /* 1111 -> 12.0x */
 };
 
-static int __initdata nehemiah_eblcr[32] = {
+static const int __initdata nehemiah_eblcr[32] = {
        50,  /* 0000 ->  5.0x */
        160, /* 0001 -> 16.0x */
        40,  /* 0010 ->  4.0x */
@@ -315,7 +315,7 @@ struct mV_pos {
        unsigned short pos;
 };
 
-static struct mV_pos __initdata vrm85_mV[32] = {
+static const struct mV_pos __initdata vrm85_mV[32] = {
        {1250, 8},      {1200, 6},      {1150, 4},      {1100, 2},
        {1050, 0},      {1800, 30},     {1750, 28},     {1700, 26},
        {1650, 24},     {1600, 22},     {1550, 20},     {1500, 18},
@@ -326,14 +326,14 @@ static struct mV_pos __initdata vrm85_mV[32] = {
        {1475, 17},     {1425, 15},     {1375, 13},     {1325, 11}
 };
 
-static unsigned char __initdata mV_vrm85[32] = {
+static const unsigned char __initdata mV_vrm85[32] = {
        0x04,   0x14,   0x03,   0x13,   0x02,   0x12,   0x01,   0x11,
        0x00,   0x10,   0x0f,   0x1f,   0x0e,   0x1e,   0x0d,   0x1d,
        0x0c,   0x1c,   0x0b,   0x1b,   0x0a,   0x1a,   0x09,   0x19,
        0x08,   0x18,   0x07,   0x17,   0x06,   0x16,   0x05,   0x15
 };
 
-static struct mV_pos __initdata mobilevrm_mV[32] = {
+static const struct mV_pos __initdata mobilevrm_mV[32] = {
        {1750, 31},     {1700, 30},     {1650, 29},     {1600, 28},
        {1550, 27},     {1500, 26},     {1450, 25},     {1400, 24},
        {1350, 23},     {1300, 22},     {1250, 21},     {1200, 20},
@@ -344,7 +344,7 @@ static struct mV_pos __initdata mobilevrm_mV[32] = {
        {675, 3},       {650, 2},       {625, 1},       {600, 0}
 };
 
-static unsigned char __initdata mV_mobilevrm[32] = {
+static const unsigned char __initdata mV_mobilevrm[32] = {
        0x1f,   0x1e,   0x1d,   0x1c,   0x1b,   0x1a,   0x19,   0x18,
        0x17,   0x16,   0x15,   0x14,   0x13,   0x12,   0x11,   0x10,
        0x0f,   0x0e,   0x0d,   0x0c,   0x0b,   0x0a,   0x09,   0x08,
index 54382760983a11312c4eb8c9bc897636eb97631d..837b04166a47dc37c7cf5822ca027b442b7381fa 100644 (file)
@@ -68,7 +68,7 @@ union powernow_acpi_control_t {
 
 #ifdef CONFIG_CPU_FREQ_DEBUG
 /* divide by 1000 to get VCore voltage in V. */
-static int mobile_vid_table[32] = {
+static const int mobile_vid_table[32] = {
     2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,
     1600, 1550, 1500, 1450, 1400, 1350, 1300, 0,
     1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100,
@@ -77,7 +77,7 @@ static int mobile_vid_table[32] = {
 #endif
 
 /* divide by 10 to get FID. */
-static int fid_codes[32] = {
+static const int fid_codes[32] = {
     110, 115, 120, 125, 50, 55, 60, 65,
     70, 75, 80, 85, 90, 95, 100, 105,
     30, 190, 40, 200, 130, 135, 140, 210,
index 8359c19d3a23d1c531a543a766d00d7ca5842b61..504434a46011e2ca553a7e6f67ccfad3c5ec7fc1 100644 (file)
@@ -12,7 +12,6 @@
 #include <asm/system.h>
 #include <asm/msr.h>
 #include <asm/apic.h>
-#include <asm/idle.h>
 
 #include <asm/therm_throt.h>
 
@@ -60,7 +59,6 @@ static void (*vendor_thermal_interrupt)(struct pt_regs *regs) = unexpected_therm
 
 fastcall void smp_thermal_interrupt(struct pt_regs *regs)
 {
-       exit_idle();
        irq_enter();
        vendor_thermal_interrupt(regs);
        irq_exit();
index e1006b7acc9e56d5be196599cd997d9cd364be8b..f3ab61ee749826282b8d1ee905f631c7b1efb06c 100644 (file)
@@ -200,6 +200,23 @@ static int hpet_next_event(unsigned long delta,
        return ((long)(hpet_readl(HPET_COUNTER) - cnt ) > 0);
 }
 
+/*
+ * Clock source related code
+ */
+static cycle_t read_hpet(void)
+{
+       return (cycle_t)hpet_readl(HPET_COUNTER);
+}
+
+static struct clocksource clocksource_hpet = {
+       .name           = "hpet",
+       .rating         = 250,
+       .read           = read_hpet,
+       .mask           = HPET_MASK,
+       .shift          = HPET_SHIFT,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
 /*
  * Try to setup the HPET timer
  */
@@ -207,6 +224,7 @@ int __init hpet_enable(void)
 {
        unsigned long id;
        uint64_t hpet_freq;
+       u64 tmp;
 
        if (!is_hpet_capable())
                return 0;
@@ -253,6 +271,25 @@ int __init hpet_enable(void)
        /* Start the counter */
        hpet_start_counter();
 
+       /* Initialize and register HPET clocksource
+        *
+        * hpet period is in femto seconds per cycle
+        * so we need to convert this to ns/cyc units
+        * aproximated by mult/2^shift
+        *
+        *  fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift
+        *  fsec/cyc * 1ns/1000000fsec * 2^shift = mult
+        *  fsec/cyc * 2^shift * 1nsec/1000000fsec = mult
+        *  (fsec/cyc << shift)/1000000 = mult
+        *  (hpet_period << shift)/FSEC_PER_NSEC = mult
+        */
+       tmp = (u64)hpet_period << HPET_SHIFT;
+       do_div(tmp, FSEC_PER_NSEC);
+       clocksource_hpet.mult = (u32)tmp;
+
+       clocksource_register(&clocksource_hpet);
+
+
        if (id & HPET_ID_LEGSUP) {
                hpet_enable_int();
                hpet_reserve_platform_timers(id);
@@ -273,49 +310,6 @@ out_nohpet:
        return 0;
 }
 
-/*
- * Clock source related code
- */
-static cycle_t read_hpet(void)
-{
-       return (cycle_t)hpet_readl(HPET_COUNTER);
-}
-
-static struct clocksource clocksource_hpet = {
-       .name           = "hpet",
-       .rating         = 250,
-       .read           = read_hpet,
-       .mask           = HPET_MASK,
-       .shift          = HPET_SHIFT,
-       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-static int __init init_hpet_clocksource(void)
-{
-       u64 tmp;
-
-       if (!hpet_virt_address)
-               return -ENODEV;
-
-       /*
-        * hpet period is in femto seconds per cycle
-        * so we need to convert this to ns/cyc units
-        * aproximated by mult/2^shift
-        *
-        *  fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift
-        *  fsec/cyc * 1ns/1000000fsec * 2^shift = mult
-        *  fsec/cyc * 2^shift * 1nsec/1000000fsec = mult
-        *  (fsec/cyc << shift)/1000000 = mult
-        *  (hpet_period << shift)/FSEC_PER_NSEC = mult
-        */
-       tmp = (u64)hpet_period << HPET_SHIFT;
-       do_div(tmp, FSEC_PER_NSEC);
-       clocksource_hpet.mult = (u32)tmp;
-
-       return clocksource_register(&clocksource_hpet);
-}
-
-module_init(init_hpet_clocksource);
 
 #ifdef CONFIG_HPET_EMULATE_RTC
 
index a6bc7bb38834282239bba67631b6ae2041b14e2b..5cbb776b3089b96f9d9a113c234037e28f3aa1c8 100644 (file)
@@ -195,4 +195,4 @@ static int __init init_pit_clocksource(void)
        clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE, 20);
        return clocksource_register(&clocksource_pit);
 }
-module_init(init_pit_clocksource);
+arch_initcall(init_pit_clocksource);
index 4ccebd454e256786d0e8e32fc9e540bf97ab5b72..e4408ff4e6747224a77a66b5b2f21d02a7992a25 100644 (file)
@@ -343,7 +343,7 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask)
                        break;
                entry = irq_2_pin + entry->next;
        }
-       set_native_irq_info(irq, cpumask);
+       irq_desc[irq].affinity = cpumask;
        spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
@@ -1354,7 +1354,6 @@ static void __init setup_IO_APIC_irqs(void)
                }
                spin_lock_irqsave(&ioapic_lock, flags);
                __ioapic_write_entry(apic, pin, entry);
-               set_native_irq_info(irq, TARGET_CPUS);
                spin_unlock_irqrestore(&ioapic_lock, flags);
        }
        }
@@ -2585,7 +2584,7 @@ static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
        msg.address_lo |= MSI_ADDR_DEST_ID(dest);
 
        write_msi_msg(irq, &msg);
-       set_native_irq_info(irq, mask);
+       irq_desc[irq].affinity = mask;
 }
 #endif /* CONFIG_SMP */
 
@@ -2669,7 +2668,7 @@ static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask)
        dest = cpu_mask_to_apicid(mask);
 
        target_ht_irq(irq, dest);
-       set_native_irq_info(irq, mask);
+       irq_desc[irq].affinity = mask;
 }
 #endif
 
@@ -2875,7 +2874,6 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
 
        spin_lock_irqsave(&ioapic_lock, flags);
        __ioapic_write_entry(ioapic, pin, entry);
-       set_native_irq_info(irq, TARGET_CPUS);
        spin_unlock_irqrestore(&ioapic_lock, flags);
 
        return 0;
index 0f2ca590bf2306411c58a149a091c5941dae7113..8db8d514c9c043d26c0a6d2f5f47d2187ba54fe8 100644 (file)
@@ -18,8 +18,6 @@
 #include <linux/cpu.h>
 #include <linux/delay.h>
 
-#include <asm/idle.h>
-
 #include <asm/apic.h>
 #include <asm/uaccess.h>
 
@@ -77,7 +75,6 @@ fastcall unsigned int do_IRQ(struct pt_regs *regs)
        union irq_ctx *curctx, *irqctx;
        u32 *isp;
 #endif
-       exit_idle();
 
        if (unlikely((unsigned)irq >= NR_IRQS)) {
                printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
index c156ecfa38727c2133ec4f3994ba8f4f9e82fc9f..2ec331e03fa9ede01a5bed5bee5faf1043b9f6dd 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/fixmap.h>
 #include <asm/apic.h>
 #include <asm/tlbflush.h>
+#include <asm/timer.h>
 
 /* nop stub */
 static void native_nop(void)
@@ -493,7 +494,7 @@ struct paravirt_ops paravirt_ops = {
        .memory_setup = machine_specific_memory_setup,
        .get_wallclock = native_get_wallclock,
        .set_wallclock = native_set_wallclock,
-       .time_init = time_init_hook,
+       .time_init = hpet_time_init,
        .init_IRQ = native_init_IRQ,
 
        .cpuid = native_cpuid,
@@ -520,6 +521,8 @@ struct paravirt_ops paravirt_ops = {
        .write_msr = native_write_msr,
        .read_tsc = native_read_tsc,
        .read_pmc = native_read_pmc,
+       .get_scheduled_cycles = native_read_tsc,
+       .get_cpu_khz = native_calculate_cpu_khz,
        .load_tr_desc = native_load_tr_desc,
        .set_ldt = native_set_ldt,
        .load_gdt = native_load_gdt,
@@ -535,7 +538,6 @@ struct paravirt_ops paravirt_ops = {
 
        .set_iopl_mask = native_set_iopl_mask,
        .io_delay = native_io_delay,
-       .const_udelay = __const_udelay,
 
 #ifdef CONFIG_X86_LOCAL_APIC
        .apic_write = native_apic_write,
@@ -550,6 +552,8 @@ struct paravirt_ops paravirt_ops = {
        .flush_tlb_kernel = native_flush_tlb_global,
        .flush_tlb_single = native_flush_tlb_single,
 
+       .map_pt_hook = (void *)native_nop,
+
        .alloc_pt = (void *)native_nop,
        .alloc_pd = (void *)native_nop,
        .alloc_pd_clone = (void *)native_nop,
index 41af692c1584908b6864356b757294b64b787de2..3ebcea033623e357904d52195d4d52d526267636 100644 (file)
@@ -110,7 +110,7 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
        return DMA_MEMORY_IO;
 
  free1_out:
-       kfree(dev->dma_mem->bitmap);
+       kfree(dev->dma_mem);
  out:
        if (mem_base)
                iounmap(mem_base);
index bea304d48cdbb8fdc150e9033ad0e53a3961c439..393a67d5d9434807ead8524b91aa3094ccd54238 100644 (file)
@@ -49,7 +49,6 @@
 #include <asm/i387.h>
 #include <asm/desc.h>
 #include <asm/vm86.h>
-#include <asm/idle.h>
 #ifdef CONFIG_MATH_EMULATION
 #include <asm/math_emu.h>
 #endif
@@ -82,42 +81,6 @@ void (*pm_idle)(void);
 EXPORT_SYMBOL(pm_idle);
 static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
 
-static ATOMIC_NOTIFIER_HEAD(idle_notifier);
-
-void idle_notifier_register(struct notifier_block *n)
-{
-       atomic_notifier_chain_register(&idle_notifier, n);
-}
-
-void idle_notifier_unregister(struct notifier_block *n)
-{
-       atomic_notifier_chain_unregister(&idle_notifier, n);
-}
-
-static DEFINE_PER_CPU(volatile unsigned long, idle_state);
-
-void enter_idle(void)
-{
-       /* needs to be atomic w.r.t. interrupts, not against other CPUs */
-       __set_bit(0, &__get_cpu_var(idle_state));
-       atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL);
-}
-
-static void __exit_idle(void)
-{
-       /* needs to be atomic w.r.t. interrupts, not against other CPUs */
-       if (__test_and_clear_bit(0, &__get_cpu_var(idle_state)) == 0)
-               return;
-       atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL);
-}
-
-void exit_idle(void)
-{
-       if (current->pid)
-               return;
-       __exit_idle();
-}
-
 void disable_hlt(void)
 {
        hlt_counter++;
@@ -168,7 +131,6 @@ EXPORT_SYMBOL(default_idle);
  */
 static void poll_idle (void)
 {
-       local_irq_enable();
        cpu_relax();
 }
 
@@ -229,16 +191,7 @@ void cpu_idle(void)
                                play_dead();
 
                        __get_cpu_var(irq_stat).idle_timestamp = jiffies;
-
-                       /*
-                        * Idle routines should keep interrupts disabled
-                        * from here on, until they go to idle.
-                        * Otherwise, idle callbacks can misfire.
-                        */
-                       local_irq_disable();
-                       enter_idle();
                        idle();
-                       __exit_idle();
                }
                tick_nohz_restart_sched_tick();
                preempt_enable_no_resched();
@@ -293,11 +246,7 @@ void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
                __monitor((void *)&current_thread_info()->flags, 0, 0);
                smp_mb();
                if (!need_resched())
-                       __sti_mwait(eax, ecx);
-               else
-                       local_irq_enable();
-       } else {
-               local_irq_enable();
+                       __mwait(eax, ecx);
        }
 }
 
index 122623dcc6e1bc94543f0d343d0fe4a19e90cef7..698c24fe482eef9085fd380233b9364333581c14 100644 (file)
@@ -657,5 +657,4 @@ void __init setup_arch(char **cmdline_p)
        conswitchp = &dummy_con;
 #endif
 #endif
-       tsc_init();
 }
index 9bd9637ae692fb731e08c836b562b5ad069eecb3..0e8977871b1ffdffd97bb8050625e0a6dd4acc7a 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <asm/mtrr.h>
 #include <asm/tlbflush.h>
-#include <asm/idle.h>
 #include <mach_apic.h>
 
 /*
@@ -624,7 +623,6 @@ fastcall void smp_call_function_interrupt(struct pt_regs *regs)
        /*
         * At this point the info structure may be out of scope unless wait==1
         */
-       exit_idle();
        irq_enter();
        (*func)(info);
        irq_exit();
index 48bfcaa13ecca45c79503f791814c75ed4a5ba54..4ff55e67557645d3683c35d1f9e6076371d09d4a 100644 (file)
  *             Dave Jones      :       Report invalid combinations of Athlon CPUs.
 *              Rusty Russell   :       Hacked into shape for new "hotplug" boot process. */
 
-
-/* SMP boot always wants to use real time delay to allow sufficient time for
- * the APs to come online */
-#define USE_REAL_TIME_DELAY
-
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -50,6 +45,7 @@
 #include <linux/notifier.h>
 #include <linux/cpu.h>
 #include <linux/percpu.h>
+#include <linux/nmi.h>
 
 #include <linux/delay.h>
 #include <linux/mc146818rtc.h>
@@ -1283,8 +1279,9 @@ void __cpu_die(unsigned int cpu)
 
 int __cpuinit __cpu_up(unsigned int cpu)
 {
+       unsigned long flags;
 #ifdef CONFIG_HOTPLUG_CPU
-       int ret=0;
+       int ret = 0;
 
        /*
         * We do warm boot only on cpus that had booted earlier
@@ -1302,23 +1299,25 @@ int __cpuinit __cpu_up(unsigned int cpu)
        /* In case one didn't come up */
        if (!cpu_isset(cpu, cpu_callin_map)) {
                printk(KERN_DEBUG "skipping cpu%d, didn't come online\n", cpu);
-               local_irq_enable();
                return -EIO;
        }
 
-       local_irq_enable();
-
        per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
        /* Unleash the CPU! */
        cpu_set(cpu, smp_commenced_mask);
 
        /*
-        * Check TSC synchronization with the AP:
+        * Check TSC synchronization with the AP (keep irqs disabled
+        * while doing so):
         */
+       local_irq_save(flags);
        check_tsc_sync_source(cpu);
+       local_irq_restore(flags);
 
-       while (!cpu_isset(cpu, cpu_online_map))
+       while (!cpu_isset(cpu, cpu_online_map)) {
                cpu_relax();
+               touch_nmi_watchdog();
+       }
 
 #ifdef CONFIG_X86_GENERICARCH
        if (num_online_cpus() > 8 && genapic == &apic_default)
index a5350059557a6541c0c96b8f8ba6933073999d05..94e5cb09110402ddc1d8b793d8b8c9d002fb5cf5 100644 (file)
@@ -262,14 +262,23 @@ void notify_arch_cmos_timer(void)
 
 extern void (*late_time_init)(void);
 /* Duplicate of time_init() below, with hpet_enable part added */
-static void __init hpet_time_init(void)
+void __init hpet_time_init(void)
 {
        if (!hpet_enable())
                setup_pit_timer();
-       do_time_init();
+       time_init_hook();
 }
 
+/*
+ * This is called directly from init code; we must delay timer setup in the
+ * HPET case as we can't make the decision to turn on HPET this early in the
+ * boot process.
+ *
+ * The chosen time_init function will usually be hpet_time_init, above, but
+ * in the case of virtual hardware, an alternative function may be substituted.
+ */
 void __init time_init(void)
 {
-       late_time_init = hpet_time_init;
+       tsc_init();
+       late_time_init = choose_time_init();
 }
index 3082a418635c11d6f3cdce2b53d3499a3124c075..602660df455c7676b2fd9400f628831b8b3d716c 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/delay.h>
 #include <asm/tsc.h>
 #include <asm/io.h>
+#include <asm/timer.h>
 
 #include "mach_timer.h"
 
@@ -23,7 +24,6 @@
  * an extra value to store the TSC freq
  */
 unsigned int tsc_khz;
-unsigned long long (*custom_sched_clock)(void);
 
 int tsc_disable;
 
@@ -102,9 +102,6 @@ unsigned long long sched_clock(void)
 {
        unsigned long long this_offset;
 
-       if (unlikely(custom_sched_clock))
-               return (*custom_sched_clock)();
-
        /*
         * Fall back to jiffies if there's no TSC available:
         */
@@ -113,13 +110,13 @@ unsigned long long sched_clock(void)
                return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ);
 
        /* read the Time Stamp Counter: */
-       rdtscll(this_offset);
+       get_scheduled_cycles(this_offset);
 
        /* return the value in ns */
        return cycles_2_ns(this_offset);
 }
 
-static unsigned long calculate_cpu_khz(void)
+unsigned long native_calculate_cpu_khz(void)
 {
        unsigned long long start, end;
        unsigned long count;
@@ -186,34 +183,6 @@ int recalibrate_cpu_khz(void)
 
 EXPORT_SYMBOL(recalibrate_cpu_khz);
 
-void __init tsc_init(void)
-{
-       if (!cpu_has_tsc || tsc_disable)
-               goto out_no_tsc;
-
-       cpu_khz = calculate_cpu_khz();
-       tsc_khz = cpu_khz;
-
-       if (!cpu_khz)
-               goto out_no_tsc;
-
-       printk("Detected %lu.%03lu MHz processor.\n",
-                               (unsigned long)cpu_khz / 1000,
-                               (unsigned long)cpu_khz % 1000);
-
-       set_cyc2ns_scale(cpu_khz);
-       use_tsc_delay();
-       return;
-
-out_no_tsc:
-       /*
-        * Set the tsc_disable flag if there's no TSC support, this
-        * makes it a fast flag for the kernel to see whether it
-        * should be using the TSC.
-        */
-       tsc_disable = 1;
-}
-
 #ifdef CONFIG_CPU_FREQ
 
 /*
@@ -383,28 +352,47 @@ static void __init check_geode_tsc_reliable(void)
 static inline void check_geode_tsc_reliable(void) { }
 #endif
 
-static int __init init_tsc_clocksource(void)
+
+void __init tsc_init(void)
 {
+       if (!cpu_has_tsc || tsc_disable)
+               goto out_no_tsc;
 
-       if (cpu_has_tsc && tsc_khz && !tsc_disable) {
-               /* check blacklist */
-               dmi_check_system(bad_tsc_dmi_table);
+       cpu_khz = calculate_cpu_khz();
+       tsc_khz = cpu_khz;
 
-               unsynchronized_tsc();
-               check_geode_tsc_reliable();
-               current_tsc_khz = tsc_khz;
-               clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz,
-                                                       clocksource_tsc.shift);
-               /* lower the rating if we already know its unstable: */
-               if (check_tsc_unstable()) {
-                       clocksource_tsc.rating = 0;
-                       clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS;
-               }
+       if (!cpu_khz)
+               goto out_no_tsc;
+
+       printk("Detected %lu.%03lu MHz processor.\n",
+                               (unsigned long)cpu_khz / 1000,
+                               (unsigned long)cpu_khz % 1000);
+
+       set_cyc2ns_scale(cpu_khz);
+       use_tsc_delay();
 
-               return clocksource_register(&clocksource_tsc);
+       /* Check and install the TSC clocksource */
+       dmi_check_system(bad_tsc_dmi_table);
+
+       unsynchronized_tsc();
+       check_geode_tsc_reliable();
+       current_tsc_khz = tsc_khz;
+       clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz,
+                                                       clocksource_tsc.shift);
+       /* lower the rating if we already know its unstable: */
+       if (check_tsc_unstable()) {
+               clocksource_tsc.rating = 0;
+               clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS;
        }
+       clocksource_register(&clocksource_tsc);
 
-       return 0;
-}
+       return;
 
-module_init(init_tsc_clocksource);
+out_no_tsc:
+       /*
+        * Set the tsc_disable flag if there's no TSC support, this
+        * makes it a fast flag for the kernel to see whether it
+        * should be using the TSC.
+        */
+       tsc_disable = 1;
+}
index bb5a7abf949cfd89c239ac7ec68ff4219969ac74..fbf45fa083207c7b70a1be6eed15bb27b4dcdb35 100644 (file)
@@ -35,6 +35,7 @@
 #include <asm/processor.h>
 #include <asm/timer.h>
 #include <asm/vmi_time.h>
+#include <asm/kmap_types.h>
 
 /* Convenient for calling VMI functions indirectly in the ROM */
 typedef u32 __attribute__((regparm(1))) (VROMFUNC)(void);
@@ -48,12 +49,13 @@ typedef u64 __attribute__((regparm(2))) (VROMLONGFUNC)(int);
 
 static struct vrom_header *vmi_rom;
 static int license_gplok;
-static int disable_nodelay;
 static int disable_pge;
 static int disable_pse;
 static int disable_sep;
 static int disable_tsc;
 static int disable_mtrr;
+static int disable_noidle;
+static int disable_vmi_timer;
 
 /* Cached VMI operations */
 struct {
@@ -255,7 +257,6 @@ static void vmi_nop(void)
 }
 
 /* For NO_IDLE_HZ, we stop the clock when halting the kernel */
-#ifdef CONFIG_NO_IDLE_HZ
 static fastcall void vmi_safe_halt(void)
 {
        int idle = vmi_stop_hz_timer();
@@ -266,7 +267,6 @@ static fastcall void vmi_safe_halt(void)
                local_irq_enable();
        }
 }
-#endif
 
 #ifdef CONFIG_DEBUG_PAGE_TYPE
 
@@ -371,6 +371,24 @@ static void vmi_check_page_type(u32 pfn, int type)
 #define vmi_check_page_type(p,t) do { } while (0)
 #endif
 
+static void vmi_map_pt_hook(int type, pte_t *va, u32 pfn)
+{
+       /*
+        * Internally, the VMI ROM must map virtual addresses to physical
+        * addresses for processing MMU updates.  By the time MMU updates
+        * are issued, this information is typically already lost.
+        * Fortunately, the VMI provides a cache of mapping slots for active
+        * page tables.
+        *
+        * We use slot zero for the linear mapping of physical memory, and
+        * in HIGHPTE kernels, slot 1 and 2 for KM_PTE0 and KM_PTE1.
+        *
+        *  args:                 SLOT                 VA    COUNT PFN
+        */
+       BUG_ON(type != KM_PTE0 && type != KM_PTE1);
+       vmi_ops.set_linear_mapping((type - KM_PTE0)+1, (u32)va, 1, pfn);
+}
+
 static void vmi_allocate_pt(u32 pfn)
 {
        vmi_set_page_type(pfn, VMI_PAGE_L1);
@@ -508,13 +526,14 @@ void vmi_pmd_clear(pmd_t *pmd)
 #endif
 
 #ifdef CONFIG_SMP
-struct vmi_ap_state ap;
 extern void setup_pda(void);
 
-static void __init /* XXX cpu hotplug */
+static void __devinit
 vmi_startup_ipi_hook(int phys_apicid, unsigned long start_eip,
                     unsigned long start_esp)
 {
+       struct vmi_ap_state ap;
+
        /* Default everything to zero.  This is fine for most GPRs. */
        memset(&ap, 0, sizeof(struct vmi_ap_state));
 
@@ -553,7 +572,7 @@ vmi_startup_ipi_hook(int phys_apicid, unsigned long start_eip,
        /* Protected mode, paging, AM, WP, NE, MP. */
        ap.cr0 = 0x80050023;
        ap.cr4 = mmu_cr4_features;
-       vmi_ops.set_initial_ap_state(__pa(&ap), phys_apicid);
+       vmi_ops.set_initial_ap_state((u32)&ap, phys_apicid);
 }
 #endif
 
@@ -645,12 +664,12 @@ static inline int __init probe_vmi_rom(void)
 void vmi_bringup(void)
 {
        /* We must establish the lowmem mapping for MMU ops to work */
-       if (vmi_rom)
+       if (vmi_ops.set_linear_mapping)
                vmi_ops.set_linear_mapping(0, __PAGE_OFFSET, max_low_pfn, 0);
 }
 
 /*
- * Return a pointer to the VMI function or a NOP stub
+ * Return a pointer to a VMI function or NULL if unimplemented
  */
 static void *vmi_get_function(int vmicall)
 {
@@ -661,12 +680,13 @@ static void *vmi_get_function(int vmicall)
        if (rel->type == VMI_RELOCATION_CALL_REL)
                return (void *)rel->eip;
        else
-               return (void *)vmi_nop;
+               return NULL;
 }
 
 /*
  * Helper macro for making the VMI paravirt-ops fill code readable.
- * For unimplemented operations, fall back to default.
+ * For unimplemented operations, fall back to default, unless nop
+ * is returned by the ROM.
  */
 #define para_fill(opname, vmicall)                             \
 do {                                                           \
@@ -675,9 +695,29 @@ do {                                                               \
        if (rel->type != VMI_RELOCATION_NONE) {                 \
                BUG_ON(rel->type != VMI_RELOCATION_CALL_REL);   \
                paravirt_ops.opname = (void *)rel->eip;         \
+       } else if (rel->type == VMI_RELOCATION_NOP)             \
+               paravirt_ops.opname = (void *)vmi_nop;          \
+} while (0)
+
+/*
+ * Helper macro for making the VMI paravirt-ops fill code readable.
+ * For cached operations which do not match the VMI ROM ABI and must
+ * go through a tranlation stub.  Ignore NOPs, since it is not clear
+ * a NOP * VMI function corresponds to a NOP paravirt-op when the
+ * functions are not in 1-1 correspondence.
+ */
+#define para_wrap(opname, wrapper, cache, vmicall)             \
+do {                                                           \
+       reloc = call_vrom_long_func(vmi_rom, get_reloc,         \
+                                   VMI_CALL_##vmicall);        \
+       BUG_ON(rel->type == VMI_RELOCATION_JUMP_REL);           \
+       if (rel->type == VMI_RELOCATION_CALL_REL) {             \
+               paravirt_ops.opname = wrapper;                  \
+               vmi_ops.cache = (void *)rel->eip;               \
        }                                                       \
 } while (0)
 
+
 /*
  * Activate the VMI interface and switch into paravirtualized mode
  */
@@ -714,13 +754,8 @@ static inline int __init activate_vmi(void)
         *  rdpmc is not yet used in Linux
         */
 
-       /* CPUID is special, so very special */
-       reloc = call_vrom_long_func(vmi_rom, get_reloc, VMI_CALL_CPUID);
-       if (rel->type != VMI_RELOCATION_NONE) {
-               BUG_ON(rel->type != VMI_RELOCATION_CALL_REL);
-               vmi_ops.cpuid = (void *)rel->eip;
-               paravirt_ops.cpuid = vmi_cpuid;
-       }
+       /* CPUID is special, so very special it gets wrapped like a present */
+       para_wrap(cpuid, vmi_cpuid, cpuid, CPUID);
 
        para_fill(clts, CLTS);
        para_fill(get_debugreg, GetDR);
@@ -737,38 +772,26 @@ static inline int __init activate_vmi(void)
        para_fill(restore_fl, SetInterruptMask);
        para_fill(irq_disable, DisableInterrupts);
        para_fill(irq_enable, EnableInterrupts);
+
        /* irq_save_disable !!! sheer pain */
        patch_offset(&irq_save_disable_callout[IRQ_PATCH_INT_MASK],
                     (char *)paravirt_ops.save_fl);
        patch_offset(&irq_save_disable_callout[IRQ_PATCH_DISABLE],
                     (char *)paravirt_ops.irq_disable);
-#ifndef CONFIG_NO_IDLE_HZ
-       para_fill(safe_halt, Halt);
-#else
-       vmi_ops.halt = vmi_get_function(VMI_CALL_Halt);
-       paravirt_ops.safe_halt = vmi_safe_halt;
-#endif
+
        para_fill(wbinvd, WBINVD);
+       para_fill(read_tsc, RDTSC);
+
+       /* The following we emulate with trap and emulate for now */
        /* paravirt_ops.read_msr = vmi_rdmsr */
        /* paravirt_ops.write_msr = vmi_wrmsr */
-       para_fill(read_tsc, RDTSC);
        /* paravirt_ops.rdpmc = vmi_rdpmc */
 
-       /* TR interface doesn't pass TR value */
-       reloc = call_vrom_long_func(vmi_rom, get_reloc, VMI_CALL_SetTR);
-       if (rel->type != VMI_RELOCATION_NONE) {
-               BUG_ON(rel->type != VMI_RELOCATION_CALL_REL);
-               vmi_ops.set_tr = (void *)rel->eip;
-               paravirt_ops.load_tr_desc = vmi_set_tr;
-       }
+       /* TR interface doesn't pass TR value, wrap */
+       para_wrap(load_tr_desc, vmi_set_tr, set_tr, SetTR);
 
        /* LDT is special, too */
-       reloc = call_vrom_long_func(vmi_rom, get_reloc, VMI_CALL_SetLDT);
-       if (rel->type != VMI_RELOCATION_NONE) {
-               BUG_ON(rel->type != VMI_RELOCATION_CALL_REL);
-               vmi_ops._set_ldt = (void *)rel->eip;
-               paravirt_ops.set_ldt = vmi_set_ldt;
-       }
+       para_wrap(set_ldt, vmi_set_ldt, _set_ldt, SetLDT);
 
        para_fill(load_gdt, SetGDT);
        para_fill(load_idt, SetIDT);
@@ -779,28 +802,14 @@ static inline int __init activate_vmi(void)
        para_fill(write_ldt_entry, WriteLDTEntry);
        para_fill(write_gdt_entry, WriteGDTEntry);
        para_fill(write_idt_entry, WriteIDTEntry);
-       reloc = call_vrom_long_func(vmi_rom, get_reloc,
-                                   VMI_CALL_UpdateKernelStack);
-       if (rel->type != VMI_RELOCATION_NONE) {
-               BUG_ON(rel->type != VMI_RELOCATION_CALL_REL);
-               vmi_ops.set_kernel_stack = (void *)rel->eip;
-               paravirt_ops.load_esp0 = vmi_load_esp0;
-       }
-
+       para_wrap(load_esp0, vmi_load_esp0, set_kernel_stack, UpdateKernelStack);
        para_fill(set_iopl_mask, SetIOPLMask);
-       paravirt_ops.io_delay = (void *)vmi_nop;
-       if (!disable_nodelay) {
-               paravirt_ops.const_udelay = (void *)vmi_nop;
-       }
-
+       para_fill(io_delay, IODelay);
        para_fill(set_lazy_mode, SetLazyMode);
 
-       reloc = call_vrom_long_func(vmi_rom, get_reloc, VMI_CALL_FlushTLB);
-       if (rel->type != VMI_RELOCATION_NONE) {
-               vmi_ops.flush_tlb = (void *)rel->eip;
-               paravirt_ops.flush_tlb_user = vmi_flush_tlb_user;
-               paravirt_ops.flush_tlb_kernel = vmi_flush_tlb_kernel;
-       }
+       /* user and kernel flush are just handled with different flags to FlushTLB */
+       para_wrap(flush_tlb_user, vmi_flush_tlb_user, flush_tlb, FlushTLB);
+       para_wrap(flush_tlb_kernel, vmi_flush_tlb_kernel, flush_tlb, FlushTLB);
        para_fill(flush_tlb_single, InvalPage);
 
        /*
@@ -815,27 +824,40 @@ static inline int __init activate_vmi(void)
        vmi_ops.set_pte = vmi_get_function(VMI_CALL_SetPxE);
        vmi_ops.update_pte = vmi_get_function(VMI_CALL_UpdatePxE);
 #endif
-       vmi_ops.set_linear_mapping = vmi_get_function(VMI_CALL_SetLinearMapping);
-       vmi_ops.allocate_page = vmi_get_function(VMI_CALL_AllocatePage);
-       vmi_ops.release_page = vmi_get_function(VMI_CALL_ReleasePage);
 
-       paravirt_ops.alloc_pt = vmi_allocate_pt;
-       paravirt_ops.alloc_pd = vmi_allocate_pd;
-       paravirt_ops.alloc_pd_clone = vmi_allocate_pd_clone;
-       paravirt_ops.release_pt = vmi_release_pt;
-       paravirt_ops.release_pd = vmi_release_pd;
-       paravirt_ops.set_pte = vmi_set_pte;
-       paravirt_ops.set_pte_at = vmi_set_pte_at;
-       paravirt_ops.set_pmd = vmi_set_pmd;
-       paravirt_ops.pte_update = vmi_update_pte;
-       paravirt_ops.pte_update_defer = vmi_update_pte_defer;
+       if (vmi_ops.set_pte) {
+               paravirt_ops.set_pte = vmi_set_pte;
+               paravirt_ops.set_pte_at = vmi_set_pte_at;
+               paravirt_ops.set_pmd = vmi_set_pmd;
 #ifdef CONFIG_X86_PAE
-       paravirt_ops.set_pte_atomic = vmi_set_pte_atomic;
-       paravirt_ops.set_pte_present = vmi_set_pte_present;
-       paravirt_ops.set_pud = vmi_set_pud;
-       paravirt_ops.pte_clear = vmi_pte_clear;
-       paravirt_ops.pmd_clear = vmi_pmd_clear;
+               paravirt_ops.set_pte_atomic = vmi_set_pte_atomic;
+               paravirt_ops.set_pte_present = vmi_set_pte_present;
+               paravirt_ops.set_pud = vmi_set_pud;
+               paravirt_ops.pte_clear = vmi_pte_clear;
+               paravirt_ops.pmd_clear = vmi_pmd_clear;
 #endif
+       }
+
+       if (vmi_ops.update_pte) {
+               paravirt_ops.pte_update = vmi_update_pte;
+               paravirt_ops.pte_update_defer = vmi_update_pte_defer;
+       }
+
+       vmi_ops.allocate_page = vmi_get_function(VMI_CALL_AllocatePage);
+       if (vmi_ops.allocate_page) {
+               paravirt_ops.alloc_pt = vmi_allocate_pt;
+               paravirt_ops.alloc_pd = vmi_allocate_pd;
+               paravirt_ops.alloc_pd_clone = vmi_allocate_pd_clone;
+       }
+
+       vmi_ops.release_page = vmi_get_function(VMI_CALL_ReleasePage);
+       if (vmi_ops.release_page) {
+               paravirt_ops.release_pt = vmi_release_pt;
+               paravirt_ops.release_pd = vmi_release_pd;
+       }
+       para_wrap(map_pt_hook, vmi_map_pt_hook, set_linear_mapping,
+                 SetLinearMapping);
+
        /*
         * These MUST always be patched.  Don't support indirect jumps
         * through these operations, as the VMI interface may use either
@@ -847,21 +869,20 @@ static inline int __init activate_vmi(void)
        paravirt_ops.iret = (void *)0xbadbab0;
 
 #ifdef CONFIG_SMP
-       paravirt_ops.startup_ipi_hook = vmi_startup_ipi_hook;
-       vmi_ops.set_initial_ap_state = vmi_get_function(VMI_CALL_SetInitialAPState);
+       para_wrap(startup_ipi_hook, vmi_startup_ipi_hook, set_initial_ap_state, SetInitialAPState);
 #endif
 
 #ifdef CONFIG_X86_LOCAL_APIC
-       paravirt_ops.apic_read = vmi_get_function(VMI_CALL_APICRead);
-       paravirt_ops.apic_write = vmi_get_function(VMI_CALL_APICWrite);
-       paravirt_ops.apic_write_atomic = vmi_get_function(VMI_CALL_APICWrite);
+       para_fill(apic_read, APICRead);
+       para_fill(apic_write, APICWrite);
+       para_fill(apic_write_atomic, APICWrite);
 #endif
 
        /*
         * Check for VMI timer functionality by probing for a cycle frequency method
         */
        reloc = call_vrom_long_func(vmi_rom, get_reloc, VMI_CALL_GetCycleFrequency);
-       if (rel->type != VMI_RELOCATION_NONE) {
+       if (!disable_vmi_timer && rel->type != VMI_RELOCATION_NONE) {
                vmi_timer_ops.get_cycle_frequency = (void *)rel->eip;
                vmi_timer_ops.get_cycle_counter =
                        vmi_get_function(VMI_CALL_GetCycleCounter);
@@ -879,9 +900,22 @@ static inline int __init activate_vmi(void)
                paravirt_ops.setup_boot_clock = vmi_timer_setup_boot_alarm;
                paravirt_ops.setup_secondary_clock = vmi_timer_setup_secondary_alarm;
 #endif
-               custom_sched_clock = vmi_sched_clock;
+               paravirt_ops.get_scheduled_cycles = vmi_get_sched_cycles;
+               paravirt_ops.get_cpu_khz = vmi_cpu_khz;
+
+               /* We have true wallclock functions; disable CMOS clock sync */
+               no_sync_cmos_clock = 1;
+       } else {
+               disable_noidle = 1;
+               disable_vmi_timer = 1;
        }
 
+       /* No idle HZ mode only works if VMI timer and no idle is enabled */
+       if (disable_noidle || disable_vmi_timer)
+               para_fill(safe_halt, Halt);
+       else
+               para_wrap(safe_halt, vmi_safe_halt, halt, Halt);
+
        /*
         * Alternative instruction rewriting doesn't happen soon enough
         * to convert VMI_IRET to a call instead of a jump; so we have
@@ -914,7 +948,9 @@ void __init vmi_init(void)
 
        local_irq_save(flags);
        activate_vmi();
-#ifdef CONFIG_SMP
+
+#ifdef CONFIG_X86_IO_APIC
+       /* This is virtual hardware; timer routing is wired correctly */
        no_timer_check = 1;
 #endif
        local_irq_restore(flags & X86_EFLAGS_IF);
@@ -925,9 +961,7 @@ static int __init parse_vmi(char *arg)
        if (!arg)
                return -EINVAL;
 
-       if (!strcmp(arg, "disable_nodelay"))
-               disable_nodelay = 1;
-       else if (!strcmp(arg, "disable_pge")) {
+       if (!strcmp(arg, "disable_pge")) {
                clear_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability);
                disable_pge = 1;
        } else if (!strcmp(arg, "disable_pse")) {
@@ -942,7 +976,11 @@ static int __init parse_vmi(char *arg)
        } else if (!strcmp(arg, "disable_mtrr")) {
                clear_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability);
                disable_mtrr = 1;
-       }
+       } else if (!strcmp(arg, "disable_timer")) {
+               disable_vmi_timer = 1;
+               disable_noidle = 1;
+       } else if (!strcmp(arg, "disable_noidle"))
+               disable_noidle = 1;
        return 0;
 }
 
index 76d2adcae5a30b74ed5505544cf5c0b45d89e427..9dfb17739b67743d13470f7b3c2893b2fd8d2e7c 100644 (file)
@@ -123,12 +123,10 @@ static struct clocksource clocksource_vmi = {
 static irqreturn_t vmi_timer_interrupt(int irq, void *dev_id);
 
 static struct irqaction vmi_timer_irq  = {
-       vmi_timer_interrupt,
-       SA_INTERRUPT,
-       CPU_MASK_NONE,
-       "VMI-alarm",
-       NULL,
-       NULL
+       .handler = vmi_timer_interrupt,
+       .flags = IRQF_DISABLED,
+       .mask = CPU_MASK_NONE,
+       .name = "VMI-alarm",
 };
 
 /* Alarm rate */
@@ -153,13 +151,6 @@ static void vmi_get_wallclock_ts(struct timespec *ts)
        ts->tv_sec = wallclock;
 }
 
-static void update_xtime_from_wallclock(void)
-{
-       struct timespec ts;
-       vmi_get_wallclock_ts(&ts);
-       do_settimeofday(&ts);
-}
-
 unsigned long vmi_get_wallclock(void)
 {
        struct timespec ts;
@@ -172,11 +163,20 @@ int vmi_set_wallclock(unsigned long now)
        return -1;
 }
 
-unsigned long long vmi_sched_clock(void)
+unsigned long long vmi_get_sched_cycles(void)
 {
        return read_available_cycles();
 }
 
+unsigned long vmi_cpu_khz(void)
+{
+       unsigned long long khz;
+
+       khz = vmi_timer_ops.get_cycle_frequency();
+       (void)do_div(khz, 1000);
+       return khz;
+}
+
 void __init vmi_time_init(void)
 {
        unsigned long long cycles_per_sec, cycles_per_msec;
@@ -188,25 +188,16 @@ void __init vmi_time_init(void)
        set_intr_gate(LOCAL_TIMER_VECTOR, apic_vmi_timer_interrupt);
 #endif
 
-       no_sync_cmos_clock = 1;
-
-       vmi_get_wallclock_ts(&xtime);
-       set_normalized_timespec(&wall_to_monotonic,
-               -xtime.tv_sec, -xtime.tv_nsec);
-
        real_cycles_accounted_system = read_real_cycles();
-       update_xtime_from_wallclock();
        per_cpu(process_times_cycles_accounted_cpu, 0) = read_available_cycles();
 
        cycles_per_sec = vmi_timer_ops.get_cycle_frequency();
-
        cycles_per_jiffy = cycles_per_sec;
        (void)do_div(cycles_per_jiffy, HZ);
        cycles_per_alarm = cycles_per_sec;
        (void)do_div(cycles_per_alarm, alarm_hz);
        cycles_per_msec = cycles_per_sec;
        (void)do_div(cycles_per_msec, 1000);
-       cpu_khz = cycles_per_msec;
 
        printk(KERN_WARNING "VMI timer cycles/sec = %llu ; cycles/jiffy = %llu ;"
               "cycles/alarm = %llu\n", cycles_per_sec, cycles_per_jiffy,
@@ -250,7 +241,7 @@ void __init vmi_timer_setup_boot_alarm(void)
 
 /* Initialize the time accounting variables for an AP on an SMP system.
  * Also, set the local alarm for the AP. */
-void __init vmi_timer_setup_secondary_alarm(void)
+void __devinit vmi_timer_setup_secondary_alarm(void)
 {
        int cpu = smp_processor_id();
 
@@ -276,16 +267,13 @@ static void vmi_account_real_cycles(unsigned long long cur_real_cycles)
 
        cycles_not_accounted = cur_real_cycles - real_cycles_accounted_system;
        while (cycles_not_accounted >= cycles_per_jiffy) {
-               /* systems wide jiffies and wallclock. */
+               /* systems wide jiffies. */
                do_timer(1);
 
                cycles_not_accounted -= cycles_per_jiffy;
                real_cycles_accounted_system += cycles_per_jiffy;
        }
 
-       if (vmi_timer_ops.wallclock_updated())
-               update_xtime_from_wallclock();
-
        write_sequnlock(&xtime_lock);
 }
 
@@ -380,7 +368,6 @@ int vmi_stop_hz_timer(void)
        unsigned long seq, next;
        unsigned long long real_cycles_expiry;
        int cpu = smp_processor_id();
-       int idle;
 
        BUG_ON(!irqs_disabled());
        if (sysctl_hz_timer != 0)
@@ -388,13 +375,13 @@ int vmi_stop_hz_timer(void)
 
        cpu_set(cpu, nohz_cpu_mask);
        smp_mb();
+
        if (rcu_needs_cpu(cpu) || local_softirq_pending() ||
-           (next = next_timer_interrupt(), time_before_eq(next, jiffies))) {
+           (next = next_timer_interrupt(),
+            time_before_eq(next, jiffies + HZ/CONFIG_VMI_ALARM_HZ))) {
                cpu_clear(cpu, nohz_cpu_mask);
-               next = jiffies;
-               idle = 0;
-       } else
-               idle = 1;
+               return 0;
+       }
 
        /* Convert jiffies to the real cycle counter. */
        do {
@@ -404,17 +391,13 @@ int vmi_stop_hz_timer(void)
        } while (read_seqretry(&xtime_lock, seq));
 
        /* This cpu is going idle. Disable the periodic alarm. */
-       if (idle) {
-               vmi_timer_ops.cancel_alarm(VMI_CYCLES_AVAILABLE);
-               per_cpu(idle_start_jiffies, cpu) = jiffies;
-       }
-
+       vmi_timer_ops.cancel_alarm(VMI_CYCLES_AVAILABLE);
+       per_cpu(idle_start_jiffies, cpu) = jiffies;
        /* Set the real time alarm to expire at the next event. */
        vmi_timer_ops.set_alarm(
-                     VMI_ALARM_WIRING | VMI_ALARM_IS_ONESHOT | VMI_CYCLES_REAL,
-                     real_cycles_expiry, 0);
-
-       return idle;
+               VMI_ALARM_WIRING | VMI_ALARM_IS_ONESHOT | VMI_CYCLES_REAL,
+               real_cycles_expiry, 0);
+       return 1;
 }
 
 static void vmi_reenable_hz_timer(int cpu)
index d86a548b8d543af5958961ccce281b83b3e15d6c..22d8ac5815f03475c6abb7376d7994e92fa57a51 100644 (file)
@@ -7,3 +7,5 @@ lib-y = checksum.o delay.o usercopy.o getuser.o putuser.o memcpy.o strstr.o \
        bitops.o semaphore.o
 
 lib-$(CONFIG_X86_USE_3DNOW) += mmx.o
+
+obj-$(CONFIG_SMP)      += msr-on-cpu.o
diff --git a/arch/i386/lib/msr-on-cpu.c b/arch/i386/lib/msr-on-cpu.c
new file mode 100644 (file)
index 0000000..1c46bda
--- /dev/null
@@ -0,0 +1,58 @@
+#include <linux/module.h>
+#include <linux/preempt.h>
+#include <linux/smp.h>
+#include <asm/msr.h>
+
+struct msr_info {
+       u32 msr_no;
+       u32 l, h;
+};
+
+static void __rdmsr_on_cpu(void *info)
+{
+       struct msr_info *rv = info;
+
+       rdmsr(rv->msr_no, rv->l, rv->h);
+}
+
+void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
+{
+       preempt_disable();
+       if (smp_processor_id() == cpu)
+               rdmsr(msr_no, *l, *h);
+       else {
+               struct msr_info rv;
+
+               rv.msr_no = msr_no;
+               smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 0, 1);
+               *l = rv.l;
+               *h = rv.h;
+       }
+       preempt_enable();
+}
+
+static void __wrmsr_on_cpu(void *info)
+{
+       struct msr_info *rv = info;
+
+       wrmsr(rv->msr_no, rv->l, rv->h);
+}
+
+void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
+{
+       preempt_disable();
+       if (smp_processor_id() == cpu)
+               wrmsr(msr_no, l, h);
+       else {
+               struct msr_info rv;
+
+               rv.msr_no = msr_no;
+               rv.l = l;
+               rv.h = h;
+               smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 0, 1);
+       }
+       preempt_enable();
+}
+
+EXPORT_SYMBOL(rdmsr_on_cpu);
+EXPORT_SYMBOL(wrmsr_on_cpu);
index 9d1cffb57cde20c3f143a529b8bd5a2d6cf114a5..a1446931b401ef54889bdd0028e37b56cf720bd0 100644 (file)
@@ -1,8 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc5
-# Mon Feb 27 15:49:18 2006
+# Linux kernel version: 2.6.21-rc3
+# Thu Mar  8 11:07:09 2007
 #
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
@@ -18,16 +19,24 @@ CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -39,11 +48,9 @@ CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -54,7 +61,6 @@ CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -63,6 +69,8 @@ CONFIG_STOP_MACHINE=y
 #
 # Block layer
 #
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -82,15 +90,20 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
 #
 CONFIG_IA64=y
 CONFIG_64BIT=y
+CONFIG_ZONE_DMA=y
 CONFIG_MMU=y
 CONFIG_SWIOTLB=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_TIME_INTERPOLATION=y
+CONFIG_DMI=y
 CONFIG_EFI=y
 CONFIG_GENERIC_IOMAP=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-CONFIG_DMA_IS_DMA32=y
+CONFIG_AUDIT_ARCH=y
 # CONFIG_IA64_GENERIC is not set
 CONFIG_IA64_DIG=y
 # CONFIG_IA64_HP_ZX1 is not set
@@ -107,6 +120,7 @@ CONFIG_PGTABLE_3=y
 # CONFIG_PGTABLE_4 is not set
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 CONFIG_IA64_L1_CACHE_SHIFT=7
@@ -116,9 +130,10 @@ CONFIG_FORCE_MAX_ZONEORDER=17
 CONFIG_SMP=y
 CONFIG_NR_CPUS=16
 CONFIG_HOTPLUG_CPU=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+# CONFIG_SCHED_SMT is not set
 CONFIG_PERMIT_BSP_REMOVE=y
 CONFIG_FORCE_CPEI_RETARGET=y
-# CONFIG_SCHED_SMT is not set
 # CONFIG_PREEMPT is not set
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -128,10 +143,13 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_VIRTUAL_MEM_MAP=y
 CONFIG_HOLES_IN_ZONE=y
 CONFIG_IA32_SUPPORT=y
@@ -139,6 +157,9 @@ CONFIG_COMPAT=y
 CONFIG_IA64_MCA_RECOVERY=y
 CONFIG_PERFMON=y
 CONFIG_IA64_PALINFO=y
+# CONFIG_IA64_ESI is not set
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
 
 #
 # Firmware Drivers
@@ -154,13 +175,16 @@ CONFIG_BINFMT_MISC=m
 CONFIG_PM=y
 CONFIG_PM_LEGACY=y
 # CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
 
 #
 # ACPI (Advanced Configuration and Power Interface) Support
 #
 CONFIG_ACPI=y
+CONFIG_ACPI_PROCFS=y
 CONFIG_ACPI_BUTTON=m
 CONFIG_ACPI_FAN=m
+# CONFIG_ACPI_DOCK is not set
 CONFIG_ACPI_PROCESSOR=m
 CONFIG_ACPI_HOTPLUG_CPU=y
 CONFIG_ACPI_THERMAL=m
@@ -181,8 +205,8 @@ CONFIG_ACPI_CONTAINER=m
 #
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
 # CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY_PROC=y
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -212,6 +236,10 @@ CONFIG_NET=y
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -226,12 +254,21 @@ CONFIG_SYN_COOKIES=y
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
 # 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_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -257,7 +294,6 @@ CONFIG_TCP_CONG_BIC=y
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 
@@ -286,6 +322,8 @@ CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=m
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
@@ -329,10 +367,16 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
+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
 #
@@ -350,6 +394,7 @@ CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 CONFIG_BLK_DEV_IDEFLOPPY=y
 CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_BLK_DEV_IDEACPI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
 
 #
@@ -376,8 +421,10 @@ CONFIG_BLK_DEV_CMD64X=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=y
+# CONFIG_BLK_DEV_IT8213 is not set
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -387,6 +434,7 @@ CONFIG_BLK_DEV_PIIX=y
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -398,6 +446,8 @@ CONFIG_IDEDMA_AUTO=y
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -417,14 +467,16 @@ CONFIG_CHR_DEV_SG=m
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=y
 # CONFIG_SCSI_ISCSI_ATTRS is not set
 # CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
 
 #
 # SCSI low-level drivers
@@ -437,29 +489,36 @@ CONFIG_SCSI_FC_ATTRS=y
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
 CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_IPR is not set
-CONFIG_SCSI_QLOGIC_FC=y
-# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
+CONFIG_SCSI_SYM53C8XX_MMIO=y
 CONFIG_SCSI_QLOGIC_1280=y
 # CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
 # CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -470,11 +529,11 @@ CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
 CONFIG_MD_RAID1=m
 # CONFIG_MD_RAID10 is not set
-CONFIG_MD_RAID5=m
-CONFIG_MD_RAID6=m
+# CONFIG_MD_RAID456 is not set
 CONFIG_MD_MULTIPATH=m
 # CONFIG_MD_FAULTY is not set
 CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
@@ -563,6 +622,7 @@ CONFIG_E100=m
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -583,13 +643,18 @@ CONFIG_E1000=y
 # CONFIG_VIA_VELOCITY is not set
 CONFIG_TIGON3=y
 # CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -631,6 +696,7 @@ CONFIG_NET_POLL_CONTROLLER=y
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -653,6 +719,7 @@ CONFIG_KEYBOARD_ATKBD=y
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 # CONFIG_MOUSE_SERIAL is not set
@@ -682,6 +749,7 @@ CONFIG_GAMEPORT=m
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
 CONFIG_SERIAL_NONSTANDARD=y
 # CONFIG_COMPUTONE is not set
 # CONFIG_ROCKETPORT is not set
@@ -689,12 +757,14 @@ CONFIG_SERIAL_NONSTANDARD=y
 # CONFIG_DIGIEPCA is not set
 # CONFIG_MOXA_INTELLIO is not set
 # CONFIG_MOXA_SMARTIO is not set
+# CONFIG_MOXA_SMARTIO_NEW is not set
 # CONFIG_ISI is not set
 # CONFIG_SYNCLINKMP is not set
 # CONFIG_SYNCLINK_GT is not set
 # CONFIG_N_HDLC is not set
 # CONFIG_SPECIALIX is not set
 # CONFIG_SX is not set
+# CONFIG_RIO is not set
 # CONFIG_STALDRV is not set
 
 #
@@ -702,7 +772,8 @@ CONFIG_SERIAL_NONSTANDARD=y
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_ACPI=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
 CONFIG_SERIAL_8250_NR_UARTS=6
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 CONFIG_SERIAL_8250_EXTENDED=y
@@ -734,10 +805,6 @@ CONFIG_EFI_RTC=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 CONFIG_AGP=m
 CONFIG_AGP_I460=m
 CONFIG_DRM=m
@@ -759,7 +826,6 @@ CONFIG_HPET_MMAP=y
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -782,16 +848,16 @@ CONFIG_HPET_MMAP=y
 #
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_VT1211 is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
-# Misc devices
-#
-
-#
-# Multimedia Capabilities Port drivers
+# Multifunction device drivers
 #
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
@@ -802,16 +868,19 @@ CONFIG_HWMON=y
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
 #
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 # CONFIG_FB is not set
 
 #
 # Console display driver support
 #
 CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
 CONFIG_DUMMY_CONSOLE=y
 
 #
@@ -819,11 +888,18 @@ CONFIG_DUMMY_CONSOLE=y
 #
 # CONFIG_SOUND is not set
 
+#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
 #
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -831,7 +907,6 @@ CONFIG_USB=y
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
@@ -842,9 +917,12 @@ CONFIG_USB_DEVICEFS=y
 CONFIG_USB_EHCI_HCD=m
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=m
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 CONFIG_USB_UHCI_HCD=y
 # CONFIG_USB_SL811_HCD is not set
@@ -873,13 +951,13 @@ CONFIG_USB_STORAGE=m
 # CONFIG_USB_STORAGE_SDDR55 is not set
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
 # CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
 # USB Input Devices
 #
 CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_HIDINPUT_POWERBOOK is not set
 # CONFIG_HID_FF is not set
 # CONFIG_USB_HIDDEV is not set
@@ -888,15 +966,14 @@ CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
 # CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
 # CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
 
 #
 # USB Imaging devices
@@ -904,15 +981,6 @@ CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
 
-#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
 #
 # USB Network Adapters
 #
@@ -920,6 +988,7 @@ CONFIG_USB_HIDINPUT=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
 
@@ -937,17 +1006,23 @@ CONFIG_USB_HIDINPUT=y
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
 # CONFIG_USB_AUERSWALD is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -964,15 +1039,55 @@ CONFIG_USB_HIDINPUT=y
 #
 # CONFIG_MMC is not set
 
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
 #
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# EDAC - error detection and reporting (RAS)
+# 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
+#
+
+#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+# CONFIG_MSPEC is not set
+
 #
 # File systems
 #
@@ -985,6 +1100,7 @@ CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -997,15 +1113,16 @@ CONFIG_REISERFS_FS_SECURITY=y
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 CONFIG_XFS_FS=y
-CONFIG_XFS_EXPORT=y
 # CONFIG_XFS_QUOTA is not set
 # CONFIG_XFS_SECURITY is not set
 # CONFIG_XFS_POSIX_ACL is not set
 # CONFIG_XFS_RT is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=y
@@ -1038,12 +1155,13 @@ CONFIG_NTFS_FS=m
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1078,7 +1196,7 @@ CONFIG_NFSD_V4=y
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=m
 CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
+CONFIG_EXPORTFS=m
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
@@ -1089,7 +1207,9 @@ CONFIG_SMB_NLS_DEFAULT=y
 CONFIG_SMB_NLS_REMOTE="cp437"
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
 # CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_CIFS_EXPERIMENTAL is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
@@ -1161,16 +1281,26 @@ CONFIG_NLS_KOI8_R=m
 CONFIG_NLS_KOI8_U=m
 CONFIG_NLS_UTF8=m
 
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_IRQ_PER_CPU=y
 
 #
 # Instrumentation Support
@@ -1182,21 +1312,31 @@ CONFIG_GENERIC_PENDING_IRQ=y
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_LOG_BUF_SHIFT=20
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
-CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
 CONFIG_IA64_GRANULE_16MB=y
 # CONFIG_IA64_GRANULE_64MB is not set
 # CONFIG_IA64_PRINT_HAZARDS is not set
@@ -1215,7 +1355,11 @@ CONFIG_SYSVIPC_COMPAT=y
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_MANAGER=m
 # CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=y
@@ -1224,7 +1368,13 @@ CONFIG_CRYPTO_MD5=y
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
 CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
@@ -1238,6 +1388,7 @@ CONFIG_CRYPTO_DES=m
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
 # CONFIG_CRYPTO_TEST is not set
 
 #
index 949dc4670a0cd333c3c50df911be2c67d44bae69..1c7955c163588110be1d8d70c584238aac4d7404 100644 (file)
@@ -1,8 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc5
-# Mon Feb 27 15:55:36 2006
+# Linux kernel version: 2.6.21-rc3
+# Thu Mar  8 11:04:20 2007
 #
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
@@ -18,16 +19,24 @@ CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
 # CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -39,11 +48,9 @@ CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -53,14 +60,16 @@ CONFIG_BASE_SMALL=0
 #
 CONFIG_MODULES=y
 # CONFIG_MODULE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 # CONFIG_KMOD is not set
+CONFIG_STOP_MACHINE=y
 
 #
 # Block layer
 #
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -80,15 +89,19 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
 #
 CONFIG_IA64=y
 CONFIG_64BIT=y
+CONFIG_ZONE_DMA=y
 CONFIG_MMU=y
-CONFIG_SWIOTLB=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_TIME_INTERPOLATION=y
+CONFIG_DMI=y
 CONFIG_EFI=y
 CONFIG_GENERIC_IOMAP=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-CONFIG_DMA_IS_DMA32=y
+CONFIG_AUDIT_ARCH=y
 # CONFIG_IA64_GENERIC is not set
 # CONFIG_IA64_DIG is not set
 CONFIG_IA64_HP_ZX1=y
@@ -105,6 +118,7 @@ CONFIG_PGTABLE_3=y
 # CONFIG_PGTABLE_4 is not set
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 CONFIG_IA64_L1_CACHE_SHIFT=7
@@ -113,8 +127,10 @@ CONFIG_IOSAPIC=y
 CONFIG_FORCE_MAX_ZONEORDER=17
 CONFIG_SMP=y
 CONFIG_NR_CPUS=16
-# CONFIG_HOTPLUG_CPU is not set
+CONFIG_HOTPLUG_CPU=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 # CONFIG_SCHED_SMT is not set
+# CONFIG_PERMIT_BSP_REMOVE is not set
 # CONFIG_PREEMPT is not set
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -124,11 +140,14 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_ARCH_SPARSEMEM_ENABLE=y
 CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_VIRTUAL_MEM_MAP=y
 CONFIG_HOLES_IN_ZONE=y
 CONFIG_IA32_SUPPORT=y
@@ -136,6 +155,9 @@ CONFIG_COMPAT=y
 CONFIG_IA64_MCA_RECOVERY=y
 CONFIG_PERFMON=y
 CONFIG_IA64_PALINFO=y
+# CONFIG_IA64_ESI is not set
+# CONFIG_KEXEC is not set
+CONFIG_CRASH_DUMP=y
 
 #
 # Firmware Drivers
@@ -151,21 +173,25 @@ CONFIG_BINFMT_MISC=y
 CONFIG_PM=y
 CONFIG_PM_LEGACY=y
 # CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
 
 #
 # ACPI (Advanced Configuration and Power Interface) Support
 #
 CONFIG_ACPI=y
+CONFIG_ACPI_PROCFS=y
 CONFIG_ACPI_BUTTON=y
 CONFIG_ACPI_FAN=y
+# CONFIG_ACPI_DOCK is not set
 CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_HOTPLUG_CPU=y
 CONFIG_ACPI_THERMAL=y
 CONFIG_ACPI_BLACKLIST_YEAR=0
 # CONFIG_ACPI_DEBUG is not set
 CONFIG_ACPI_EC=y
 CONFIG_ACPI_POWER=y
 CONFIG_ACPI_SYSTEM=y
-# CONFIG_ACPI_CONTAINER is not set
+CONFIG_ACPI_CONTAINER=y
 
 #
 # CPU Frequency scaling
@@ -177,8 +203,8 @@ CONFIG_ACPI_SYSTEM=y
 #
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
 # CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY_PROC=y
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -208,6 +234,10 @@ CONFIG_NET=y
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -222,17 +252,26 @@ CONFIG_IP_FIB_HASH=y
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
 # 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_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 
 #
 # IP: Virtual Server Configuration
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -240,14 +279,15 @@ CONFIG_NETFILTER=y
 # Core Netfilter Configuration
 #
 # CONFIG_NETFILTER_NETLINK is not set
-# CONFIG_NF_CONNTRACK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
 # CONFIG_NETFILTER_XTABLES is not set
 
 #
 # IP: Netfilter Configuration
 #
-# CONFIG_IP_NF_CONNTRACK is not set
 # CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
 
 #
 # DCCP Configuration (EXPERIMENTAL)
@@ -272,7 +312,6 @@ CONFIG_NETFILTER=y
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 
@@ -285,6 +324,7 @@ CONFIG_NETFILTER=y
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_TCPPROBE is not set
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
@@ -301,6 +341,8 @@ CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
@@ -344,10 +386,16 @@ CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
+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
 #
@@ -365,6 +413,7 @@ CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_BLK_DEV_IDEACPI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
 
 #
@@ -390,8 +439,10 @@ CONFIG_BLK_DEV_CMD64X=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_IT8213 is not set
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -401,6 +452,7 @@ CONFIG_BLK_DEV_CMD64X=y
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -412,6 +464,8 @@ CONFIG_BLK_DEV_IDEDMA=y
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -431,14 +485,16 @@ CONFIG_CHR_DEV_SG=y
 CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
+# CONFIG_SCSI_SCAN_ASYNC is not set
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=y
 # CONFIG_SCSI_ISCSI_ATTRS is not set
 # CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
 
 #
 # SCSI low-level drivers
@@ -451,28 +507,36 @@ CONFIG_SCSI_FC_ATTRS=y
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
 CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
+CONFIG_SCSI_SYM53C8XX_MMIO=y
 CONFIG_SCSI_QLOGIC_1280=y
 # CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
 # CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -562,6 +626,7 @@ CONFIG_E100=y
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -582,13 +647,18 @@ CONFIG_E1000=y
 # CONFIG_VIA_VELOCITY is not set
 CONFIG_TIGON3=y
 # CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -628,6 +698,7 @@ CONFIG_TIGON3=y
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -666,6 +737,7 @@ CONFIG_SERIO=y
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -673,7 +745,8 @@ CONFIG_HW_CONSOLE=y
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_ACPI=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
 CONFIG_SERIAL_8250_NR_UARTS=8
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 CONFIG_SERIAL_8250_EXTENDED=y
@@ -705,10 +778,6 @@ CONFIG_EFI_RTC=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 CONFIG_AGP=y
 CONFIG_AGP_HP_ZX1=y
 CONFIG_DRM=y
@@ -727,7 +796,6 @@ CONFIG_DRM_RADEON=y
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -754,10 +822,11 @@ CONFIG_I2C_ALGOPCF=y
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_PIIX4 is not set
 # CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PASEMI is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
@@ -776,9 +845,7 @@ CONFIG_I2C_ALGOPCF=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
 # CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
@@ -802,28 +869,31 @@ CONFIG_I2C_ALGOPCF=y
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
-# Multimedia Capabilities Port drivers
+# Multifunction device drivers
 #
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
 #
 CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
 
 #
-# Video For Linux
+# Video Capture Adapters
 #
 
 #
-# Video Adapters
+# Video Capture Adapters
 #
 # CONFIG_VIDEO_ADV_DEBUG is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
 # CONFIG_VIDEO_BT848 is not set
 # CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
 # CONFIG_VIDEO_SAA5246A is not set
 # CONFIG_VIDEO_SAA5249 is not set
 # CONFIG_TUNER_3036 is not set
@@ -835,10 +905,27 @@ CONFIG_VIDEO_DEV=y
 # CONFIG_VIDEO_HEXIUM_ORION is not set
 # CONFIG_VIDEO_HEXIUM_GEMINI is not set
 # CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_CAFE_CCIC is not set
+
+#
+# V4L USB devices
+#
+# CONFIG_VIDEO_PVRUSB2 is not set
 # CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_USBVISION is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_QUICKCAM_MESSENGER is not set
+# CONFIG_USB_ET61X251 is not set
 # CONFIG_VIDEO_OVCAMCHIP is not set
-# CONFIG_VIDEO_AUDIO_DECODER is not set
-# CONFIG_VIDEO_DECODER is not set
+# CONFIG_USB_W9968CF is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_ZC0301 is not set
+# CONFIG_USB_PWC is not set
 
 #
 # Radio Adapters
@@ -846,22 +933,35 @@ CONFIG_VIDEO_DEV=y
 # CONFIG_RADIO_GEMTEK_PCI is not set
 # CONFIG_RADIO_MAXIRADIO is not set
 # CONFIG_RADIO_MAESTRO is not set
+# CONFIG_USB_DSBR is not set
 
 #
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
 #
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
 CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB_DDC=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
+CONFIG_FB_BACKLIGHT=y
 CONFIG_FB_MODE_HELPERS=y
 # CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frambuffer hardware drivers
+#
 # CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
@@ -871,12 +971,13 @@ CONFIG_FB_MODE_HELPERS=y
 # CONFIG_FB_NVIDIA is not set
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
 CONFIG_FB_RADEON=y
 CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
 CONFIG_FB_RADEON_DEBUG=y
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
 # CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
 # CONFIG_FB_NEOMAGIC is not set
@@ -890,6 +991,7 @@ CONFIG_FB_RADEON_DEBUG=y
 # Console display driver support
 #
 CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
@@ -904,7 +1006,6 @@ CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
 # CONFIG_LOGO_LINUX_VGA16 is not set
 CONFIG_LOGO_LINUX_CLUT224=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -924,9 +1025,11 @@ CONFIG_SND_SEQUENCER=y
 CONFIG_SND_OSSEMUL=y
 CONFIG_SND_MIXER_OSS=y
 CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
 CONFIG_SND_SEQUENCER_OSS=y
 # CONFIG_SND_DYNAMIC_MINORS is not set
 CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
 
@@ -936,7 +1039,6 @@ CONFIG_SND_SUPPORT_OLD_API=y
 CONFIG_SND_MPU401_UART=y
 CONFIG_SND_OPL3_LIB=y
 CONFIG_SND_AC97_CODEC=y
-CONFIG_SND_AC97_BUS=y
 # CONFIG_SND_DUMMY is not set
 # CONFIG_SND_VIRMIDI is not set
 # CONFIG_SND_MTPAV is not set
@@ -947,6 +1049,7 @@ CONFIG_SND_AC97_BUS=y
 # PCI devices
 #
 # CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
 # CONFIG_SND_ALI5451 is not set
 # CONFIG_SND_ATIIXP is not set
 # CONFIG_SND_ATIIXP_MODEM is not set
@@ -959,6 +1062,18 @@ CONFIG_SND_AC97_BUS=y
 # CONFIG_SND_CMIPCI is not set
 # CONFIG_SND_CS4281 is not set
 # CONFIG_SND_CS46XX is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
 # CONFIG_SND_EMU10K1 is not set
 # CONFIG_SND_EMU10K1X is not set
 # CONFIG_SND_ENS1370 is not set
@@ -966,7 +1081,7 @@ CONFIG_SND_AC97_BUS=y
 # CONFIG_SND_ES1938 is not set
 # CONFIG_SND_ES1968 is not set
 CONFIG_SND_FM801=y
-CONFIG_SND_FM801_TEA575X=y
+# CONFIG_SND_FM801_TEA575X_BOOL is not set
 # CONFIG_SND_HDA_INTEL is not set
 # CONFIG_SND_HDSP is not set
 # CONFIG_SND_HDSPM is not set
@@ -979,6 +1094,7 @@ CONFIG_SND_FM801_TEA575X=y
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
 # CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
 # CONFIG_SND_RME32 is not set
 # CONFIG_SND_RME96 is not set
 # CONFIG_SND_RME9652 is not set
@@ -988,22 +1104,36 @@ CONFIG_SND_FM801_TEA575X=y
 # CONFIG_SND_VIA82XX_MODEM is not set
 # CONFIG_SND_VX222 is not set
 # CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_AC97_POWER_SAVE is not set
 
 #
 # USB devices
 #
 # CONFIG_SND_USB_AUDIO is not set
 
+#
+# SoC audio support
+#
+# CONFIG_SND_SOC is not set
+
 #
 # Open Sound System
 #
 # CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=y
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
 
 #
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -1011,7 +1141,6 @@ CONFIG_USB=y
 # Miscellaneous USB options
 #
 # CONFIG_USB_DEVICEFS is not set
-CONFIG_USB_BANDWIDTH=y
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
@@ -1022,9 +1151,12 @@ CONFIG_USB_BANDWIDTH=y
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 CONFIG_USB_UHCI_HCD=y
 # CONFIG_USB_SL811_HCD is not set
@@ -1032,7 +1164,6 @@ CONFIG_USB_UHCI_HCD=y
 #
 # USB Device Class drivers
 #
-# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
 
@@ -1054,13 +1185,13 @@ CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_SDDR55 is not set
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
 # CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
 # USB Input Devices
 #
 CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_HIDINPUT_POWERBOOK is not set
 # CONFIG_HID_FF is not set
 CONFIG_USB_HIDDEV=y
@@ -1069,15 +1200,14 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
 # CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
 # CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
 
 #
 # USB Imaging devices
@@ -1085,21 +1215,6 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
 
-#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-# CONFIG_USB_VICAM is not set
-# CONFIG_USB_DSBR is not set
-# CONFIG_USB_ET61X251 is not set
-# CONFIG_USB_IBMCAM is not set
-# CONFIG_USB_KONICAWC is not set
-# CONFIG_USB_OV511 is not set
-# CONFIG_USB_SE401 is not set
-# CONFIG_USB_SN9C102 is not set
-# CONFIG_USB_STV680 is not set
-# CONFIG_USB_PWC is not set
-
 #
 # USB Network Adapters
 #
@@ -1107,6 +1222,7 @@ 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=y
 
@@ -1124,17 +1240,23 @@ CONFIG_USB_MON=y
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
 # CONFIG_USB_AUERSWALD is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
 
 #
 # USB DSL modem support
@@ -1150,14 +1272,54 @@ CONFIG_USB_MON=y
 #
 # CONFIG_MMC is not set
 
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
 #
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# EDAC - error detection and reporting (RAS)
+# 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
+#
+
+#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+# CONFIG_MSPEC is not set
 
 #
 # File systems
@@ -1171,6 +1333,7 @@ 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
@@ -1178,6 +1341,7 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -1212,12 +1376,14 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_VMCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1330,16 +1496,26 @@ CONFIG_NLS_KOI8_R=y
 CONFIG_NLS_KOI8_U=y
 CONFIG_NLS_UTF8=y
 
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_IRQ_PER_CPU=y
 
 #
 # Instrumentation Support
@@ -1351,21 +1527,32 @@ CONFIG_KPROBES=y
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
-CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_LKDTM is not set
+# CONFIG_FAULT_INJECTION is not set
 CONFIG_IA64_GRANULE_16MB=y
 # CONFIG_IA64_GRANULE_64MB is not set
 CONFIG_IA64_PRINT_HAZARDS=y
@@ -1384,7 +1571,11 @@ CONFIG_SYSVIPC_COMPAT=y
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
 # CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=y
@@ -1393,7 +1584,13 @@ CONFIG_CRYPTO_MD5=y
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
 CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
@@ -1407,6 +1604,7 @@ CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
 # CONFIG_CRYPTO_TEST is not set
 
 #
index 9001b3fbaa3244c53a535fc62e23adef893a7166..153bfdc0182d6edf2cf6f3738feacf14e4119bad 100644 (file)
@@ -1,8 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc5
-# Mon Feb 27 16:02:28 2006
+# Linux kernel version: 2.6.21-rc3
+# Thu Mar  8 11:01:03 2007
 #
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
@@ -18,16 +19,24 @@ CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -39,11 +48,9 @@ CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -54,7 +61,6 @@ CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
@@ -63,6 +69,8 @@ CONFIG_STOP_MACHINE=y
 #
 # Block layer
 #
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -82,15 +90,20 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
 #
 CONFIG_IA64=y
 CONFIG_64BIT=y
+CONFIG_ZONE_DMA=y
 CONFIG_MMU=y
 CONFIG_SWIOTLB=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_TIME_INTERPOLATION=y
+CONFIG_DMI=y
 CONFIG_EFI=y
 CONFIG_GENERIC_IOMAP=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-CONFIG_DMA_IS_DMA32=y
+CONFIG_AUDIT_ARCH=y
 CONFIG_IA64_GENERIC=y
 # CONFIG_IA64_DIG is not set
 # CONFIG_IA64_HP_ZX1 is not set
@@ -107,6 +120,7 @@ CONFIG_PGTABLE_3=y
 # CONFIG_PGTABLE_4 is not set
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 CONFIG_IA64_L1_CACHE_SHIFT=7
@@ -116,9 +130,10 @@ CONFIG_IOSAPIC=y
 CONFIG_FORCE_MAX_ZONEORDER=17
 CONFIG_SMP=y
 CONFIG_NR_CPUS=512
-CONFIG_IA64_NR_NODES=256
 CONFIG_HOTPLUG_CPU=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 # CONFIG_SCHED_SMT is not set
+# CONFIG_PERMIT_BSP_REMOVE is not set
 # CONFIG_PREEMPT is not set
 CONFIG_SELECT_MEMORY_MODEL=y
 # CONFIG_FLATMEM_MANUAL is not set
@@ -130,21 +145,34 @@ CONFIG_NEED_MULTIPLE_NODES=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_MIGRATION=y
+CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_ARCH_SPARSEMEM_ENABLE=y
 CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y
 CONFIG_NUMA=y
+CONFIG_NODES_SHIFT=10
+CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_VIRTUAL_MEM_MAP=y
 CONFIG_HOLES_IN_ZONE=y
 CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
+CONFIG_HAVE_ARCH_NODEDATA_EXTENSION=y
 CONFIG_IA32_SUPPORT=y
 CONFIG_COMPAT=y
 CONFIG_IA64_MCA_RECOVERY=y
 CONFIG_PERFMON=y
 CONFIG_IA64_PALINFO=y
 CONFIG_SGI_SN=y
+# CONFIG_IA64_ESI is not set
+
+#
+# SN Devices
+#
+CONFIG_SGI_IOC3=m
+CONFIG_KEXEC=y
+CONFIG_CRASH_DUMP=y
 
 #
 # Firmware Drivers
@@ -160,13 +188,16 @@ CONFIG_BINFMT_MISC=m
 CONFIG_PM=y
 CONFIG_PM_LEGACY=y
 # CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
 
 #
 # ACPI (Advanced Configuration and Power Interface) Support
 #
 CONFIG_ACPI=y
+CONFIG_ACPI_PROCFS=y
 CONFIG_ACPI_BUTTON=m
 CONFIG_ACPI_FAN=m
+# CONFIG_ACPI_DOCK is not set
 CONFIG_ACPI_PROCESSOR=m
 CONFIG_ACPI_HOTPLUG_CPU=y
 CONFIG_ACPI_THERMAL=m
@@ -188,8 +219,8 @@ CONFIG_ACPI_CONTAINER=m
 #
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
 # CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY_PROC=y
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -220,6 +251,10 @@ CONFIG_NET=y
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -234,12 +269,21 @@ CONFIG_SYN_COOKIES=y
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
 # 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_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -265,7 +309,6 @@ CONFIG_TCP_CONG_BIC=y
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 
@@ -294,6 +337,8 @@ CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=m
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
@@ -337,10 +382,16 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
+#
+# Misc devices
+#
+CONFIG_SGI_IOC4=y
+# CONFIG_TIFM_CORE is not set
+
 #
 # ATA/ATAPI/MFM/RLL support
 #
@@ -358,6 +409,7 @@ CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 CONFIG_BLK_DEV_IDEFLOPPY=y
 CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_BLK_DEV_IDEACPI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
 
 #
@@ -384,8 +436,10 @@ CONFIG_BLK_DEV_CMD64X=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=y
+# CONFIG_BLK_DEV_IT8213 is not set
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -396,6 +450,7 @@ CONFIG_BLK_DEV_SGIIOC4=y
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -407,6 +462,8 @@ CONFIG_IDEDMA_AUTO=y
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -426,14 +483,16 @@ CONFIG_CHR_DEV_SG=m
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=y
 # CONFIG_SCSI_ISCSI_ATTRS is not set
 # CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
 
 #
 # SCSI low-level drivers
@@ -446,43 +505,36 @@ CONFIG_SCSI_FC_ATTRS=y
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
-CONFIG_SCSI_SATA=y
-# CONFIG_SCSI_SATA_AHCI is not set
-# CONFIG_SCSI_SATA_SVW is not set
-# CONFIG_SCSI_ATA_PIIX is not set
-# CONFIG_SCSI_SATA_MV is not set
-# CONFIG_SCSI_SATA_NV is not set
-# CONFIG_SCSI_PDC_ADMA is not set
-# CONFIG_SCSI_SATA_QSTOR is not set
-# CONFIG_SCSI_SATA_PROMISE is not set
-# CONFIG_SCSI_SATA_SX4 is not set
-# CONFIG_SCSI_SATA_SIL is not set
-# CONFIG_SCSI_SATA_SIL24 is not set
-# CONFIG_SCSI_SATA_SIS is not set
-# CONFIG_SCSI_SATA_ULI is not set
-# CONFIG_SCSI_SATA_VIA is not set
-CONFIG_SCSI_SATA_VITESSE=y
+# CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
 CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
+CONFIG_SCSI_SYM53C8XX_MMIO=y
 CONFIG_SCSI_QLOGIC_1280=y
 # CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
 # CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -493,11 +545,11 @@ CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
 CONFIG_MD_RAID1=m
 # CONFIG_MD_RAID10 is not set
-CONFIG_MD_RAID5=m
-CONFIG_MD_RAID6=m
+# CONFIG_MD_RAID456 is not set
 CONFIG_MD_MULTIPATH=m
 # CONFIG_MD_FAULTY is not set
 CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
@@ -587,6 +639,7 @@ CONFIG_E100=m
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -607,13 +660,18 @@ CONFIG_E1000=y
 # CONFIG_VIA_VELOCITY is not set
 CONFIG_TIGON3=y
 # CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -655,6 +713,7 @@ CONFIG_NET_POLL_CONTROLLER=y
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -677,6 +736,7 @@ CONFIG_KEYBOARD_ATKBD=y
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 # CONFIG_MOUSE_SERIAL is not set
@@ -706,6 +766,7 @@ CONFIG_GAMEPORT=m
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
 CONFIG_SERIAL_NONSTANDARD=y
 # CONFIG_COMPUTONE is not set
 # CONFIG_ROCKETPORT is not set
@@ -713,12 +774,14 @@ CONFIG_SERIAL_NONSTANDARD=y
 # CONFIG_DIGIEPCA is not set
 # CONFIG_MOXA_INTELLIO is not set
 # CONFIG_MOXA_SMARTIO is not set
+# CONFIG_MOXA_SMARTIO_NEW is not set
 # CONFIG_ISI is not set
 # CONFIG_SYNCLINKMP is not set
 # CONFIG_SYNCLINK_GT is not set
 # CONFIG_N_HDLC is not set
 # CONFIG_SPECIALIX is not set
 # CONFIG_SX is not set
+# CONFIG_RIO is not set
 # CONFIG_STALDRV is not set
 CONFIG_SGI_SNSC=y
 CONFIG_SGI_TIOCX=y
@@ -729,7 +792,8 @@ CONFIG_SGI_MBCS=m
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_ACPI=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
 CONFIG_SERIAL_8250_NR_UARTS=6
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 CONFIG_SERIAL_8250_EXTENDED=y
@@ -764,10 +828,6 @@ CONFIG_EFI_RTC=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 CONFIG_AGP=m
 CONFIG_AGP_I460=m
 CONFIG_AGP_HP_ZX1=m
@@ -792,7 +852,6 @@ CONFIG_MMTIMER=y
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -815,16 +874,16 @@ CONFIG_MMTIMER=y
 #
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_VT1211 is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
-# Misc devices
-#
-
-#
-# Multimedia Capabilities Port drivers
+# Multifunction device drivers
 #
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
@@ -835,16 +894,19 @@ CONFIG_HWMON=y
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
 #
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 # CONFIG_FB is not set
 
 #
 # Console display driver support
 #
 CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
 CONFIG_DUMMY_CONSOLE=y
 
 #
@@ -865,9 +927,11 @@ CONFIG_SND_SEQ_DUMMY=m
 CONFIG_SND_OSSEMUL=y
 CONFIG_SND_MIXER_OSS=m
 CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
 CONFIG_SND_SEQUENCER_OSS=y
 # CONFIG_SND_DYNAMIC_MINORS is not set
 CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
 CONFIG_SND_VERBOSE_PRINTK=y
 # CONFIG_SND_DEBUG is not set
 
@@ -877,7 +941,6 @@ CONFIG_SND_VERBOSE_PRINTK=y
 CONFIG_SND_MPU401_UART=m
 CONFIG_SND_OPL3_LIB=m
 CONFIG_SND_AC97_CODEC=m
-CONFIG_SND_AC97_BUS=m
 CONFIG_SND_DUMMY=m
 CONFIG_SND_VIRMIDI=m
 CONFIG_SND_MTPAV=m
@@ -888,6 +951,7 @@ CONFIG_SND_MPU401=m
 # PCI devices
 #
 # CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
 # CONFIG_SND_ALI5451 is not set
 # CONFIG_SND_ATIIXP is not set
 # CONFIG_SND_ATIIXP_MODEM is not set
@@ -901,6 +965,18 @@ CONFIG_SND_MPU401=m
 CONFIG_SND_CS4281=m
 CONFIG_SND_CS46XX=m
 CONFIG_SND_CS46XX_NEW_DSP=y
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
 CONFIG_SND_EMU10K1=m
 # CONFIG_SND_EMU10K1X is not set
 # CONFIG_SND_ENS1370 is not set
@@ -908,7 +984,7 @@ CONFIG_SND_EMU10K1=m
 # CONFIG_SND_ES1938 is not set
 # CONFIG_SND_ES1968 is not set
 CONFIG_SND_FM801=m
-# CONFIG_SND_FM801_TEA575X is not set
+# CONFIG_SND_FM801_TEA575X_BOOL is not set
 # CONFIG_SND_HDA_INTEL is not set
 # CONFIG_SND_HDSP is not set
 # CONFIG_SND_HDSPM is not set
@@ -921,6 +997,7 @@ CONFIG_SND_FM801=m
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
 # CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
 # CONFIG_SND_RME32 is not set
 # CONFIG_SND_RME96 is not set
 # CONFIG_SND_RME9652 is not set
@@ -930,22 +1007,36 @@ CONFIG_SND_FM801=m
 # CONFIG_SND_VIA82XX_MODEM is not set
 # CONFIG_SND_VX222 is not set
 # CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_AC97_POWER_SAVE is not set
 
 #
 # USB devices
 #
 # CONFIG_SND_USB_AUDIO is not set
 
+#
+# SoC audio support
+#
+# CONFIG_SND_SOC is not set
+
 #
 # Open Sound System
 #
 # CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
 
 #
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 CONFIG_USB=m
 # CONFIG_USB_DEBUG is not set
 
@@ -953,7 +1044,6 @@ CONFIG_USB=m
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
@@ -964,9 +1054,12 @@ CONFIG_USB_DEVICEFS=y
 CONFIG_USB_EHCI_HCD=m
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=m
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 CONFIG_USB_UHCI_HCD=m
 # CONFIG_USB_SL811_HCD is not set
@@ -974,7 +1067,6 @@ CONFIG_USB_UHCI_HCD=m
 #
 # USB Device Class drivers
 #
-# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
 
@@ -996,13 +1088,13 @@ CONFIG_USB_STORAGE=m
 # CONFIG_USB_STORAGE_SDDR55 is not set
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
 # CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
 # USB Input Devices
 #
 CONFIG_USB_HID=m
-CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_HIDINPUT_POWERBOOK is not set
 # CONFIG_HID_FF is not set
 # CONFIG_USB_HIDDEV is not set
@@ -1017,15 +1109,14 @@ CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
 # CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
 # CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
 
 #
 # USB Imaging devices
@@ -1033,15 +1124,6 @@ CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
 
-#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
 #
 # USB Network Adapters
 #
@@ -1049,6 +1131,7 @@ CONFIG_USB_HIDINPUT=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=y
 
@@ -1066,17 +1149,23 @@ CONFIG_USB_MON=y
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
 # CONFIG_USB_AUERSWALD is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -1093,27 +1182,66 @@ CONFIG_USB_MON=y
 #
 # CONFIG_MMC is not set
 
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
 #
 # InfiniBand support
 #
 CONFIG_INFINIBAND=m
 # CONFIG_INFINIBAND_USER_MAD is not set
 # CONFIG_INFINIBAND_USER_ACCESS is not set
+CONFIG_INFINIBAND_ADDR_TRANS=y
 CONFIG_INFINIBAND_MTHCA=m
-# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+# CONFIG_INFINIBAND_AMSO1100 is not set
 CONFIG_INFINIBAND_IPOIB=m
-# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
+# CONFIG_INFINIBAND_IPOIB_CM is not set
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
 # CONFIG_INFINIBAND_SRP is not set
+# CONFIG_INFINIBAND_ISER is not set
 
 #
-# SN Devices
+# 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
+#
+
+#
+# Auxiliary Display support
 #
-CONFIG_SGI_IOC4=y
-CONFIG_SGI_IOC3=m
 
 #
-# EDAC - error detection and reporting (RAS)
+# Virtualization
 #
+# CONFIG_MSPEC is not set
 
 #
 # File systems
@@ -1127,6 +1255,7 @@ CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -1139,15 +1268,16 @@ CONFIG_REISERFS_FS_SECURITY=y
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 CONFIG_XFS_FS=y
-CONFIG_XFS_EXPORT=y
 # CONFIG_XFS_QUOTA is not set
 # CONFIG_XFS_SECURITY is not set
 # CONFIG_XFS_POSIX_ACL is not set
 # CONFIG_XFS_RT is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=y
@@ -1180,12 +1310,14 @@ CONFIG_NTFS_FS=m
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_VMCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1220,7 +1352,7 @@ CONFIG_NFSD_V4=y
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=m
 CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
+CONFIG_EXPORTFS=m
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
@@ -1231,7 +1363,9 @@ CONFIG_SMB_NLS_DEFAULT=y
 CONFIG_SMB_NLS_REMOTE="cp437"
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
 # CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_CIFS_EXPERIMENTAL is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
@@ -1303,16 +1437,26 @@ CONFIG_NLS_KOI8_R=m
 CONFIG_NLS_KOI8_U=m
 CONFIG_NLS_UTF8=m
 
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_IRQ_PER_CPU=y
 
 #
 # HP Simulator drivers
@@ -1331,21 +1475,31 @@ CONFIG_GENERIC_PENDING_IRQ=y
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_LOG_BUF_SHIFT=20
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
-CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
 CONFIG_IA64_GRANULE_16MB=y
 # CONFIG_IA64_GRANULE_64MB is not set
 # CONFIG_IA64_PRINT_HAZARDS is not set
@@ -1364,7 +1518,11 @@ CONFIG_SYSVIPC_COMPAT=y
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_MANAGER=m
 # CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=y
@@ -1373,7 +1531,13 @@ CONFIG_CRYPTO_MD5=y
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
 CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
@@ -1387,6 +1551,7 @@ CONFIG_CRYPTO_DES=m
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
 # CONFIG_CRYPTO_TEST is not set
 
 #
index d430d36ae49d62763757d05c354ec4590781d6da..0afb4fe7c35b8bfeff14d1aebd0e892a7a1a1d64 100644 (file)
@@ -1267,6 +1267,10 @@ sys32_getdents (unsigned int fd, struct compat_dirent __user *dirent, unsigned i
        struct getdents32_callback buf;
        int error;
 
+       error = -EFAULT;
+       if (!access_ok(VERIFY_WRITE, dirent, count))
+               goto out;
+
        error = -EBADF;
        file = fget(fd);
        if (!file)
@@ -1283,10 +1287,10 @@ sys32_getdents (unsigned int fd, struct compat_dirent __user *dirent, unsigned i
        error = buf.error;
        lastdirent = buf.previous;
        if (lastdirent) {
-               error = -EINVAL;
                if (put_user(file->f_pos, &lastdirent->d_off))
-                       goto out_putf;
-               error = count - buf.count;
+                       error = -EFAULT;
+               else
+                       error = count - buf.count;
        }
 
 out_putf:
index 75a2a2c12258179b53fb1b76b0243ef3d9cf602d..2236fabbb3c60fcf6453a8b07a1448b9cb09e6bd 100644 (file)
@@ -35,6 +35,7 @@ void foo(void)
        BLANK();
 
        DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+       DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
        DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count));
 
        BLANK();
index 5cdd2f5fa064acbcd5ab266526545a5b4e77f3fd..7d1bbb4403ba435e073ed0854efcb897f15d4f62 100644 (file)
@@ -21,9 +21,9 @@
 #include <asm/mca.h>
 
 int kdump_status[NR_CPUS];
-atomic_t kdump_cpu_freezed;
+static atomic_t kdump_cpu_frozen;
 atomic_t kdump_in_progress;
-int kdump_on_init = 1;
+static int kdump_on_init = 1;
 
 static inline Elf64_Word
 *append_elf_note(Elf64_Word *buf, char *name, unsigned type, void *data,
@@ -86,7 +86,7 @@ kdump_wait_cpu_freeze(void)
        int cpu_num = num_online_cpus() - 1;
        int timeout = 1000;
        while(timeout-- > 0) {
-               if (atomic_read(&kdump_cpu_freezed) == cpu_num)
+               if (atomic_read(&kdump_cpu_frozen) == cpu_num)
                        return 0;
                udelay(1000);
        }
@@ -108,8 +108,8 @@ machine_crash_shutdown(struct pt_regs *pt)
        kexec_disable_iosapic();
 #ifdef CONFIG_SMP
        kdump_smp_send_stop();
+       /* not all cpu response to IPI, send INIT to freeze them */
        if (kdump_wait_cpu_freeze() && kdump_on_init)   {
-               //not all cpu response to IPI, send INIT to freeze them
                kdump_smp_send_init();
        }
 #endif
@@ -136,7 +136,7 @@ kdump_cpu_freeze(struct unw_frame_info *info, void *arg)
        cpuid = smp_processor_id();
        crash_save_this_cpu();
        current->thread.ksp = (__u64)info->sw - 16;
-       atomic_inc(&kdump_cpu_freezed);
+       atomic_inc(&kdump_cpu_frozen);
        kdump_status[cpuid] = 1;
        mb();
 #ifdef CONFIG_HOTPLUG_CPU
index 772ba6fe110f6c0f56da55c491669debc2ec3787..f45f91d38caba314092a9e87173036ca1318dbec 100644 (file)
@@ -21,6 +21,7 @@
  *     Skip non-WB memory and ignore empty memory ranges.
  */
 #include <linux/module.h>
+#include <linux/bootmem.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
@@ -970,6 +971,11 @@ efi_memmap_init(unsigned long *s, unsigned long *e)
                if (!is_memory_available(md))
                        continue;
 
+#ifdef CONFIG_CRASH_DUMP
+               /* saved_max_pfn should ignore max_addr= command line arg */
+               if (saved_max_pfn < (efi_md_end(md) >> PAGE_SHIFT))
+                       saved_max_pfn = (efi_md_end(md) >> PAGE_SHIFT);
+#endif
                /*
                 * Round ends inward to granule boundaries
                 * Give trimmings to uncached allocator
@@ -1136,7 +1142,7 @@ efi_initialize_iomem_resources(struct resource *code_resource,
 /* find a block of memory aligned to 64M exclude reserved regions
    rsvd_regions are sorted
  */
-unsigned long
+unsigned long __init
 kdump_find_rsvd_region (unsigned long size,
                struct rsvd_region *r, int n)
 {
@@ -1177,3 +1183,33 @@ kdump_find_rsvd_region (unsigned long size,
   return ~0UL;
 }
 #endif
+
+#ifdef CONFIG_PROC_VMCORE
+/* locate the size find a the descriptor at a certain address */
+unsigned long
+vmcore_find_descriptor_size (unsigned long address)
+{
+       void *efi_map_start, *efi_map_end, *p;
+       efi_memory_desc_t *md;
+       u64 efi_desc_size;
+       unsigned long ret = 0;
+
+       efi_map_start = __va(ia64_boot_param->efi_memmap);
+       efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
+       efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+       for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+               md = p;
+               if (efi_wb(md) && md->type == EFI_LOADER_DATA
+                   && md->phys_addr == address) {
+                       ret = efi_md_size(md);
+                       break;
+               }
+       }
+
+       if (ret == 0)
+               printk(KERN_WARNING "Cannot locate EFI vmcore descriptor\n");
+
+       return ret;
+}
+#endif
index 7a05b1cb2ad5289598d50c200ded84de399c6b8d..8589e84a27c66119e9297757673faa198d70a4fa 100644 (file)
@@ -10,6 +10,8 @@
  *                     probably broke it along the way... ;-)
  * 13-Jul-04 clameter   Implement fsys_clock_gettime and revise fsys_gettimeofday to make
  *                      it capable of using memory based clocks without falling back to C code.
+ * 08-Feb-07 Fenghua Yu Implement fsys_getcpu.
+ *
  */
 
 #include <asm/asmmacro.h>
@@ -505,6 +507,59 @@ EX(.fail_efault, (p15) st8 [r34]=r3)
 #endif
 END(fsys_rt_sigprocmask)
 
+/*
+ * fsys_getcpu doesn't use the third parameter in this implementation. It reads
+ * current_thread_info()->cpu and corresponding node in cpu_to_node_map.
+ */
+ENTRY(fsys_getcpu)
+       .prologue
+       .altrp b6
+       .body
+       ;;
+       add r2=TI_FLAGS+IA64_TASK_SIZE,r16
+       tnat.nz p6,p0 = r32                     // guard against NaT argument
+       add r3=TI_CPU+IA64_TASK_SIZE,r16
+       ;;
+       ld4 r3=[r3]                             // M r3 = thread_info->cpu
+       ld4 r2=[r2]                             // M r2 = thread_info->flags
+(p6)    br.cond.spnt.few .fail_einval          // B
+       ;;
+       tnat.nz p7,p0 = r33                     // I guard against NaT argument
+(p7)    br.cond.spnt.few .fail_einval          // B
+#ifdef CONFIG_NUMA
+       movl r17=cpu_to_node_map
+       ;;
+EX(.fail_efault, probe.w.fault r32, 3)         // M This takes 5 cycles
+EX(.fail_efault, probe.w.fault r33, 3)         // M This takes 5 cycles
+       shladd r18=r3,1,r17
+       ;;
+       ld2 r20=[r18]                           // r20 = cpu_to_node_map[cpu]
+       and r2 = TIF_ALLWORK_MASK,r2
+       ;;
+       cmp.ne p8,p0=0,r2
+(p8)   br.spnt.many fsys_fallback_syscall
+       ;;
+       ;;
+EX(.fail_efault, st4 [r32] = r3)
+EX(.fail_efault, st2 [r33] = r20)
+       mov r8=0
+       ;;
+#else
+EX(.fail_efault, probe.w.fault r32, 3)         // M This takes 5 cycles
+EX(.fail_efault, probe.w.fault r33, 3)         // M This takes 5 cycles
+       and r2 = TIF_ALLWORK_MASK,r2
+       ;;
+       cmp.ne p8,p0=0,r2
+(p8)   br.spnt.many fsys_fallback_syscall
+       ;;
+EX(.fail_efault, st4 [r32] = r3)
+EX(.fail_efault, st2 [r33] = r0)
+       mov r8=0
+       ;;
+#endif
+       FSYS_RETURN
+END(fsys_getcpu)
+
 ENTRY(fsys_fallback_syscall)
        .prologue
        .altrp b6
@@ -878,6 +933,56 @@ fsyscall_table:
        data8 0                         // timer_delete
        data8 0                         // clock_settime
        data8 fsys_clock_gettime        // clock_gettime
+       data8 0                         // clock_getres         // 1255
+       data8 0                         // clock_nanosleep
+       data8 0                         // fstatfs64
+       data8 0                         // statfs64
+       data8 0                         // mbind
+       data8 0                         // get_mempolicy        // 1260
+       data8 0                         // set_mempolicy
+       data8 0                         // mq_open
+       data8 0                         // mq_unlink
+       data8 0                         // mq_timedsend
+       data8 0                         // mq_timedreceive      // 1265
+       data8 0                         // mq_notify
+       data8 0                         // mq_getsetattr
+       data8 0                         // kexec_load
+       data8 0                         // vserver
+       data8 0                         // waitid               // 1270
+       data8 0                         // add_key
+       data8 0                         // request_key
+       data8 0                         // keyctl
+       data8 0                         // ioprio_set
+       data8 0                         // ioprio_get           // 1275
+       data8 0                         // move_pages
+       data8 0                         // inotify_init
+       data8 0                         // inotify_add_watch
+       data8 0                         // inotify_rm_watch
+       data8 0                         // migrate_pages        // 1280
+       data8 0                         // openat
+       data8 0                         // mkdirat
+       data8 0                         // mknodat
+       data8 0                         // fchownat
+       data8 0                         // futimesat            // 1285
+       data8 0                         // newfstatat
+       data8 0                         // unlinkat
+       data8 0                         // renameat
+       data8 0                         // linkat
+       data8 0                         // symlinkat            // 1290
+       data8 0                         // readlinkat
+       data8 0                         // fchmodat
+       data8 0                         // faccessat
+       data8 0
+       data8 0                                                 // 1295
+       data8 0                         // unshare
+       data8 0                         // splice
+       data8 0                         // set_robust_list
+       data8 0                         // get_robust_list
+       data8 0                         // sync_file_range      // 1300
+       data8 0                         // tee
+       data8 0                         // vmsplice
+       data8 0
+       data8 fsys_getcpu               // getcpu               // 1304
 
        // fill in zeros for the remaining entries
        .zero:
index d6aab40c64166ecdf6ae8c3529134e46ac4cd7a6..dcfbf3e7a9ef6113e90e07e7f0c79901995116c1 100644 (file)
@@ -446,7 +446,7 @@ iosapic_end_level_irq (unsigned int irq)
 #define iosapic_disable_level_irq      mask_irq
 #define iosapic_ack_level_irq          nop
 
-struct hw_interrupt_type irq_type_iosapic_level = {
+struct irq_chip irq_type_iosapic_level = {
        .name =         "IO-SAPIC-level",
        .startup =      iosapic_startup_level_irq,
        .shutdown =     iosapic_shutdown_level_irq,
@@ -454,6 +454,8 @@ struct hw_interrupt_type irq_type_iosapic_level = {
        .disable =      iosapic_disable_level_irq,
        .ack =          iosapic_ack_level_irq,
        .end =          iosapic_end_level_irq,
+       .mask =         mask_irq,
+       .unmask =       unmask_irq,
        .set_affinity = iosapic_set_affinity
 };
 
@@ -493,7 +495,7 @@ iosapic_ack_edge_irq (unsigned int irq)
 #define iosapic_disable_edge_irq       nop
 #define iosapic_end_edge_irq           nop
 
-struct hw_interrupt_type irq_type_iosapic_edge = {
+struct irq_chip irq_type_iosapic_edge = {
        .name =         "IO-SAPIC-edge",
        .startup =      iosapic_startup_edge_irq,
        .shutdown =     iosapic_disable_edge_irq,
@@ -501,6 +503,8 @@ struct hw_interrupt_type irq_type_iosapic_edge = {
        .disable =      iosapic_disable_edge_irq,
        .ack =          iosapic_ack_edge_irq,
        .end =          iosapic_end_edge_irq,
+       .mask =         mask_irq,
+       .unmask =       unmask_irq,
        .set_affinity = iosapic_set_affinity
 };
 
index a76add3e76a213d809cf6562c0507b247f67529a..491687f84fb557d446bdfa39d9475b1ba2bcd19d 100644 (file)
@@ -1192,8 +1192,6 @@ void
 ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
                 struct ia64_sal_os_state *sos)
 {
-       pal_processor_state_info_t *psp = (pal_processor_state_info_t *)
-               &sos->proc_state_param;
        int recover, cpu = smp_processor_id();
        struct task_struct *previous_current;
        struct ia64_mca_notify_die nd =
@@ -1223,10 +1221,8 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
        /* Get the MCA error record and log it */
        ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA);
 
-       /* TLB error is only exist in this SAL error record */
-       recover = (psp->tc && !(psp->cc || psp->bc || psp->rc || psp->uc))
-       /* other error recovery */
-          || (ia64_mca_ucmc_extension
+       /* MCA error recovery */
+       recover = (ia64_mca_ucmc_extension
                && ia64_mca_ucmc_extension(
                        IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_MCA),
                        sos));
index afc1403799c9511505503d564c6bb30f18df0ea4..832cf1e647e821f8543b8682b8675c95accc9828 100644 (file)
@@ -602,11 +602,40 @@ recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx,
                default:
                        break;
                }
+       } else if (psp->cc && !psp->bc) {       /* Cache error */
+               status = recover_from_read_error(slidx, peidx, pbci, sos);
        }
 
        return status;
 }
 
+/*
+ * recover_from_tlb_check
+ * @peidx:     pointer of index of processor error section
+ *
+ * Return value:
+ *     1 on Success / 0 on Failure
+ */
+static int
+recover_from_tlb_check(peidx_table_t *peidx)
+{
+       sal_log_mod_error_info_t *smei;
+       pal_tlb_check_info_t *ptci;
+
+       smei = (sal_log_mod_error_info_t *)peidx_tlb_check(peidx, 0);
+       ptci = (pal_tlb_check_info_t *)&(smei->check_info);
+
+       /*
+        * Look for signature of a duplicate TLB DTC entry, which is
+        * a SW bug and always fatal.
+        */
+       if (ptci->op == PAL_TLB_CHECK_OP_PURGE
+           && !(ptci->itr || ptci->dtc || ptci->itc))
+               return fatal_mca("Duplicate TLB entry");
+
+       return mca_recovered("TLB check recovered");
+}
+
 /**
  * recover_from_processor_error
  * @platform:  whether there are some platform error section or not
@@ -618,13 +647,6 @@ recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx,
  * Return value:
  *     1 on Success / 0 on Failure
  */
-/*
- *  Later we try to recover when below all conditions are satisfied.
- *   1. Only one processor error section is exist.
- *   2. BUS_CHECK is exist and the others are not exist.(Except TLB_CHECK)
- *   3. The entry of BUS_CHECK_INFO is 1.
- *   4. "External bus error" flag is set and the others are not set.
- */
 
 static int
 recover_from_processor_error(int platform, slidx_table_t *slidx,
@@ -651,39 +673,40 @@ recover_from_processor_error(int platform, slidx_table_t *slidx,
        if (psp->us || psp->ci == 0)
                return fatal_mca("error not contained");
 
+       /*
+        * Look for recoverable TLB check
+        */
+       if (psp->tc && !(psp->cc || psp->bc || psp->rc || psp->uc))
+               return recover_from_tlb_check(peidx);
+
        /*
         * The cache check and bus check bits have four possible states
         *   cc bc
-        *    0  0      Weird record, not recovered
-        *    1  0      Cache error, not recovered
-        *    0  1      I/O error, attempt recovery
         *    1  1      Memory error, attempt recovery
+        *    1  0      Cache error, attempt recovery
+        *    0  1      I/O error, attempt recovery
+        *    0  0      Other error type, not recovered
         */
-       if (psp->bc == 0 || pbci == NULL)
-               return fatal_mca("No bus check");
+       if (psp->cc == 0 && (psp->bc == 0 || pbci == NULL))
+               return fatal_mca("No cache or bus check");
 
        /*
-        * Sorry, we cannot handle so many.
+        * Cannot handle more than one bus check.
         */
        if (peidx_bus_check_num(peidx) > 1)
                return fatal_mca("Too many bus checks");
-       /*
-        * Well, here is only one bus error.
-        */
+
        if (pbci->ib)
                return fatal_mca("Internal Bus error");
-       if (pbci->cc)
-               return fatal_mca("Cache-cache error");
        if (pbci->eb && pbci->bsi > 0)
                return fatal_mca("External bus check fatal status");
 
        /*
-        * This is a local MCA and estimated as recoverble external bus error.
-        * (e.g. a load from poisoned memory)
-        * This means "there are some platform errors".
+        * This is a local MCA and estimated as a recoverble error.
         */
        if (platform)
                return recover_from_platform_error(slidx, peidx, pbci, sos);
+
        /*
         * On account of strange SAL error record, we cannot recover.
         */
index 0d05450c91c458211b8f00b72f9e3e169460d601..e7220900ea14b012afe30aa09cced503f15a3937 100644 (file)
@@ -60,7 +60,7 @@ static void ia64_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask)
        msg.address_lo = addr;
 
        write_msi_msg(irq, &msg);
-       set_native_irq_info(irq, cpu_mask);
+       irq_desc[irq].affinity = cpu_mask;
 }
 #endif /* CONFIG_SMP */
 
index 9ddf896a137a6033509739e4453b6963c116516d..abc7ad03588630ed9ade6a593a8a96cbda619918 100644 (file)
@@ -2299,7 +2299,7 @@ pfm_remap_buffer(struct vm_area_struct *vma, unsigned long buf, unsigned long ad
  * allocate a sampling buffer and remaps it into the user address space of the task
  */
 static int
-pfm_smpl_buffer_alloc(struct task_struct *task, pfm_context_t *ctx, unsigned long rsize, void **user_vaddr)
+pfm_smpl_buffer_alloc(struct task_struct *task, struct file *filp, pfm_context_t *ctx, unsigned long rsize, void **user_vaddr)
 {
        struct mm_struct *mm = task->mm;
        struct vm_area_struct *vma = NULL;
@@ -2349,6 +2349,7 @@ pfm_smpl_buffer_alloc(struct task_struct *task, pfm_context_t *ctx, unsigned lon
         * partially initialize the vma for the sampling buffer
         */
        vma->vm_mm           = mm;
+       vma->vm_file         = filp;
        vma->vm_flags        = VM_READ| VM_MAYREAD |VM_RESERVED;
        vma->vm_page_prot    = PAGE_READONLY; /* XXX may need to change */
 
@@ -2387,6 +2388,8 @@ pfm_smpl_buffer_alloc(struct task_struct *task, pfm_context_t *ctx, unsigned lon
                goto error;
        }
 
+       get_file(filp);
+
        /*
         * now insert the vma in the vm list for the process, must be
         * done with mmap lock held
@@ -2464,7 +2467,7 @@ pfarg_is_sane(struct task_struct *task, pfarg_context_t *pfx)
 }
 
 static int
-pfm_setup_buffer_fmt(struct task_struct *task, pfm_context_t *ctx, unsigned int ctx_flags,
+pfm_setup_buffer_fmt(struct task_struct *task, struct file *filp, pfm_context_t *ctx, unsigned int ctx_flags,
                     unsigned int cpu, pfarg_context_t *arg)
 {
        pfm_buffer_fmt_t *fmt = NULL;
@@ -2505,7 +2508,7 @@ pfm_setup_buffer_fmt(struct task_struct *task, pfm_context_t *ctx, unsigned int
                /*
                 * buffer is always remapped into the caller's address space
                 */
-               ret = pfm_smpl_buffer_alloc(current, ctx, size, &uaddr);
+               ret = pfm_smpl_buffer_alloc(current, filp, ctx, size, &uaddr);
                if (ret) goto error;
 
                /* keep track of user address of buffer */
@@ -2716,7 +2719,7 @@ pfm_context_create(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg
         * does the user want to sample?
         */
        if (pfm_uuid_cmp(req->ctx_smpl_buf_id, pfm_null_uuid)) {
-               ret = pfm_setup_buffer_fmt(current, ctx, ctx_flags, 0, req);
+               ret = pfm_setup_buffer_fmt(current, filp, ctx, ctx_flags, 0, req);
                if (ret) goto buffer_error;
        }
 
index 3f8918782e0c992721a1758c1f83e2446f5261fe..00f80324694829f5eef2e647299a8227213689f1 100644 (file)
@@ -1573,6 +1573,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data)
 
              case PTRACE_DETACH:
                /* detach a process that was attached. */
+               clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
                ret = ptrace_detach(child, data);
                goto out_tsk;
 
index 5fa09d141ab7a8545a963dfb1e9e60fdb316ea7e..339e8a54c2f1dc860eb8e0279b6a5ca88eb77cf9 100644 (file)
@@ -91,8 +91,6 @@ static struct resource code_resource = {
        .name   = "Kernel code",
        .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
 };
-extern void efi_initialize_iomem_resources(struct resource *,
-               struct resource *);
 extern char _text[], _end[], _etext[];
 
 unsigned long ia64_max_cacheline_size;
@@ -251,6 +249,12 @@ reserve_memory (void)
        }
 #endif
 
+#ifdef CONFIG_PROC_VMCORE
+       if (reserve_elfcorehdr(&rsvd_region[n].start,
+                              &rsvd_region[n].end) == 0)
+               n++;
+#endif
+
        efi_memmap_init(&rsvd_region[n].start, &rsvd_region[n].end);
        n++;
 
@@ -453,6 +457,30 @@ static int __init parse_elfcorehdr(char *arg)
        return 0;
 }
 early_param("elfcorehdr", parse_elfcorehdr);
+
+int __init reserve_elfcorehdr(unsigned long *start, unsigned long *end)
+{
+       unsigned long length;
+
+       /* We get the address using the kernel command line,
+        * but the size is extracted from the EFI tables.
+        * Both address and size are required for reservation
+        * to work properly.
+        */
+
+       if (elfcorehdr_addr >= ELFCORE_ADDR_MAX)
+               return -EINVAL;
+
+       if ((length = vmcore_find_descriptor_size(elfcorehdr_addr)) == 0) {
+               elfcorehdr_addr = ELFCORE_ADDR_MAX;
+               return -EINVAL;
+       }
+
+       *start = (unsigned long)__va(elfcorehdr_addr);
+       *end = *start + length;
+       return 0;
+}
+
 #endif /* CONFIG_PROC_VMCORE */
 
 void __init
index 38fa6e49e791a0789c2c57ecf584744c29862fce..46edf8444c7ed0c9d3351e30e2c080e9a8fd7f0a 100644 (file)
@@ -9,12 +9,11 @@ lib-y := __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o                        \
        checksum.o clear_page.o csum_partial_copy.o                     \
        clear_user.o strncpy_from_user.o strlen_user.o strnlen_user.o   \
        flush.o ip_fast_csum.o do_csum.o                                \
-       memset.o strlen.o
+       memset.o strlen.o xor.o
 
 lib-$(CONFIG_ITANIUM)  += copy_page.o copy_user.o memcpy.o
 lib-$(CONFIG_MCKINLEY) += copy_page_mck.o memcpy_mck.o
 lib-$(CONFIG_PERFMON)  += carta_random.o
-lib-$(CONFIG_MD_RAID456)       += xor.o
 
 AFLAGS___divdi3.o      =
 AFLAGS___udivdi3.o     = -DUNSIGNED
index ca4d41e5f177563c5739816c14ee563dc51ed87b..fb0f4698f5d0dd243e62eee23de87dfd810ce6e5 100644 (file)
@@ -197,11 +197,6 @@ find_memory (void)
 
        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
index 16835108bb5bc71a3e19cdcc1f582473ce89899c..11a2d8825d89c398ed88bc76f70614c3d566e171 100644 (file)
@@ -480,12 +480,6 @@ void __init find_memory(void)
        max_pfn = max_low_pfn;
 
        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
index 8c331ca6e5c9088a8a8542ebae195306f4d9a6bc..c6216f454ffb5ee81d2246bb05361a073ff51268 100644 (file)
@@ -53,12 +53,15 @@ sal_ioif_init(u64 *result)
 }
 
 /*
- * sn_hubdev_add - The 'add' function of the acpi_sn_hubdev_driver.
- *                Called for every "SGIHUB" or "SGITIO" device defined
- *                in the ACPI namespace.
+ * sn_acpi_hubdev_init() - This function is called by acpi_ns_get_device_callback()
+ *                        for all SGIHUB and SGITIO acpi devices defined in the
+ *                        DSDT. It obtains the hubdev_info pointer from the
+ *                        ACPI vendor resource, which the PROM setup, and sets up the
+ *                        hubdev_info in the pda.
  */
-static int __init
-sn_hubdev_add(struct acpi_device *device)
+
+static acpi_status __init
+sn_acpi_hubdev_init(acpi_handle handle, u32 depth, void *context, void **ret)
 {
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
        u64 addr;
@@ -67,18 +70,19 @@ sn_hubdev_add(struct acpi_device *device)
        int i;
        u64 nasid;
        struct acpi_resource *resource;
-       int ret = 0;
        acpi_status status;
        struct acpi_resource_vendor_typed *vendor;
        extern void sn_common_hubdev_init(struct hubdev_info *);
 
-       status = acpi_get_vendor_resource(device->handle, METHOD_NAME__CRS,
+       status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
                                          &sn_uuid, &buffer);
        if (ACPI_FAILURE(status)) {
                printk(KERN_ERR
-                      "sn_hubdev_add: acpi_get_vendor_resource() failed: %d\n",
-                       status);
-               return 1;
+                      "sn_acpi_hubdev_init: acpi_get_vendor_resource() "
+                      "(0x%x) failed for: ", status);
+               acpi_ns_print_node_pathname(handle, NULL);
+               printk("\n");
+               return AE_OK;           /* Continue walking namespace */
        }
 
        resource = buffer.pointer;
@@ -86,9 +90,10 @@ sn_hubdev_add(struct acpi_device *device)
        if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
            sizeof(struct hubdev_info *)) {
                printk(KERN_ERR
-                      "sn_hubdev_add: Invalid vendor data length: %d\n",
+                      "sn_acpi_hubdev_init: Invalid vendor data length: %d for: ",
                        vendor->byte_length);
-               ret = 1;
+               acpi_ns_print_node_pathname(handle, NULL);
+               printk("\n");
                goto exit;
        }
 
@@ -103,7 +108,7 @@ sn_hubdev_add(struct acpi_device *device)
 
 exit:
        kfree(buffer.pointer);
-       return ret;
+       return AE_OK;           /* Continue walking namespace */
 }
 
 /*
@@ -441,14 +446,6 @@ sn_acpi_slot_fixup(struct pci_dev *dev)
 
 EXPORT_SYMBOL(sn_acpi_slot_fixup);
 
-static struct acpi_driver acpi_sn_hubdev_driver = {
-       .name = "SGI HUBDEV Driver",
-       .ids = "SGIHUB,SGITIO",
-       .ops = {
-               .add = sn_hubdev_add,
-               },
-};
-
 
 /*
  * sn_acpi_bus_fixup -  Perform SN specific setup of software structs
@@ -492,7 +489,10 @@ sn_io_acpi_init(void)
        /* SN Altix does not follow the IOSAPIC IRQ routing model */
        acpi_irq_model = ACPI_IRQ_MODEL_PLATFORM;
 
-       acpi_bus_register_driver(&acpi_sn_hubdev_driver);
+       /* Setup hubdev_info for all SGIHUB/SGITIO devices */
+       acpi_get_devices("SGIHUB", sn_acpi_hubdev_init, NULL, NULL);
+       acpi_get_devices("SGITIO", sn_acpi_hubdev_init, NULL, NULL);
+
        status = sal_ioif_init(&result);
        if (status || result)
                panic("sal_ioif_init failed: [%lx] %s\n",
index 8c5bee01eaa28cf5e4666aa617194ed927cf581c..8d2a1bfbfe7c03f4d4b7e687fbf1a978d5dd1c71 100644 (file)
@@ -205,7 +205,17 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
                (void)sn_retarget_vector(sn_irq_info, nasid, slice);
 }
 
-struct hw_interrupt_type irq_type_sn = {
+static void
+sn_mask_irq(unsigned int irq)
+{
+}
+
+static void
+sn_unmask_irq(unsigned int irq)
+{
+}
+
+struct irq_chip irq_type_sn = {
        .name           = "SN hub",
        .startup        = sn_startup_irq,
        .shutdown       = sn_shutdown_irq,
@@ -213,6 +223,8 @@ struct hw_interrupt_type irq_type_sn = {
        .disable        = sn_disable_irq,
        .ack            = sn_ack_irq,
        .end            = sn_end_irq,
+       .mask           = sn_mask_irq,
+       .unmask         = sn_unmask_irq,
        .set_affinity   = sn_set_affinity_irq
 };
 
index ea3dc38d73fd49a3a022eee42373d80c8c74065f..49873aa4a37dcb2e1705e70081dfb7e9c11d291d 100644 (file)
@@ -204,7 +204,7 @@ static void sn_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask)
        msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff);
 
        write_msi_msg(irq, &msg);
-       set_native_irq_info(irq, cpu_mask);
+       irq_desc[irq].affinity = cpu_mask;
 }
 #endif /* CONFIG_SMP */
 
index 8571e52c2efde6785b1927cb4540b8383fea44d2..bd5373d593e1034a3999c94ba2529f3c94087c36 100644 (file)
@@ -397,6 +397,8 @@ void __init sn_setup(char **cmdline_p)
        ia64_sn_set_os_feature(OSF_PCISEGMENT_ENABLE);
        ia64_sn_set_os_feature(OSF_ACPI_ENABLE);
 
+       /* Load the new DSDT and SSDT tables into the global table list. */
+       acpi_table_init();
 
 #if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)
        /*
index d5c25d27b64d7f5e02ed8282fbc4867fb411b0d4..8133b1047353da6665fcf8966b374c6c9bbb6f44 100644 (file)
@@ -51,7 +51,7 @@ static void dummy_waitbut(void)
 {
 }
 
-void (*mach_sched_init) (irqreturn_t (*handler)(int, void *, struct pt_regs *));
+void (*mach_sched_init) (irq_handler_t handler);
 void (*mach_tick)( void );
 /* machine dependent keyboard functions */
 int (*mach_keyb_init) (void);
@@ -66,7 +66,7 @@ void (*mach_trap_init) (void);
 /* machine dependent timer functions */
 unsigned long (*mach_gettimeoffset) (void);
 void (*mach_gettod) (int*, int*, int*, int*, int*, int*);
-int (*mach_hwclk) (int, struct hwclk_time*);
+int (*mach_hwclk) (int, struct rtc_time*);
 int (*mach_set_clock_mmss) (unsigned long);
 void (*mach_mksound)( unsigned int count, unsigned int ticks );
 void (*mach_reset)( void );
index 20f12a19a52257e8ef0072aa7dc0c8e894891a34..751633038c4b79061e34e5fd5bd351ed72d4955f 100644 (file)
@@ -42,7 +42,6 @@ static irq_node_t nodes[NUM_IRQ_NODES];
 /* The number of spurious interrupts */
 volatile unsigned int num_spurious;
 
-unsigned int local_bh_count[NR_CPUS];
 unsigned int local_irq_count[NR_CPUS];
 
 static irqreturn_t default_irq_handler(int irq, void *ptr)
index 2dda7339aae5cf00136df28f0896926144d0674f..3de6e337554ed5e46565e009eb45bf23030566eb 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <linux/errno.h>
+#include <linux/interrupt.h>
 
 #include <asm/system.h>
 #include <asm/irq.h>
@@ -64,7 +65,7 @@ asmlinkage void trap44(void);
 asmlinkage void trap45(void);
 asmlinkage void trap46(void);
 asmlinkage void trap47(void);
-asmlinkage irqreturn_t bad_interrupt(int, void *, struct pt_regs *);
+asmlinkage irqreturn_t bad_interrupt(int, void *);
 asmlinkage irqreturn_t inthandler(void);
 asmlinkage irqreturn_t inthandler1(void);
 asmlinkage irqreturn_t inthandler2(void);
@@ -121,7 +122,7 @@ void init_IRQ(void)
 
 int request_irq(
        unsigned int irq,
-       irqreturn_t (*handler)(int, void *, struct pt_regs *),
+       irq_handler_t handler,
        unsigned long flags,
        const char *devname,
        void *dev_id)
index 438ef6ee9720bdd7883cae83d3d73195bd8a319c..ef067f4c3cd47b8a241ea364869eda661a469ffc 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <linux/interrupt.h>
 #include <asm/setup.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
@@ -52,7 +53,7 @@
 
 /***************************************************************************/
 
-void m68328_timer_init(irqreturn_t (*timer_routine) (int, void *, struct pt_regs *))
+void m68328_timer_init(irq_handler_t timer_routine)
 {
        /* disable timer 1 */
        TCTL = 0;
index 1b36f62617645358a2c8b0aadd20d7c77bbc1f6c..4ff13bd51ffd0e536e06e3f176ad9a18b5c7d2e4 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/mm.h>
 #include <linux/tty.h>
 #include <linux/console.h>
+#include <linux/interrupt.h>
 
 #include <asm/setup.h>
 #include <asm/system.h>
@@ -50,7 +51,7 @@ extern unsigned long int system_clock; //In kernel setup.c
 
 extern void config_M68360_irq(void);
 
-void BSP_sched_init(void (*timer_routine)(int, void *, struct pt_regs *))
+void BSP_sched_init(irq_handler_t timer_routine)
 {
   unsigned char prescaler;
   unsigned short tgcr_save;
index 659b80aca118c2734664b0972f5d9016aefc4ef7..ab36551fc969616fdb7dd7773dd4c9b14f2ffe58 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/mm.h>
 #include <linux/tty.h>
 #include <linux/console.h>
+#include <linux/interrupt.h>
 
 #include <asm/setup.h>
 #include <asm/system.h>
@@ -31,7 +32,7 @@
 
 /***************************************************************************/
 
-void m68328_timer_init(irqreturn_t (*timer_routine) (int, void *, struct pt_regs *));
+void m68328_timer_init(irq_handler_t timer_routine);
 void m68328_timer_tick(void);
 unsigned long m68328_timer_gettimeoffset(void);
 void m68328_timer_gettod(int *year, int *mon, int *day, int *hour, int *min, int *sec);
index fcd100b7594d580ed4d484cbe959af21b4b8deb5..8abe0f6e7235b8e9984adca29f5d90ada099dde8 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/console.h>
 #include <linux/kd.h>
 #include <linux/netdevice.h>
+#include <linux/interrupt.h>
 
 #include <asm/setup.h>
 #include <asm/system.h>
@@ -36,7 +37,7 @@
 
 /***************************************************************************/
 
-void m68328_timer_init(irqreturn_t (*timer_routine) (int, void *, struct pt_regs *));
+void m68328_timer_init(irq_handler_t timer_routine);
 void m68328_timer_tick(void);
 unsigned long m68328_timer_gettimeoffset(void);
 void m68328_timer_gettod(int *year, int *mon, int *day, int *hour, int *min, int *sec);
index c6f74f1c6398322d1eb7e23af914886602fbd256..a1cd84f9b3bcc75e716057df0c879f463afede6f 100644 (file)
@@ -133,7 +133,7 @@ config MIPS_MIRAGE
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config BASLER_EXCITE
-       bool "Basler eXcite smart camera support"
+       bool "Basler eXcite smart camera"
        select DMA_COHERENT
        select HW_HAS_PCI
        select IRQ_CPU
@@ -147,7 +147,7 @@ config BASLER_EXCITE
        select SYS_SUPPORTS_KGDB
        help
          The eXcite is a smart camera platform manufactured by
-         Basler Vision Technologies AG
+         Basler Vision Technologies AG.
 
 config BASLER_EXCITE_PROTOTYPE
        bool "Support for pre-release units"
@@ -167,6 +167,7 @@ config MIPS_COBALT
        select IRQ_CPU
        select MIPS_GT64111
        select SYS_HAS_CPU_NEVADA
+       select SYS_HAS_EARLY_PRINTK
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
        select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -176,7 +177,7 @@ config MACH_DECSTATION
        bool "DECstations"
        select BOOT_ELF32
        select DMA_NONCOHERENT
-       select EARLY_PRINTK
+       select SYS_HAS_EARLY_PRINTK
        select IRQ_CPU
        select SYS_HAS_CPU_R3000
        select SYS_HAS_CPU_R4X00
@@ -242,6 +243,7 @@ config MACH_JAZZ
 config LASAT
        bool "LASAT Networks platforms"
        select DMA_NONCOHERENT
+       select SYS_HAS_EARLY_PRINTK
        select HW_HAS_PCI
        select MIPS_GT64120
        select MIPS_NILE4
@@ -256,6 +258,7 @@ config MIPS_ATLAS
        bool "MIPS Atlas board"
        select BOOT_ELF32
        select DMA_NONCOHERENT
+       select SYS_HAS_EARLY_PRINTK
        select IRQ_CPU
        select HW_HAS_PCI
        select MIPS_BOARDS_GEN
@@ -274,6 +277,7 @@ config MIPS_ATLAS
        select SYS_SUPPORTS_BIG_ENDIAN
        select SYS_SUPPORTS_LITTLE_ENDIAN
        select SYS_SUPPORTS_MULTITHREADING if EXPERIMENTAL
+       select SYS_SUPPORTS_SMARTMIPS
        select GENERIC_HARDIRQS_NO__DO_IRQ
        help
          This enables support for the MIPS Technologies Atlas evaluation
@@ -300,11 +304,13 @@ config MIPS_MALTA
        select SYS_HAS_CPU_MIPS64_R1
        select SYS_HAS_CPU_NEVADA
        select SYS_HAS_CPU_RM7000
+       select SYS_HAS_EARLY_PRINTK
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_64BIT_KERNEL
        select SYS_SUPPORTS_BIG_ENDIAN
        select SYS_SUPPORTS_LITTLE_ENDIAN
        select SYS_SUPPORTS_MULTITHREADING
+       select SYS_SUPPORTS_SMARTMIPS
        help
          This enables support for the MIPS Technologies Malta evaluation
          board.
@@ -314,6 +320,7 @@ config MIPS_SEAD
        depends on EXPERIMENTAL
        select IRQ_CPU
        select DMA_NONCOHERENT
+       select SYS_HAS_EARLY_PRINTK
        select MIPS_BOARDS_GEN
        select SYS_HAS_CPU_MIPS32_R1
        select SYS_HAS_CPU_MIPS32_R2
@@ -322,6 +329,7 @@ config MIPS_SEAD
        select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
        select SYS_SUPPORTS_BIG_ENDIAN
        select SYS_SUPPORTS_LITTLE_ENDIAN
+       select SYS_SUPPORTS_SMARTMIPS
        help
          This enables support for the MIPS Technologies SEAD evaluation
          board.
@@ -350,9 +358,11 @@ config WR_PPMC
 config MIPS_SIM
        bool 'MIPS simulator (MIPSsim)'
        select DMA_NONCOHERENT
+       select SYS_HAS_EARLY_PRINTK
        select IRQ_CPU
        select SYS_HAS_CPU_MIPS32_R1
        select SYS_HAS_CPU_MIPS32_R2
+       select SYS_HAS_EARLY_PRINTK
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_BIG_ENDIAN
        select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -373,6 +383,7 @@ config MOMENCO_JAGUAR_ATX
        select RM7000_CPU_SCACHE
        select SWAP_IO_SPACE
        select SYS_HAS_CPU_RM9000
+       select SYS_HAS_EARLY_PRINTK
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_64BIT_KERNEL
        select SYS_SUPPORTS_BIG_ENDIAN
@@ -510,6 +521,7 @@ config PMC_YOSEMITE
        select IRQ_CPU_RM9K
        select SWAP_IO_SPACE
        select SYS_HAS_CPU_RM9000
+       select SYS_HAS_EARLY_PRINTK
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_64BIT_KERNEL
        select SYS_SUPPORTS_BIG_ENDIAN
@@ -570,6 +582,7 @@ config SGI_IP22
        select SWAP_IO_SPACE
        select SYS_HAS_CPU_R4X00
        select SYS_HAS_CPU_R5000
+       select SYS_HAS_EARLY_PRINTK
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_64BIT_KERNEL
        select SYS_SUPPORTS_BIG_ENDIAN
@@ -584,7 +597,7 @@ config SGI_IP27
        select ARC64
        select BOOT_ELF64
        select DMA_IP27
-       select EARLY_PRINTK
+       select SYS_HAS_EARLY_PRINTK
        select HW_HAS_PCI
        select NR_CPUS_DEFAULT_64
        select PCI_DOMAINS
@@ -746,6 +759,7 @@ config SNI_RM
        select SYS_HAS_CPU_R5000
        select SYS_HAS_CPU_R10000
        select R5000_CPU_SCACHE
+       select SYS_HAS_EARLY_PRINTK
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
        select SYS_SUPPORTS_BIG_ENDIAN
@@ -824,7 +838,6 @@ source "arch/mips/tx4927/Kconfig"
 source "arch/mips/tx4938/Kconfig"
 source "arch/mips/vr41xx/Kconfig"
 source "arch/mips/philips/pnx8550/common/Kconfig"
-source "arch/mips/cobalt/Kconfig"
 
 endmenu
 
@@ -894,6 +907,20 @@ config DMA_NEED_PCI_MAP_STATE
        bool
 
 config EARLY_PRINTK
+       bool "Early printk" if EMBEDDED && DEBUG_KERNEL
+       depends on SYS_HAS_EARLY_PRINTK
+       default y
+       help
+         This option enables special console drivers which allow the kernel
+         to print messages very early in the bootup process.
+
+         This is useful for kernel debugging when your machine crashes very
+         early before the console code is initialized. For normal operation
+         it is not recommended because it looks on some machines ugly and
+         oesn't cooperate with an X server. You should normally N here,
+         unless you want to debug such a crash.
+
+config SYS_HAS_EARLY_PRINTK
        bool
 
 config GENERIC_ISA_DMA
@@ -1030,6 +1057,7 @@ config SOC_PNX8550
        select DMA_NONCOHERENT
        select HW_HAS_PCI
        select SYS_HAS_CPU_MIPS32_R1
+       select SYS_HAS_EARLY_PRINTK
        select SYS_SUPPORTS_32BIT_KERNEL
        select GENERIC_HARDIRQS_NO__DO_IRQ
        select SYS_SUPPORTS_KGDB
@@ -1090,7 +1118,7 @@ config HAVE_STD_PC_SERIAL_PORT
 
 config ARC_CONSOLE
        bool "ARC console support"
-       depends on SGI_IP22 || SNI_RM
+       depends on SGI_IP22 || (SNI_RM && CPU_LITTLE_ENDIAN)
 
 config ARC_MEMORY
        bool
@@ -1641,6 +1669,18 @@ config 64BIT_PHYS_ADDR
 config CPU_HAS_LLSC
        bool
 
+config CPU_HAS_SMARTMIPS
+       depends on SYS_SUPPORTS_SMARTMIPS
+       bool "Support for the SmartMIPS ASE"
+       help
+         SmartMIPS is a extension of the MIPS32 architecture aimed at
+         increased security at both hardware and software level for
+         smartcards.  Enabling this option will allow proper use of the
+         SmartMIPS instructions by Linux applications.  However a kernel with
+         this option will not work on a MIPS core without SmartMIPS core.  If
+         you don't know you probably don't have SmartMIPS and should say N
+         here.
+
 config CPU_HAS_WB
        bool
 
@@ -1704,6 +1744,9 @@ config CPU_SUPPORTS_HIGHMEM
 config SYS_SUPPORTS_HIGHMEM
        bool
 
+config SYS_SUPPORTS_SMARTMIPS
+       bool
+
 config ARCH_FLATMEM_ENABLE
        def_bool y
        depends on !NUMA
@@ -1877,10 +1920,6 @@ config HZ
 
 source "kernel/Kconfig.preempt"
 
-config RTC_DS1742
-       bool "DS1742 BRAM/RTC support"
-       depends on TOSHIBA_JMR3927 || TOSHIBA_RBTX4927
-
 config MIPS_INSANE_LARGE
        bool "Support for large 64-bit configurations"
        depends on CPU_R10000 && 64BIT
index d5e60a0c1ded6b55f0fdbdc3eb895a38560c7a7e..72d5c198e790bdaa5ca9b38f7399f3beb4e147ea 100644 (file)
@@ -37,6 +37,15 @@ config DEBUG_STACK_USAGE
 
          This option will slow down process creation somewhat.
 
+config CONFIG_SMTC_IDLE_HOOK_DEBUG
+       bool "Enable additional debug checks before going into CPU idle loop"
+       depends on DEBUG_KERNEL && MIPS_MT_SMTC
+       help
+         This option enables Enable additional debug checks before going into
+         CPU idle loop.  For details on these checks, see
+         arch/mips/kernel/smtc.c.  This debugging option result in significant
+         overhead so should be disabled in production kernels.
+
 config KGDB
        bool "Remote GDB kernel debugging"
        depends on DEBUG_KERNEL && SYS_SUPPORTS_KGDB
index c68b5d3e5d180c639e964df00557b60d43f3f3bd..92bca6ad6ab18178630e1f4c1064208501d02b69 100644 (file)
@@ -103,6 +103,8 @@ predef-le += -DMIPSEL -D_MIPSEL -D__MIPSEL -D__MIPSEL__
 cflags-$(CONFIG_CPU_BIG_ENDIAN)                += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' && echo -EB $(undef-all) $(predef-be))
 cflags-$(CONFIG_CPU_LITTLE_ENDIAN)     += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' || echo -EL $(undef-all) $(predef-le))
 
+cflags-$(CONFIG_CPU_HAS_SMARTMIPS)     += $(call cc-option,-msmartmips)
+
 cflags-$(CONFIG_SB1XXX_CORELIS)        += $(call cc-option,-mno-sched-prolog) \
                                   -fno-omit-frame-pointer
 
index 6a9d144512c01dcb34d58517d7fbb94140b22155..0fe6032999cbc4f2ff602c7c791490e68bb981e8 100644 (file)
@@ -29,35 +29,3 @@ void prom_putchar(char c)
        ArcWrite(1, &it, 1, &cnt);
        bc_enable();
 }
-
-char prom_getchar(void)
-{
-       ULONG cnt;
-       CHAR c;
-
-       bc_disable();
-       ArcRead(0, &c, 1, &cnt);
-       bc_enable();
-
-       return c;
-}
-
-void prom_printf(char *fmt, ...)
-{
-       va_list args;
-       char ppbuf[1024];
-       char *bptr;
-
-       va_start(args, fmt);
-       vsprintf(ppbuf, fmt, args);
-
-       bptr = ppbuf;
-
-       while (*bptr != 0) {
-               if (*bptr == '\n')
-                       prom_putchar('\r');
-
-               prom_putchar(*bptr++);
-       }
-       va_end(args);
-}
index 76ab505ca69302e59c43cc8eb974d4e77457f888..e2f75b13312f1a3940b1469462711f35e8cb2f31 100644 (file)
@@ -23,13 +23,16 @@ LONG *_prom_argv, *_prom_envp;
 void __init prom_init(void)
 {
        PSYSTEM_PARAMETER_BLOCK pb = PROMBLOCK;
+
        romvec = ROMVECTOR;
+
        prom_argc = fw_arg0;
        _prom_argv = (LONG *) fw_arg1;
        _prom_envp = (LONG *) fw_arg2;
 
        if (pb->magic != 0x53435241) {
-               prom_printf("Aieee, bad prom vector magic %08lx\n", pb->magic);
+               printk(KERN_CRIT "Aieee, bad prom vector magic %08lx\n",
+                      (unsigned long) pb->magic);
                while(1)
                        ;
        }
@@ -41,8 +44,8 @@ void __init prom_init(void)
        prom_meminit();
 
 #ifdef DEBUG_PROM_INIT
-       prom_printf("Press a key to reboot\n");
-       prom_getchar();
+       pr_info("Press a key to reboot\n");
+       ArcRead(0, &c, 1, &cnt);
        ArcEnterInteractiveMode();
 #endif
 }
index 456cb81a32d9c88edb5d9abba1138f37cccb30aa..83d15791ef6a589a596e2004b7e2de1ccd11867d 100644 (file)
@@ -118,11 +118,11 @@ void __init prom_meminit(void)
 #ifdef DEBUG
        int i = 0;
 
-       prom_printf("ARCS MEMORY DESCRIPTOR dump:\n");
+       printk("ARCS MEMORY DESCRIPTOR dump:\n");
        p = ArcGetMemoryDescriptor(PROM_NULL_MDESC);
        while(p) {
-               prom_printf("[%d,%p]: base<%08lx> pages<%08lx> type<%s>\n",
-                           i, p, p->base, p->pages, mtypes(p->type));
+               printk("[%d,%p]: base<%08lx> pages<%08lx> type<%s>\n",
+                      i, p, p->base, p->pages, mtypes(p->type));
                p = ArcGetMemoryDescriptor(p);
                i++;
        }
index 2aedd4f528392632e788a3ea7d43a072deb03be5..abd1786ea09b13bd33ecabacc5508c69590e0840 100644 (file)
@@ -93,11 +93,11 @@ static char *iflags[] = {
 static void __init
 dump_component(pcomponent *p)
 {
-       prom_printf("[%p]:class<%s>type<%s>flags<%s>ver<%d>rev<%d>",
-                   p, classes[p->class], types[p->type],
-                   iflags[p->iflags], p->vers, p->rev);
-       prom_printf("key<%08lx>\n\tamask<%08lx>cdsize<%d>ilen<%d>iname<%s>\n",
-                   p->key, p->amask, (int)p->cdsize, (int)p->ilen, p->iname);
+       printk("[%p]:class<%s>type<%s>flags<%s>ver<%d>rev<%d>",
+              p, classes[p->class], types[p->type],
+              iflags[p->iflags], p->vers, p->rev);
+       printk("key<%08lx>\n\tamask<%08lx>cdsize<%d>ilen<%d>iname<%s>\n",
+              p->key, p->amask, (int)p->cdsize, (int)p->ilen, p->iname);
 }
 
 static void __init
index 13f9bf5f91a628c10e92b6522c9db2d9a921d87d..7bc5af8917dafacde69719fa6fafb14ff0eed8d1 100644 (file)
@@ -43,6 +43,9 @@
 #include <asm/pgtable.h>
 #include <asm/mach-au1x00/au1000.h>
 
+extern int (*board_pci_idsel)(unsigned int devsel, int assert);
+int    mtx1_pci_idsel(unsigned int devsel, int assert);
+
 void board_reset (void)
 {
        /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
@@ -66,19 +69,43 @@ void __init board_setup(void)
 #endif
 
        // initialize sys_pinfunc:
-       // disable second ethernet port (SYS_PF_NI2)
-       // set U3/GPIO23 to GPIO23 (SYS_PF_U3)
-       au_writel( SYS_PF_NI2 | SYS_PF_U3, SYS_PINFUNC );
+       au_writel( SYS_PF_NI2, SYS_PINFUNC );
 
        // initialize GPIO
        au_writel( 0xFFFFFFFF, SYS_TRIOUTCLR );
        au_writel( 0x00000001, SYS_OUTPUTCLR ); // set M66EN (PCI 66MHz) to OFF
        au_writel( 0x00000008, SYS_OUTPUTSET ); // set PCI CLKRUN# to OFF
+       au_writel( 0x00000002, SYS_OUTPUTSET ); // set EXT_IO3 ON
        au_writel( 0x00000020, SYS_OUTPUTCLR ); // set eth PHY TX_ER to OFF
 
        // enable LED and set it to green
        au_writel( au_readl(GPIO2_DIR) | 0x1800, GPIO2_DIR );
        au_writel( 0x18000800, GPIO2_OUTPUT );
 
+       board_pci_idsel = mtx1_pci_idsel;
+
        printk("4G Systems MTX-1 Board\n");
 }
+
+int
+mtx1_pci_idsel(unsigned int devsel, int assert)
+{
+#define MTX_IDSEL_ONLY_0_AND_3 0
+#if MTX_IDSEL_ONLY_0_AND_3
+       if (devsel != 0 && devsel != 3) {
+               printk("*** not 0 or 3\n");
+               return 0;
+       }
+#endif
+
+       if (assert && devsel != 0) {
+               // supress signal to cardbus
+               au_writel( 0x00000002, SYS_OUTPUTCLR ); // set EXT_IO3 OFF
+       }
+       else {
+               au_writel( 0x00000002, SYS_OUTPUTSET ); // set EXT_IO3 ON
+       }
+       au_sync_udelay(1);
+       return 1;
+}
+
index 4693a4eb2b829972966a0ee1306b54cb07ade10e..a4fa0f227e420d2958b8645a109bd0bd3688e79c 100644 (file)
@@ -48,7 +48,7 @@
 #include <asm/mach-au1x00/au1000.h>
 
 char irq_tab_alchemy[][5] __initdata = {
- [0] = { -1, INTA, INTB, INTX, INTX},   /* IDSEL 00 - AdapterA-Slot0 (top)    */
+ [0] = { -1, INTA, INTA, INTX, INTX},   /* IDSEL 00 - AdapterA-Slot0 (top)    */
  [1] = { -1, INTB, INTA, INTX, INTX},   /* IDSEL 01 - AdapterA-Slot1 (bottom) */
  [2] = { -1, INTC, INTD, INTX, INTX},   /* IDSEL 02 - AdapterB-Slot0 (top)    */
  [3] = { -1, INTD, INTC, INTX, INTX},   /* IDSEL 03 - AdapterB-Slot1 (bottom) */
index a1ce4580058dfc936cb137f82dabbce7b7cd7021..42f0eda1d51f1994ff163ae5dca8030f3cf8daf8 100644 (file)
@@ -112,7 +112,7 @@ static int __init excite_init_console(void)
        up.irq          = TITAN_IRQ;
        up.uartclk      = TITAN_UART_CLK;
        up.regshift     = 0;
-       up.iotype       = UPIO_MEM32;
+       up.iotype       = UPIO_RM9000;
        up.type         = PORT_RM9000;
        up.flags        = UPF_SHARE_IRQ;
        up.line         = 0;
diff --git a/arch/mips/cobalt/Kconfig b/arch/mips/cobalt/Kconfig
deleted file mode 100644 (file)
index 7c42b08..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-config EARLY_PRINTK
-       bool "Early console support"
-       depends on MIPS_COBALT
-       help
-         Provide early console support by direct access to the
-         on board UART. The UART must have been previously
-         initialised by the boot loader.
index 225ac8f34ccd574cb3dd6f9d68d9d569c4782ada..b36dd8f538f9e310789581faebd679d8e7a3bb98 100644 (file)
@@ -5,5 +5,4 @@
 obj-y   := irq.o reset.o setup.o
 
 obj-$(CONFIG_EARLY_PRINTK)     += console.o
-
-EXTRA_AFLAGS := $(CFLAGS)
+obj-$(CONFIG_MTD_PHYSMAP)      += mtd.o
index 46c23b66bc171883d2d9ae2e58dc8d750ffd7bab..ca56b415b8ac30c3e6b45a7c02767a9226e12ce1 100644 (file)
@@ -9,39 +9,10 @@
 #include <asm/addrspace.h>
 #include <asm/mach-cobalt/cobalt.h>
 
-static void putchar(int c)
+void prom_putchar(char c)
 {
-       if(c == '\n')
-               putchar('\r');
-
        while(!(COBALT_UART[UART_LSR] & UART_LSR_THRE))
                ;
 
        COBALT_UART[UART_TX] = c;
 }
-
-static void cons_write(struct console *c, const char *s, unsigned n)
-{
-       while(n-- && *s)
-               putchar(*s++);
-}
-
-static struct console cons_info =
-{
-       .name   = "uart",
-       .write  = cons_write,
-       .flags  = CON_PRINTBUFFER | CON_BOOT,
-       .index  = -1,
-};
-
-void __init cobalt_early_console(void)
-{
-       register_console(&cons_info);
-
-       printk("Cobalt: early console registered\n");
-}
-
-void __init disable_early_printk(void)
-{
-       unregister_console(&cons_info);
-}
diff --git a/arch/mips/cobalt/mtd.c b/arch/mips/cobalt/mtd.c
new file mode 100644 (file)
index 0000000..2b088ef
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ *  Registration of Cobalt MTD device.
+ *
+ *  Copyright (C) 2006  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+
+static struct mtd_partition cobalt_mtd_partitions[] = {
+       {
+               .name   = "firmware",
+               .offset = 0x0,
+               .size   = 0x80000,
+       },
+};
+
+static struct physmap_flash_data cobalt_flash_data = {
+       .width          = 1,
+       .nr_parts       = 1,
+       .parts          = cobalt_mtd_partitions,
+};
+
+static struct resource cobalt_mtd_resource = {
+       .start  = 0x1fc00000,
+       .end    = 0x1fc7ffff,
+       .flags  = IORESOURCE_MEM,
+};
+
+static struct platform_device cobalt_mtd = {
+       .name           = "physmap-flash",
+       .dev            = {
+               .platform_data  = &cobalt_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &cobalt_mtd_resource,
+};
+
+static int __init cobalt_mtd_init(void)
+{
+       platform_device_register(&cobalt_mtd);
+
+       return 0;
+}
+
+module_init(cobalt_mtd_init);
index 415ff8710b553d3e76ea3f0589d70da63cedbb67..88d34f11385acc6c42d5b518a805357e686cfecc 100644 (file)
@@ -79,37 +79,38 @@ static struct resource cobalt_io_resource = {
        .flags  = IORESOURCE_IO
 };
 
-static struct resource cobalt_io_resources[] = {
-       {
+/*
+ * Cobalt doesn't have PS/2 keyboard/mouse interfaces,
+ * keyboard conntroller is never used.
+ * Also PCI-ISA bridge DMA contoroller is never used.
+ */
+static struct resource cobalt_reserved_resources[] = {
+       {       /* dma1 */
                .start  = 0x00,
                .end    = 0x1f,
-               .name   = "dma1",
-               .flags  = IORESOURCE_BUSY
-       }, {
-               .start  = 0x40,
-               .end    = 0x5f,
-               .name   = "timer",
-               .flags  = IORESOURCE_BUSY
-       }, {
+               .name   = "reserved",
+               .flags  = IORESOURCE_BUSY | IORESOURCE_IO,
+       },
+       {       /* keyboard */
                .start  = 0x60,
                .end    = 0x6f,
-               .name   = "keyboard",
-               .flags  = IORESOURCE_BUSY
-       }, {
+               .name   = "reserved",
+               .flags  = IORESOURCE_BUSY | IORESOURCE_IO,
+       },
+       {       /* dma page reg */
                .start  = 0x80,
                .end    = 0x8f,
-               .name   = "dma page reg",
-               .flags  = IORESOURCE_BUSY
-       }, {
+               .name   = "reserved",
+               .flags  = IORESOURCE_BUSY | IORESOURCE_IO,
+       },
+       {       /* dma2 */
                .start  = 0xc0,
                .end    = 0xdf,
-               .name   = "dma2",
-               .flags  = IORESOURCE_BUSY
+               .name   = "reserved",
+               .flags  = IORESOURCE_BUSY | IORESOURCE_IO,
        },
 };
 
-#define COBALT_IO_RESOURCES (sizeof(cobalt_io_resources)/sizeof(struct resource))
-
 static struct pci_controller cobalt_pci_controller = {
        .pci_ops        = &gt64111_pci_ops,
        .mem_resource   = &cobalt_mem_resource,
@@ -133,9 +134,9 @@ void __init plat_mem_setup(void)
        /* I/O port resource must include LCD/buttons */
        ioport_resource.end = 0x0fffffff;
 
-       /* request I/O space for devices used on all i[345]86 PCs */
-       for (i = 0; i < COBALT_IO_RESOURCES; i++)
-               request_resource(&ioport_resource, cobalt_io_resources + i);
+       /* These resources have been reserved by VIA SuperI/O chip. */
+       for (i = 0; i < ARRAY_SIZE(cobalt_reserved_resources); i++)
+               request_resource(&ioport_resource, cobalt_reserved_resources + i);
 
         /* Read the cobalt id register out of the PCI config space */
         PCI_CFG_SET(devfn, (VIA_COBALT_BRD_ID_REG & ~0x3));
@@ -150,10 +151,6 @@ void __init plat_mem_setup(void)
 #endif
 
        if (cobalt_board_id > COBALT_BRD_ID_RAQ1) {
-#ifdef CONFIG_EARLY_PRINTK
-               cobalt_early_console();
-#endif
-
 #ifdef CONFIG_SERIAL_8250
                uart.line       = 0;
                uart.type       = PORT_UNKNOWN;
index 45874d1038d33d2ddf7a50a8e994f930a0cce4b3..458894933a4c731e03e88ce44f7e02dcd3a28f20 100644 (file)
@@ -139,10 +139,12 @@ CONFIG_MIPS_MT_DISABLED=y
 CONFIG_SYS_SUPPORTS_MULTITHREADING=y
 # CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_HAS_SMARTMIPS is not set
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_SYS_SUPPORTS_SMARTMIPS=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
index b4cdd3e7cdfc4ca37e800e3bba4ea837ddcf1059..aa05e294ea6223fa9585de10d4e12f2962fdad19 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:35 2007
+# Tue Feb 20 21:47:22 2007
 #
 CONFIG_MIPS=y
 
@@ -417,6 +417,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -589,6 +590,7 @@ CONFIG_NET_SB1250_MAC=y
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 # CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -1025,7 +1027,6 @@ CONFIG_FORCED_INLINING=y
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 # CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_KGDB is not set
 # CONFIG_SB1XXX_CORELIS is not set
 # CONFIG_RUNTIME_DEBUG is not set
 
index b05469e0bcd0c2a55dc29eb26bf5f8b4e5342295..b2594fa556f3373ea8a885ddb39cf6295fff9d3a 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:36 2007
+# Tue Feb 20 21:47:22 2007
 #
 CONFIG_MIPS=y
 
@@ -388,6 +388,7 @@ CONFIG_CONNECTOR=m
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
index 1a3d776ad1e4d889e81d32bc93e2130843dc4af0..9090a7aba6c1cbd2a481687b1ca47788b1a015ea 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:37 2007
+# Tue Feb 20 21:47:24 2007
 #
 CONFIG_MIPS=y
 
@@ -373,7 +373,87 @@ CONFIG_PROC_EVENTS=y
 #
 # Memory Technology Devices (MTD)
 #
-# CONFIG_MTD is not set
+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_BLKDEVS=y
+# CONFIG_MTD_BLOCK is not set
+# CONFIG_MTD_BLOCK_RO is not set
+# 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 is not set
+CONFIG_MTD_JEDECPROBE=y
+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=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
 
 #
 # Parallel port support
@@ -383,6 +463,7 @@ CONFIG_PROC_EVENTS=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -577,6 +658,7 @@ CONFIG_TULIP=y
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_QLA3XXX=y
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -901,6 +983,7 @@ CONFIG_CONFIGFS_FS=y
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_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
index 1db19f1bfd4dd74c1dcd62ef6af16a702ccdf3c8..4cb8cf4255a2dd732d412768af8db45a6da6e893 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:39 2007
+# Tue Feb 20 21:47:24 2007
 #
 CONFIG_MIPS=y
 
@@ -548,6 +548,7 @@ CONFIG_MTD_ALCHEMY=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -1103,6 +1104,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
index 529e6ebe2a8d2dda0e8f68969f9ec1b38669cd97..d86dedf27fc4fcd4dfd042afe24f1b9dcc0e5175 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:39 2007
+# Tue Feb 20 21:47:24 2007
 #
 CONFIG_MIPS=y
 
@@ -537,6 +537,7 @@ CONFIG_MTD_ALCHEMY=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -1103,6 +1104,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
index 9e86dcd3c31e17754c4fa0825b4f05f814172c40..c24b6008345e67bc2df17a271bcc2a2d41be74e7 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:40 2007
+# Tue Feb 20 21:47:25 2007
 #
 CONFIG_MIPS=y
 
@@ -541,6 +541,7 @@ CONFIG_MTD_NAND_IDS=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -1185,6 +1186,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="mem=48M"
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
index 9c944611edaa6282977af2d87e504f2906edab71..baad2c5223ba34339bbc04934d9218c9f17eb8b9 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:41 2007
+# Tue Feb 20 21:47:26 2007
 #
 CONFIG_MIPS=y
 
@@ -542,7 +542,6 @@ CONFIG_MTD_ALCHEMY=y
 # NAND Flash Device Drivers
 #
 # CONFIG_MTD_NAND is not set
-# CONFIG_MTD_NAND_CAFE is not set
 
 #
 # OneNAND Flash Device Drivers
@@ -557,6 +556,7 @@ CONFIG_MTD_ALCHEMY=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -715,6 +715,7 @@ CONFIG_MIPS_AU1X00_ENET=y
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -1145,6 +1146,7 @@ CONFIG_USB_MON=y
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -1402,6 +1404,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
index 5b18d5da985870d5e7bb7c0de8ff9a75a8cb1187..c29fdab0423a229293b360496e9fe94f0d0713f7 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:42 2007
+# Tue Feb 20 21:47:27 2007
 #
 CONFIG_MIPS=y
 
@@ -562,6 +562,7 @@ CONFIG_MTD_NAND_AU1550=m
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -751,6 +752,7 @@ CONFIG_MIPS_AU1X00_ENET=y
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -1219,6 +1221,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
index 1210188861894b666f9f92d73c570fbe12da59c5..f4b316d2cd707256ba62a709fdb7917c4b59ffe3 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:43 2007
+# Tue Feb 20 21:47:28 2007
 #
 CONFIG_MIPS=y
 
@@ -386,6 +386,7 @@ CONFIG_PROC_EVENTS=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -925,6 +926,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="ip=any"
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
index 2d717455a82fc413cf1a26157fae9c9980c9b4ae..9c38e5c777617a963cafb2202a877b91e8751569 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:44 2007
+# Tue Feb 20 21:47:28 2007
 #
 CONFIG_MIPS=y
 
@@ -398,6 +398,7 @@ CONFIG_CONNECTOR=m
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
index 0ee2fbb35f14e5059729f6ac851321c15ffa4a99..922af379aa4114155103d7bd96b10270e7920784 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:44 2007
+# Tue Feb 20 21:47:28 2007
 #
 CONFIG_MIPS=y
 
@@ -294,6 +294,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # Plug and Play support
 #
 # CONFIG_PNP is not set
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
index 218fe6e5f2dbe035c4f43bcf63f02faea2900e36..c0db8f14713d2f851cb73ffa378f1a1a6b105f6b 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:46 2007
+# Tue Feb 20 21:47:29 2007
 #
 CONFIG_MIPS=y
 
@@ -611,7 +611,6 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
 # NAND Flash Device Drivers
 #
 # CONFIG_MTD_NAND is not set
-# CONFIG_MTD_NAND_CAFE is not set
 
 #
 # OneNAND Flash Device Drivers
@@ -626,6 +625,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -1039,6 +1039,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ADM9240 is not set
 # CONFIG_SENSORS_ASB100 is not set
index 5ad4870ad5ebff33e81549fd69b78f1e906f757a..ce088b36291d56c26bb605e1a86a43207fa16cb6 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:46 2007
+# Tue Feb 20 21:47:30 2007
 #
 CONFIG_MIPS=y
 
@@ -391,6 +391,7 @@ CONFIG_CONNECTOR=m
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -520,6 +521,7 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -914,6 +916,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs rw nfsroot=192.168.1.1:/mnt/disk2/fs.gal ip=192.168.1.211:192.168.1.1:::gt::"
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
index 5e179fe599b3bb7150976361a62c0848b5db98a0..82f204d080b765aae8a666cbdc4078fe572a8431 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:47 2007
+# Tue Feb 20 21:47:31 2007
 #
 CONFIG_MIPS=y
 
@@ -451,6 +451,7 @@ CONFIG_MTD_NAND_VERIFY_WRITE=y
 # CONFIG_MTD_NAND_ECC_SMC is not set
 CONFIG_MTD_NAND_IDS=y
 # CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_BASLER_EXCITE is not set
 # CONFIG_MTD_NAND_CAFE is not set
 # CONFIG_MTD_NAND_NANDSIM is not set
 
@@ -467,6 +468,7 @@ CONFIG_MTD_NAND_IDS=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -638,6 +640,7 @@ CONFIG_NETDEVICES=y
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -1008,6 +1011,7 @@ CONFIG_USB_HID=m
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -1277,6 +1281,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
index 864de219eb67bedb9ca5aed065282970f09832e7..cb81f13bd45a937e01461f6b3b40590ec370e600 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:48 2007
+# Tue Feb 20 21:47:32 2007
 #
 CONFIG_MIPS=y
 
@@ -620,6 +620,7 @@ CONFIG_CONNECTOR=m
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
index 7b2f5f8397a2c7d70a5efbfa30f29277b3eac74c..46f6ac4083b97ae6c82767e17b6b6f72a8707b03 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:49 2007
+# Tue Feb 20 21:47:32 2007
 #
 CONFIG_MIPS=y
 
@@ -456,6 +456,7 @@ CONFIG_CONNECTOR=m
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -672,6 +673,7 @@ CONFIG_SGI_IOC3_ETH=y
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -1060,6 +1062,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_LOG_BUF_SHIFT=15
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
index 14398e8a1768fea0c159dbe7bd0ccbdd38261647..d9e5000d5329aa6b842b34471b752b69c4ee188e 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:50 2007
+# Tue Feb 20 21:47:33 2007
 #
 CONFIG_MIPS=y
 
@@ -396,6 +396,7 @@ CONFIG_PROC_EVENTS=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -600,6 +601,7 @@ CONFIG_SGI_O2MACE_ETH=y
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_QLA3XXX=y
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
index b38978794a5a2c05b7efa78b561c97ea5397b87f..57ef0c45a62b7049a817a65c19c7f829c1dc7bcc 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:51 2007
+# Tue Feb 20 21:47:33 2007
 #
 CONFIG_MIPS=y
 
@@ -375,6 +375,7 @@ CONFIG_CONNECTOR=m
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -518,9 +519,6 @@ CONFIG_EEPRO100=y
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_MV643XX_ETH=y
-CONFIG_MV643XX_ETH_0=y
-CONFIG_MV643XX_ETH_1=y
-CONFIG_MV643XX_ETH_2=y
 CONFIG_QLA3XXX=m
 
 #
@@ -833,6 +831,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
index dacf0a618d574949d0a5412dc6610da54b2c3efc..21d979f8326cd5cebdade48219ba3a860090fdbf 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:52 2007
+# Tue Feb 20 21:47:33 2007
 #
 CONFIG_MIPS=y
 
@@ -646,6 +646,7 @@ CONFIG_PARPORT_1284=y
 # Plug and Play support
 #
 # CONFIG_PNP is not set
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
index 29ed772455f133a8fc944467d546b2f6831f6895..98b9fbc042f42f54c83eecbd826d64db7486aeae 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:53 2007
+# Tue Feb 20 21:47:34 2007
 #
 CONFIG_MIPS=y
 
@@ -148,7 +148,6 @@ CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
-CONFIG_RTC_DS1742=y
 # CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
@@ -384,6 +383,7 @@ CONFIG_PROC_EVENTS=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -513,6 +513,7 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_QLA3XXX=y
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -800,7 +801,28 @@ CONFIG_USB_ARCH_HAS_EHCI=y
 #
 # Real Time Clock
 #
-# CONFIG_RTC_CLASS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+CONFIG_RTC_DRV_DS1742=y
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_V3020 is not set
 
 #
 # DMA Engine support
index a1437b34e18f7115bd85a39e144a3b2f8a4aaba0..b3f767ff1c5ae7d967ee951fefb4d77fdfc71ddd 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:54 2007
+# Tue Feb 20 21:47:34 2007
 #
 CONFIG_MIPS=y
 
@@ -454,7 +454,6 @@ CONFIG_MTD_LASAT=y
 # NAND Flash Device Drivers
 #
 # CONFIG_MTD_NAND is not set
-# CONFIG_MTD_NAND_CAFE is not set
 
 #
 # OneNAND Flash Device Drivers
@@ -469,6 +468,7 @@ CONFIG_MTD_LASAT=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -654,6 +654,7 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
index 8d21bb96349e24fe57ab36f810d71c0f721f711d..a5f379d626d6101e1d17e0c6658db75ac792b358 100644 (file)
@@ -145,6 +145,7 @@ CONFIG_SYS_SUPPORTS_MULTITHREADING=y
 CONFIG_MIPS_MT_FPAFF=y
 # CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_HAS_SMARTMIPS is not set
 CONFIG_CPU_MIPSR2_IRQ_VI=y
 CONFIG_CPU_MIPSR2_SRS=y
 CONFIG_CPU_HAS_SYNC=y
@@ -152,6 +153,7 @@ CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_SYS_SUPPORTS_SMARTMIPS=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
index 2acb99bf2eca3e9498d8da6e67d20ca7c53cc742..5ff53e184912d314ec1c6a216a20401c3bd3f0be 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:56 2007
+# Tue Feb 20 21:47:35 2007
 #
 CONFIG_MIPS=y
 
@@ -436,6 +436,7 @@ CONFIG_FIB_RULES=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -878,7 +879,6 @@ CONFIG_FORCED_INLINING=y
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="nfsroot=192.168.192.169:/u1/mipsel,timeo=20 ip=dhcp"
 # CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_KGDB is not set
 # CONFIG_RUNTIME_DEBUG is not set
 # CONFIG_MIPS_UNCACHED is not set
 
index d52a5a4877da9871acc5dd64daa98ab3832c6e67..750e6445c613ebc5b42e2d2cbf14f1d5f528509c 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:56 2007
+# Tue Feb 20 21:47:35 2007
 #
 CONFIG_MIPS=y
 
@@ -405,6 +405,7 @@ CONFIG_CONNECTOR=m
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -531,6 +532,7 @@ CONFIG_MII=m
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -883,6 +885,7 @@ CONFIG_USB_PEGASUS=m
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
index 746106b88babbf8abbbcee6eeed2a4fda58b9c0d..2febd0a7fba293b65cbc2c0dfb54a152196239d6 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:58 2007
+# Tue Feb 20 21:47:35 2007
 #
 CONFIG_MIPS=y
 
@@ -496,6 +496,7 @@ CONFIG_CONNECTOR=m
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -713,9 +714,6 @@ CONFIG_E100=y
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_MV643XX_ETH=y
-CONFIG_MV643XX_ETH_0=y
-CONFIG_MV643XX_ETH_1=y
-CONFIG_MV643XX_ETH_2=y
 CONFIG_QLA3XXX=m
 # CONFIG_ATL1 is not set
 
index 4b32b270df39316df062eaa32b85d8902da904a0..b8f457300bbf9a328d24780b7e6f2df7d7a7c628 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:58 2007
+# Tue Feb 20 21:47:36 2007
 #
 CONFIG_MIPS=y
 
@@ -393,6 +393,7 @@ CONFIG_PROC_EVENTS=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -523,6 +524,7 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_BNX2 is not set
 # CONFIG_MV643XX_ETH is not set
 CONFIG_QLA3XXX=y
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
index 674631b09c99ab90313b912994118451e4d62afa..8ade072271cd4e52fbab8c74c0115276628cc126 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:59 2007
+# Tue Feb 20 21:47:36 2007
 #
 CONFIG_MIPS=y
 
@@ -390,6 +390,7 @@ CONFIG_PROC_EVENTS=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -854,6 +855,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
index 260026392347d6bf439337bccbc5feac08fd8651..d20a2216c11d6705e4640146889ad515bdcd11d4 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:28:00 2007
+# Tue Feb 20 21:47:36 2007
 #
 CONFIG_MIPS=y
 
@@ -392,6 +392,7 @@ CONFIG_PROC_EVENTS=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -522,6 +523,7 @@ CONFIG_GALILEO_64240_ETH=y
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_QLA3XXX=y
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
index 05a33a2aeb25f70751210f23941665e1cb732b3c..33fcc8133bc04ae4e52ab25fcacbff76cf32ec70 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:28:01 2007
+# Tue Feb 20 21:47:37 2007
 #
 CONFIG_MIPS=y
 
@@ -549,6 +549,7 @@ CONFIG_MTD_ALCHEMY=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -1096,6 +1097,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
index 34a6bee589bd21e38b5b5a15bc39a767069f7f0e..e07c55dc8dc19b6b78f6fb2c58006964a3a88302 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:28:02 2007
+# Tue Feb 20 21:47:37 2007
 #
 CONFIG_MIPS=y
 
@@ -541,7 +541,6 @@ CONFIG_MTD_ALCHEMY=y
 # NAND Flash Device Drivers
 #
 # CONFIG_MTD_NAND is not set
-# CONFIG_MTD_NAND_CAFE is not set
 
 #
 # OneNAND Flash Device Drivers
@@ -556,6 +555,7 @@ CONFIG_MTD_ALCHEMY=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -745,6 +745,7 @@ CONFIG_MIPS_AU1X00_ENET=y
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -1213,6 +1214,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
index e3bff462e62e11e35971293302d82ac3d27a560a..df210dd2247685d83bb7ebf5bb93758fa2b2a2b3 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:28:03 2007
+# Tue Feb 20 21:47:37 2007
 #
 CONFIG_MIPS=y
 
@@ -542,7 +542,6 @@ CONFIG_MTD_ALCHEMY=y
 # NAND Flash Device Drivers
 #
 # CONFIG_MTD_NAND is not set
-# CONFIG_MTD_NAND_CAFE is not set
 
 #
 # OneNAND Flash Device Drivers
@@ -557,6 +556,7 @@ CONFIG_MTD_ALCHEMY=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -746,6 +746,7 @@ CONFIG_MIPS_AU1X00_ENET=y
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -1206,6 +1207,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
index 009b3f87b44e261e773f0da34246981855e8595d..106a1641c0b5e44faba8062e3219287180f7c144 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:28:04 2007
+# Tue Feb 20 21:47:38 2007
 #
 CONFIG_MIPS=y
 
@@ -389,6 +389,7 @@ CONFIG_FW_LOADER=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -962,6 +963,7 @@ CONFIG_USB_MON=y
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -1229,6 +1231,7 @@ CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="console=ttyS1,38400n8 kgdb=ttyS0 root=/dev/nfs ip=bootp"
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_KGDB is not set
+CONFIG_SYS_SUPPORTS_KGDB=y
 # CONFIG_RUNTIME_DEBUG is not set
 # CONFIG_MIPS_UNCACHED is not set
 
index 5bd377bdbb2c5425b878b49d369b124df3516c6f..8caa2cd1aa7ce0d23eb3348140bc16d7ea84d24c 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:28:04 2007
+# Tue Feb 20 21:47:38 2007
 #
 CONFIG_MIPS=y
 
@@ -386,6 +386,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -952,6 +953,7 @@ CONFIG_USB_MON=y
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -1219,6 +1221,7 @@ CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="console=ttyS1,38400n8 kgdb=ttyS0 root=/dev/nfs ip=bootp"
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_KGDB is not set
+CONFIG_SYS_SUPPORTS_KGDB=y
 # CONFIG_RUNTIME_DEBUG is not set
 # CONFIG_MIPS_UNCACHED is not set
 
index cc694709ba6591c126a3a03da4c711ac0e92ab83..43f1becec2a49dc664fd0529ee33d9f980fb04c4 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:28:06 2007
+# Tue Feb 20 21:47:39 2007
 #
 CONFIG_MIPS=y
 
@@ -474,6 +474,7 @@ CONFIG_FW_LOADER=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -987,6 +988,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ADM9240 is not set
 # CONFIG_SENSORS_ASB100 is not set
@@ -1209,6 +1211,7 @@ CONFIG_USB_MON=y
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -1466,6 +1469,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
index c18c5e71d8ac45217104dc9d4553e8d32b0845f5..f68396d19f9aeaf4bd0606b4bd7a3fc1bce55d79 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:28:06 2007
+# Tue Feb 20 21:47:39 2007
 #
 CONFIG_MIPS=y
 
@@ -348,6 +348,7 @@ CONFIG_PROC_EVENTS=y
 # Plug and Play support
 #
 # CONFIG_PNP is not set
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
index 678f23217c9a62bc8428d90818753f739c9d2570..a6a824fcc87450bc9bb7441fc03a461a9ff5522a 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:28:07 2007
+# Tue Feb 20 21:47:39 2007
 #
 CONFIG_MIPS=y
 
@@ -560,7 +560,6 @@ CONFIG_MTD_CFI_UTIL=y
 # NAND Flash Device Drivers
 #
 # CONFIG_MTD_NAND is not set
-# CONFIG_MTD_NAND_CAFE is not set
 
 #
 # OneNAND Flash Device Drivers
@@ -576,6 +575,7 @@ CONFIG_MTD_CFI_UTIL=y
 # Plug and Play support
 #
 # CONFIG_PNP is not set
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -1191,6 +1191,7 @@ CONFIG_USB_MON=y
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -1462,6 +1463,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
index 0417e86ab627752f0817da0ac4efb240b05a3cf2..bee3702d501d9ec37d0fe4f63b9ed960a9557980 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:28:09 2007
+# Tue Feb 20 21:47:40 2007
 #
 CONFIG_MIPS=y
 
@@ -661,6 +661,7 @@ CONFIG_PARPORT_NOT_PC=y
 # Plug and Play support
 #
 # CONFIG_PNP is not set
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -1397,6 +1398,7 @@ CONFIG_USB_AUERSWALD=m
 CONFIG_USB_RIO500=m
 CONFIG_USB_LEGOTOWER=m
 CONFIG_USB_LCD=m
+# CONFIG_USB_BERRY_CHARGE is not set
 CONFIG_USB_LED=m
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 CONFIG_USB_CYTHERM=m
index 533df6fd8b4d1ef05ebce7a92535b7eab1208300..3c891ed101414a0150f7084e2f643d76327c5e17 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:28:09 2007
+# Tue Feb 20 21:47:40 2007
 #
 CONFIG_MIPS=y
 
@@ -424,6 +424,7 @@ CONFIG_CONNECTOR=m
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -581,6 +582,7 @@ CONFIG_NET_SB1250_MAC=y
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -945,6 +947,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_LOG_BUF_SHIFT=15
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 # CONFIG_SB1XXX_CORELIS is not set
 
 #
index 38816fe264a9f8f2a03b84a4b472d6f03e905e9d..e31d964a053b8ff44a4e3c0d4a237ff582d97277 100644 (file)
@@ -129,10 +129,12 @@ CONFIG_MIPS_MT_DISABLED=y
 # CONFIG_MIPS_VPE_LOADER is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_HAS_SMARTMIPS is not set
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_SYS_SUPPORTS_SMARTMIPS=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
index c2f7c8cea1e8156778d291327aaf1dbaf178a277..5771c1aee76a34d90301ca06afcd5f34678b8df9 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:28:11 2007
+# Tue Feb 20 21:47:41 2007
 #
 CONFIG_MIPS=y
 
@@ -396,6 +396,7 @@ CONFIG_CONNECTOR=m
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -920,6 +921,7 @@ CONFIG_USB_STORAGE=y
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
index 33b788089ab562dfdb86e241cbd25c9751c8ba7d..a8eb4b182d34f1d5dcd4e386f1d8b48e3fd359c5 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:28:12 2007
+# Tue Feb 20 21:47:41 2007
 #
 CONFIG_MIPS=y
 
@@ -397,6 +397,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -530,6 +531,7 @@ CONFIG_R8169=y
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -819,6 +821,7 @@ CONFIG_USB_MON=y
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
index d180586d63857a628aa03dec2e33b184110db073..c58afa2eac6bb105b623238bf62a00c70b975220 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Sun Feb 18 21:28:13 2007
+# Linux kernel version: 2.6.21-rc1
+# Thu Feb 22 10:38:09 2007
 #
 CONFIG_MIPS=y
 
@@ -409,6 +409,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -675,6 +676,7 @@ CONFIG_R8169=y
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 # CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -823,6 +825,11 @@ CONFIG_GPIO_VR41XX=y
 # CONFIG_HWMON is not set
 # CONFIG_HWMON_VID is not set
 
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_SM501=y
+
 #
 # Multimedia devices
 #
@@ -837,8 +844,10 @@ CONFIG_GPIO_VR41XX=y
 #
 # Graphics support
 #
-# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
@@ -847,6 +856,10 @@ CONFIG_FB_CFB_IMAGEBLIT=y
 # CONFIG_FB_BACKLIGHT is not set
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frambuffer hardware drivers
+#
 # CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
@@ -866,8 +879,9 @@ CONFIG_FB_CFB_IMAGEBLIT=y
 # CONFIG_FB_KYRO is not set
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
-CONFIG_FB_SMIVGX=y
+# CONFIG_FB_SMIVGX is not set
 # CONFIG_FB_TRIDENT is not set
+CONFIG_FB_SM501=y
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -881,7 +895,6 @@ CONFIG_DUMMY_CONSOLE=y
 # Logo configuration
 #
 # CONFIG_LOGO is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -1016,6 +1029,7 @@ CONFIG_USB_MON=y
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
index 570f0c1475b3c9eaa1c3df628b838030f3af5971..2abbd6827720f45adb61b3c66fbfc67104219fb2 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:28:13 2007
+# Tue Feb 20 21:47:42 2007
 #
 CONFIG_MIPS=y
 
@@ -396,6 +396,7 @@ CONFIG_CONNECTOR=m
 # Plug and Play support
 #
 # CONFIG_PNP is not set
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
index 08f3190dda89a2b08f3499c69de339595f91b5d0..44b6b7c1fdb689527924e4fbf14c244ab87d620c 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:28:14 2007
+# Tue Feb 20 21:47:42 2007
 #
 CONFIG_MIPS=y
 
@@ -400,6 +400,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
index aa69fee321d2d78fd961e121340e01ef9b225efe..f24e1c6fc484b62eb0663cc0f4a9c8ee4b5ee800 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:28:15 2007
+# Tue Feb 20 21:47:42 2007
 #
 CONFIG_MIPS=y
 
@@ -381,6 +381,7 @@ CONFIG_CONNECTOR=m
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -841,6 +842,7 @@ CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_KGDB is not set
+CONFIG_SYS_SUPPORTS_KGDB=y
 # CONFIG_RUNTIME_DEBUG is not set
 
 #
index ea68815ad17ae5be6542f0bba36107c5f4fd6b62..23fd3b81fe1ad7f22748ebfd05f016170da7a1e0 100644 (file)
@@ -6,5 +6,3 @@ obj-y                   += irq.o irq_5477.o setup.o lcd44780.o
 
 obj-$(CONFIG_RUNTIME_DEBUG)    += debug.o
 obj-$(CONFIG_KGDB)             += kgdb_io.o
-
-EXTRA_AFLAGS := $(CFLAGS)
index 8b790c2900d5b5c84af4d30479eddfc61507bc8c..9eb2f9c036aad596584427a5512255aab1769f8b 100644 (file)
@@ -8,5 +8,3 @@ obj-y           := ecc-berr.o int-handler.o ioasic-irq.o kn01-berr.o \
 obj-$(CONFIG_PROM_CONSOLE)     += promcon.o
 obj-$(CONFIG_TC)               += tc.o
 obj-$(CONFIG_CPU_HAS_WB)       += wbflush.o
-
-EXTRA_AFLAGS := $(CFLAGS)
index bcd0247b3a66731636ec6aad45733b793e6e40f3..064ae7a76bdc204c28e0c8e92ccd63400fbbf403 100644 (file)
@@ -7,5 +7,3 @@ lib-y                   += init.o memory.o cmdline.o identify.o console.o
 
 lib-$(CONFIG_32BIT)    += locore.o
 lib-$(CONFIG_64BIT)    += call_o32.o
-
-EXTRA_AFLAGS := $(CFLAGS)
index cade16ec7e5a2c140e79f6c9acbad5ede7b80978..65419bf32441be996b689a28790a1a610dcc8d37 100644 (file)
 
 #include <asm/dec/prom.h>
 
-static void __init prom_console_write(struct console *con, const char *s,
-                                     unsigned int c)
+void prom_putchar(char c)
 {
-       static char sfmt[] __initdata = "%%%us";
-       char fmt[13];
+       char s[2];
 
-       snprintf(fmt, sizeof(fmt), sfmt, c);
-       prom_printf(fmt, s);
-}
-
-static struct console promcons __initdata = {
-       .name   = "prom",
-       .write  = prom_console_write,
-       .flags  = CON_PRINTBUFFER,
-       .index  = -1,
-};
-
-static int promcons_output __initdata = 0;
-
-void __init register_prom_console(void)
-{
-       if (!promcons_output) {
-               promcons_output = 1;
-               register_console(&promcons);
-       }
-}
+       s[0] = c;
+       s[1] = '\0';
 
-void __init unregister_prom_console(void)
-{
-       if (promcons_output) {
-               unregister_console(&promcons);
-               promcons_output = 0;
-       }
+       prom_printf( s);
 }
-
-void disable_early_printk(void)
-       __attribute__((alias("unregister_prom_console")));
index c4e3c1ea0d48946f0c84b315817c43dab0f1aef6..cd85924e25723697ae6927369b7dce59baa7b4ad 100644 (file)
@@ -26,9 +26,6 @@
 
 #include "dectypes.h"
 
-extern unsigned long mips_machgroup;
-extern unsigned long mips_machtype;
-
 static const char *dec_system_strings[] = {
        [MACH_DSUNKNOWN]        "unknown DECstation",
        [MACH_DS23100]          "DECstation 2100/3100",
index bf2858071f1fc79969b3e7d25e0d4b9a1fb61073..a217aafe59f6aa9e2d61bf78239fdc64e8e128a4 100644 (file)
@@ -103,9 +103,6 @@ void __init prom_init(void)
        if (prom_is_rex(magic))
                rex_clear_cache();
 
-       /* Register the early console.  */
-       register_prom_console();
-
        /* Were we compiled with the right CPU option? */
 #if defined(CONFIG_CPU_R3000)
        if ((current_cpu_data.cputype == CPU_R4000SC) ||
index 6c2a233e36cb0fc5c99b3f0c3d61ad0f6fe6fd3b..8cb8f591919434056a424943920eb7e9a3a1afb9 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.20
-# Sun Feb 18 21:27:34 2007
+# Tue Feb 20 21:47:14 2007
 #
 CONFIG_MIPS=y
 
@@ -620,6 +620,7 @@ CONFIG_CONNECTOR=m
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
index c191b3e9d9d9e3101a9614fb4be17f0fa55bd9b6..d956047736675db99cbe5453ce1016570ee5142b 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/irq.h>
 #include <linux/types.h>
 
-#include <asm/i8259.h>
 #include <asm/system.h>
 #include <asm/mipsregs.h>
 #include <asm/debug.h>
index 3299b6dfe764435328887de1e7d0b23544e4ea93..e266300263750d4e0277ba7fa467a37fce884464 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/ptrace.h>
 #include <linux/delay.h>
 
-#include <asm/i8259.h>
 #include <asm/irq_cpu.h>
 #include <asm/system.h>
 #include <asm/mipsregs.h>
index b2c53a8f8718a71476006fcdff36e76fa07c6318..323b2cebc691ebf6f3bc1397fb165711dca89979 100644 (file)
@@ -7,5 +7,3 @@
 #
 
 obj-y  += irq.o promcon.o reset.o serialGT.o setup.o
-
-EXTRA_AFLAGS := $(CFLAGS)
index b5937c4ba7db18827ca2ef967ed09baf3356fd73..6e0ecfed964045d7356d29f6a5323263a0d21e03 100644 (file)
@@ -24,11 +24,6 @@ static void prom_console_write(struct console *co, const char *s,
        }
 }
 
-int prom_getchar(void)
-{
-       return 0;
-}
-
 static struct console sercons = {
     .name      = "ttyS",
     .write     = prom_console_write,
index 6f708df8373be147689ee6b88f55189137ab77a2..9f9a33fc76b918094aabb9e2a672e366adc8b69a 100644 (file)
@@ -5,5 +5,3 @@
 obj-y                  += irq.o prom.o reset.o setup.o
 
 obj-$(CONFIG_KGDB)     += dbg_io.o
-
-EXTRA_AFLAGS := $(CFLAGS)
index 7cf52205511ccad299507a650188fb223fbef919..e4250435ad893b5823dc4bbd9f22c1cdd10cbf39 100644 (file)
@@ -10,5 +10,3 @@
 #
 
 obj-y += irq.o reset.o setup.o time.o pci.o
-
-EXTRA_AFLAGS := $(CFLAGS)
index 02bd39add891c042a90295a0bd2abd2e2729df99..dd9d99bfcf7a2d5cf6535740f2a7cb1594aa2e58 100644 (file)
@@ -3,5 +3,3 @@
 #
 
 obj-y          := irq.o jazzdma.o reset.o setup.o
-
-EXTRA_AFLAGS := $(CFLAGS)
index cb09a8eede155cf177484844a197d0cbe8bb8449..01e7db19bcbe23a02a151349c54374eedbfd9d64 100644 (file)
@@ -2,4 +2,4 @@
 # Makefile for the common code of TOSHIBA JMR-TX3927 board
 #
 
-obj-y   += prom.o puts.o rtc_ds1742.o
+obj-y   += prom.o puts.o
diff --git a/arch/mips/jmr3927/common/rtc_ds1742.c b/arch/mips/jmr3927/common/rtc_ds1742.c
deleted file mode 100644 (file)
index e656134..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *              ahennessy@mvista.com
- *
- * arch/mips/jmr3927/common/rtc_ds1742.c
- * Based on arch/mips/ddb5xxx/common/rtc_ds1386.c
- *     low-level RTC hookups for s for Dallas 1742 chip.
- *
- * Copyright (C) 2000-2001 Toshiba 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.
- *
- *  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.
- */
-
-
-/*
- * This file exports a function, rtc_ds1386_init(), which expects an
- * uncached base address as the argument.  It will set the two function
- * pointers expected by the MIPS generic timer code.
- */
-
-#include <linux/bcd.h>
-#include <linux/types.h>
-#include <linux/time.h>
-#include <linux/rtc.h>
-#include <linux/ds1742rtc.h>
-
-#include <asm/time.h>
-#include <asm/addrspace.h>
-
-#include <asm/debug.h>
-
-#define        EPOCH           2000
-
-static unsigned long rtc_base;
-
-static unsigned long
-rtc_ds1742_get_time(void)
-{
-       unsigned int year, month, day, hour, minute, second;
-       unsigned int century;
-       unsigned long flags;
-
-       spin_lock_irqsave(&rtc_lock, flags);
-       rtc_write(RTC_READ, RTC_CONTROL);
-       second = BCD2BIN(rtc_read(RTC_SECONDS) & RTC_SECONDS_MASK);
-       minute = BCD2BIN(rtc_read(RTC_MINUTES));
-       hour = BCD2BIN(rtc_read(RTC_HOURS));
-       day = BCD2BIN(rtc_read(RTC_DATE));
-       month = BCD2BIN(rtc_read(RTC_MONTH));
-       year = BCD2BIN(rtc_read(RTC_YEAR));
-       century = BCD2BIN(rtc_read(RTC_CENTURY) & RTC_CENTURY_MASK);
-       rtc_write(0, RTC_CONTROL);
-       spin_unlock_irqrestore(&rtc_lock, flags);
-
-       year += century * 100;
-
-       return mktime(year, month, day, hour, minute, second);
-}
-extern void to_tm(unsigned long tim, struct rtc_time * tm);
-
-static int
-rtc_ds1742_set_time(unsigned long t)
-{
-       struct rtc_time tm;
-       u8 year, month, day, hour, minute, second;
-       u8 cmos_year, cmos_month, cmos_day, cmos_hour, cmos_minute, cmos_second;
-       int cmos_century;
-       unsigned long flags;
-
-       spin_lock_irqsave(&rtc_lock, flags);
-       rtc_write(RTC_READ, RTC_CONTROL);
-       cmos_second = (u8)(rtc_read(RTC_SECONDS) & RTC_SECONDS_MASK);
-       cmos_minute = (u8)rtc_read(RTC_MINUTES);
-       cmos_hour = (u8)rtc_read(RTC_HOURS);
-       cmos_day = (u8)rtc_read(RTC_DATE);
-       cmos_month = (u8)rtc_read(RTC_MONTH);
-       cmos_year = (u8)rtc_read(RTC_YEAR);
-       cmos_century = rtc_read(RTC_CENTURY) & RTC_CENTURY_MASK;
-
-       rtc_write(RTC_WRITE, RTC_CONTROL);
-
-       /* convert */
-       to_tm(t, &tm);
-
-       /* check each field one by one */
-       year = BIN2BCD(tm.tm_year - EPOCH);
-       if (year != cmos_year) {
-               rtc_write(year,RTC_YEAR);
-       }
-
-       month = BIN2BCD(tm.tm_mon);
-       if (month != (cmos_month & 0x1f)) {
-               rtc_write((month & 0x1f) | (cmos_month & ~0x1f),RTC_MONTH);
-       }
-
-       day = BIN2BCD(tm.tm_mday);
-       if (day != cmos_day) {
-
-               rtc_write(day, RTC_DATE);
-       }
-
-       if (cmos_hour & 0x40) {
-               /* 12 hour format */
-               hour = 0x40;
-               if (tm.tm_hour > 12) {
-                       hour |= 0x20 | (BIN2BCD(hour-12) & 0x1f);
-               } else {
-                       hour |= BIN2BCD(tm.tm_hour);
-               }
-       } else {
-               /* 24 hour format */
-               hour = BIN2BCD(tm.tm_hour) & 0x3f;
-       }
-       if (hour != cmos_hour) rtc_write(hour, RTC_HOURS);
-
-       minute = BIN2BCD(tm.tm_min);
-       if (minute !=  cmos_minute) {
-               rtc_write(minute, RTC_MINUTES);
-       }
-
-       second = BIN2BCD(tm.tm_sec);
-       if (second !=  cmos_second) {
-               rtc_write(second & RTC_SECONDS_MASK,RTC_SECONDS);
-       }
-
-       /* RTC_CENTURY and RTC_CONTROL share same address... */
-       rtc_write(cmos_century, RTC_CONTROL);
-       spin_unlock_irqrestore(&rtc_lock, flags);
-
-       return 0;
-}
-
-void
-rtc_ds1742_init(unsigned long base)
-{
-       u8  cmos_second;
-
-       /* remember the base */
-       rtc_base = base;
-       db_assert((rtc_base & 0xe0000000) == KSEG1);
-
-       /* set the function pointers */
-       rtc_mips_get_time = rtc_ds1742_get_time;
-       rtc_mips_set_time = rtc_ds1742_set_time;
-
-       /* clear oscillator stop bit */
-       rtc_write(RTC_READ, RTC_CONTROL);
-       cmos_second = (u8)(rtc_read(RTC_SECONDS) & RTC_SECONDS_MASK);
-       rtc_write(RTC_WRITE, RTC_CONTROL);
-       rtc_write(cmos_second, RTC_SECONDS); /* clear msb */
-       rtc_write(0, RTC_CONTROL);
-}
index baf5077813c1ac2489be2ff0488c9aa6e42b679f..18fe9a898cb792c3fd1d8e9543380ae34c637ca2 100644 (file)
@@ -5,5 +5,3 @@
 obj-y                          += init.o irq.o setup.o
 obj-$(CONFIG_RUNTIME_DEBUG)    += debug.o
 obj-$(CONFIG_KGDB)             += kgdb_io.o
-
-EXTRA_AFLAGS := $(CFLAGS)
index 7ca3d6d07b34f9c9998ed7e136c2722fcfbe9e92..fc523bda068f4a109c5bb42d55f52550224d1347 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/param.h>       /* for HZ */
 #include <linux/delay.h>
 #include <linux/pm.h>
+#include <linux/platform_device.h>
 #ifdef CONFIG_SERIAL_TXX9
 #include <linux/tty.h>
 #include <linux/serial.h>
@@ -137,10 +138,6 @@ int jmr3927_ccfg_toeon = 0;
 
 static inline void do_reset(void)
 {
-#ifdef CONFIG_TC35815
-       extern void tc35815_killall(void);
-       tc35815_killall();
-#endif
 #if 1  /* Resetting PCI bus */
        jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR);
        jmr3927_ioc_reg_out(JMR3927_IOC_RESET_PCI, JMR3927_IOC_RESET_ADDR);
@@ -176,19 +173,10 @@ static cycle_t jmr3927_hpt_read(void)
        return jiffies * (JMR3927_TIMER_CLK / HZ) + jmr3927_tmrptr->trr;
 }
 
-#define USE_RTC_DS1742
-#ifdef USE_RTC_DS1742
-extern void rtc_ds1742_init(unsigned long base);
-#endif
 static void __init jmr3927_time_init(void)
 {
        clocksource_mips.read = jmr3927_hpt_read;
        mips_hpt_frequency = JMR3927_TIMER_CLK;
-#ifdef USE_RTC_DS1742
-       if (jmr3927_have_nvram()) {
-               rtc_ds1742_init(JMR3927_IOC_NVRAMB_ADDR);
-       }
-#endif
 }
 
 void __init plat_timer_setup(struct irqaction *irq)
@@ -544,3 +532,32 @@ void __init tx3927_setup(void)
                        printk("TX3927 D-Cache WriteBack (CWF) .\n");
        }
 }
+
+/* This trick makes rtc-ds1742 driver usable as is. */
+unsigned long __swizzle_addr_b(unsigned long port)
+{
+       if ((port & 0xffff0000) != JMR3927_IOC_NVRAMB_ADDR)
+               return port;
+       port = (port & 0xffff0000) | (port & 0x7fff << 1);
+#ifdef __BIG_ENDIAN
+       return port;
+#else
+       return port | 1;
+#endif
+}
+EXPORT_SYMBOL(__swizzle_addr_b);
+
+static int __init jmr3927_rtc_init(void)
+{
+       struct resource res = {
+               .start  = JMR3927_IOC_NVRAMB_ADDR - IO_BASE,
+               .end    = JMR3927_IOC_NVRAMB_ADDR - IO_BASE + 0x800 - 1,
+               .flags  = IORESOURCE_MEM,
+       };
+       struct platform_device *dev;
+       if (!jmr3927_have_nvram())
+               return -ENODEV;
+       dev = platform_device_register_simple("ds1742", -1, &res, 1);
+       return IS_ERR(dev) ? PTR_ERR(dev) : 0;
+}
+device_initcall(jmr3927_rtc_init);
index 8faf1b40cd660401cd7c20902c4be2f34aa47c90..49246264cc7c66a0386bb44733dbc79396006b1e 100644 (file)
@@ -65,7 +65,6 @@ obj-$(CONFIG_64BIT)           += cpu-bugs64.o
 obj-$(CONFIG_I8253)            += i8253.o
 
 obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel.o
+obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
 
 CFLAGS_cpu-bugs64.o    = $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
-
-EXTRA_AFLAGS := $(CFLAGS)
index c0b089d47181bcd946f740571f0aed7b788c517b..222de465db73a809eeba3c887a8f4a38d905e26e 100644 (file)
@@ -64,6 +64,9 @@ void output_ptreg_defines(void)
        offset("#define PT_R31    ", struct pt_regs, regs[31]);
        offset("#define PT_LO     ", struct pt_regs, lo);
        offset("#define PT_HI     ", struct pt_regs, hi);
+#ifdef CONFIG_CPU_HAS_SMARTMIPS
+       offset("#define PT_ACX    ", struct pt_regs, acx);
+#endif
        offset("#define PT_EPC    ", struct pt_regs, cp0_epc);
        offset("#define PT_BVADDR ", struct pt_regs, cp0_badvaddr);
        offset("#define PT_STATUS ", struct pt_regs, cp0_status);
@@ -246,6 +249,7 @@ void output_sc_defines(void)
        text("/* Linux sigcontext offsets. */");
        offset("#define SC_REGS       ", struct sigcontext, sc_regs);
        offset("#define SC_FPREGS     ", struct sigcontext, sc_fpregs);
+       offset("#define SC_ACX        ", struct sigcontext, sc_acx);
        offset("#define SC_MDHI       ", struct sigcontext, sc_mdhi);
        offset("#define SC_MDLO       ", struct sigcontext, sc_mdlo);
        offset("#define SC_PC         ", struct sigcontext, sc_pc);
diff --git a/arch/mips/kernel/early_printk.c b/arch/mips/kernel/early_printk.c
new file mode 100644 (file)
index 0000000..304efdc
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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) 2002, 2003, 06, 07 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2007 MIPS Technologies, Inc.
+ *   written by Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/console.h>
+#include <linux/init.h>
+
+extern void prom_putchar(char);
+
+static void early_console_write(struct console *con, const char *s, unsigned n)
+{
+       while (n-- && *s) {
+               if (*s == '\n')
+                       prom_putchar('\r');
+               prom_putchar(*s);
+               s++;
+       }
+}
+
+static struct console early_console = {
+       .name   = "early",
+       .write  = early_console_write,
+       .flags  = CON_PRINTBUFFER | CON_BOOT,
+       .index  = -1
+};
+
+void __init setup_early_printk(void)
+{
+       register_console(&early_console);
+}
+
+void __init disable_early_printk(void)
+{
+       unregister_console(&early_console);
+}
index b33ba6cd7f5bca912896746ed4cbec133169bcdc..9c79703979b2b128da7b2040e508515d662e43d4 100644 (file)
@@ -28,7 +28,7 @@
  * moves to arch independent land
  */
 
-static int i8259A_auto_eoi;
+static int i8259A_auto_eoi = -1;
 DEFINE_SPINLOCK(i8259A_lock);
 /* some platforms call this... */
 void mask_and_ack_8259A(unsigned int);
@@ -216,7 +216,8 @@ spurious_8259A_irq:
 
 static int i8259A_resume(struct sys_device *dev)
 {
-       init_8259A(i8259A_auto_eoi);
+       if (i8259A_auto_eoi >= 0)
+               init_8259A(i8259A_auto_eoi);
        return 0;
 }
 
@@ -226,8 +227,10 @@ static int i8259A_shutdown(struct sys_device *dev)
         * the kernel initialization code can get it
         * out of.
         */
-       outb(0xff, PIC_MASTER_IMR);     /* mask all of 8259A-1 */
-       outb(0xff, PIC_SLAVE_IMR);      /* mask all of 8259A-1 */
+       if (i8259A_auto_eoi >= 0) {
+               outb(0xff, PIC_MASTER_IMR);     /* mask all of 8259A-1 */
+               outb(0xff, PIC_SLAVE_IMR);      /* mask all of 8259A-1 */
+       }
        return 0;
 }
 
@@ -252,7 +255,7 @@ static int __init i8259A_init_sysfs(void)
 
 device_initcall(i8259A_init_sysfs);
 
-void __init init_8259A(int auto_eoi)
+void init_8259A(int auto_eoi)
 {
        unsigned long flags;
 
index fc4dd6c9dd802c8308f16f422b7f93cc15734905..1df544c1f966e1e10b21664e95c9da7a40efe106 100644 (file)
@@ -166,34 +166,6 @@ out:
        return error;
 }
 
-asmlinkage long
-sysn32_waitid(int which, compat_pid_t pid,
-             siginfo_t __user *uinfo, int options,
-             struct compat_rusage __user *uru)
-{
-       struct rusage ru;
-       long ret;
-       mm_segment_t old_fs = get_fs();
-       int si_signo;
-
-       if (!access_ok(VERIFY_WRITE, uinfo, sizeof(*uinfo)))
-               return -EFAULT;
-
-       set_fs (KERNEL_DS);
-       ret = sys_waitid(which, pid, uinfo, options,
-                        uru ? (struct rusage __user *) &ru : NULL);
-       set_fs (old_fs);
-
-       if (__get_user(si_signo, &uinfo->si_signo))
-               return -EFAULT;
-       if (ret < 0 || si_signo == 0)
-               return ret;
-
-       if (uru)
-               ret = put_compat_rusage(&ru, uru);
-       return ret;
-}
-
 #define RLIM_INFINITY32        0x7fffffff
 #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
 
@@ -572,151 +544,6 @@ asmlinkage long sys32_sync_file_range(int fd, int __pad,
                        flags);
 }
 
-/* Argument list sizes for sys_socketcall */
-#define AL(x) ((x) * sizeof(unsigned int))
-static unsigned char socketcall_nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
-                               AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
-                               AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
-#undef AL
-
-/*
- *     System call vectors.
- *
- *     Argument checking cleaned up. Saved 20% in size.
- *  This function doesn't need to set the kernel lock because
- *  it is set by the callees.
- */
-
-asmlinkage long sys32_socketcall(int call, unsigned int __user *args32)
-{
-       unsigned int a[6];
-       unsigned int a0,a1;
-       int err;
-
-       extern asmlinkage long sys_socket(int family, int type, int protocol);
-       extern asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen);
-       extern asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen);
-       extern asmlinkage long sys_listen(int fd, int backlog);
-       extern asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen);
-       extern asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len);
-       extern asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len);
-       extern asmlinkage long sys_socketpair(int family, int type, int protocol, int __user *usockvec);
-       extern asmlinkage long sys_send(int fd, void __user * buff, size_t len, unsigned flags);
-       extern asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flags,
-                                         struct sockaddr __user *addr, int addr_len);
-       extern asmlinkage long sys_recv(int fd, void __user * ubuf, size_t size, unsigned flags);
-       extern asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned flags,
-                                           struct sockaddr __user *addr, int __user *addr_len);
-       extern asmlinkage long sys_shutdown(int fd, int how);
-       extern asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen);
-       extern asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int __user *optlen);
-       extern asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags);
-       extern asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flags);
-
-
-       if(call<1||call>SYS_RECVMSG)
-               return -EINVAL;
-
-       /* copy_from_user should be SMP safe. */
-       if (copy_from_user(a, args32, socketcall_nargs[call]))
-               return -EFAULT;
-
-       a0=a[0];
-       a1=a[1];
-
-       switch(call)
-       {
-               case SYS_SOCKET:
-                       err = sys_socket(a0,a1,a[2]);
-                       break;
-               case SYS_BIND:
-                       err = sys_bind(a0,(struct sockaddr __user *)A(a1), a[2]);
-                       break;
-               case SYS_CONNECT:
-                       err = sys_connect(a0, (struct sockaddr __user *)A(a1), a[2]);
-                       break;
-               case SYS_LISTEN:
-                       err = sys_listen(a0,a1);
-                       break;
-               case SYS_ACCEPT:
-                       err = sys_accept(a0,(struct sockaddr __user *)A(a1), (int __user *)A(a[2]));
-                       break;
-               case SYS_GETSOCKNAME:
-                       err = sys_getsockname(a0,(struct sockaddr __user *)A(a1), (int __user *)A(a[2]));
-                       break;
-               case SYS_GETPEERNAME:
-                       err = sys_getpeername(a0, (struct sockaddr __user *)A(a1), (int __user *)A(a[2]));
-                       break;
-               case SYS_SOCKETPAIR:
-                       err = sys_socketpair(a0,a1, a[2], (int __user *)A(a[3]));
-                       break;
-               case SYS_SEND:
-                       err = sys_send(a0, (void __user *)A(a1), a[2], a[3]);
-                       break;
-               case SYS_SENDTO:
-                       err = sys_sendto(a0,(void __user *)A(a1), a[2], a[3],
-                                        (struct sockaddr __user *)A(a[4]), a[5]);
-                       break;
-               case SYS_RECV:
-                       err = sys_recv(a0, (void __user *)A(a1), a[2], a[3]);
-                       break;
-               case SYS_RECVFROM:
-                       err = sys_recvfrom(a0, (void __user *)A(a1), a[2], a[3],
-                                          (struct sockaddr __user *)A(a[4]), (int __user *)A(a[5]));
-                       break;
-               case SYS_SHUTDOWN:
-                       err = sys_shutdown(a0,a1);
-                       break;
-               case SYS_SETSOCKOPT:
-                       err = sys_setsockopt(a0, a1, a[2], (char __user *)A(a[3]), a[4]);
-                       break;
-               case SYS_GETSOCKOPT:
-                       err = sys_getsockopt(a0, a1, a[2], (char __user *)A(a[3]), (int __user *)A(a[4]));
-                       break;
-               case SYS_SENDMSG:
-                       err = sys_sendmsg(a0, (struct msghdr __user *) A(a1), a[2]);
-                       break;
-               case SYS_RECVMSG:
-                       err = sys_recvmsg(a0, (struct msghdr __user *) A(a1), a[2]);
-                       break;
-               default:
-                       err = -EINVAL;
-                       break;
-       }
-       return err;
-}
-
-struct sigevent32 {
-       u32 sigev_value;
-       u32 sigev_signo;
-       u32 sigev_notify;
-       u32 payload[(64 / 4) - 3];
-};
-
-extern asmlinkage long
-sys_timer_create(clockid_t which_clock,
-                struct sigevent __user *timer_event_spec,
-                timer_t __user * created_timer_id);
-
-long
-sys32_timer_create(u32 clock, struct sigevent32 __user *se32, timer_t __user *timer_id)
-{
-       struct sigevent __user *p = NULL;
-       if (se32) {
-               struct sigevent se;
-               p = compat_alloc_user_space(sizeof(struct sigevent));
-               memset(&se, 0, sizeof(struct sigevent));
-               if (get_user(se.sigev_value.sival_int,  &se32->sigev_value) ||
-                   __get_user(se.sigev_signo, &se32->sigev_signo) ||
-                   __get_user(se.sigev_notify, &se32->sigev_notify) ||
-                   __copy_from_user(&se._sigev_un._pad, &se32->payload,
-                                    sizeof(se32->payload)) ||
-                   copy_to_user(p, &se, sizeof(se)))
-                       return -EFAULT;
-       }
-       return sys_timer_create(clock, p, timer_id);
-}
-
 save_static_function(sys32_clone);
 __attribute_used__ noinline static int
 _sys32_clone(nabi_no_regargs struct pt_regs regs)
@@ -737,49 +564,3 @@ _sys32_clone(nabi_no_regargs struct pt_regs regs)
        return do_fork(clone_flags, newsp, &regs, 0,
                       parent_tidptr, child_tidptr);
 }
-
-/*
- * Implement the event wait interface for the eventpoll file. It is the kernel
- * part of the user space epoll_pwait(2).
- */
-asmlinkage long compat_sys_epoll_pwait(int epfd,
-       struct epoll_event __user *events, int maxevents, int timeout,
-       const compat_sigset_t __user *sigmask, size_t sigsetsize)
-{
-       int error;
-       sigset_t ksigmask, sigsaved;
-
-       /*
-        * If the caller wants a certain signal mask to be set during the wait,
-        * we apply it here.
-        */
-       if (sigmask) {
-               if (sigsetsize != sizeof(sigset_t))
-                       return -EINVAL;
-               if (!access_ok(VERIFY_READ, sigmask, sizeof(ksigmask)))
-                       return -EFAULT;
-               if (__copy_conv_sigset_from_user(&ksigmask, sigmask))
-                       return -EFAULT;
-               sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
-               sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
-       }
-
-       error = sys_epoll_wait(epfd, events, maxevents, timeout);
-
-       /*
-        * If we changed the signal mask, we need to restore the original one.
-        * In case we've got a signal while waiting, we do not restore the
-        * signal mask yet, and we allow do_signal() to deliver the signal on
-        * the way back to userspace, before the signal mask is restored.
-        */
-       if (sigmask) {
-               if (error == -EINTR) {
-                       memcpy(&current->saved_sigmask, &sigsaved,
-                               sizeof(sigsaved));
-                       set_thread_flag(TIF_RESTORE_SIGMASK);
-               } else
-                       sigprocmask(SIG_SETMASK, &sigsaved, NULL);
-       }
-
-       return error;
-}
index 2ef857c3ee53ec23462906a56c5e19c6b591030a..225755d0c1f651479b7190562bdb2b0506f5b276 100644 (file)
@@ -37,6 +37,7 @@ EXPORT_SYMBOL(kernel_thread);
  * Userspace access stuff.
  */
 EXPORT_SYMBOL(__copy_user);
+EXPORT_SYMBOL(__copy_user_inatomic);
 EXPORT_SYMBOL(__bzero);
 EXPORT_SYMBOL(__strncpy_from_user_nocheck_asm);
 EXPORT_SYMBOL(__strncpy_from_user_asm);
index a669089e46724c98a924825bde927dd2eca3f02d..6bdfb5a9fa1a465ee9ec15193999780cea1b8d16 100644 (file)
@@ -51,11 +51,11 @@ ATTRIB_NORET void cpu_idle(void)
        /* endless idle loop with no priority at all */
        while (1) {
                while (!need_resched()) {
-#ifdef CONFIG_MIPS_MT_SMTC
+#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
                        extern void smtc_idle_loop_hook(void);
 
                        smtc_idle_loop_hook();
-#endif /* CONFIG_MIPS_MT_SMTC */
+#endif
                        if (cpu_wait)
                                (*cpu_wait)();
                }
index 258d74fd0b638a8eb7c64c9431c3b7bdc26dc58e..201ae194d1b86a7b13c568a0e837d2b2cbcff8ea 100644 (file)
@@ -236,6 +236,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                case MMLO:
                        tmp = regs->lo;
                        break;
+#ifdef CONFIG_CPU_HAS_SMARTMIPS
+               case ACX:
+                       tmp = regs->acx;
+                       break;
+#endif
                case FPC_CSR:
                        tmp = child->thread.fpu.fcr31;
                        break;
@@ -362,6 +367,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                case MMLO:
                        regs->lo = data;
                        break;
+#ifdef CONFIG_CPU_HAS_SMARTMIPS
+               case ACX:
+                       regs->acx = data;
+                       break;
+#endif
                case FPC_CSR:
                        child->thread.fpu.fcr31 = data;
                        break;
index d92c48e0d7a6dd1aac6e5260e3d2f148530bdef2..e14ae09eda2b7a94dd4d264bd9d0b7c864380811 100644 (file)
@@ -53,7 +53,7 @@ static char module_name[] = "rtlx";
 static struct chan_waitqueues {
        wait_queue_head_t rt_queue;
        wait_queue_head_t lx_queue;
-       int in_open;
+       atomic_t in_open;
 } channel_wqs[RTLX_CHANNELS];
 
 static struct irqaction irq;
@@ -146,110 +146,80 @@ static void stopping(int vpe)
 
 int rtlx_open(int index, int can_sleep)
 {
-       int ret;
-       struct rtlx_channel *chan;
        volatile struct rtlx_info **p;
+       struct rtlx_channel *chan;
+       enum rtlx_state state;
+       int ret = 0;
 
        if (index >= RTLX_CHANNELS) {
                printk(KERN_DEBUG "rtlx_open index out of range\n");
                return -ENOSYS;
        }
 
-       if (channel_wqs[index].in_open) {
-               printk(KERN_DEBUG "rtlx_open channel %d already opened\n", index);
-               return -EBUSY;
+       if (atomic_inc_return(&channel_wqs[index].in_open) > 1) {
+               printk(KERN_DEBUG "rtlx_open channel %d already opened\n",
+                      index);
+               ret = -EBUSY;
+               goto out_fail;
        }
 
-       channel_wqs[index].in_open++;
-
        if (rtlx == NULL) {
                if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) {
                        if (can_sleep) {
-                               DECLARE_WAITQUEUE(wait, current);
-
-                               /* go to sleep */
-                               add_wait_queue(&channel_wqs[index].lx_queue, &wait);
-
-                               set_current_state(TASK_INTERRUPTIBLE);
-                               while ((p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) {
-                                       schedule();
-                                       set_current_state(TASK_INTERRUPTIBLE);
-                               }
-
-                               set_current_state(TASK_RUNNING);
-                               remove_wait_queue(&channel_wqs[index].lx_queue, &wait);
-
-                               /* back running */
+                               __wait_event_interruptible(channel_wqs[index].lx_queue,
+                                                          (p = vpe_get_shared(RTLX_TARG_VPE)),
+                                                          ret);
+                               if (ret)
+                                       goto out_fail;
                        } else {
-                               printk( KERN_DEBUG "No SP program loaded, and device "
+                               printk(KERN_DEBUG "No SP program loaded, and device "
                                        "opened with O_NONBLOCK\n");
-                               channel_wqs[index].in_open = 0;
-                               return -ENOSYS;
+                               ret = -ENOSYS;
+                               goto out_fail;
                        }
                }
 
                if (*p == NULL) {
                        if (can_sleep) {
-                               DECLARE_WAITQUEUE(wait, current);
-
-                               /* go to sleep */
-                               add_wait_queue(&channel_wqs[index].lx_queue, &wait);
-
-                               set_current_state(TASK_INTERRUPTIBLE);
-                               while (*p == NULL) {
-                                       schedule();
-
-                                       /* reset task state to interruptable otherwise
-                                          we'll whizz round here like a very fast loopy
-                                          thing. schedule() appears to return with state
-                                          set to TASK_RUNNING.
-
-                                          If the loaded SP program, for whatever reason,
-                                          doesn't set up the shared structure *p will never
-                                          become true. So whoever connected to either /dev/rt?
-                                          or if it was kspd, will then take up rather a lot of
-                                          processor cycles.
-                                       */
-
-                                       set_current_state(TASK_INTERRUPTIBLE);
-                               }
-
-                               set_current_state(TASK_RUNNING);
-                               remove_wait_queue(&channel_wqs[index].lx_queue, &wait);
-
-                               /* back running */
-                       }
-                       else {
+                               __wait_event_interruptible(channel_wqs[index].lx_queue,
+                                                          *p != NULL,
+                                                          ret);
+                               if (ret)
+                                       goto out_fail;
+                       } else {
                                printk(" *vpe_get_shared is NULL. "
                                       "Has an SP program been loaded?\n");
-                               channel_wqs[index].in_open = 0;
-                               return -ENOSYS;
+                               ret = -ENOSYS;
+                               goto out_fail;
                        }
                }
 
                if ((unsigned int)*p < KSEG0) {
                        printk(KERN_WARNING "vpe_get_shared returned an invalid pointer "
                               "maybe an error code %d\n", (int)*p);
-                       channel_wqs[index].in_open = 0;
-                       return -ENOSYS;
+                       ret = -ENOSYS;
+                       goto out_fail;
                }
 
-               if ((ret = rtlx_init(*p)) < 0) {
-                       channel_wqs[index].in_open = 0;
-                       return ret;
-               }
+               if ((ret = rtlx_init(*p)) < 0)
+                       goto out_ret;
        }
 
        chan = &rtlx->channel[index];
 
-       if (chan->lx_state == RTLX_STATE_OPENED) {
-               channel_wqs[index].in_open = 0;
-               return -EBUSY;
-       }
+       state = xchg(&chan->lx_state, RTLX_STATE_OPENED);
+       if (state == RTLX_STATE_OPENED) {
+               ret = -EBUSY;
+               goto out_fail;
+       }
 
-       chan->lx_state = RTLX_STATE_OPENED;
-       channel_wqs[index].in_open = 0;
-       return 0;
+out_fail:
+       smp_mb();
+       atomic_dec(&channel_wqs[index].in_open);
+       smp_mb();
+
+out_ret:
+       return ret;
 }
 
 int rtlx_release(int index)
@@ -270,30 +240,17 @@ unsigned int rtlx_read_poll(int index, int can_sleep)
        /* data available to read? */
        if (chan->lx_read == chan->lx_write) {
                if (can_sleep) {
-                       DECLARE_WAITQUEUE(wait, current);
-
-                       /* go to sleep */
-                       add_wait_queue(&channel_wqs[index].lx_queue, &wait);
-
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       while (chan->lx_read == chan->lx_write) {
-                               schedule();
+                       int ret = 0;
 
-                               set_current_state(TASK_INTERRUPTIBLE);
+                       __wait_event_interruptible(channel_wqs[index].lx_queue,
+                                                  chan->lx_read != chan->lx_write || sp_stopping,
+                                                  ret);
+                       if (ret)
+                               return ret;
 
-                               if (sp_stopping) {
-                                       set_current_state(TASK_RUNNING);
-                                       remove_wait_queue(&channel_wqs[index].lx_queue, &wait);
-                                       return 0;
-                               }
-                       }
-
-                       set_current_state(TASK_RUNNING);
-                       remove_wait_queue(&channel_wqs[index].lx_queue, &wait);
-
-                       /* back running */
-               }
-               else
+                       if (sp_stopping)
+                               return 0;
+               } else
                        return 0;
        }
 
@@ -454,25 +411,22 @@ static ssize_t file_write(struct file *file, const char __user * buffer,
 {
        int minor;
        struct rtlx_channel *rt;
-       DECLARE_WAITQUEUE(wait, current);
 
        minor = iminor(file->f_path.dentry->d_inode);
        rt = &rtlx->channel[minor];
 
        /* any space left... */
        if (!rtlx_write_poll(minor)) {
+               int ret = 0;
 
                if (file->f_flags & O_NONBLOCK)
                        return -EAGAIN;
 
-               add_wait_queue(&channel_wqs[minor].rt_queue, &wait);
-               set_current_state(TASK_INTERRUPTIBLE);
-
-               while (!rtlx_write_poll(minor))
-                       schedule();
-
-               set_current_state(TASK_RUNNING);
-               remove_wait_queue(&channel_wqs[minor].rt_queue, &wait);
+               __wait_event_interruptible(channel_wqs[minor].rt_queue,
+                                          rtlx_write_poll(minor),
+                                          ret);
+               if (ret)
+                       return ret;
        }
 
        return rtlx_write(minor, (void *)buffer, count, 1);
@@ -513,7 +467,7 @@ static int rtlx_module_init(void)
        for (i = 0; i < RTLX_CHANNELS; i++) {
                init_waitqueue_head(&channel_wqs[i].rt_queue);
                init_waitqueue_head(&channel_wqs[i].lx_queue);
-               channel_wqs[i].in_open = 0;
+               atomic_set(&channel_wqs[i].in_open, 0);
 
                dev = device_create(mt_class, NULL, MKDEV(major, i),
                                    "%s%d", module_name, i);
index 7c0b3936ba447dbeb159828227ef26a3aa38d1d7..0c9a9ff8cd25ec1c200347206f762f8f09b1ac27 100644 (file)
@@ -656,6 +656,8 @@ einval:     li      v0, -EINVAL
        sys     sys_kexec_load          4
        sys     sys_getcpu              3
        sys     sys_epoll_pwait         6
+       sys     sys_ioprio_set          3
+       sys     sys_ioprio_get          2
        .endm
 
        /* We pre-compute the number of _instruction_ bytes needed to
index 10e9a18630aa47b168c8140b99f80875e5c76c32..23f3b118f7183221c8807d388a6df771a797388a 100644 (file)
@@ -470,4 +470,7 @@ sys_call_table:
        PTR     sys_get_robust_list
        PTR     sys_kexec_load                  /* 5270 */
        PTR     sys_getcpu
-       PTR     compat_sys_epoll_pwait
+       PTR     sys_epoll_pwait
+       PTR     sys_ioprio_set
+       PTR     sys_ioprio_get
+       .size   sys_call_table,.-sys_call_table
index 2ceda4644a4d7b4ee64d778753b8fcd0c9dce170..6eac28337423536c3f1bf19988b0606611706f39 100644 (file)
@@ -340,7 +340,7 @@ EXPORT(sysn32_call_table)
        PTR     compat_sys_statfs64
        PTR     compat_sys_fstatfs64
        PTR     sys_sendfile64
-       PTR     sys32_timer_create              /* 6220 */
+       PTR     compat_sys_timer_create         /* 6220 */
        PTR     compat_sys_timer_settime
        PTR     compat_sys_timer_gettime
        PTR     sys_timer_getoverrun
@@ -361,7 +361,7 @@ EXPORT(sysn32_call_table)
        PTR     compat_sys_mq_notify
        PTR     compat_sys_mq_getsetattr
        PTR     sys_ni_syscall                  /* 6240, sys_vserver */
-       PTR     sysn32_waitid
+       PTR     compat_sys_waitid
        PTR     sys_ni_syscall                  /* available, was setaltroot */
        PTR     sys_add_key
        PTR     sys_request_key
@@ -395,5 +395,8 @@ EXPORT(sysn32_call_table)
        PTR     compat_sys_set_robust_list
        PTR     compat_sys_get_robust_list
        PTR     compat_sys_kexec_load
-       PTR     sys_getcpu
+       PTR     sys_getcpu                      /* 6275 */
        PTR     compat_sys_epoll_pwait
+       PTR     sys_ioprio_set
+       PTR     sys_ioprio_get
+       .size   sysn32_call_table,.-sysn32_call_table
index c5f590ca99b09d47a293a40b2c55ae83a01687dd..7e74b412a782b8133b1557a6d69c58a710872a14 100644 (file)
@@ -307,7 +307,7 @@ sys_call_table:
        PTR     compat_sys_statfs
        PTR     compat_sys_fstatfs              /* 4100 */
        PTR     sys_ni_syscall                  /* sys_ioperm */
-       PTR     sys32_socketcall
+       PTR     compat_sys_socketcall
        PTR     sys_syslog
        PTR     compat_sys_setitimer
        PTR     compat_sys_getitimer            /* 4105 */
@@ -462,7 +462,7 @@ sys_call_table:
        PTR     sys_fadvise64_64
        PTR     compat_sys_statfs64             /* 4255 */
        PTR     compat_sys_fstatfs64
-       PTR     sys32_timer_create
+       PTR     compat_sys_timer_create
        PTR     compat_sys_timer_settime
        PTR     compat_sys_timer_gettime
        PTR     sys_timer_getoverrun            /* 4260 */
@@ -518,5 +518,7 @@ sys_call_table:
        PTR     compat_sys_get_robust_list      /* 4310 */
        PTR     compat_sys_kexec_load
        PTR     sys_getcpu
-       PTR     sys_epoll_pwait
+       PTR     compat_sys_epoll_pwait
+       PTR     sys_ioprio_set
+       PTR     sys_ioprio_get                  /* 4315 */
        .size   sys_call_table,.-sys_call_table
index 11ab222a2e972226ab406d3aefa2093804f05311..4975da0bfb634cdf52ebffbfe2bffe68da61ace0 100644 (file)
@@ -525,6 +525,14 @@ void __init setup_arch(char **cmdline_p)
 {
        cpu_probe();
        prom_init();
+
+#ifdef CONFIG_EARLY_PRINTK
+       {
+               extern void setup_early_printk(void);
+
+               setup_early_printk();
+       }
+#endif
        cpu_report();
 
 #if defined(CONFIG_VT)
index adbfb95e42d0f80b927b0a216d442fa7ac21dcb0..f091786187a69b8b7b41c596b0cbec573a8fe16a 100644 (file)
@@ -89,6 +89,9 @@ int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
        for (i = 1; i < 32; i++)
                err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
 
+#ifdef CONFIG_CPU_HAS_SMARTMIPS
+       err |= __put_user(regs->acx, &sc->sc_acx);
+#endif
        err |= __put_user(regs->hi, &sc->sc_mdhi);
        err |= __put_user(regs->lo, &sc->sc_mdlo);
        if (cpu_has_dsp) {
@@ -132,6 +135,10 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
        current_thread_info()->restart_block.fn = do_no_restart_syscall;
 
        err |= __get_user(regs->cp0_epc, &sc->sc_pc);
+
+#ifdef CONFIG_CPU_HAS_SMARTMIPS
+       err |= __get_user(regs->acx, &sc->sc_acx);
+#endif
        err |= __get_user(regs->hi, &sc->sc_mdhi);
        err |= __get_user(regs->lo, &sc->sc_mdlo);
        if (cpu_has_dsp) {
index 02062fc59f776bd08171351959ad4de90b2401c5..19bbef001959ce9fe0305867f9af3379d4203604 100644 (file)
@@ -108,13 +108,6 @@ typedef struct compat_siginfo {
 
 /* 32-bit compatibility types */
 
-#define _NSIG_BPW32    32
-#define _NSIG_WORDS32  (_NSIG / _NSIG_BPW32)
-
-typedef struct {
-       unsigned int sig[_NSIG_WORDS32];
-} sigset_t32;
-
 typedef unsigned int __sighandler32_t;
 typedef void (*vfptr_t)(void);
 
@@ -136,7 +129,7 @@ struct ucontext32 {
        s32                 uc_link;
        stack32_t           uc_stack;
        struct sigcontext32 uc_mcontext;
-       sigset_t32          uc_sigmask;   /* mask last for extensibility */
+       compat_sigset_t     uc_sigmask;   /* mask last for extensibility */
 };
 
 /*
index 0555fc554f6544619e77b7d102ec486d56dbae67..c46e479c992b4dae0f620fb3c0399e5674089b39 100644 (file)
@@ -51,31 +51,14 @@ int __cpu_logical_map[NR_CPUS];             /* Map logical to physical */
 EXPORT_SYMBOL(phys_cpu_present_map);
 EXPORT_SYMBOL(cpu_online_map);
 
+/* This happens early in bootup, can't really do it better */
 static void smp_tune_scheduling (void)
 {
        struct cache_desc *cd = &current_cpu_data.scache;
-       unsigned long cachesize;       /* kB   */
-       unsigned long cpu_khz;
+       unsigned long cachesize = cd->linesz * cd->sets * cd->ways;
 
-       /*
-        * Crude estimate until we actually meassure ...
-        */
-       cpu_khz = loops_per_jiffy * 2 * HZ / 1000;
-
-       /*
-        * Rough estimation for SMP scheduling, this is the number of
-        * cycles it takes for a fully memory-limited process to flush
-        * the SMP-local cache.
-        *
-        * (For a P5 this pretty much means we will choose another idle
-        *  CPU almost always at wakeup time (this is due to the small
-        *  L1 cache), on PIIs it's around 50-100 usecs, depending on
-        *  the cache size)
-        */
-       if (!cpu_khz)
-               return;
-
-       cachesize = cd->linesz * cd->sets * cd->ways;
+       if (cachesize > max_cache_size)
+               max_cache_size = cachesize;
 }
 
 extern void __init calibrate_delay(void);
index 9251ea82493746a4829e69ba3f433f123e94eb24..f253eda27fa388a4cac1c7963784fa1773ddbbf9 100644 (file)
@@ -141,10 +141,7 @@ __setup("ipibufs=", ipibufs);
 __setup("nostlb", stlb_disable);
 __setup("asidmask=", asidmask_set);
 
-/* Enable additional debug checks before going into CPU idle loop */
-#define SMTC_IDLE_HOOK_DEBUG
-
-#ifdef SMTC_IDLE_HOOK_DEBUG
+#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
 
 static int hang_trig = 0;
 
@@ -176,7 +173,7 @@ int tcnoprog[NR_CPUS];
 static atomic_t idle_hook_initialized = {0};
 static int clock_hang_reported[NR_CPUS];
 
-#endif /* SMTC_IDLE_HOOK_DEBUG */
+#endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */
 
 /* Initialize shared TLB - the should probably migrate to smtc_setup_cpus() */
 
@@ -394,10 +391,10 @@ void mipsmt_prepare_cpus(void)
                printk("ASID mask value override to 0x%x\n", asidmask);
 
        /* Temporary */
-#ifdef SMTC_IDLE_HOOK_DEBUG
+#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
        if (hang_trig)
                printk("Logic Analyser Trigger on suspected TC hang\n");
-#endif /* SMTC_IDLE_HOOK_DEBUG */
+#endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */
 
        /* Put MVPE's into 'configuration state' */
        write_c0_mvpcontrol( read_c0_mvpcontrol() | MVPCONTROL_VPC );
@@ -817,9 +814,9 @@ void ipi_decode(struct smtc_ipi *pipi)
        case SMTC_CLOCK_TICK:
                /* Invoke Clock "Interrupt" */
                ipi_timer_latch[dest_copy] = 0;
-#ifdef SMTC_IDLE_HOOK_DEBUG
+#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
                clock_hang_reported[dest_copy] = 0;
-#endif /* SMTC_IDLE_HOOK_DEBUG */
+#endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */
                local_timer_interrupt(0, NULL);
                break;
        case LINUX_SMP_IPI:
@@ -1020,7 +1017,7 @@ EXPORT_SYMBOL(smtc_ipi_replay);
 
 void smtc_idle_loop_hook(void)
 {
-#ifdef SMTC_IDLE_HOOK_DEBUG
+#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
        int im;
        int flags;
        int mtflags;
@@ -1113,7 +1110,7 @@ void smtc_idle_loop_hook(void)
        local_irq_restore(flags);
        if (pdb_msg != &id_ho_db_msg[0])
                printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg);
-#endif /* SMTC_IDLE_HOOK_DEBUG */
+#endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */
 
        /*
         * Replay any accumulated deferred IPIs. If "Instant Replay"
index f663c63d5dd31c4bd8049741d3c05735c912c801..18f56a9dbcfa487831e30d86dff1e4688d006634 100644 (file)
@@ -229,6 +229,9 @@ void show_regs(struct pt_regs *regs)
                        printk("\n");
        }
 
+#ifdef CONFIG_CPU_HAS_SMARTMIPS
+       printk("Acx    : %0*lx\n", field, regs->acx);
+#endif
        printk("Hi    : %0*lx\n", field, regs->hi);
        printk("Lo    : %0*lx\n", field, regs->lo);
 
@@ -704,6 +707,7 @@ asmlinkage void do_bp(struct pt_regs *regs)
                die_if_kernel("Break instruction in kernel code", regs);
                force_sig(SIGTRAP, current);
        }
+       return;
 
 out_sigsegv:
        force_sig(SIGSEGV, current);
@@ -747,6 +751,7 @@ asmlinkage void do_tr(struct pt_regs *regs)
                die_if_kernel("Trap instruction in kernel code", regs);
                force_sig(SIGTRAP, current);
        }
+       return;
 
 out_sigsegv:
        force_sig(SIGSEGV, current);
index 7e7d54823486f0acc367451a527a2a481925b829..24b7b053cfe916fe6a073791b4e9ddbc1765c603 100644 (file)
@@ -515,7 +515,7 @@ asmlinkage void do_ade(struct pt_regs *regs)
                goto sigbus;
 
        pc = (unsigned int __user *) exception_epc(regs);
-       if ((current->thread.mflags & MF_FIXADE) == 0)
+       if (user_mode(regs) && (current->thread.mflags & MF_FIXADE) == 0)
                goto sigbus;
 
        /*
index 9aca871a307f8f161215099085c716c0e08db8de..c9ee9d2d5856a896a64e16321c92b37a174b7c6d 100644 (file)
@@ -1079,6 +1079,7 @@ static int getcwd(char *buff, int size)
 static int vpe_open(struct inode *inode, struct file *filp)
 {
        int minor, ret;
+       enum vpe_state state;
        struct vpe *v;
        struct vpe_notifications *not;
 
@@ -1093,7 +1094,8 @@ static int vpe_open(struct inode *inode, struct file *filp)
                return -ENODEV;
        }
 
-       if (v->state != VPE_STATE_UNUSED) {
+       state = xchg(&v->state, VPE_STATE_INUSE);
+       if (state != VPE_STATE_UNUSED) {
                dvpe();
 
                printk(KERN_DEBUG "VPE loader: tc in use dumping regs\n");
@@ -1108,9 +1110,6 @@ static int vpe_open(struct inode *inode, struct file *filp)
                cleanup_tc(get_tc(minor));
        }
 
-       // allocate it so when we get write ops we know it's expected.
-       v->state = VPE_STATE_INUSE;
-
        /* this of-course trashes what was there before... */
        v->pbuffer = vmalloc(P_SIZE);
        v->plen = P_SIZE;
index d425120b0282f28e54c96f6c15444dcb20c689a6..fbe9a87bd0ade6686062a99c68bbd461de59b059 100644 (file)
@@ -110,12 +110,13 @@ int lasat_init_board_info(void)
                    sizeof(struct lasat_eeprom_struct) - 4);
 
        if (crc != lasat_board_info.li_eeprom_info.crc32) {
-               prom_printf("WARNING...\nWARNING...\nEEPROM CRC does not match calculated, attempting to soldier on...\n");
+               printk(KERN_WARNING "WARNING...\nWARNING...\nEEPROM CRC does "
+                      "not match calculated, attempting to soldier on...\n");
        }
 
-       if (lasat_board_info.li_eeprom_info.version != LASAT_EEPROM_VERSION)
-       {
-               prom_printf("WARNING...\nWARNING...\nEEPROM version %d, wanted version %d, attempting to soldier on...\n",
+       if (lasat_board_info.li_eeprom_info.version != LASAT_EEPROM_VERSION) {
+               printk(KERN_WARNING "WARNING...\nWARNING...\nEEPROM version "
+                      "%d, wanted version %d, attempting to soldier on...\n",
                       (unsigned int)lasat_board_info.li_eeprom_info.version,
                       LASAT_EEPROM_VERSION);
        }
@@ -124,7 +125,9 @@ int lasat_init_board_info(void)
        cfg1 = lasat_board_info.li_eeprom_info.cfg[1];
 
        if ( LASAT_W0_DSCTYPE(cfg0) != 1) {
-               prom_printf("WARNING...\nWARNING...\nInvalid configuration read from EEPROM, attempting to soldier on...");
+               printk(KERN_WARNING "WARNING...\nWARNING...\n"
+                      "Invalid configuration read from EEPROM, attempting to "
+                      "soldier on...");
        }
        /* We have a valid configuration */
 
index d47692f73a26ee0f619428526eb45535f631ab3e..812c6ac366bea2571933732fc86f5035197b6e28 100644 (file)
 #define PROM_PUTC_ADDR         PROM_JUMP_TABLE_ENTRY(1)
 #define PROM_MONITOR_ADDR      PROM_JUMP_TABLE_ENTRY(2)
 
-static void null_prom_printf(const char * fmt, ...)
-{
-}
-
 static void null_prom_display(const char *string, int pos, int clear)
 {
 }
@@ -40,50 +36,29 @@ static void null_prom_putc(char c)
 }
 
 /* these are functions provided by the bootloader */
-static void (* prom_putc)(char c) = null_prom_putc;
-void (* prom_printf)(const char * fmt, ...) = null_prom_printf;
+static void (* __prom_putc)(char c) = null_prom_putc;
+
+void prom_putchar(char c)
+{
+       __prom_putc(c);
+}
+
 void (* prom_display)(const char *string, int pos, int clear) =
                null_prom_display;
 void (* prom_monitor)(void) = null_prom_monitor;
 
 unsigned int lasat_ndelay_divider;
 
-#define PROM_PRINTFBUF_SIZE 256
-static char prom_printfbuf[PROM_PRINTFBUF_SIZE];
-
-static void real_prom_printf(const char * fmt, ...)
-{
-       va_list ap;
-       int len;
-       char *c = prom_printfbuf;
-       int i;
-
-       va_start(ap, fmt);
-       len = vsnprintf(prom_printfbuf, PROM_PRINTFBUF_SIZE, fmt, ap);
-       va_end(ap);
-
-       /* output overflowed the buffer */
-       if (len < 0 || len > PROM_PRINTFBUF_SIZE)
-               len = PROM_PRINTFBUF_SIZE;
-
-       for (i=0; i < len; i++) {
-               if (*c == '\n')
-                       prom_putc('\r');
-               prom_putc(*c++);
-       }
-}
-
 static void setup_prom_vectors(void)
 {
        u32 version = *(u32 *)(RESET_VECTOR + 0x90);
 
        if (version >= 307) {
                prom_display = (void *)PROM_DISPLAY_ADDR;
-               prom_putc = (void *)PROM_PUTC_ADDR;
-               prom_printf = real_prom_printf;
+               __prom_putc = (void *)PROM_PUTC_ADDR;
                prom_monitor = (void *)PROM_MONITOR_ADDR;
        }
-       prom_printf("prom vectors set up\n");
+       printk("prom vectors set up\n");
 }
 
 static struct at93c_defs at93c_defs[N_MACHTYPES] = {
@@ -101,11 +76,11 @@ void __init prom_init(void)
        setup_prom_vectors();
 
        if (current_cpu_data.cputype == CPU_R5000) {
-               prom_printf("LASAT 200 board\n");
+               printk("LASAT 200 board\n");
                mips_machtype = MACH_LASAT_200;
                 lasat_ndelay_divider = LASAT_200_DIVIDER;
         } else {
-               prom_printf("LASAT 100 board\n");
+               printk("LASAT 100 board\n");
                mips_machtype = MACH_LASAT_100;
                 lasat_ndelay_divider = LASAT_100_DIVIDER;
         }
index 07be7bf1e4a3960cd55b76dc8792f7679e4a569b..019d45fbd268e634b6dd19747fc90f34d79ac636 100644 (file)
@@ -2,5 +2,4 @@
 #define PROM_H
 extern void (* prom_display)(const char *string, int pos, int clear);
 extern void (* prom_monitor)(void);
-extern void (* prom_printf)(const char * fmt, ...);
 #endif
index 14c55168f1ff11d50016fa0afe25feea24443f73..488007f13988402a1fb5348cc6f7e1c09e0f784f 100644 (file)
@@ -116,7 +116,6 @@ static void lasat_time_init(void)
 
 void __init plat_timer_setup(struct irqaction *irq)
 {
-       write_c0_compare( read_c0_count() + mips_hpt_frequency / HZ);
        change_c0_status(ST0_IM, IE_IRQ0 | IE_IRQ5);
 }
 
@@ -179,5 +178,5 @@ void __init plat_mem_setup(void)
        /* Switch from prom exception handler to normal mode */
        change_c0_status(ST0_BEV,0);
 
-       prom_printf("Lasat specific initialization complete\n");
+       pr_info("Lasat specific initialization complete\n");
 }
index 2036cf5e6857fe924e3bd934b9a01535afacdec5..8b94d4cc5a304efd54ac1bec1528f190943d7d25 100644 (file)
@@ -21,5 +21,3 @@ obj-$(CONFIG_CPU_SB1)         += dump_tlb.o
 obj-$(CONFIG_CPU_TX39XX)       += r3k_dump_tlb.o
 obj-$(CONFIG_CPU_TX49XX)       += dump_tlb.o
 obj-$(CONFIG_CPU_VR41XX)       += dump_tlb.o
-
-EXTRA_AFLAGS := $(CFLAGS)
index 2036cf5e6857fe924e3bd934b9a01535afacdec5..8b94d4cc5a304efd54ac1bec1528f190943d7d25 100644 (file)
@@ -21,5 +21,3 @@ obj-$(CONFIG_CPU_SB1)         += dump_tlb.o
 obj-$(CONFIG_CPU_TX39XX)       += r3k_dump_tlb.o
 obj-$(CONFIG_CPU_TX49XX)       += dump_tlb.o
 obj-$(CONFIG_CPU_VR41XX)       += dump_tlb.o
-
-EXTRA_AFLAGS := $(CFLAGS)
index 2453ea244cb8dd722c17afc5caa237ee7818db83..d7d3b14dcfb2ba0bd3043e98253ed0aeac4cf5f1 100644 (file)
@@ -2,13 +2,11 @@
 # Makefile for MIPS-specific library files..
 #
 
-lib-y  += csum_partial.o memcpy.o memcpy-inatomic.o memset.o promlib.o \
-          strlen_user.o strncpy_user.o strnlen_user.o uncached.o
+lib-y  += csum_partial.o memcpy.o memcpy-inatomic.o memset.o strlen_user.o \
+          strncpy_user.o strnlen_user.o uncached.o
 
 obj-y                  += iomap.o
 obj-$(CONFIG_PCI)      += iomap-pci.o
 
 # libgcc-style stuff needed in the kernel
 lib-y += ashldi3.o ashrdi3.o lshrdi3.o
-
-EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/lib/promlib.c b/arch/mips/lib/promlib.c
deleted file mode 100644 (file)
index dddfe98..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#include <stdarg.h>
-#include <linux/kernel.h>
-
-extern void prom_putchar(char);
-
-void prom_printf(char *fmt, ...)
-{
-       va_list args;
-       char ppbuf[1024];
-       char *bptr;
-
-       va_start(args, fmt);
-       vsprintf(ppbuf, fmt, args);
-
-       bptr = ppbuf;
-
-       while (*bptr != 0) {
-               if (*bptr == '\n')
-                       prom_putchar('\r');
-
-               prom_putchar(*bptr++);
-       }
-       va_end(args);
-}
index be47c1c2bc8020f33726c620749a28ac2e48315f..aade36d7878777ef3a2289b844b718818a8c9b5a 100644 (file)
@@ -18,9 +18,9 @@
 # Makefile for the MIPS boards generic routines under Linux.
 #
 
-obj-y                          := reset.o display.o init.o memory.o printf.o \
+obj-y                          := reset.o display.o init.o memory.o \
                                   cmdline.o time.o
+
+obj-$(CONFIG_EARLY_PRINTK)     += console.o
 obj-$(CONFIG_PCI)              += pci.o
 obj-$(CONFIG_KGDB)             += gdb_hook.o
-
-EXTRA_AFLAGS := $(CFLAGS)
similarity index 91%
rename from arch/mips/mips-boards/generic/printf.c
rename to arch/mips/mips-boards/generic/console.c
index 1a711bd79b51520e900271cccc981cbd350779f3..4d8ab99e4155404395eef9b16a72a4fb8153c210 100644 (file)
  *
  * Putting things on the screen/serial line using YAMONs facilities.
  */
+#include <linux/console.h>
 #include <linux/init.h>
-#include <linux/kernel.h>
 #include <linux/serial_reg.h>
-#include <linux/spinlock.h>
 #include <asm/io.h>
 
 #ifdef CONFIG_MIPS_ATLAS
@@ -67,12 +66,3 @@ int prom_putchar(char c)
 
        return 1;
 }
-
-char prom_getchar(void)
-{
-       while (!(serial_in(UART_LSR) & UART_LSR_DR))
-               ;
-
-       return serial_in(UART_RX);
-}
-
index 58a0fe883591467333c2624640ab5840e850b0ea..1acdf091c25877246fccae76d988ab6a3320de83 100644 (file)
@@ -167,7 +167,7 @@ static void __init console_config(void)
                        flow = 'r';
                sprintf (console_string, " console=ttyS0,%d%c%c%c", baud, parity, bits, flow);
                strcat (prom_getcmdline(), console_string);
-               prom_printf("Config serial console:%s\n", console_string);
+               pr_info("Config serial console:%s\n", console_string);
        }
 }
 #endif
@@ -210,8 +210,9 @@ void __init kgdb_config (void)
                        generic_getDebugChar = rs_getDebugChar;
                }
 
-               prom_printf("KGDB: Using serial line /dev/ttyS%d at %d for session, "
-                           "please connect your debugger\n", line ? 1 : 0, speed);
+               pr_info("KGDB: Using serial line /dev/ttyS%d at %d for "
+                       "session, please connect your debugger\n",
+                       line ? 1 : 0, speed);
 
                {
                        char *s;
@@ -250,8 +251,6 @@ void __init mips_ejtag_setup (void)
 
 void __init prom_init(void)
 {
-       u32 start, map, mask, data;
-
        prom_argc = fw_arg0;
        _prom_argv = (int *) fw_arg1;
        _prom_envp = (int *) fw_arg2;
@@ -277,6 +276,8 @@ void __init prom_init(void)
                        mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_MSC;
        }
        switch(mips_revision_corid) {
+               u32 start, map, mask, data;
+
        case MIPS_REVISION_CORID_QED_RM5261:
        case MIPS_REVISION_CORID_CORE_LV:
        case MIPS_REVISION_CORID_CORE_FPGA:
@@ -382,7 +383,7 @@ void __init prom_init(void)
        board_nmi_handler_setup = mips_nmi_setup;
        board_ejtag_handler_setup = mips_ejtag_setup;
 
-       prom_printf("\nLINUX started...\n");
+       pr_info("\nLINUX started...\n");
        prom_init_cmdline();
        prom_meminit();
 #ifdef CONFIG_SERIAL_8250_CONSOLE
index ebf0e16c5a0de5c36ff4c63016f42a9dbaf95328..ae39953da2c485d3b39d227728aab3f882a7aad8 100644 (file)
@@ -59,11 +59,12 @@ struct prom_pmemblock * __init prom_getmdesc(void)
        /* otherwise look in the environment */
        memsize_str = prom_getenv("memsize");
        if (!memsize_str) {
-               prom_printf("memsize not set in boot prom, set to default (32Mb)\n");
+               printk(KERN_WARNING
+                      "memsize not set in boot prom, set to default (32Mb)\n");
                physical_memsize = 0x02000000;
        } else {
 #ifdef DEBUG
-               prom_printf("prom_memsize = %s\n", memsize_str);
+               pr_debug("prom_memsize = %s\n", memsize_str);
 #endif
                physical_memsize = simple_strtol(memsize_str, NULL, 0);
        }
@@ -141,12 +142,12 @@ void __init prom_meminit(void)
        struct prom_pmemblock *p;
 
 #ifdef DEBUG
-       prom_printf("YAMON MEMORY DESCRIPTOR dump:\n");
+       pr_debug("YAMON MEMORY DESCRIPTOR dump:\n");
        p = prom_getmdesc();
        while (p->size) {
                int i = 0;
-               prom_printf("[%d,%p]: base<%08lx> size<%08lx> type<%s>\n",
-                           i, p, p->base, p->size, mtypes[p->type]);
+               pr_debug("[%d,%p]: base<%08lx> size<%08lx> type<%s>\n",
+                        i, p, p->base, p->size, mtypes[p->type]);
                p++;
                i++;
        }
index a3c3a1d462b272f39900d9c9910ac1f1d8bde455..df2a2bd3aa5d198188e0fc3f8e1eadb167ee5dfd 100644 (file)
@@ -295,7 +295,4 @@ void __init plat_timer_setup(struct irqaction *irq)
        irq_desc[mips_cpu_timer_irq].status |= IRQ_PER_CPU;
        set_irq_handler(mips_cpu_timer_irq, handle_percpu_irq);
 #endif
-
-        /* to generate the first timer interrupt */
-       write_c0_compare (read_c0_count() + mips_hpt_frequency/HZ);
 }
index cb7f349b051448376a554749d4c4c1dc0c1963f8..377d9e8f250a31f717cf908ea5160c7c781d919e 100644 (file)
@@ -21,4 +21,4 @@
 
 obj-y := malta_int.o malta_setup.o
 obj-$(CONFIG_MTD) += malta_mtd.o
-obj-$(CONFIG_SMP) += malta_smp.o
+obj-$(CONFIG_MIPS_MT_SMTC) += malta_smtc.o
similarity index 67%
rename from arch/mips/mips-boards/malta/malta_smp.c
rename to arch/mips/mips-boards/malta/malta_smtc.c
index cf967170fe295ebaa4e191b47c16f925a0c7ab3e..d1c80f6311005e7b48d7192698cb236dcd7b2936 100644 (file)
@@ -1,25 +1,14 @@
 /*
  * Malta Platform-specific hooks for SMP operation
  */
+#include <linux/init.h>
 
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/cpumask.h>
-#include <linux/interrupt.h>
-
-#include <asm/atomic.h>
-#include <asm/cpu.h>
-#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/hardirq.h>
-#include <asm/mmu_context.h>
-#include <asm/smp.h>
-#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsregs.h>
+#include <asm/mipsmtregs.h>
+#include <asm/smtc.h>
 #include <asm/smtc_ipi.h>
-#endif /* CONFIG_MIPS_MT_SMTC */
 
 /* VPE/SMP Prototype implements platform interfaces directly */
-#if !defined(CONFIG_MIPS_MT_SMP)
 
 /*
  * Cause the specified action to be performed on a targeted "CPU"
 
 void core_send_ipi(int cpu, unsigned int action)
 {
-/* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */
-#ifdef CONFIG_MIPS_MT_SMTC
+       /* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */
        smtc_send_ipi(cpu, LINUX_SMP_IPI, action);
-#endif /* CONFIG_MIPS_MT_SMTC */
 }
 
 /*
@@ -39,9 +26,7 @@ void core_send_ipi(int cpu, unsigned int action)
 
 void prom_boot_secondary(int cpu, struct task_struct *idle)
 {
-#ifdef CONFIG_MIPS_MT_SMTC
        smtc_boot_secondary(cpu, idle);
-#endif /* CONFIG_MIPS_MT_SMTC */
 }
 
 /*
@@ -50,7 +35,6 @@ void prom_boot_secondary(int cpu, struct task_struct *idle)
 
 void prom_init_secondary(void)
 {
-#ifdef CONFIG_MIPS_MT_SMTC
         void smtc_init_secondary(void);
        int myvpe;
 
@@ -65,7 +49,6 @@ void prom_init_secondary(void)
        }
 
         smtc_init_secondary();
-#endif /* CONFIG_MIPS_MT_SMTC */
 }
 
 /*
@@ -93,9 +76,7 @@ void __init plat_prepare_cpus(unsigned int max_cpus)
 
 void prom_smp_finish(void)
 {
-#ifdef CONFIG_MIPS_MT_SMTC
        smtc_smp_finish();
-#endif /* CONFIG_MIPS_MT_SMTC */
 }
 
 /*
@@ -105,5 +86,3 @@ void prom_smp_finish(void)
 void prom_cpus_done(void)
 {
 }
-
-#endif /* CONFIG_MIPS32R2_MT_SMP */
index a12e32aafde09476bd230a0b37aa679e914201c5..6aeebc9122f25ff96de48b107833a7a324a6de65 100644 (file)
@@ -1,5 +1,7 @@
 #
 # Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+# Copyright (C) 2007 MIPS Technologies, Inc.
+#   written by Ralf Baechle (ralf@linux-mips.org)
 #
 # This program is free software; you can distribute it and/or modify it
 # under the terms of the GNU General Public License (Version 2) as
@@ -15,5 +17,7 @@
 # 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
 #
 
-obj-y := sim_setup.o sim_mem.o sim_time.o sim_printf.o sim_int.o sim_cmdline.o
+obj-y := sim_setup.o sim_mem.o sim_time.o sim_int.o sim_cmdline.o
+
+obj-$(CONFIG_EARLY_PRINTK) += sim_console.o
 obj-$(CONFIG_SMP) += sim_smp.o
similarity index 63%
rename from arch/mips/mips-boards/sim/sim_printf.c
rename to arch/mips/mips-boards/sim/sim_console.c
index 3ee5a0b501a6aede28d02b695858ac26970f40e1..de595a9ccb27578bb507ecc8875dc7533f67ec14 100644 (file)
@@ -1,7 +1,4 @@
 /*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
- *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
  *  published by the Free Software Foundation.
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
- * Putting things on the screen/serial line using YAMONs facilities.
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 2007 MIPS Technologies, Inc.
+ *   written by Ralf Baechle
  */
 #include <linux/init.h>
-#include <linux/kernel.h>
 #include <linux/serial_reg.h>
-#include <linux/spinlock.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 static inline unsigned int serial_in(int offset)
 {
@@ -34,41 +31,10 @@ static inline void serial_out(int offset, int value)
        outb(value, 0x3f8 + offset);
 }
 
-int putPromChar(char c)
+void __init prom_putchar(char c)
 {
        while ((serial_in(UART_LSR) & UART_LSR_THRE) == 0)
                ;
 
        serial_out(UART_TX, c);
-
-       return 1;
-}
-
-char getPromChar(void)
-{
-       while (!(serial_in(UART_LSR) & 1))
-               ;
-
-       return serial_in(UART_RX);
-}
-
-void prom_printf(char *fmt, ...)
-{
-       va_list args;
-       int l;
-       char *p, *buf_end;
-       char buf[1024];
-
-       va_start(args, fmt);
-       l = vsprintf(buf, fmt, args); /* hopefully i < sizeof(buf) */
-       va_end(args);
-
-       buf_end = buf + l;
-
-       for (p = buf; p < buf_end; p++) {
-               /* Crude cr/nl handling is better than none */
-               if (*p == '\n')
-                       putPromChar('\r');
-               putPromChar(*p);
-       }
 }
index 46bc16f8b15d3fe4d50e3a9ab989a17f3e440114..e408ef0bcd6e4af27f89ce3aba9df885a5b9dcaf 100644 (file)
@@ -46,7 +46,7 @@ struct prom_pmemblock * __init prom_getmdesc(void)
        unsigned int memsize;
 
        memsize = 0x02000000;
-       prom_printf("Setting default memory size 0x%08x\n", memsize);
+       pr_info("Setting default memory size 0x%08x\n", memsize);
 
        memset(mdesc, 0, sizeof(mdesc));
 
index ea2066c3a1f77e43ca1c6f0f0af5e38ac8046572..b705f09e57c311a8b6fc64fea54776a1dbd21626 100644 (file)
@@ -55,7 +55,7 @@ void __init plat_mem_setup(void)
        serial_init();
 
        board_time_init = sim_time_init;
-       prom_printf("Linux started...\n");
+       pr_info("Linux started...\n");
 
 #ifdef CONFIG_MIPS_MT_SMP
        sanitize_tlb_entries();
@@ -66,7 +66,7 @@ void prom_init(void)
 {
        set_io_port_base(0xbfd00000);
 
-       prom_printf("\nLINUX started...\n");
+       pr_info("\nLINUX started...\n");
        prom_init_cmdline();
        prom_meminit();
 }
@@ -91,7 +91,7 @@ static void __init serial_init(void)
        s.timeout = 4;
 
        if (early_serial_setup(&s) != 0) {
-               prom_printf(KERN_ERR "Serial setup failed!\n");
+               printk(KERN_ERR "Serial setup failed!\n");
        }
 
 #endif
index 30711d016fed008a7520b1341e32c0d81fbf2ccb..d3a21c741514617abb962c931188d24f0d30e9fb 100644 (file)
@@ -199,7 +199,4 @@ void __init plat_timer_setup(struct irqaction *irq)
        irq_desc[mips_cpu_timer_irq].flags |= IRQ_PER_CPU;
        set_irq_handler(mips_cpu_timer_irq, handle_percpu_irq);
 #endif
-
-       /* to generate the first timer interrupt */
-       write_c0_compare(read_c0_count() + (mips_hpt_frequency/HZ));
 }
index de5727385bc67c2a03a91845a1d66c86fa61cfcb..293697b156036ba35188d4ee94a58b50fe6d9e22 100644 (file)
@@ -31,5 +31,3 @@ obj-$(CONFIG_IP22_CPU_SCACHE) += sc-ip22.o
 obj-$(CONFIG_R5000_CPU_SCACHE)  += sc-r5k.o
 obj-$(CONFIG_RM7000_CPU_SCACHE)        += sc-rm7k.o
 obj-$(CONFIG_MIPS_CPU_SCACHE)  += sc-mips.o
-
-EXTRA_AFLAGS := $(CFLAGS)
index f32ebde30ccf1cee1dbe06b29a623b00ea07a744..560a6de9655620254234557674a080f897448189 100644 (file)
@@ -128,7 +128,6 @@ static inline void tx39_flush_cache_all(void)
                return;
 
        tx39_blast_dcache();
-       tx39_blast_icache();
 }
 
 static inline void tx39___flush_cache_all(void)
@@ -142,24 +141,19 @@ static void tx39_flush_cache_mm(struct mm_struct *mm)
        if (!cpu_has_dc_aliases)
                return;
 
-       if (cpu_context(smp_processor_id(), mm) != 0) {
-               tx39_flush_cache_all();
-       }
+       if (cpu_context(smp_processor_id(), mm) != 0)
+               tx39_blast_dcache();
 }
 
 static void tx39_flush_cache_range(struct vm_area_struct *vma,
        unsigned long start, unsigned long end)
 {
-       int exec;
-
+       if (!cpu_has_dc_aliases)
+               return;
        if (!(cpu_context(smp_processor_id(), vma->vm_mm)))
                return;
 
-       exec = vma->vm_flags & VM_EXEC;
-       if (cpu_has_dc_aliases || exec)
-               tx39_blast_dcache();
-       if (exec)
-               tx39_blast_icache();
+       tx39_blast_dcache();
 }
 
 static void tx39_flush_cache_page(struct vm_area_struct *vma, unsigned long page, unsigned long pfn)
@@ -218,7 +212,7 @@ static void tx39_flush_cache_page(struct vm_area_struct *vma, unsigned long page
 
 static void local_tx39_flush_data_cache_page(void * addr)
 {
-       tx39_blast_dcache_page(addr);
+       tx39_blast_dcache_page((unsigned long)addr);
 }
 
 static void tx39_flush_data_cache_page(unsigned long addr)
index e19fbb9ee47f240e9785cef121e819aacc6f8436..11a916629d3b57859796766d589ac5a1837b2c84 100644 (file)
@@ -77,66 +77,66 @@ static uint32_t     extract_dc(unsigned short addr, int data);
 static inline void breakout_errctl(unsigned int val)
 {
        if (val & CP0_ERRCTL_RECOVERABLE)
-               prom_printf(" recoverable");
+               printk(" recoverable");
        if (val & CP0_ERRCTL_DCACHE)
-               prom_printf(" dcache");
+               printk(" dcache");
        if (val & CP0_ERRCTL_ICACHE)
-               prom_printf(" icache");
+               printk(" icache");
        if (val & CP0_ERRCTL_MULTIBUS)
-               prom_printf(" multiple-buserr");
-       prom_printf("\n");
+               printk(" multiple-buserr");
+       printk("\n");
 }
 
 static inline void breakout_cerri(unsigned int val)
 {
        if (val & CP0_CERRI_TAG_PARITY)
-               prom_printf(" tag-parity");
+               printk(" tag-parity");
        if (val & CP0_CERRI_DATA_PARITY)
-               prom_printf(" data-parity");
+               printk(" data-parity");
        if (val & CP0_CERRI_EXTERNAL)
-               prom_printf(" external");
-       prom_printf("\n");
+               printk(" external");
+       printk("\n");
 }
 
 static inline void breakout_cerrd(unsigned int val)
 {
        switch (val & CP0_CERRD_CAUSES) {
        case CP0_CERRD_LOAD:
-               prom_printf(" load,");
+               printk(" load,");
                break;
        case CP0_CERRD_STORE:
-               prom_printf(" store,");
+               printk(" store,");
                break;
        case CP0_CERRD_FILLWB:
-               prom_printf(" fill/wb,");
+               printk(" fill/wb,");
                break;
        case CP0_CERRD_COHERENCY:
-               prom_printf(" coherency,");
+               printk(" coherency,");
                break;
        case CP0_CERRD_DUPTAG:
-               prom_printf(" duptags,");
+               printk(" duptags,");
                break;
        default:
-               prom_printf(" NO CAUSE,");
+               printk(" NO CAUSE,");
                break;
        }
        if (!(val & CP0_CERRD_TYPES))
-               prom_printf(" NO TYPE");
+               printk(" NO TYPE");
        else {
                if (val & CP0_CERRD_MULTIPLE)
-                       prom_printf(" multi-err");
+                       printk(" multi-err");
                if (val & CP0_CERRD_TAG_STATE)
-                       prom_printf(" tag-state");
+                       printk(" tag-state");
                if (val & CP0_CERRD_TAG_ADDRESS)
-                       prom_printf(" tag-address");
+                       printk(" tag-address");
                if (val & CP0_CERRD_DATA_SBE)
-                       prom_printf(" data-SBE");
+                       printk(" data-SBE");
                if (val & CP0_CERRD_DATA_DBE)
-                       prom_printf(" data-DBE");
+                       printk(" data-DBE");
                if (val & CP0_CERRD_EXTERNAL)
-                       prom_printf(" external");
+                       printk(" external");
        }
-       prom_printf("\n");
+       printk("\n");
 }
 
 #ifndef CONFIG_SIBYTE_BUS_WATCHER
@@ -157,18 +157,18 @@ static void check_bus_watcher(void)
                l2_tag = in64(IO_SPACE_BASE | A_L2_ECC_TAG);
 #endif
                memio_err = csr_in32(IOADDR(A_BUS_MEM_IO_ERRORS));
-               prom_printf("Bus watcher error counters: %08x %08x\n", l2_err, memio_err);
-               prom_printf("\nLast recorded signature:\n");
-               prom_printf("Request %02x from %d, answered by %d with Dcode %d\n",
+               printk("Bus watcher error counters: %08x %08x\n", l2_err, memio_err);
+               printk("\nLast recorded signature:\n");
+               printk("Request %02x from %d, answered by %d with Dcode %d\n",
                       (unsigned int)(G_SCD_BERR_TID(status) & 0x3f),
                       (int)(G_SCD_BERR_TID(status) >> 6),
                       (int)G_SCD_BERR_RID(status),
                       (int)G_SCD_BERR_DCODE(status));
 #ifdef DUMP_L2_ECC_TAG_ON_ERROR
-               prom_printf("Last L2 tag w/ bad ECC: %016llx\n", l2_tag);
+               printk("Last L2 tag w/ bad ECC: %016llx\n", l2_tag);
 #endif
        } else {
-               prom_printf("Bus watcher indicates no error\n");
+               printk("Bus watcher indicates no error\n");
        }
 }
 #else
@@ -187,11 +187,11 @@ asmlinkage void sb1_cache_error(void)
 #else
        csr_out32(M_SCD_TRACE_CFG_FREEZE, IO_SPACE_BASE | A_SCD_TRACE_CFG);
 #endif
-       prom_printf("Trace buffer frozen\n");
+       printk("Trace buffer frozen\n");
 #endif
 
-       prom_printf("Cache error exception on CPU %x:\n",
-                   (read_c0_prid() >> 25) & 0x7);
+       printk("Cache error exception on CPU %x:\n",
+              (read_c0_prid() >> 25) & 0x7);
 
        __asm__ __volatile__ (
        "       .set    push\n\t"
@@ -209,43 +209,43 @@ asmlinkage void sb1_cache_error(void)
          "=r" (dpahi), "=r" (dpalo), "=r" (eepc));
 
        cerr_dpa = (((uint64_t)dpahi) << 32) | dpalo;
-       prom_printf(" c0_errorepc ==   %08x\n", eepc);
-       prom_printf(" c0_errctl   ==   %08x", errctl);
+       printk(" c0_errorepc ==   %08x\n", eepc);
+       printk(" c0_errctl   ==   %08x", errctl);
        breakout_errctl(errctl);
        if (errctl & CP0_ERRCTL_ICACHE) {
-               prom_printf(" c0_cerr_i   ==   %08x", cerr_i);
+               printk(" c0_cerr_i   ==   %08x", cerr_i);
                breakout_cerri(cerr_i);
                if (CP0_CERRI_IDX_VALID(cerr_i)) {
                        /* Check index of EPC, allowing for delay slot */
                        if (((eepc & SB1_CACHE_INDEX_MASK) != (cerr_i & SB1_CACHE_INDEX_MASK)) &&
                            ((eepc & SB1_CACHE_INDEX_MASK) != ((cerr_i & SB1_CACHE_INDEX_MASK) - 4)))
-                               prom_printf(" cerr_i idx doesn't match eepc\n");
+                               printk(" cerr_i idx doesn't match eepc\n");
                        else {
                                res = extract_ic(cerr_i & SB1_CACHE_INDEX_MASK,
                                                 (cerr_i & CP0_CERRI_DATA) != 0);
                                if (!(res & cerr_i))
-                                       prom_printf("...didn't see indicated icache problem\n");
+                                       printk("...didn't see indicated icache problem\n");
                        }
                }
        }
        if (errctl & CP0_ERRCTL_DCACHE) {
-               prom_printf(" c0_cerr_d   ==   %08x", cerr_d);
+               printk(" c0_cerr_d   ==   %08x", cerr_d);
                breakout_cerrd(cerr_d);
                if (CP0_CERRD_DPA_VALID(cerr_d)) {
-                       prom_printf(" c0_cerr_dpa == %010llx\n", cerr_dpa);
+                       printk(" c0_cerr_dpa == %010llx\n", cerr_dpa);
                        if (!CP0_CERRD_IDX_VALID(cerr_d)) {
                                res = extract_dc(cerr_dpa & SB1_CACHE_INDEX_MASK,
                                                 (cerr_d & CP0_CERRD_DATA) != 0);
                                if (!(res & cerr_d))
-                                       prom_printf("...didn't see indicated dcache problem\n");
+                                       printk("...didn't see indicated dcache problem\n");
                        } else {
                                if ((cerr_dpa & SB1_CACHE_INDEX_MASK) != (cerr_d & SB1_CACHE_INDEX_MASK))
-                                       prom_printf(" cerr_d idx doesn't match cerr_dpa\n");
+                                       printk(" cerr_d idx doesn't match cerr_dpa\n");
                                else {
                                        res = extract_dc(cerr_d & SB1_CACHE_INDEX_MASK,
                                                         (cerr_d & CP0_CERRD_DATA) != 0);
                                        if (!(res & cerr_d))
-                                               prom_printf("...didn't see indicated problem\n");
+                                               printk("...didn't see indicated problem\n");
                                }
                        }
                }
@@ -334,7 +334,7 @@ static uint32_t extract_ic(unsigned short addr, int data)
        uint8_t lru;
        int res = 0;
 
-       prom_printf("Icache index 0x%04x  ", addr);
+       printk("Icache index 0x%04x  ", addr);
        for (way = 0; way < 4; way++) {
                /* Index-load-tag-I */
                __asm__ __volatile__ (
@@ -354,7 +354,7 @@ static uint32_t extract_ic(unsigned short addr, int data)
                taglo = ((unsigned long long)taglohi << 32) | taglolo;
                if (way == 0) {
                        lru = (taghi >> 14) & 0xff;
-                       prom_printf("[Bank %d Set 0x%02x]  LRU > %d %d %d %d > MRU\n",
+                       printk("[Bank %d Set 0x%02x]  LRU > %d %d %d %d > MRU\n",
                                    ((addr >> 5) & 0x3), /* bank */
                                    ((addr >> 7) & 0x3f), /* index */
                                    (lru & 0x3),
@@ -369,19 +369,19 @@ static uint32_t extract_ic(unsigned short addr, int data)
                if (valid) {
                        tlo_tmp = taglo & 0xfff3ff;
                        if (((taglo >> 10) & 1) ^ range_parity(tlo_tmp, 23, 0)) {
-                               prom_printf("   ** bad parity in VTag0/G/ASID\n");
+                               printk("   ** bad parity in VTag0/G/ASID\n");
                                res |= CP0_CERRI_TAG_PARITY;
                        }
                        if (((taglo >> 11) & 1) ^ range_parity(taglo, 63, 24)) {
-                               prom_printf("   ** bad parity in R/VTag1\n");
+                               printk("   ** bad parity in R/VTag1\n");
                                res |= CP0_CERRI_TAG_PARITY;
                        }
                }
                if (valid ^ ((taghi >> 27) & 1)) {
-                       prom_printf("   ** bad parity for valid bit\n");
+                       printk("   ** bad parity for valid bit\n");
                        res |= CP0_CERRI_TAG_PARITY;
                }
-               prom_printf(" %d  [VA %016llx]  [Vld? %d]  raw tags: %08X-%016llX\n",
+               printk(" %d  [VA %016llx]  [Vld? %d]  raw tags: %08X-%016llX\n",
                            way, va, valid, taghi, taglo);
 
                if (data) {
@@ -407,21 +407,21 @@ static uint32_t extract_ic(unsigned short addr, int data)
                                : "r" ((way << 13) | addr | (offset << 3)));
                                predecode = (datahi >> 8) & 0xff;
                                if (((datahi >> 16) & 1) != (uint32_t)range_parity(predecode, 7, 0)) {
-                                       prom_printf("   ** bad parity in predecode\n");
+                                       printk("   ** bad parity in predecode\n");
                                        res |= CP0_CERRI_DATA_PARITY;
                                }
                                /* XXXKW should/could check predecode bits themselves */
                                if (((datahi >> 4) & 0xf) ^ inst_parity(insta)) {
-                                       prom_printf("   ** bad parity in instruction a\n");
+                                       printk("   ** bad parity in instruction a\n");
                                        res |= CP0_CERRI_DATA_PARITY;
                                }
                                if ((datahi & 0xf) ^ inst_parity(instb)) {
-                                       prom_printf("   ** bad parity in instruction b\n");
+                                       printk("   ** bad parity in instruction b\n");
                                        res |= CP0_CERRI_DATA_PARITY;
                                }
-                               prom_printf("  %05X-%08X%08X", datahi, insta, instb);
+                               printk("  %05X-%08X%08X", datahi, insta, instb);
                        }
-                       prom_printf("\n");
+                       printk("\n");
                }
        }
        return res;
@@ -489,7 +489,7 @@ static uint32_t extract_dc(unsigned short addr, int data)
        uint8_t ecc, lru;
        int res = 0;
 
-       prom_printf("Dcache index 0x%04x  ", addr);
+       printk("Dcache index 0x%04x  ", addr);
        for (way = 0; way < 4; way++) {
                __asm__ __volatile__ (
                "       .set    push\n\t"
@@ -509,7 +509,7 @@ static uint32_t extract_dc(unsigned short addr, int data)
                pa = (taglo & 0xFFFFFFE000ULL) | addr;
                if (way == 0) {
                        lru = (taghi >> 14) & 0xff;
-                       prom_printf("[Bank %d Set 0x%02x]  LRU > %d %d %d %d > MRU\n",
+                       printk("[Bank %d Set 0x%02x]  LRU > %d %d %d %d > MRU\n",
                                    ((addr >> 11) & 0x2) | ((addr >> 5) & 1), /* bank */
                                    ((addr >> 6) & 0x3f), /* index */
                                    (lru & 0x3),
@@ -519,15 +519,15 @@ static uint32_t extract_dc(unsigned short addr, int data)
                }
                state = (taghi >> 25) & 0x1f;
                valid = DC_TAG_VALID(state);
-               prom_printf(" %d  [PA %010llx]  [state %s (%02x)]  raw tags: %08X-%016llX\n",
+               printk(" %d  [PA %010llx]  [state %s (%02x)]  raw tags: %08X-%016llX\n",
                            way, pa, dc_state_str(state), state, taghi, taglo);
                if (valid) {
                        if (((taglo >> 11) & 1) ^ range_parity(taglo, 39, 26)) {
-                               prom_printf("   ** bad parity in PTag1\n");
+                               printk("   ** bad parity in PTag1\n");
                                res |= CP0_CERRD_TAG_ADDRESS;
                        }
                        if (((taglo >> 10) & 1) ^ range_parity(taglo, 25, 13)) {
-                               prom_printf("   ** bad parity in PTag0\n");
+                               printk("   ** bad parity in PTag0\n");
                                res |= CP0_CERRD_TAG_ADDRESS;
                        }
                } else {
@@ -567,13 +567,13 @@ static uint32_t extract_dc(unsigned short addr, int data)
                                        }
                                        res |= (bits == 1) ? CP0_CERRD_DATA_SBE : CP0_CERRD_DATA_DBE;
                                }
-                               prom_printf("  %02X-%016llX", datahi, datalo);
+                               printk("  %02X-%016llX", datahi, datalo);
                        }
-                       prom_printf("\n");
+                       printk("\n");
                        if (bad_ecc)
-                               prom_printf("  dwords w/ bad ECC: %d %d %d %d\n",
-                                           !!(bad_ecc & 8), !!(bad_ecc & 4),
-                                           !!(bad_ecc & 2), !!(bad_ecc & 1));
+                               printk("  dwords w/ bad ECC: %d %d %d %d\n",
+                                      !!(bad_ecc & 8), !!(bad_ecc & 4),
+                                      !!(bad_ecc & 2), !!(bad_ecc & 1));
                }
        }
        return res;
index 4a32e939698f6206fd29a8e454309c8b02687236..f503d02e403bbf78bdb421402ff6a6dfddf6f742 100644 (file)
@@ -246,10 +246,10 @@ void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
 {
        BUG_ON(direction == DMA_NONE);
 
-       if (cpu_is_noncoherent_r10000(dev)) {
+       if (!plat_device_is_coherent(dev)) {
                unsigned long addr;
 
-               addr = plat_dma_addr_to_phys(dma_handle);
+               addr = PAGE_OFFSET + plat_dma_addr_to_phys(dma_handle);
                __dma_sync(addr, size, direction);
        }
 }
@@ -276,7 +276,7 @@ void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
 {
        BUG_ON(direction == DMA_NONE);
 
-       if (cpu_is_noncoherent_r10000(dev)) {
+       if (!plat_device_is_coherent(dev)) {
                unsigned long addr;
 
                addr = PAGE_OFFSET + plat_dma_addr_to_phys(dma_handle);
@@ -295,7 +295,7 @@ void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
 
        /* Make sure that gcc doesn't leave the empty loop body.  */
        for (i = 0; i < nelems; i++, sg++) {
-               if (!plat_device_is_coherent(dev))
+               if (cpu_is_noncoherent_r10000(dev))
                        __dma_sync((unsigned long)page_address(sg->page),
                                   sg->length, direction);
                plat_unmap_dma_mem(sg->dma_address);
index fc2c96f0a1fd6bd532b233da431ca7dc4f6db5ff..cea7d0ea36e44c42b30d1a4b36bf7c461f7b4b66 100644 (file)
@@ -6,13 +6,98 @@
  * (C) Copyright 1995 1996 Linus Torvalds
  * (C) Copyright 2001, 2002 Ralf Baechle
  */
-#include <linux/mm.h>
 #include <linux/module.h>
 #include <asm/addrspace.h>
 #include <asm/byteorder.h>
 
 #include <linux/vmalloc.h>
-#include <linux/io.h>
+#include <asm/cacheflush.h>
+#include <asm/io.h>
+#include <asm/tlbflush.h>
+
+static inline void remap_area_pte(pte_t * pte, unsigned long address,
+       phys_t size, phys_t phys_addr, unsigned long flags)
+{
+       phys_t end;
+       unsigned long pfn;
+       pgprot_t pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | __READABLE
+                                  | __WRITEABLE | flags);
+
+       address &= ~PMD_MASK;
+       end = address + size;
+       if (end > PMD_SIZE)
+               end = PMD_SIZE;
+       if (address >= end)
+               BUG();
+       pfn = phys_addr >> PAGE_SHIFT;
+       do {
+               if (!pte_none(*pte)) {
+                       printk("remap_area_pte: page already exists\n");
+                       BUG();
+               }
+               set_pte(pte, pfn_pte(pfn, pgprot));
+               address += PAGE_SIZE;
+               pfn++;
+               pte++;
+       } while (address && (address < end));
+}
+
+static inline int remap_area_pmd(pmd_t * pmd, unsigned long address,
+       phys_t size, phys_t phys_addr, unsigned long flags)
+{
+       phys_t end;
+
+       address &= ~PGDIR_MASK;
+       end = address + size;
+       if (end > PGDIR_SIZE)
+               end = PGDIR_SIZE;
+       phys_addr -= address;
+       if (address >= end)
+               BUG();
+       do {
+               pte_t * pte = pte_alloc_kernel(pmd, address);
+               if (!pte)
+                       return -ENOMEM;
+               remap_area_pte(pte, address, end - address, address + phys_addr, flags);
+               address = (address + PMD_SIZE) & PMD_MASK;
+               pmd++;
+       } while (address && (address < end));
+       return 0;
+}
+
+static int remap_area_pages(unsigned long address, phys_t phys_addr,
+       phys_t size, unsigned long flags)
+{
+       int error;
+       pgd_t * dir;
+       unsigned long end = address + size;
+
+       phys_addr -= address;
+       dir = pgd_offset(&init_mm, address);
+       flush_cache_all();
+       if (address >= end)
+               BUG();
+       do {
+               pud_t *pud;
+               pmd_t *pmd;
+
+               error = -ENOMEM;
+               pud = pud_alloc(&init_mm, dir, address);
+               if (!pud)
+                       break;
+               pmd = pmd_alloc(&init_mm, pud, address);
+               if (!pmd)
+                       break;
+               if (remap_area_pmd(pmd, address, end - address,
+                                        phys_addr + address, flags))
+                       break;
+               error = 0;
+               address = (address + PGDIR_SIZE) & PGDIR_MASK;
+               dir++;
+       } while (address && (address < end));
+       flush_tlb_all();
+       return error;
+}
 
 /*
  * Generic mapping function (not visible outside):
@@ -36,7 +121,6 @@ void __iomem * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags)
        unsigned long offset;
        phys_t last_addr;
        void * addr;
-       pgprot_t pgprot;
 
        phys_addr = fixup_bigphys_addr(phys_addr, size);
 
@@ -68,9 +152,6 @@ void __iomem * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags)
                                return NULL;
        }
 
-       pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | __READABLE
-                         | __WRITEABLE | flags);
-
        /*
         * Mappings have to be page-aligned
         */
@@ -85,8 +166,7 @@ void __iomem * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags)
        if (!area)
                return NULL;
        addr = area->addr;
-       if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
-                              phys_addr, pgprot)) {
+       if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
                vunmap(addr);
                return NULL;
        }
index 2292d0ec47fc27aadfe255499214293f81ea5622..2c30b4f562456ef12c68b277adfccaa8da98dfb6 100644 (file)
@@ -74,11 +74,6 @@ void prom_putchar(char c)
        uart->iu_thr = c;
 }
 
-char __init prom_getchar(void)
-{
-       return 0;
-}
-
 static void inline ja_console_probe(void)
 {
        struct uart_port up;
index 81037709ba0d4cc2a4f5daefb83c02401cf3e5f6..561844878a90075a475130a3440b7ae96c023429 100644 (file)
@@ -38,8 +38,6 @@ static struct platform_device mv643xx_eth_shared_device = {
 #define MV64x60_IRQ_ETH_1 49
 #define MV64x60_IRQ_ETH_2 50
 
-#ifdef CONFIG_MV643XX_ETH_0
-
 static struct resource mv64x60_eth0_resources[] = {
        [0] = {
                .name   = "eth0 irq",
@@ -49,10 +47,8 @@ static struct resource mv64x60_eth0_resources[] = {
        },
 };
 
-static char eth0_mac_addr[ETH_ALEN];
-
 static struct mv643xx_eth_platform_data eth0_pd = {
-       .mac_addr       = eth0_mac_addr,
+       .port_number    = 0,
 
        .tx_sram_addr   = MV_SRAM_BASE_ETH0,
        .tx_sram_size   = MV_SRAM_TXRING_SIZE,
@@ -72,9 +68,6 @@ static struct platform_device eth0_device = {
                .platform_data = &eth0_pd,
        },
 };
-#endif /* CONFIG_MV643XX_ETH_0 */
-
-#ifdef CONFIG_MV643XX_ETH_1
 
 static struct resource mv64x60_eth1_resources[] = {
        [0] = {
@@ -85,10 +78,8 @@ static struct resource mv64x60_eth1_resources[] = {
        },
 };
 
-static char eth1_mac_addr[ETH_ALEN];
-
 static struct mv643xx_eth_platform_data eth1_pd = {
-       .mac_addr       = eth1_mac_addr,
+       .port_number    = 1,
 
        .tx_sram_addr   = MV_SRAM_BASE_ETH1,
        .tx_sram_size   = MV_SRAM_TXRING_SIZE,
@@ -108,9 +99,6 @@ static struct platform_device eth1_device = {
                .platform_data = &eth1_pd,
        },
 };
-#endif /* CONFIG_MV643XX_ETH_1 */
-
-#ifdef CONFIG_MV643XX_ETH_2
 
 static struct resource mv64x60_eth2_resources[] = {
        [0] = {
@@ -121,10 +109,8 @@ static struct resource mv64x60_eth2_resources[] = {
        },
 };
 
-static char eth2_mac_addr[ETH_ALEN];
-
 static struct mv643xx_eth_platform_data eth2_pd = {
-       .mac_addr       = eth2_mac_addr,
+       .port_number    = 2,
 };
 
 static struct platform_device eth2_device = {
@@ -136,19 +122,12 @@ static struct platform_device eth2_device = {
                .platform_data = &eth2_pd,
        },
 };
-#endif /* CONFIG_MV643XX_ETH_2 */
 
 static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
        &mv643xx_eth_shared_device,
-#ifdef CONFIG_MV643XX_ETH_0
        &eth0_device,
-#endif
-#ifdef CONFIG_MV643XX_ETH_1
        &eth1_device,
-#endif
-#ifdef CONFIG_MV643XX_ETH_2
        &eth2_device,
-#endif
 };
 
 static u8 __init exchange_bit(u8 val, u8 cs)
@@ -215,15 +194,9 @@ static int __init mv643xx_eth_add_pds(void)
        int ret;
 
        get_mac(mac);
-#ifdef CONFIG_MV643XX_ETH_0
-       eth_mac_add(eth1_mac_addr, mac, 0);
-#endif
-#ifdef CONFIG_MV643XX_ETH_1
-       eth_mac_add(eth1_mac_addr, mac, 1);
-#endif
-#ifdef CONFIG_MV643XX_ETH_2
-       eth_mac_add(eth2_mac_addr, mac, 2);
-#endif
+       eth_mac_add(eth0_pd.mac_addr, mac, 0);
+       eth_mac_add(eth1_pd.mac_addr, mac, 1);
+       eth_mac_add(eth2_pd.mac_addr, mac, 2);
        ret = platform_add_devices(mv643xx_eth_pd_devs,
                        ARRAY_SIZE(mv643xx_eth_pd_devs));
 
index 57cfe5c6e4a8e71cef2c89e1c34f2a7d749fcc9b..44e4c3fc740398fdbfc6680c973864b6316f2bf1 100644 (file)
@@ -38,8 +38,6 @@ static struct platform_device mv643xx_eth_shared_device = {
 #define MV64x60_IRQ_ETH_1 49
 #define MV64x60_IRQ_ETH_2 50
 
-#ifdef CONFIG_MV643XX_ETH_0
-
 static struct resource mv64x60_eth0_resources[] = {
        [0] = {
                .name   = "eth0 irq",
@@ -49,10 +47,8 @@ static struct resource mv64x60_eth0_resources[] = {
        },
 };
 
-static char eth0_mac_addr[ETH_ALEN];
-
 static struct mv643xx_eth_platform_data eth0_pd = {
-       .mac_addr       = eth0_mac_addr,
+       .port_number    = 0,
 
        .tx_sram_addr   = MV_SRAM_BASE_ETH0,
        .tx_sram_size   = MV_SRAM_TXRING_SIZE,
@@ -72,9 +68,6 @@ static struct platform_device eth0_device = {
                .platform_data = &eth0_pd,
        },
 };
-#endif /* CONFIG_MV643XX_ETH_0 */
-
-#ifdef CONFIG_MV643XX_ETH_1
 
 static struct resource mv64x60_eth1_resources[] = {
        [0] = {
@@ -85,10 +78,8 @@ static struct resource mv64x60_eth1_resources[] = {
        },
 };
 
-static char eth1_mac_addr[ETH_ALEN];
-
 static struct mv643xx_eth_platform_data eth1_pd = {
-       .mac_addr       = eth1_mac_addr,
+       .port_number    = 1,
 
        .tx_sram_addr   = MV_SRAM_BASE_ETH1,
        .tx_sram_size   = MV_SRAM_TXRING_SIZE,
@@ -108,9 +99,6 @@ static struct platform_device eth1_device = {
                .platform_data = &eth1_pd,
        },
 };
-#endif /* CONFIG_MV643XX_ETH_1 */
-
-#ifdef CONFIG_MV643XX_ETH_2
 
 static struct resource mv64x60_eth2_resources[] = {
        [0] = {
@@ -121,10 +109,8 @@ static struct resource mv64x60_eth2_resources[] = {
        },
 };
 
-static char eth2_mac_addr[ETH_ALEN];
-
 static struct mv643xx_eth_platform_data eth2_pd = {
-       .mac_addr       = eth2_mac_addr,
+       .port_number    = 2,
 };
 
 static struct platform_device eth2_device = {
@@ -136,19 +122,12 @@ static struct platform_device eth2_device = {
                .platform_data = &eth2_pd,
        },
 };
-#endif /* CONFIG_MV643XX_ETH_2 */
 
 static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
        &mv643xx_eth_shared_device,
-#ifdef CONFIG_MV643XX_ETH_0
        &eth0_device,
-#endif
-#ifdef CONFIG_MV643XX_ETH_1
        &eth1_device,
-#endif
-#ifdef CONFIG_MV643XX_ETH_2
        &eth2_device,
-#endif
 };
 
 static u8 __init exchange_bit(u8 val, u8 cs)
@@ -215,15 +194,9 @@ static int __init mv643xx_eth_add_pds(void)
        int ret;
 
        get_mac(mac);
-#ifdef CONFIG_MV643XX_ETH_0
-       eth_mac_add(eth1_mac_addr, mac, 0);
-#endif
-#ifdef CONFIG_MV643XX_ETH_1
-       eth_mac_add(eth1_mac_addr, mac, 1);
-#endif
-#ifdef CONFIG_MV643XX_ETH_2
-       eth_mac_add(eth2_mac_addr, mac, 2);
-#endif
+       eth_mac_add(eth0_pd.mac_addr, mac, 0);
+       eth_mac_add(eth1_pd.mac_addr, mac, 1);
+       eth_mac_add(eth2_pd.mac_addr, mac, 2);
        ret = platform_add_devices(mv643xx_eth_pd_devs,
                        ARRAY_SIZE(mv643xx_eth_pd_devs));
 
index 6c495b2f1560f71936c3f2ac7617b98b275bf5a9..7780aa0c655538c40cff3866337bdcaafc3ad42a 100644 (file)
@@ -37,8 +37,6 @@ static struct platform_device mv643xx_eth_shared_device = {
 #define MV64x60_IRQ_ETH_0 48
 #define MV64x60_IRQ_ETH_1 49
 
-#ifdef CONFIG_MV643XX_ETH_0
-
 static struct resource mv64x60_eth0_resources[] = {
        [0] = {
                .name   = "eth0 irq",
@@ -48,10 +46,8 @@ static struct resource mv64x60_eth0_resources[] = {
        },
 };
 
-static char eth0_mac_addr[ETH_ALEN];
-
 static struct mv643xx_eth_platform_data eth0_pd = {
-       .mac_addr       = eth0_mac_addr,
+       .port_number    = 0,
 
        .tx_sram_addr   = MV_SRAM_BASE_ETH0,
        .tx_sram_size   = MV_SRAM_TXRING_SIZE,
@@ -71,9 +67,6 @@ static struct platform_device eth0_device = {
                .platform_data = &eth0_pd,
        },
 };
-#endif /* CONFIG_MV643XX_ETH_0 */
-
-#ifdef CONFIG_MV643XX_ETH_1
 
 static struct resource mv64x60_eth1_resources[] = {
        [0] = {
@@ -84,10 +77,8 @@ static struct resource mv64x60_eth1_resources[] = {
        },
 };
 
-static char eth1_mac_addr[ETH_ALEN];
-
 static struct mv643xx_eth_platform_data eth1_pd = {
-       .mac_addr       = eth1_mac_addr,
+       .port_number    = 1,
 
        .tx_sram_addr   = MV_SRAM_BASE_ETH1,
        .tx_sram_size   = MV_SRAM_TXRING_SIZE,
@@ -107,16 +98,11 @@ static struct platform_device eth1_device = {
                .platform_data = &eth1_pd,
        },
 };
-#endif /* CONFIG_MV643XX_ETH_1 */
 
 static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
        &mv643xx_eth_shared_device,
-#ifdef CONFIG_MV643XX_ETH_0
        &eth0_device,
-#endif
-#ifdef CONFIG_MV643XX_ETH_1
        &eth1_device,
-#endif
        /* The third port is not wired up on the Ocelot C */
 };
 
@@ -184,12 +170,8 @@ static int __init mv643xx_eth_add_pds(void)
        int ret;
 
        get_mac(mac);
-#ifdef CONFIG_MV643XX_ETH_0
-       eth_mac_add(eth1_mac_addr, mac, 0);
-#endif
-#ifdef CONFIG_MV643XX_ETH_1
-       eth_mac_add(eth1_mac_addr, mac, 1);
-#endif
+       eth_mac_add(eth0_pd.mac_addr, mac, 0);
+       eth_mac_add(eth1_pd.mac_addr, mac, 1);
        ret = platform_add_devices(mv643xx_eth_pd_devs,
                        ARRAY_SIZE(mv643xx_eth_pd_devs));
 
index adb5665d40a950cf19f3f6ace46dba092ffc4e44..c0a0030d949d70ec5bfc0e85e8dc0dd1bb56677d 100644 (file)
@@ -4,5 +4,3 @@
 
 obj-y                  += irq.o gt-irq.o prom.o reset.o setup.o
 obj-$(CONFIG_KGDB)     += dbg_io.o
-
-EXTRA_AFLAGS := $(CFLAGS)
index ca395ef06d4e9514b82b4fdd41493199d7d1392f..fb6f235348b0d232b7d37dbeac0b90cc4d8922af 100644 (file)
@@ -11,7 +11,7 @@ config PROFILING
 
 config OPROFILE
        tristate "OProfile system profiling (EXPERIMENTAL)"
-       depends on PROFILING && !!MIPS_MT_SMTC && EXPERIMENTAL
+       depends on PROFILING && !MIPS_MT_SMTC && EXPERIMENTAL
        help
          OProfile is a profiling system capable of profiling the
          whole system, include the kernel, kernel modules, libraries,
index 455d76ad06d83cf1eb3045c3ca6691cb088584c3..9d08608aaa513568a41b94a38c59c0d8e1e752be 100644 (file)
@@ -223,10 +223,12 @@ static inline int n_counters(void)
        switch (current_cpu_data.cputype) {
        case CPU_R10000:
                counters = 2;
+               break;
 
        case CPU_R12000:
        case CPU_R14000:
                counters = 4;
+               break;
 
        default:
                counters = __n_counters();
index f8696081c5b1fd089dc99d0abfc1021af6ec6868..6e72d213f4cd0512461a93c64ce32e84b06fff34 100644 (file)
@@ -38,6 +38,10 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
        unsigned char irq = pin;
 
+       /* SMSC SLC90E66 IDE uses irq 14, 15 (default) */
+       if (dev->vendor == PCI_VENDOR_ID_EFAR &&
+           dev->device == PCI_DEVICE_ID_EFAR_SLC90E66_1)
+               return irq;
        /* IRQ rotation (PICMG) */
        irq--;                  /* 0-3 */
        if (dev->bus->parent == NULL &&
@@ -93,13 +97,3 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
 {
        return 0;
 }
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-       /* SMSC SLC90E66 IDE uses irq 14, 15 (default) */
-       if (!(dev->vendor == PCI_VENDOR_ID_EFAR &&
-             dev->device == PCI_DEVICE_ID_EFAR_SLC90E66_1))
-               return pci_get_irq(dev, pin);
-
-       dev->irq = irq;
-}
index 0c9a4732d45506d3495192efbee8029b08575d0b..36e5fb1b3786b7c17a3202f8b6457aef9f642096 100644 (file)
@@ -14,6 +14,8 @@
 #include <asm/mipsregs.h>
 #include <asm/sni.h>
 
+#include <irq.h>
+
 /*
  * PCIMT Shortcuts ...
  */
index 8ae46481fcb720d98b608b5adea07458396ae59d..7932dfe5eb9be5c9ab01c4b34702cac82c024cae 100644 (file)
@@ -172,7 +172,11 @@ static int config_access(unsigned char access_type, struct pci_bus *bus,
                error = -1;
                DBG("Au1x Master Abort\n");
        } else if ((status >> 28) & 0xf) {
-               DBG("PCI ERR detected: status %x\n", status);
+               DBG("PCI ERR detected: device %d, status %x\n", device, ((status >> 28) & 0xf));
+
+               /* clear errors */
+               au_writel(status & 0xf000ffff, Au1500_PCI_STATCMD);
+
                *data = 0xffffffff;
                error = -1;
        }
index 697a7e48cb8d1498f2572b72dd5838ed287eccb4..de7cfc559ddbdc56980711374577b8a001f5469e 100644 (file)
@@ -231,7 +231,7 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
        return pcibios_plat_dev_init(dev);
 }
 
-static void __init pcibios_fixup_device_resources(struct pci_dev *dev,
+static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev,
        struct pci_bus *bus)
 {
        /* Update device resources.  */
index 8aeed6c2b8c36417b0ce84c9bf2420df6a5b7430..2f567452e7acd890b4609bc7e166ab4bc98e743e 100644 (file)
@@ -112,7 +112,7 @@ void __init prom_free_prom_memory(void)
 
 extern int pnx8550_console_port;
 
-/* used by prom_printf */
+/* used by early printk */
 void prom_putchar(char c)
 {
        if (pnx8550_console_port != -1) {
index e62123ca9b64899c51176a2c6ad6ae95381f5882..5bd737477685840410f3e73b400f75495f8990b2 100644 (file)
@@ -41,8 +41,6 @@
 #include <uart.h>
 #include <nand.h>
 
-extern void prom_printf(char *fmt, ...);
-
 extern void __init board_setup(void);
 extern void pnx8550_machine_restart(char *);
 extern void pnx8550_machine_halt(void);
@@ -51,7 +49,6 @@ extern struct resource ioport_resource;
 extern struct resource iomem_resource;
 extern void pnx8550_time_init(void);
 extern void rs_kgdb_hook(int tty_no);
-extern void prom_printf(char *fmt, ...);
 extern char *prom_getcmdline(void);
 
 struct resource standard_io_resources[] = {
@@ -141,7 +138,7 @@ void __init plat_mem_setup(void)
                argptr += strlen("console=ttyS");
                pnx8550_console_port = *argptr == '0' ? 0 : 1;
 
-               /* We must initialize the UART (console) before prom_printf */
+               /* We must initialize the UART (console) before early printk */
                /* Set LCR to 8-bit and BAUD to 38400 (no 5)                */
                ip3106_lcr(UART_BASE, pnx8550_console_port) =
                        PNX8XXX_UART_LCR_8BIT;
@@ -155,8 +152,8 @@ void __init plat_mem_setup(void)
                argptr += strlen("kgdb=ttyS");
                line = *argptr == '0' ? 0 : 1;
                rs_kgdb_hook(line);
-               prom_printf("KGDB: Using ttyS%i for session, "
-                               "please connect your debugger\n", line ? 1 : 0);
+               pr_info("KGDB: Using ttyS%i for session, "
+                       "please connect your debugger\n", line ? 1 : 0);
        }
 #endif
        return;
index 757e605693ff7bbac17ace1d032dbf19107aaf86..b7f1d9c4a8a3c7d588b270d6bd6e1bad0590f6b2 100644 (file)
@@ -107,8 +107,3 @@ void prom_putchar(char c)
        while ((readb_outer_space(lsr) & 0x20) == 0);
        writeb_outer_space(thr, c);
 }
-
-char __init prom_getchar(void)
-{
-       return 0;
-}
index 6aa4c0cd169ce513eba9dcafadd98faf2f797cb6..b6d649241dc1bdc00c2106499de946e0483ee3d1 100644 (file)
@@ -7,5 +7,3 @@ obj-y   += ip22-mc.o ip22-hpc.o ip22-int.o ip22-berr.o \
           ip22-time.o ip22-nvram.o ip22-reset.o ip22-setup.o
 
 obj-$(CONFIG_EISA)     += ip22-eisa.o
-
-EXTRA_AFLAGS := $(CFLAGS)
index a457263f4391811d102bfa593dcdcf03374b0a57..7ce76e20beb963baa8a62bef1707bbd9c18a483d 100644 (file)
@@ -9,5 +9,3 @@ obj-y   := ip27-berr.o ip27-irq.o ip27-init.o ip27-klconfig.o ip27-klnuma.o \
 obj-$(CONFIG_EARLY_PRINTK)     += ip27-console.o
 obj-$(CONFIG_KGDB)             += ip27-dbgio.o
 obj-$(CONFIG_SMP)              += ip27-smp.o
-
-EXTRA_AFLAGS := $(CFLAGS)
index 14211e382374609ac4166bb3900fde69bc3368cc..3ba830651c58f93d317212a04b784b00d6a17155 100644 (file)
@@ -6,12 +6,6 @@
  * Copyright (C) 2001, 2002 Ralf Baechle
  */
 #include <linux/init.h>
-#include <linux/console.h>
-#include <linux/kdev_t.h>
-#include <linux/major.h>
-#include <linux/termios.h>
-#include <linux/sched.h>
-#include <linux/tty.h>
 
 #include <asm/page.h>
 #include <asm/semaphore.h>
@@ -38,37 +32,10 @@ static inline struct ioc3_uartregs *console_uart(void)
        return &ioc3->sregs.uarta;
 }
 
-void prom_putchar(char c)
+void __init prom_putchar(char c)
 {
        struct ioc3_uartregs *uart = console_uart();
 
        while ((uart->iu_lsr & 0x20) == 0);
        uart->iu_thr = c;
 }
-
-static void ioc3_console_write(struct console *con, const char *s, unsigned n)
-{
-       while (n-- && *s) {
-               if (*s == '\n')
-                       prom_putchar('\r');
-               prom_putchar(*s);
-               s++;
-       }
-}
-
-static struct console ioc3_console = {
-       .name   = "ioc3",
-       .write  = ioc3_console_write,
-       .flags  = CON_PRINTBUFFER | CON_BOOT,
-       .index  = -1
-};
-
-__init void ip27_setup_console(void)
-{
-       register_console(&ioc3_console);
-}
-
-void __init disable_early_printk(void)
-{
-       unregister_console(&ioc3_console);
-}
index 9094baf31d0e8c8d7b4c6d40ccc3ce1fbea4a96c..74158d34963013eaad33eff4218beed7bcf8143a 100644 (file)
@@ -191,7 +191,6 @@ static inline void ioc3_eth_init(void)
        ioc3->eier = 0;
 }
 
-extern void ip27_setup_console(void);
 extern void ip27_time_init(void);
 extern void ip27_reboot_setup(void);
 
@@ -200,7 +199,6 @@ void __init plat_mem_setup(void)
        hubreg_t p, e, n_mode;
        nasid_t nid;
 
-       ip27_setup_console();
        ip27_reboot_setup();
 
        /*
index 530bf848c3d065fae9442b1175d3f4f5e6cceabb..7e1416768a60bd7f9c17551d0eaed0d1abc7122a 100644 (file)
@@ -5,5 +5,3 @@
 
 obj-y  += ip32-berr.o ip32-irq.o ip32-setup.o ip32-reset.o \
           crime.o ip32-memory.o
-
-EXTRA_AFLAGS := $(CFLAGS)
index ec7a2cffacf01430485da171a33142ee9de5f1f6..bdf24a7b54941ce75132b83adc6861695e15b819 100644 (file)
@@ -1,31 +1,35 @@
 config SIBYTE_SB1250
        bool
        select HW_HAS_PCI
-       select SIBYTE_HAS_LDT
+       select SIBYTE_ENABLE_LDT_IF_PCI
        select SIBYTE_SB1xxx_SOC
        select SYS_SUPPORTS_SMP
 
 config SIBYTE_BCM1120
        bool
        select SIBYTE_BCM112X
+       select SIBYTE_HAS_ZBUS_PROFILING
        select SIBYTE_SB1xxx_SOC
 
 config SIBYTE_BCM1125
        bool
        select HW_HAS_PCI
        select SIBYTE_BCM112X
+       select SIBYTE_HAS_ZBUS_PROFILING
        select SIBYTE_SB1xxx_SOC
 
 config SIBYTE_BCM1125H
        bool
        select HW_HAS_PCI
        select SIBYTE_BCM112X
-       select SIBYTE_HAS_LDT
+       select SIBYTE_ENABLE_LDT_IF_PCI
+       select SIBYTE_HAS_ZBUS_PROFILING
        select SIBYTE_SB1xxx_SOC
 
 config SIBYTE_BCM112X
        bool
        select SIBYTE_SB1xxx_SOC
+       select SIBYTE_HAS_ZBUS_PROFILING
 
 config SIBYTE_BCM1x80
        bool
@@ -37,6 +41,7 @@ config SIBYTE_BCM1x55
        bool
        select HW_HAS_PCI
        select SIBYTE_SB1xxx_SOC
+       select SIBYTE_HAS_ZBUS_PROFILING
        select SYS_SUPPORTS_SMP
 
 config SIBYTE_SB1xxx_SOC
@@ -95,8 +100,10 @@ config CPU_SB1_PASS_2
 
 config SIBYTE_HAS_LDT
        bool
-       depends on PCI && (SIBYTE_SB1250 || SIBYTE_BCM1125H)
-       default y
+
+config SIBYTE_ENABLE_LDT_IF_PCI
+       bool
+       select SIBYTE_HAS_LDT if PCI
 
 config SIMULATION
        bool "Running under simulation"
@@ -116,6 +123,7 @@ config SB1_CERR_STALL
 config SIBYTE_CFE
        bool "Booting from CFE"
        depends on SIBYTE_SB1xxx_SOC
+       select SYS_HAS_EARLY_PRINTK
        help
          Make use of the CFE API for enumerating available memory,
          controlling secondary CPUs, and possibly console output.
@@ -131,6 +139,7 @@ config SIBYTE_CFE_CONSOLE
 config SIBYTE_STANDALONE
        bool
        depends on SIBYTE_SB1xxx_SOC && !SIBYTE_CFE
+       select SYS_HAS_EARLY_PRINTK
        default y
 
 config SIBYTE_STANDALONE_RAM_SIZE
@@ -160,5 +169,8 @@ config SIBYTE_SB1250_PROF
        depends on SIBYTE_SB1xxx_SOC
 
 config SIBYTE_TBPROF
-       bool "Support for ZBbus profiling"
-       depends on SIBYTE_SB1xxx_SOC
+       tristate "Support for ZBbus profiling"
+       depends on SIBYTE_HAS_ZBUS_PROFILING
+
+config SIBYTE_HAS_ZBUS_PROFILING
+       bool
index 7b36ff3873b7f75d0dccf86875ae8854d54f6310..cdc4c56c3e29238158cafa0e09422780e46af1ac 100644 (file)
@@ -1,5 +1,3 @@
 obj-y := setup.o irq.o time.o
 
 obj-$(CONFIG_SMP)                      += smp.o
-
-EXTRA_AFLAGS := $(CFLAGS)
index 1dc5d05d8962067fc9ef206ee019b2da90c0e6f5..20af0f1bb7bf9b8af97d0e486b67cc76892c8d0d 100644 (file)
@@ -420,7 +420,7 @@ void __init arch_init_irq(void)
 #ifdef CONFIG_GDB_CONSOLE
                register_gdb_console();
 #endif
-               prom_printf("Waiting for GDB on UART port %d\n", kgdb_port);
+               printk("Waiting for GDB on UART port %d\n", kgdb_port);
                set_debug_traps();
                breakpoint();
        }
index 8236d0c48542cc7dbaedd672588e13f46e513283..bdaac34ae70897dc796e343d8bfe0b4346879311 100644 (file)
@@ -69,7 +69,7 @@ static inline int sys_rev_decode(void)
                break;
 
            default:
-               prom_printf("Unknown part type %x\n", part_type);
+               printk("Unknown part type %x\n", part_type);
                ret = 1;
                break;
        }
@@ -102,7 +102,7 @@ static inline int setup_bcm1x80_bcm1x55(void)
                pass_str = "B0 (pass2)";
                break;
            default:
-               prom_printf("Unknown %s rev %x\n", soc_str, soc_pass);
+               printk("Unknown %s rev %x\n", soc_str, soc_pass);
                periph_rev = 1;
                pass_str = "Unknown Revision";
                break;
@@ -122,14 +122,14 @@ void bcm1480_setup(void)
        soc_pass = G_SYS_REVISION(sys_rev);
 
        if (sys_rev_decode()) {
-               prom_printf("Restart after failure to identify SiByte chip\n");
+               printk("Restart after failure to identify SiByte chip\n");
                machine_restart(NULL);
        }
 
        plldiv = G_BCM1480_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG)));
        zbbus_mhz = ((plldiv >> 1) * 50) + ((plldiv & 1) * 25);
 
-       prom_printf("Broadcom SiByte %s %s @ %d MHz (SB-1A rev %d)\n",
+       printk("Broadcom SiByte %s %s @ %d MHz (SB-1A rev %d)\n",
                    soc_str, pass_str, zbbus_mhz * 2, sb1_pass);
-       prom_printf("Board type: %s\n", get_system_type());
+       printk("Board type: %s\n", get_system_type());
 }
index 9e6099e6962266ed27023c9bdcbb59c32fa4b96c..ae4a92c3e529bf8cfd09d5cbbd19508d95776292 100644 (file)
@@ -221,10 +221,10 @@ static int __init initrd_setup(char *str)
                goto fail;
        }
        initrd_end = initrd_start + initrd_size;
-       prom_printf("Found initrd of %lx@%lx\n", initrd_size, initrd_start);
+       printk("Found initrd of %lx@%lx\n", initrd_size, initrd_start);
        return 1;
  fail:
-       prom_printf("Bad initrd argument.  Disabling initrd\n");
+       printk("Bad initrd argument.  Disabling initrd\n");
        initrd_start = 0;
        initrd_end = 0;
        return 1;
@@ -281,7 +281,7 @@ void __init prom_init(void)
        }
        if (cfe_eptseal != CFE_EPTSEAL) {
                /* too early for panic to do any good */
-               prom_printf("CFE's entrypoint seal doesn't match. Spinning.");
+               printk("CFE's entrypoint seal doesn't match. Spinning.");
                while (1) ;
        }
        cfe_init(cfe_handle, cfe_ept);
@@ -303,7 +303,7 @@ void __init prom_init(void)
                } else {
                        /* The loader should have set the command line */
                        /* too early for panic to do any good */
-                       prom_printf("LINUX_CMDLINE not defined in cfe.");
+                       printk("LINUX_CMDLINE not defined in cfe.");
                        while (1) ;
                }
        }
index a2fdbd62f8ac0f78852f92b3870a5c2f721dd9ea..04c0f1a7f616599895e2906d299a4f8c3e124196 100644 (file)
@@ -4,5 +4,3 @@ obj-$(CONFIG_SMP)                       += smp.o
 obj-$(CONFIG_SIBYTE_TBPROF)            += bcm1250_tbprof.o
 obj-$(CONFIG_SIBYTE_STANDALONE)                += prom.o
 obj-$(CONFIG_SIBYTE_BUS_WATCHER)       += bus_watcher.o
-
-EXTRA_AFLAGS := $(CFLAGS)
index 212547c573102b0060955a3cd54d01b42c60c2e3..ea0ca131a3cfaceb770c6cfea3720a5ebd680b69 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * Copyright (C) 2001, 2002, 2003 Broadcom Corporation
- *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * 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.
+ *
+ * Copyright (C) 2001, 2002, 2003 Broadcom Corporation
+ * Copyright (C) 2007 Ralf Baechle <ralf@linux-mips.org>
+ * Copyright (C) 2007 MIPS Technologies, Inc.
+ *    written by Ralf Baechle <ralf@linux-mips.org>
  */
 
-#define SBPROF_TB_DEBUG 0
+#undef DEBUG
 
+#include <linux/device.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
 #include <linux/errno.h>
-#include <linux/reboot.h>
-#include <linux/smp_lock.h>
+#include <linux/types.h>
 #include <linux/wait.h>
-#include <asm/uaccess.h>
+
 #include <asm/io.h>
 #include <asm/sibyte/sb1250.h>
 #include <asm/sibyte/sb1250_regs.h>
 #include <asm/sibyte/sb1250_scd.h>
 #include <asm/sibyte/sb1250_int.h>
-#include <asm/sibyte/trace_prof.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
 
-#define DEVNAME "bcm1250_tbprof"
+#define SBPROF_TB_MAJOR 240
+
+typedef u64 tb_sample_t[6*256];
+
+enum open_status {
+       SB_CLOSED,
+       SB_OPENING,
+       SB_OPEN
+};
+
+struct sbprof_tb {
+       wait_queue_head_t       tb_sync;
+       wait_queue_head_t       tb_read;
+       struct mutex            lock;
+       enum open_status        open;
+       tb_sample_t             *sbprof_tbbuf;
+       int                     next_tb_sample;
+
+       volatile int            tb_enable;
+       volatile int            tb_armed;
+
+};
 
 static struct sbprof_tb sbp;
 
+#define MAX_SAMPLE_BYTES (24*1024*1024)
+#define MAX_TBSAMPLE_BYTES (12*1024*1024)
+
+#define MAX_SAMPLES (MAX_SAMPLE_BYTES/sizeof(u_int32_t))
+#define TB_SAMPLE_SIZE (sizeof(tb_sample_t))
+#define MAX_TB_SAMPLES (MAX_TBSAMPLE_BYTES/TB_SAMPLE_SIZE)
+
+/* ioctls */
+#define SBPROF_ZBSTART         _IOW('s', 0, int)
+#define SBPROF_ZBSTOP          _IOW('s', 1, int)
+#define SBPROF_ZBWAITFULL      _IOW('s', 2, int)
+
+/*
+ * Routines for using 40-bit SCD cycle counter
+ *
+ * Client responsible for either handling interrupts or making sure
+ * the cycles counter never saturates, e.g., by doing
+ * zclk_timer_init(0) at least every 2^40 - 1 ZCLKs.
+ */
+
+/*
+ * Configures SCD counter 0 to count ZCLKs starting from val;
+ * Configures SCD counters1,2,3 to count nothing.
+ * Must not be called while gathering ZBbus profiles.
+ */
+
+#define zclk_timer_init(val) \
+  __asm__ __volatile__ (".set push;" \
+                       ".set mips64;" \
+                       "la   $8, 0xb00204c0;" /* SCD perf_cnt_cfg */ \
+                       "sd   %0, 0x10($8);"   /* write val to counter0 */ \
+                       "sd   %1, 0($8);"      /* config counter0 for zclks*/ \
+                       ".set pop" \
+                       : /* no outputs */ \
+                                                    /* enable, counter0 */ \
+                       : /* inputs */ "r"(val), "r" ((1ULL << 33) | 1ULL) \
+                       : /* modifies */ "$8" )
+
+
+/* Reads SCD counter 0 and puts result in value
+   unsigned long long val; */
+#define zclk_get(val) \
+  __asm__ __volatile__ (".set push;" \
+                       ".set mips64;" \
+                       "la   $8, 0xb00204c0;" /* SCD perf_cnt_cfg */ \
+                       "ld   %0, 0x10($8);"   /* write val to counter0 */ \
+                       ".set pop" \
+                       : /* outputs */ "=r"(val) \
+                       : /* inputs */ \
+                       : /* modifies */ "$8" )
+
+#define DEVNAME "bcm1250_tbprof"
+
 #define TB_FULL (sbp.next_tb_sample == MAX_TB_SAMPLES)
 
-/************************************************************************
+/*
  * Support for ZBbus sampling using the trace buffer
  *
  * We use the SCD performance counter interrupt, caused by a Zclk counter
@@ -54,30 +132,36 @@ static struct sbprof_tb sbp;
  * overflow.
  *
  * We map the interrupt for trace_buffer_freeze to handle it on CPU 0.
- *
- ************************************************************************/
+ */
 
-static u_int64_t tb_period;
+static u64 tb_period;
 
 static void arm_tb(void)
 {
-        u_int64_t scdperfcnt;
-       u_int64_t next = (1ULL << 40) - tb_period;
-       u_int64_t tb_options = M_SCD_TRACE_CFG_FREEZE_FULL;
-       /* Generate an SCD_PERFCNT interrupt in TB_PERIOD Zclks to
-          trigger start of trace.  XXX vary sampling period */
+        u64 scdperfcnt;
+       u64 next = (1ULL << 40) - tb_period;
+       u64 tb_options = M_SCD_TRACE_CFG_FREEZE_FULL;
+
+       /*
+        * Generate an SCD_PERFCNT interrupt in TB_PERIOD Zclks to trigger
+        *start of trace.  XXX vary sampling period
+        */
        __raw_writeq(0, IOADDR(A_SCD_PERF_CNT_1));
        scdperfcnt = __raw_readq(IOADDR(A_SCD_PERF_CNT_CFG));
-       /* Unfortunately, in Pass 2 we must clear all counters to knock down
-          a previous interrupt request.  This means that bus profiling
-          requires ALL of the SCD perf counters. */
+
+       /*
+        * Unfortunately, in Pass 2 we must clear all counters to knock down a
+        * previous interrupt request.  This means that bus profiling requires
+        * ALL of the SCD perf counters.
+        */
        __raw_writeq((scdperfcnt & ~M_SPC_CFG_SRC1) |
-                                               // keep counters 0,2,3 as is
-                    M_SPC_CFG_ENABLE |         // enable counting
-                    M_SPC_CFG_CLEAR |          // clear all counters
-                    V_SPC_CFG_SRC1(1),         // counter 1 counts cycles
+                                               /* keep counters 0,2,3 as is */
+                    M_SPC_CFG_ENABLE |         /* enable counting */
+                    M_SPC_CFG_CLEAR |          /* clear all counters */
+                    V_SPC_CFG_SRC1(1),         /* counter 1 counts cycles */
                     IOADDR(A_SCD_PERF_CNT_CFG));
        __raw_writeq(next, IOADDR(A_SCD_PERF_CNT_1));
+
        /* Reset the trace buffer */
        __raw_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
 #if 0 && defined(M_SCD_TRACE_CFG_FORCECNT)
@@ -91,43 +175,45 @@ static void arm_tb(void)
 static irqreturn_t sbprof_tb_intr(int irq, void *dev_id)
 {
        int i;
-       DBG(printk(DEVNAME ": tb_intr\n"));
+
+       pr_debug(DEVNAME ": tb_intr\n");
+
        if (sbp.next_tb_sample < MAX_TB_SAMPLES) {
                /* XXX should use XKPHYS to make writes bypass L2 */
-               u_int64_t *p = sbp.sbprof_tbbuf[sbp.next_tb_sample++];
+               u64 *p = sbp.sbprof_tbbuf[sbp.next_tb_sample++];
                /* Read out trace */
                __raw_writeq(M_SCD_TRACE_CFG_START_READ,
                             IOADDR(A_SCD_TRACE_CFG));
                __asm__ __volatile__ ("sync" : : : "memory");
                /* Loop runs backwards because bundles are read out in reverse order */
                for (i = 256 * 6; i > 0; i -= 6) {
-                       // Subscripts decrease to put bundle in the order
-                       //   t0 lo, t0 hi, t1 lo, t1 hi, t2 lo, t2 hi
+                       /* Subscripts decrease to put bundle in the order */
+                       /*   t0 lo, t0 hi, t1 lo, t1 hi, t2 lo, t2 hi */
                        p[i - 1] = __raw_readq(IOADDR(A_SCD_TRACE_READ));
-                                                               // read t2 hi
+                                                               /* read t2 hi */
                        p[i - 2] = __raw_readq(IOADDR(A_SCD_TRACE_READ));
-                                                               // read t2 lo
+                                                               /* read t2 lo */
                        p[i - 3] = __raw_readq(IOADDR(A_SCD_TRACE_READ));
-                                                               // read t1 hi
+                                                               /* read t1 hi */
                        p[i - 4] = __raw_readq(IOADDR(A_SCD_TRACE_READ));
-                                                               // read t1 lo
+                                                               /* read t1 lo */
                        p[i - 5] = __raw_readq(IOADDR(A_SCD_TRACE_READ));
-                                                               // read t0 hi
+                                                               /* read t0 hi */
                        p[i - 6] = __raw_readq(IOADDR(A_SCD_TRACE_READ));
-                                                               // read t0 lo
+                                                               /* read t0 lo */
                }
                if (!sbp.tb_enable) {
-                       DBG(printk(DEVNAME ": tb_intr shutdown\n"));
+                       pr_debug(DEVNAME ": tb_intr shutdown\n");
                        __raw_writeq(M_SCD_TRACE_CFG_RESET,
                                     IOADDR(A_SCD_TRACE_CFG));
                        sbp.tb_armed = 0;
                        wake_up(&sbp.tb_sync);
                } else {
-                       arm_tb();       // knock down current interrupt and get another one later
+                       arm_tb();       /* knock down current interrupt and get another one later */
                }
        } else {
                /* No more trace buffer samples */
-               DBG(printk(DEVNAME ": tb_intr full\n"));
+               pr_debug(DEVNAME ": tb_intr full\n");
                __raw_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
                sbp.tb_armed = 0;
                if (!sbp.tb_enable) {
@@ -135,6 +221,7 @@ static irqreturn_t sbprof_tb_intr(int irq, void *dev_id)
                }
                wake_up(&sbp.tb_read);
        }
+
        return IRQ_HANDLED;
 }
 
@@ -144,23 +231,30 @@ static irqreturn_t sbprof_pc_intr(int irq, void *dev_id)
        return IRQ_NONE;
 }
 
-int sbprof_zbprof_start(struct file *filp)
+/*
+ * Requires: Already called zclk_timer_init with a value that won't
+ *           saturate 40 bits.  No subsequent use of SCD performance counters
+ *           or trace buffer.
+ */
+
+static int sbprof_zbprof_start(struct file *filp)
 {
-       u_int64_t scdperfcnt;
+       u64 scdperfcnt;
+       int err;
 
-       if (sbp.tb_enable)
+       if (xchg(&sbp.tb_enable, 1))
                return -EBUSY;
 
-       DBG(printk(DEVNAME ": starting\n"));
+       pr_debug(DEVNAME ": starting\n");
 
-       sbp.tb_enable = 1;
        sbp.next_tb_sample = 0;
        filp->f_pos = 0;
 
-       if (request_irq
-           (K_INT_TRACE_FREEZE, sbprof_tb_intr, 0, DEVNAME " trace freeze", &sbp)) {
+       err = request_irq(K_INT_TRACE_FREEZE, sbprof_tb_intr, 0,
+                       DEVNAME " trace freeze", &sbp);
+       if (err)
                return -EBUSY;
-       }
+
        /* Make sure there isn't a perf-cnt interrupt waiting */
        scdperfcnt = __raw_readq(IOADDR(A_SCD_PERF_CNT_CFG));
        /* Disable and clear counters, override SRC_1 */
@@ -168,18 +262,21 @@ int sbprof_zbprof_start(struct file *filp)
                     M_SPC_CFG_ENABLE | M_SPC_CFG_CLEAR | V_SPC_CFG_SRC1(1),
                     IOADDR(A_SCD_PERF_CNT_CFG));
 
-       /* We grab this interrupt to prevent others from trying to use
-           it, even though we don't want to service the interrupts
-           (they only feed into the trace-on-interrupt mechanism) */
-       if (request_irq
-           (K_INT_PERF_CNT, sbprof_pc_intr, 0, DEVNAME " scd perfcnt", &sbp)) {
-               free_irq(K_INT_TRACE_FREEZE, &sbp);
-               return -EBUSY;
-       }
-
-       /* I need the core to mask these, but the interrupt mapper to
-          pass them through.  I am exploiting my knowledge that
-          cp0_status masks out IP[5]. krw */
+       /*
+        * We grab this interrupt to prevent others from trying to use it, even
+        * though we don't want to service the interrupts (they only feed into
+        * the trace-on-interrupt mechanism)
+        */
+       err = request_irq(K_INT_PERF_CNT, sbprof_pc_intr, 0,
+                       DEVNAME " scd perfcnt", &sbp);
+       if (err)
+               goto out_free_irq;
+
+       /*
+        * I need the core to mask these, but the interrupt mapper to pass them
+        * through.  I am exploiting my knowledge that cp0_status masks out
+        * IP[5]. krw
+        */
        __raw_writeq(K_INT_MAP_I3,
                     IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
                            (K_INT_PERF_CNT << 3)));
@@ -201,7 +298,7 @@ int sbprof_zbprof_start(struct file *filp)
        __raw_writeq(0, IOADDR(A_ADDR_TRAP_CFG_3));
 
        /* Initialize Trace Event 0-7 */
-       //                              when interrupt
+       /*                              when interrupt */
        __raw_writeq(M_SCD_TREVT_INTERRUPT, IOADDR(A_SCD_TRACE_EVENT_0));
        __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_1));
        __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_2));
@@ -212,10 +309,10 @@ int sbprof_zbprof_start(struct file *filp)
        __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_7));
 
        /* Initialize Trace Sequence 0-7 */
-       //                                   Start on event 0 (interrupt)
+       /*                                   Start on event 0 (interrupt) */
        __raw_writeq(V_SCD_TRSEQ_FUNC_START | 0x0fff,
                     IOADDR(A_SCD_TRACE_SEQUENCE_0));
-       //                        dsamp when d used | asamp when a used
+       /*                        dsamp when d used | asamp when a used */
        __raw_writeq(M_SCD_TRSEQ_ASAMPLE | M_SCD_TRSEQ_DSAMPLE |
                     K_SCD_TRSEQ_TRIGGER_ALL,
                     IOADDR(A_SCD_TRACE_SEQUENCE_1));
@@ -232,33 +329,41 @@ int sbprof_zbprof_start(struct file *filp)
 
        arm_tb();
 
-       DBG(printk(DEVNAME ": done starting\n"));
+       pr_debug(DEVNAME ": done starting\n");
 
        return 0;
+
+out_free_irq:
+       free_irq(K_INT_TRACE_FREEZE, &sbp);
+
+       return err;
 }
 
-int sbprof_zbprof_stop(void)
+static int sbprof_zbprof_stop(void)
 {
-       DEFINE_WAIT(wait);
-       DBG(printk(DEVNAME ": stopping\n"));
+       int err;
+
+       pr_debug(DEVNAME ": stopping\n");
 
        if (sbp.tb_enable) {
+               /*
+                * XXXKW there is a window here where the intr handler may run,
+                * see the disable, and do the wake_up before this sleep
+                * happens.
+                */
+               pr_debug(DEVNAME ": wait for disarm\n");
+               err = wait_event_interruptible(sbp.tb_sync, !sbp.tb_armed);
+               pr_debug(DEVNAME ": disarm complete, stat %d\n", err);
+
+               if (err)
+                       return err;
+
                sbp.tb_enable = 0;
-               /* XXXKW there is a window here where the intr handler
-                  may run, see the disable, and do the wake_up before
-                  this sleep happens. */
-               if (sbp.tb_armed) {
-                       DBG(printk(DEVNAME ": wait for disarm\n"));
-                       prepare_to_wait(&sbp.tb_sync, &wait, TASK_INTERRUPTIBLE);
-                       schedule();
-                       finish_wait(&sbp.tb_sync, &wait);
-                       DBG(printk(DEVNAME ": disarm complete\n"));
-               }
                free_irq(K_INT_TRACE_FREEZE, &sbp);
                free_irq(K_INT_PERF_CNT, &sbp);
        }
 
-       DBG(printk(DEVNAME ": done stopping\n"));
+       pr_debug(DEVNAME ": done stopping\n");
 
        return 0;
 }
@@ -268,42 +373,45 @@ static int sbprof_tb_open(struct inode *inode, struct file *filp)
        int minor;
 
        minor = iminor(inode);
-       if (minor != 0) {
+       if (minor != 0)
                return -ENODEV;
-       }
-       if (sbp.open) {
+
+       if (xchg(&sbp.open, SB_OPENING) != SB_CLOSED)
                return -EBUSY;
-       }
 
        memset(&sbp, 0, sizeof(struct sbprof_tb));
+
        sbp.sbprof_tbbuf = vmalloc(MAX_TBSAMPLE_BYTES);
-       if (!sbp.sbprof_tbbuf) {
+       if (!sbp.sbprof_tbbuf)
                return -ENOMEM;
-       }
+
        memset(sbp.sbprof_tbbuf, 0, MAX_TBSAMPLE_BYTES);
        init_waitqueue_head(&sbp.tb_sync);
        init_waitqueue_head(&sbp.tb_read);
-       sbp.open = 1;
+       mutex_init(&sbp.lock);
+
+       sbp.open = SB_OPEN;
 
        return 0;
 }
 
 static int sbprof_tb_release(struct inode *inode, struct file *filp)
 {
-       int minor;
+       int minor = iminor(inode);
 
-       minor = iminor(inode);
-       if (minor != 0 || !sbp.open) {
+       if (minor != 0 || !sbp.open)
                return -ENODEV;
-       }
 
-       if (sbp.tb_armed || sbp.tb_enable) {
+       mutex_lock(&sbp.lock);
+
+       if (sbp.tb_armed || sbp.tb_enable)
                sbprof_zbprof_stop();
-       }
 
        vfree(sbp.sbprof_tbbuf);
        sbp.open = 0;
 
+       mutex_unlock(&sbp.lock);
+
        return 0;
 }
 
@@ -311,21 +419,35 @@ static ssize_t sbprof_tb_read(struct file *filp, char *buf,
                              size_t size, loff_t *offp)
 {
        int cur_sample, sample_off, cur_count, sample_left;
-       char *src;
-       int   count   =  0;
-       char *dest    =  buf;
        long  cur_off = *offp;
+       char *dest    =  buf;
+       int   count   =  0;
+       char *src;
+
+       if (!access_ok(VERIFY_WRITE, buf, size))
+               return -EFAULT;
+
+       mutex_lock(&sbp.lock);
 
        count = 0;
        cur_sample = cur_off / TB_SAMPLE_SIZE;
        sample_off = cur_off % TB_SAMPLE_SIZE;
        sample_left = TB_SAMPLE_SIZE - sample_off;
+
        while (size && (cur_sample < sbp.next_tb_sample)) {
+               int err;
+
                cur_count = size < sample_left ? size : sample_left;
                src = (char *)(((long)sbp.sbprof_tbbuf[cur_sample])+sample_off);
-               copy_to_user(dest, src, cur_count);
-               DBG(printk(DEVNAME ": read from sample %d, %d bytes\n",
-                          cur_sample, cur_count));
+               err = __copy_to_user(dest, src, cur_count);
+               if (err) {
+                       *offp = cur_off + cur_count - err;
+                       mutex_unlock(&sbp.lock);
+                       return err;
+               }
+
+               pr_debug(DEVNAME ": read from sample %d, %d bytes\n",
+                        cur_sample, cur_count);
                size -= cur_count;
                sample_left -= cur_count;
                if (!sample_left) {
@@ -339,37 +461,43 @@ static ssize_t sbprof_tb_read(struct file *filp, char *buf,
                dest += cur_count;
                count += cur_count;
        }
+
        *offp = cur_off;
+       mutex_unlock(&sbp.lock);
 
        return count;
 }
 
-static long sbprof_tb_ioctl(struct file *filp,
-                           unsigned int command,
-                           unsigned long arg)
+static long sbprof_tb_ioctl(struct file *filp, unsigned int command,
+       unsigned long arg)
 {
        int error = 0;
 
-       lock_kernel();
        switch (command) {
        case SBPROF_ZBSTART:
+               mutex_lock(&sbp.lock);
                error = sbprof_zbprof_start(filp);
+               mutex_unlock(&sbp.lock);
                break;
+
        case SBPROF_ZBSTOP:
+               mutex_lock(&sbp.lock);
                error = sbprof_zbprof_stop();
+               mutex_unlock(&sbp.lock);
                break;
+
        case SBPROF_ZBWAITFULL:
-               DEFINE_WAIT(wait);
-               prepare_to_wait(&sbp.tb_read, &wait, TASK_INTERRUPTIBLE);
-               schedule();
-               finish_wait(&sbp.tb_read, &wait);
-               /* XXXKW check if interrupted? */
-               return put_user(TB_FULL, (int *) arg);
+               error = wait_event_interruptible(sbp.tb_read, TB_FULL);
+               if (error)
+                       break;
+
+               error = put_user(TB_FULL, (int *) arg);
+               break;
+
        default:
                error = -EINVAL;
                break;
        }
-       unlock_kernel();
 
        return error;
 }
@@ -384,23 +512,60 @@ static const struct file_operations sbprof_tb_fops = {
        .mmap           = NULL,
 };
 
+static struct class *tb_class;
+static struct device *tb_dev;
+
 static int __init sbprof_tb_init(void)
 {
+       struct device *dev;
+       struct class *tbc;
+       int err;
+
        if (register_chrdev(SBPROF_TB_MAJOR, DEVNAME, &sbprof_tb_fops)) {
                printk(KERN_WARNING DEVNAME ": initialization failed (dev %d)\n",
                       SBPROF_TB_MAJOR);
                return -EIO;
        }
+
+       tbc = class_create(THIS_MODULE, "sb_tracebuffer");
+       if (IS_ERR(tbc)) {
+               err = PTR_ERR(tbc);
+               goto out_chrdev;
+       }
+
+       tb_class = tbc;
+
+       dev = device_create(tbc, NULL, MKDEV(SBPROF_TB_MAJOR, 0), "tb");
+       if (IS_ERR(dev)) {
+               err = PTR_ERR(dev);
+               goto out_class;
+       }
+       tb_dev = dev;
+
        sbp.open = 0;
        tb_period = zbbus_mhz * 10000LL;
-       printk(KERN_INFO DEVNAME ": initialized - tb_period = %lld\n", tb_period);
+       pr_info(DEVNAME ": initialized - tb_period = %lld\n", tb_period);
+
        return 0;
+
+out_class:
+       class_destroy(tb_class);
+out_chrdev:
+       unregister_chrdev(SBPROF_TB_MAJOR, DEVNAME);
+
+       return err;
 }
 
 static void __exit sbprof_tb_cleanup(void)
 {
+       device_destroy(tb_class, MKDEV(SBPROF_TB_MAJOR, 0));
        unregister_chrdev(SBPROF_TB_MAJOR, DEVNAME);
+       class_destroy(tb_class);
 }
 
 module_init(sbprof_tb_init);
 module_exit(sbprof_tb_cleanup);
+
+MODULE_ALIAS_CHARDEV_MAJOR(SBPROF_TB_MAJOR);
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
index d0ee1d5b822388bfaf32496da80d9b8238903fdf..87188f0f6fbe1e4f7d61683c8cdc9bec1b5afb19 100644 (file)
@@ -16,6 +16,7 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/reboot.h>
 #include <linux/string.h>
@@ -32,6 +33,7 @@ unsigned int soc_pass;
 unsigned int soc_type;
 unsigned int periph_rev;
 unsigned int zbbus_mhz;
+EXPORT_SYMBOL(zbbus_mhz);
 
 static char *soc_str;
 static char *pass_str;
@@ -67,7 +69,7 @@ static int __init sys_rev_decode(void)
                ret = setup_bcm112x();
                break;
        default:
-               prom_printf("Unknown SOC type %x\n", soc_type);
+               printk("Unknown SOC type %x\n", soc_type);
                ret = 1;
                break;
        }
@@ -112,7 +114,7 @@ static int __init setup_bcm1250(void)
                        pass_str = "A0-A6";
                        war_pass = K_SYS_REVISION_BCM1250_PASS2;
                } else {
-                       prom_printf("Unknown BCM1250 rev %x\n", soc_pass);
+                       printk("Unknown BCM1250 rev %x\n", soc_pass);
                        ret = 1;
                }
                break;
@@ -140,7 +142,7 @@ static int __init setup_bcm112x(void)
                pass_str = "A2";
                break;
        default:
-               prom_printf("Unknown %s rev %x\n", soc_str, soc_pass);
+               printk("Unknown %s rev %x\n", soc_str, soc_pass);
                ret = 1;
        }
        return ret;
@@ -158,21 +160,21 @@ void __init sb1250_setup(void)
        soc_pass = G_SYS_REVISION(sys_rev);
 
        if (sys_rev_decode()) {
-               prom_printf("Restart after failure to identify SiByte chip\n");
+               printk("Restart after failure to identify SiByte chip\n");
                machine_restart(NULL);
        }
 
        plldiv = G_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG)));
        zbbus_mhz = ((plldiv >> 1) * 50) + ((plldiv & 1) * 25);
 
-       prom_printf("Broadcom SiByte %s %s @ %d MHz (SB1 rev %d)\n",
+       printk("Broadcom SiByte %s %s @ %d MHz (SB1 rev %d)\n",
                    soc_str, pass_str, zbbus_mhz * 2, sb1_pass);
-       prom_printf("Board type: %s\n", get_system_type());
+       printk("Board type: %s\n", get_system_type());
 
        switch (war_pass) {
        case K_SYS_REVISION_BCM1250_PASS1:
 #ifndef CONFIG_SB1_PASS_1_WORKAROUNDS
-               prom_printf("@@@@ This is a BCM1250 A0-A2 (Pass 1) board, "
+               printk("@@@@ This is a BCM1250 A0-A2 (Pass 1) board, "
                            "and the kernel doesn't have the proper "
                            "workarounds compiled in. @@@@\n");
                bad_config = 1;
@@ -182,27 +184,27 @@ void __init sb1250_setup(void)
                /* Pass 2 - easiest as default for now - so many numbers */
 #if !defined(CONFIG_SB1_PASS_2_WORKAROUNDS) || \
     !defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS)
-               prom_printf("@@@@ This is a BCM1250 A3-A10 board, and the "
+               printk("@@@@ This is a BCM1250 A3-A10 board, and the "
                            "kernel doesn't have the proper workarounds "
                            "compiled in. @@@@\n");
                bad_config = 1;
 #endif
 #ifdef CONFIG_CPU_HAS_PREFETCH
-               prom_printf("@@@@ Prefetches may be enabled in this kernel, "
+               printk("@@@@ Prefetches may be enabled in this kernel, "
                            "but are buggy on this board.  @@@@\n");
                bad_config = 1;
 #endif
                break;
        case K_SYS_REVISION_BCM1250_PASS2_2:
 #ifndef CONFIG_SB1_PASS_2_WORKAROUNDS
-               prom_printf("@@@@ This is a BCM1250 B1/B2. board, and the "
+               printk("@@@@ This is a BCM1250 B1/B2. board, and the "
                            "kernel doesn't have the proper workarounds "
                            "compiled in. @@@@\n");
                bad_config = 1;
 #endif
 #if defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS) || \
     !defined(CONFIG_CPU_HAS_PREFETCH)
-               prom_printf("@@@@ This is a BCM1250 B1/B2, but the kernel is "
+               printk("@@@@ This is a BCM1250 B1/B2, but the kernel is "
                            "conservatively configured for an 'A' stepping. "
                            "@@@@\n");
 #endif
@@ -211,7 +213,7 @@ void __init sb1250_setup(void)
                break;
        }
        if (bad_config) {
-               prom_printf("Invalid configuration for this chip.\n");
+               printk("Invalid configuration for this chip.\n");
                machine_restart(NULL);
        }
 }
index e30809a921512c30da9eac811ad898d894804e8f..e5777b7e2bc9507555535647a4aa8a5c80f8c027 100644 (file)
@@ -4,5 +4,3 @@
 
 obj-y += irq.o reset.o setup.o ds1216.o a20r.o rm200.o pcimt.o pcit.o time.o
 obj-$(CONFIG_CPU_BIG_ENDIAN) += sniprom.o
-
-EXTRA_AFLAGS := $(CFLAGS)
index 6c0dad7cbf4e25715d924e9aca6c9f7112cebfba..39e5b4abc5555f37666d73cb158907065b78c8dc 100644 (file)
@@ -336,9 +336,9 @@ static void sni_pcimt_hwint(void)
        u32 pending = (read_c0_cause() & read_c0_status());
 
        if (pending & C_IRQ5)
-               do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 7);
+               do_IRQ (MIPS_CPU_IRQ_BASE + 7);
        else if (pending & C_IRQ4)
-               do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 6);
+               do_IRQ (MIPS_CPU_IRQ_BASE + 6);
        else if (pending & C_IRQ3)
                pcimt_hwint3();
        else if (pending & C_IRQ1)
index 3921096023c3d919a2999a063a94e5bb12238955..8d6b3d5b13a1303bac8ffc41c050ab4cc87504eb 100644 (file)
@@ -276,11 +276,11 @@ static void sni_pcit_hwint(void)
        if (pending & C_IRQ1)
                pcit_hwint1();
        else if (pending & C_IRQ2)
-               do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 4);
+               do_IRQ (MIPS_CPU_IRQ_BASE + 4);
        else if (pending & C_IRQ3)
-               do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 5);
+               do_IRQ (MIPS_CPU_IRQ_BASE + 5);
        else if (pending & C_IRQ5)
-               do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 7);
+               do_IRQ (MIPS_CPU_IRQ_BASE + 7);
 }
 
 static void sni_pcit_hwint_cplus(void)
@@ -290,11 +290,11 @@ static void sni_pcit_hwint_cplus(void)
        if (pending & C_IRQ0)
                pcit_hwint0();
        else if (pending & C_IRQ2)
-               do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 4);
+               do_IRQ (MIPS_CPU_IRQ_BASE + 4);
        else if (pending & C_IRQ3)
-               do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 5);
+               do_IRQ (MIPS_CPU_IRQ_BASE + 5);
        else if (pending & C_IRQ5)
-               do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 7);
+               do_IRQ (MIPS_CPU_IRQ_BASE + 7);
 }
 
 void __init sni_pcit_irq_init(void)
index 517dc698c08302381b6a8bb6e5085e5105f23586..b82ff129f5ead20d452f8f76d6ea3a6b90a9d1fb 100644 (file)
@@ -148,7 +148,7 @@ static void sni_rm200_hwint(void)
        int irq;
 
        if (pending & C_IRQ5)
-               do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 7);
+               do_IRQ (MIPS_CPU_IRQ_BASE + 7);
        else if (pending & C_IRQ0) {
                clear_c0_status (IE_IRQ0);
                mask = *(volatile u8 *)SNI_RM200_INT_ENA_REG ^ 0x1f;
index 6a44bbf0b732e7cab43bfb0d8a8256972c111259..643366eb854a6de81cfb9abd4a86cd2da5193fe2 100644 (file)
@@ -9,6 +9,8 @@
  * Copyright (C) 2005-2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
  */
 
+#define DEBUG
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/string.h>
 #define PROM_ENTRY(x)          (PROM_VEC + (x))
 
 
-#define DEBUG
-#ifdef DEBUG
-#define DBG_PRINTF(x...)     prom_printf(x)
-#else
-#define DBG_PRINTF(x...)
-#endif
-
 static int *(*__prom_putchar)(int)        = (int *(*)(int))PROM_ENTRY(PROM_PUTCHAR);
+
+void prom_putchar(char c)
+{
+       __prom_putchar(c);
+}
+
 static char *(*__prom_getenv)(char *)     = (char *(*)(char *))PROM_ENTRY(PROM_GETENV);
 static void (*__prom_get_memconf)(void *) = (void (*)(void *))PROM_ENTRY(PROM_GET_MEMCONF);
 
@@ -48,26 +49,6 @@ char *prom_getenv (char *s)
        return __prom_getenv(s);
 }
 
-void prom_printf(char *fmt, ...)
-{
-       va_list args;
-       char ppbuf[1024];
-       char *bptr;
-
-       va_start(args, fmt);
-       vsprintf(ppbuf, fmt, args);
-
-       bptr = ppbuf;
-
-       while (*bptr != 0) {
-               if (*bptr == '\n')
-                       __prom_putchar('\r');
-
-               __prom_putchar(*bptr++);
-       }
-       va_end(args);
-}
-
 void __init prom_free_prom_memory(void)
 {
 }
@@ -94,15 +75,15 @@ static void sni_idprom_dump(void)
 {
        int     i;
 
-       prom_printf("SNI IDProm dump:\n");
+       pr_debug("SNI IDProm dump:\n");
        for (i = 0; i < 256; i++) {
                if (i%16 == 0)
-                       prom_printf("%04x ", i);
+                       pr_debug("%04x ", i);
 
-               prom_printf("%02x ", *(unsigned char *) (SNI_IDPROM_BASE + i));
+               printk("%02x ", *(unsigned char *) (SNI_IDPROM_BASE + i));
 
                if (i % 16 == 15)
-                       prom_printf("\n");
+                       printk("\n");
        }
 }
 #endif
@@ -121,12 +102,12 @@ static void sni_mem_init(void )
        /* MemSIZE from prom in 16MByte chunks */
        memsize = *((unsigned char *) SNI_IDPROM_MEMSIZE) * 16;
 
-       DBG_PRINTF("IDProm memsize: %lu MByte\n", memsize);
+       pr_debug("IDProm memsize: %lu MByte\n", memsize);
 
        /* get memory bank layout from prom */
        __prom_get_memconf(&memconf);
 
-       DBG_PRINTF("prom_get_mem_conf memory configuration:\n");
+       pr_debug("prom_get_mem_conf memory configuration:\n");
        for (i = 0;i < 8 && memconf[i].size; i++) {
                if (sni_brd_type == SNI_BRD_PCI_TOWER ||
                    sni_brd_type == SNI_BRD_PCI_TOWER_CPLUS) {
@@ -135,7 +116,7 @@ static void sni_mem_init(void )
                                memconf[i].base -= 0x20000000;
                        }
        }
-               DBG_PRINTF("Bank%d: %08x @ %08x\n", i,
+               pr_debug("Bank%d: %08x @ %08x\n", i,
                        memconf[i].size, memconf[i].base);
                add_memory_region(memconf[i].base, memconf[i].size, BOOT_MEM_RAM);
        }
@@ -248,7 +229,7 @@ void __init prom_init(void)
                systype = "RM300-Exx";
                break;
        }
-       DBG_PRINTF("Found SNI brdtype %02x name %s\n", sni_brd_type,systype);
+       pr_debug("Found SNI brdtype %02x name %s\n", sni_brd_type,systype);
 
 #ifdef DEBUG
        sni_idprom_dump();
index 941c441729b0a17f24a92127deba002d702feb61..c8e49feb345b2aa2a5365f4f80339b94e9460af8 100644 (file)
@@ -81,18 +81,8 @@ void __init tx4927_time_init(void)
 
 void __init plat_timer_setup(struct irqaction *irq)
 {
-       u32 count;
-       u32 c1;
-       u32 c2;
-
        setup_irq(TX4927_IRQ_CPU_TIMER, irq);
 
-       /* to generate the first timer interrupt */
-       c1 = read_c0_count();
-       count = c1 + (mips_hpt_frequency / HZ);
-       write_c0_compare(count);
-       c2 = read_c0_count();
-
 #ifdef CONFIG_TOSHIBA_RBTX4927
        {
                extern void toshiba_rbtx4927_timer_setup(struct irqaction
index c1a377a80a5d3de7d0069f3fb4e980476599fd2c..8a991f3c1a6f88c1189bac38104a3e2b98952520 100644 (file)
@@ -1,5 +1,3 @@
 obj-y  += toshiba_rbtx4927_prom.o
 obj-y  += toshiba_rbtx4927_setup.o
 obj-y  += toshiba_rbtx4927_irq.o
-
-EXTRA_AFLAGS := $(CFLAGS)
index dcce88f403c9030145ac19577d25061305bfedad..5cc30c10e746128f5e544e0a06dfd9f57c747885 100644 (file)
@@ -132,9 +132,6 @@ JP7 is not bus master -- do NOT use -- only 4 pci bus master's allowed -- SouthB
 #include <asm/wbflush.h>
 #include <linux/bootmem.h>
 #include <linux/blkdev.h>
-#ifdef CONFIG_RTC_DS1742
-#include <linux/ds1742rtc.h>
-#endif
 #ifdef CONFIG_TOSHIBA_FPCIB0
 #include <asm/tx4927/smsc_fdc37m81x.h>
 #endif
index 7316a78fdd6832e0b3e4a3cf581297579350e9e7..0f7576dfd1413ad46363b8eaa52e3c89bcf8ec62 100644 (file)
@@ -53,6 +53,7 @@
 #include <linux/pci.h>
 #include <linux/timex.h>
 #include <linux/pm.h>
+#include <linux/platform_device.h>
 
 #include <asm/bootinfo.h>
 #include <asm/page.h>
@@ -64,9 +65,6 @@
 #include <asm/time.h>
 #include <linux/bootmem.h>
 #include <linux/blkdev.h>
-#ifdef CONFIG_RTC_DS1742
-#include <linux/ds1742rtc.h>
-#endif
 #ifdef CONFIG_TOSHIBA_FPCIB0
 #include <asm/tx4927/smsc_fdc37m81x.h>
 #endif
@@ -1020,69 +1018,12 @@ void __init toshiba_rbtx4927_setup(void)
                               "+\n");
 }
 
-#ifdef CONFIG_RTC_DS1742
-extern unsigned long rtc_ds1742_get_time(void);
-extern int rtc_ds1742_set_time(unsigned long);
-extern void rtc_ds1742_wait(void);
-#endif
-
 void __init
 toshiba_rbtx4927_time_init(void)
 {
-       u32 c1;
-       u32 c2;
-
        TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, "-\n");
 
-#ifdef CONFIG_RTC_DS1742
-
-       rtc_mips_get_time = rtc_ds1742_get_time;
-       rtc_mips_set_time = rtc_ds1742_set_time;
-
-       TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT,
-                                      ":rtc_ds1742_init()-\n");
-       rtc_ds1742_init(0xbc010000);
-       TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT,
-                                      ":rtc_ds1742_init()+\n");
-
-       TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT,
-                                      ":Calibrate mips_hpt_frequency-\n");
-       rtc_ds1742_wait();
-
-       /* get the count */
-       c1 = read_c0_count();
-
-       /* wait for the seconds to change again */
-       rtc_ds1742_wait();
-
-       /* get the count again */
-       c2 = read_c0_count();
-
-       TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT,
-                                      ":Calibrate mips_hpt_frequency+\n");
-       TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT,
-                                      ":c1=%12u\n", c1);
-       TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT,
-                                      ":c2=%12u\n", c2);
-
-       /* this diff is as close as we are going to get to counter ticks per sec */
-       mips_hpt_frequency = abs(c2 - c1);
-       TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT,
-                                      ":f1=%12u\n", mips_hpt_frequency);
-
-       /* round to 1/10th of a MHz */
-       mips_hpt_frequency /= (100 * 1000);
-       mips_hpt_frequency *= (100 * 1000);
-       TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT,
-                                      ":f2=%12u\n", mips_hpt_frequency);
-
-       TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_INFO,
-                                      ":mips_hpt_frequency=%uHz (%uMHz)\n",
-                                      mips_hpt_frequency,
-                                      mips_hpt_frequency / 1000000);
-#else
-       mips_hpt_frequency = 100000000;
-#endif
+       mips_hpt_frequency = tx4927_cpu_clock / 2;
 
        TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, "+\n");
 
@@ -1095,3 +1036,16 @@ void __init toshiba_rbtx4927_timer_setup(struct irqaction *irq)
        TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIMER_SETUP,
                                       "+\n");
 }
+
+static int __init toshiba_rbtx4927_rtc_init(void)
+{
+       struct resource res = {
+               .start  = 0x1c010000,
+               .end    = 0x1c010000 + 0x800 - 1,
+               .flags  = IORESOURCE_MEM,
+       };
+       struct platform_device *dev =
+               platform_device_register_simple("ds1742", -1, &res, 1);
+       return IS_ERR(dev) ? PTR_ERR(dev) : 0;
+}
+device_initcall(toshiba_rbtx4927_rtc_init);
index dc87d92bb08d267a4119d96b417e9b9a4588b2db..142abf453e4079e307909130618c0927a2ac53aa 100644 (file)
@@ -55,14 +55,5 @@ tx4938_time_init(void)
 
 void __init plat_timer_setup(struct irqaction *irq)
 {
-       u32 count;
-       u32 c1;
-       u32 c2;
-
        setup_irq(TX4938_IRQ_CPU_TIMER, irq);
-
-       c1 = read_c0_count();
-       count = c1 + (mips_hpt_frequency / HZ);
-       write_c0_compare(count);
-       c2 = read_c0_count();
 }
index 975d5caf9d1be0c965461e2adf781ea002e8118e..f842783acd863bc4cdc300bddad3921eb3fd16ab 100644 (file)
@@ -3,5 +3,3 @@
 #
 
 obj-y  += bcu.o cmu.o icu.o init.o irq.o pmu.o type.o
-
-EXTRA_AFLAGS := $(CFLAGS)
index 28da4e71c44311e7111f8a2b2182b0d595a2d62d..3d73545e8c484d158b96788be65a9a7fcab60f48 100644 (file)
@@ -37,6 +37,11 @@ config GENERIC_FIND_NEXT_BIT
        bool
        default y
 
+config GENERIC_BUG
+       bool
+       default y
+       depends on BUG
+
 config GENERIC_HWEIGHT
        bool
        default y
@@ -45,6 +50,10 @@ config GENERIC_CALIBRATE_DELAY
        bool
        default y
 
+config GENERIC_TIME
+       bool
+       default y
+
 config TIME_LOW_RES
        bool
        depends on SMP
index 9b7e42490dd1f147fc6a1002f13767a49a81467f..760567a9ba16e55e78b9def374a940bf65a74785 100644 (file)
@@ -35,12 +35,8 @@ FINAL_LD=$(CROSS_COMPILE)ld --warn-common --warn-section-align
 
 OBJCOPY_FLAGS =-O binary -R .note -R .comment -S
 
-GCC_VERSION     := $(call cc-version)
-ifneq ($(shell if [ -z $(GCC_VERSION) ] ; then echo "bad"; fi ;),)
-$(error Sorry, couldn't find ($(cc-version)).)
-endif
-ifneq ($(shell if [ $(GCC_VERSION) -lt 0303 ] ; then echo "bad"; fi ;),)
-$(error Sorry, your compiler is too old ($(GCC_VERSION)).  GCC v3.3 or above is required.)
+ifneq ($(call cc-ifversion, -lt, 0303, "bad"),)
+$(error Sorry, GCC v3.3 or above is required.)
 endif
 
 cflags-y       := -pipe
index 31c8cccfba31a7a478aff8647c36619f70921cd9..d15a413572f00845e2460f61c7242b23ab9bcef1 100644 (file)
  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include <asm/unistd.h>
+#include <asm/assembly.h>
 #include <linux/sys.h>
 #include <linux/linkage.h>
-#include <asm/unistd.h>
 
-#define ENTRY_NAME(_name_) .word _name_
+#define ENTRY_NAME(_name_) ASM_ULONG_INSN _name_
 
        .section .rodata,"a"
-       .align 4
-       .export hpux_call_table
        .import hpux_unimplemented_wrapper
-hpux_call_table:
+ENTRY(hpux_call_table)
        ENTRY_NAME(sys_ni_syscall)      /* 0 */
        ENTRY_NAME(sys_exit)
        ENTRY_NAME(hpux_fork_wrapper)
@@ -542,5 +541,6 @@ hpux_call_table:
        ENTRY_NAME(hpux_unimplemented_wrapper)      /* 510 */
        ENTRY_NAME(hpux_unimplemented_wrapper)
        ENTRY_NAME(hpux_unimplemented_wrapper)
+END(hpux_call_table)
 .end
 
index 4204cd1f3cf9c2f3fce7769b51e606278055635e..c7a81a2c014c98657ccb52357c315a2cfa2103f0 100644 (file)
@@ -35,13 +35,13 @@ int hpux_execve(struct pt_regs *regs)
        int error;
        char *filename;
 
-       filename = getname((char *) regs->gr[26]);
+       filename = getname((char __user *) regs->gr[26]);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
 
-       error = do_execve(filename, (char **) regs->gr[25],
-               (char **)regs->gr[24], regs);
+       error = do_execve(filename, (char __user * __user *) regs->gr[25],
+               (char __user * __user *) regs->gr[24], regs);
 
        if (error == 0) {
                task_lock(current);
@@ -63,19 +63,19 @@ struct hpux_dirent {
 };
 
 struct getdents_callback {
-       struct hpux_dirent *current_dir;
-       struct hpux_dirent *previous;
+       struct hpux_dirent __user *current_dir;
+       struct hpux_dirent __user *previous;
        int count;
        int error;
 };
 
-#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
 #define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
 
 static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
                u64 ino, unsigned d_type)
 {
-       struct hpux_dirent * dirent;
+       struct hpux_dirent __user * dirent;
        struct getdents_callback * buf = (struct getdents_callback *) __buf;
        ino_t d_ino;
        int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
@@ -105,10 +105,10 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
 #undef NAME_OFFSET
 #undef ROUND_UP
 
-int hpux_getdents(unsigned int fd, struct hpux_dirent *dirent, unsigned int count)
+int hpux_getdents(unsigned int fd, struct hpux_dirent __user *dirent, unsigned int count)
 {
        struct file * file;
-       struct hpux_dirent * lastdirent;
+       struct hpux_dirent __user * lastdirent;
        struct getdents_callback buf;
        int error = -EBADF;
 
@@ -143,7 +143,7 @@ int hpux_mount(const char *fs, const char *path, int mflag,
        return -ENOSYS;
 }
 
-static int cp_hpux_stat(struct kstat *stat, struct hpux_stat64 *statbuf)
+static int cp_hpux_stat(struct kstat *stat, struct hpux_stat64 __user *statbuf)
 {
        struct hpux_stat64 tmp;
 
@@ -169,7 +169,7 @@ static int cp_hpux_stat(struct kstat *stat, struct hpux_stat64 *statbuf)
        return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
 }
 
-long hpux_stat64(char *filename, struct hpux_stat64 *statbuf)
+long hpux_stat64(char __user *filename, struct hpux_stat64 __user *statbuf)
 {
        struct kstat stat;
        int error = vfs_stat(filename, &stat);
@@ -180,7 +180,7 @@ long hpux_stat64(char *filename, struct hpux_stat64 *statbuf)
        return error;
 }
 
-long hpux_fstat64(unsigned int fd, struct hpux_stat64 *statbuf)
+long hpux_fstat64(unsigned int fd, struct hpux_stat64 __user *statbuf)
 {
        struct kstat stat;
        int error = vfs_fstat(fd, &stat);
@@ -191,7 +191,7 @@ long hpux_fstat64(unsigned int fd, struct hpux_stat64 *statbuf)
        return error;
 }
 
-long hpux_lstat64(char *filename, struct hpux_stat64 *statbuf)
+long hpux_lstat64(char __user *filename, struct hpux_stat64 __user *statbuf)
 {
        struct kstat stat;
        int error = vfs_lstat(filename, &stat);
index aaaf3306c05acaff2cf87a07a5e5fcf9de0f3c05..0b9d5b1e4b37e0ccec15e8e3c819071f47adf422 100644 (file)
 #include <asm/asm-offsets.h>
 #include <asm/unistd.h>
 #include <asm/errno.h>
+#include <linux/linkage.h>
 
-#ifdef __LP64__
-       .level          2.0w
-#else
-       .level          1.1
-#endif
+       .level  LEVEL
        .text
 
-#ifdef __LP64__
-#define FRAME_SIZE     128
-#else
-#define FRAME_SIZE     64
-#endif
        .import hpux_call_table
        .import hpux_syscall_exit,code
-       .export hpux_gateway_page
 
        .align 4096
-hpux_gateway_page:
+ENTRY(hpux_gateway_page)
        nop
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 #warning NEEDS WORK for 64-bit
 #endif
        ldw     -64(%r30), %r29                 ;! 8th argument
@@ -101,7 +92,7 @@ hpux_gateway_page:
        ldo     R%hpux_call_table(%r21), %r21
        comiclr,>>=     __NR_HPUX_syscalls, %r22, %r0
        b,n     syscall_nosys
-       ldwx,s  %r22(%r21), %r21
+       LDREGX  %r22(%r21), %r21
        ldil    L%hpux_syscall_exit,%r2
        be      0(%sr7,%r21)
        ldo     R%hpux_syscall_exit(%r2),%r2
@@ -110,7 +101,7 @@ syscall_nosys:
        ldil    L%hpux_syscall_exit,%r1
        be      R%hpux_syscall_exit(%sr7,%r1)
        ldo     -ENOSYS(%r0),%r28
+ENDPROC(hpux_gateway_page)
 
        .align 4096
-       .export end_hpux_gateway_page
-end_hpux_gateway_page:
+ENTRY(end_hpux_gateway_page)
index 04c2ff444396b56cb38438c65c217bc6f9980e0b..3e025df2dc863763eee5568bcb0628603d537cd4 100644 (file)
@@ -61,7 +61,7 @@ int hpux_ptrace(void)
        return -ENOSYS;
 }
 
-int hpux_wait(int *stat_loc)
+int hpux_wait(int __user *stat_loc)
 {
        return sys_waitpid(-1, stat_loc, 0);
 }
@@ -255,7 +255,7 @@ asmlinkage long hpux_fstatfs(unsigned int fd, struct hpux_statfs __user * buf)
 /*  TODO: Are these put_user calls OK?  Should they pass an int?
  *        (I copied it from sys_i386.c like this.)
  */
-static int hpux_uname(struct hpux_utsname *name)
+static int hpux_uname(struct hpux_utsname __user *name)
 {
        int error;
 
@@ -300,14 +300,14 @@ static int hpux_uname(struct hpux_utsname *name)
 /*  Note: HP-UX just uses the old suser() function to check perms
  *  in this system call.  We'll use capable(CAP_SYS_ADMIN).
  */
-int hpux_utssys(char *ubuf, int n, int type)
+int hpux_utssys(char __user *ubuf, int n, int type)
 {
        int len;
        int error;
        switch( type ) {
        case 0:
                /*  uname():  */
-               return( hpux_uname( (struct hpux_utsname *)ubuf ) );
+               return hpux_uname((struct hpux_utsname __user *)ubuf);
                break ;
        case 1:
                /*  Obsolete (used to be umask().)  */
@@ -315,8 +315,9 @@ int hpux_utssys(char *ubuf, int n, int type)
                break ;
        case 2:
                /*  ustat():  */
-               return( hpux_ustat(new_decode_dev(n), (struct hpux_ustat *)ubuf) );
-               break ;
+               return hpux_ustat(new_decode_dev(n),
+                                 (struct hpux_ustat __user *)ubuf);
+               break;
        case 3:
                /*  setuname():
                 *
@@ -332,7 +333,7 @@ int hpux_utssys(char *ubuf, int n, int type)
                        return -EINVAL ;
                /*  Unlike Linux, HP-UX truncates it if n is too big:  */
                len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ;
-               return( sys_sethostname(ubuf, len) );
+               return sys_sethostname(ubuf, len);
                break ;
        case 4:
                /*  sethostname():
@@ -346,7 +347,7 @@ int hpux_utssys(char *ubuf, int n, int type)
                        return -EINVAL ;
                /*  Unlike Linux, HP-UX truncates it if n is too big:  */
                len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ;
-               return( sys_sethostname(ubuf, len) );
+               return sys_sethostname(ubuf, len);
                break ;
        case 5:
                /*  gethostname():
@@ -356,7 +357,7 @@ int hpux_utssys(char *ubuf, int n, int type)
                /*  Unlike Linux, HP-UX returns an error if n==0:  */
                if ( n <= 0 )
                        return -EINVAL ;
-               return( sys_gethostname(ubuf, n) );
+               return sys_gethostname(ubuf, n);
                break ;
        case 6:
                /*  Supposedly called from setuname() in libc.
@@ -420,7 +421,7 @@ int hpux_utssys(char *ubuf, int n, int type)
        }
 }
 
-int hpux_getdomainname(char *name, int len)
+int hpux_getdomainname(char __user *name, int len)
 {
        int nlen;
        int err = -EFAULT;
@@ -471,17 +472,18 @@ int hpux_sysfs(int opcode, unsigned long arg1, unsigned long arg2)
        printk(KERN_DEBUG "hpux_sysfs called with arg1='%lx'\n", arg1);
 
        if ( opcode == 1 ) { /* GETFSIND */     
-               len = strlen_user((char *)arg1);
+               char __user *user_fsname = (char __user *)arg1;
+               len = strlen_user(user_fsname);
                printk(KERN_DEBUG "len of arg1 = %d\n", len);
                if (len == 0)
                        return 0;
                fsname = kmalloc(len, GFP_KERNEL);
-               if ( !fsname ) {
+               if (!fsname) {
                        printk(KERN_DEBUG "failed to kmalloc fsname\n");
                        return 0;
                }
 
-               if ( copy_from_user(fsname, (char *)arg1, len) ) {
+               if (copy_from_user(fsname, user_fsname, len)) {
                        printk(KERN_DEBUG "failed to copy_from_user fsname\n");
                        kfree(fsname);
                        return 0;
@@ -495,7 +497,7 @@ int hpux_sysfs(int opcode, unsigned long arg1, unsigned long arg2)
                        fstype = 0;
                } else {
                        fstype = 0;
-               };
+               }
 
                kfree(fsname);
 
@@ -509,7 +511,7 @@ int hpux_sysfs(int opcode, unsigned long arg1, unsigned long arg2)
 
 
 /* Table of syscall names and handle for unimplemented routines */
-static const char *syscall_names[] = {
+static const char * const syscall_names[] = {
        "nosys",                  /* 0 */
        "exit",                  
        "fork",                  
index 0b0c3a66b1becfbf4bc09be41087317ed7869647..58c53c879c02773d427eb699af11b20e244b198c 100644 (file)
  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 #warning PA64 support needs more work...did first cut
 #endif
 
 #include <asm/asm-offsets.h>
 #include <asm/assembly.h>
 #include <asm/signal.h>
+#include <linux/linkage.h>
 
-#ifdef __LP64__
-       .level          2.0w
-#else
-       .level          1.1
-#endif
+       .level  LEVEL
        .text
 
        /* These should probably go in a header file somewhere.
@@ -41,7 +38,7 @@
         * register save/restore macros.
         */
        .macro  reg_save regs
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 #warning NEEDS WORK for 64-bit
 #endif
        STREG   %r3, PT_GR3(\regs)
        .endm
 
 
-       .export hpux_fork_wrapper
-       .export hpux_child_return
        .import sys_fork
 
-hpux_fork_wrapper:
+ENTRY(hpux_fork_wrapper)
        ldo     TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1         ;! get pt regs
                                                            ;! pointer in task
        reg_save %r1
@@ -128,27 +123,26 @@ fork_return:
 fork_exit:
        bv      %r0(%r2)
        nop
+ENDPROC(hpux_fork_wrapper)
 
        /* Set the return value for the child */
 
-hpux_child_return:
+ENTRY(hpux_child_return)
 #if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
-       bl      schedule_tail, %r2
-       nop
+       bl,n    schedule_tail, %r2
 #endif
 
        LDREG   TASK_PT_GR19-TASK_SZ_ALGN-128(%r30),%r2
        b fork_return
        copy %r0,%r28
+ENDPROC(hpux_child_return)
 
-       .export hpux_execve_wrapper
-       .export hpux_execv_wrapper
        .import hpux_execve
 
-hpux_execv_wrapper:
+ENTRY(hpux_execv_wrapper)
        copy %r0,%r24  /* NULL environment */
 
-hpux_execve_wrapper:
+ENTRY(hpux_execve_wrapper)
 
        ldo     TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1         ;! get pt regs
 
@@ -187,13 +181,13 @@ hpux_execve_wrapper:
 exec_error:
        bv %r0(%r19)
        nop
+ENDPROC(hpux_execv_wrapper)
 
-       .export hpux_pipe_wrapper
        .import hpux_pipe
 
        /* HP-UX expects pipefd's returned in r28 & r29 */
 
-hpux_pipe_wrapper:
+ENTRY(hpux_pipe_wrapper)
        STREG %r2,-20(%r30)
        ldo 64(%r30),%r30
        bl hpux_pipe,%r2
@@ -212,12 +206,11 @@ hpux_pipe_wrapper:
 pipe_exit:
        bv %r0(%r2)
        ldo -64(%r30),%r30
+ENDPROC(hpux_pipe_wrapper)
 
-       .export hpux_syscall_exit
        .import syscall_exit
 
-hpux_syscall_exit:
-
+ENTRY(hpux_syscall_exit)
        /*
         *
         * HP-UX call return conventions:
@@ -246,12 +239,12 @@ hpux_syscall_exit:
        ldo 1(%r0),%r22
 
 no_error:
-       b syscall_exit
-       nop
+       b,n syscall_exit
+ENDPROC(hpux_syscall_exit)
 
-       .export hpux_unimplemented_wrapper
        .import hpux_unimplemented
 
-hpux_unimplemented_wrapper:
+ENTRY(hpux_unimplemented_wrapper)
        b hpux_unimplemented
        STREG %r22,-64(%r30)  /* overwrite arg8 with syscall number */
+ENDPROC(hpux_unimplemented_wrapper)
index c11a5bc7c067220af7ce3c552261f53e2fa93010..54fdb959149c4236f1e0a95204c1debbb94ac305 100644 (file)
@@ -44,7 +44,7 @@
 
 #define BLANK() asm volatile("\n->" : : )
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 #define FRAME_SIZE     128
 #else
 #define FRAME_SIZE     64
index 0be51e92a2fc62f1e82387249d3dbead462606d7..0dc924ccceb51c220f6790cc3813303c390ecf9c 100644 (file)
@@ -68,16 +68,6 @@ flush_cache_all_local(void)
 }
 EXPORT_SYMBOL(flush_cache_all_local);
 
-/* flushes EVERYTHING (tlb & cache) */
-
-void
-flush_all_caches(void)
-{
-       flush_cache_all();
-       flush_tlb_all();
-}
-EXPORT_SYMBOL(flush_all_caches);
-
 void
 update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
 {
@@ -99,7 +89,7 @@ show_cache_info(struct seq_file *m)
 
        seq_printf(m, "I-cache\t\t: %ld KB\n", 
                cache_info.ic_size/1024 );
-       if (cache_info.dc_loop == 1)
+       if (cache_info.dc_loop != 1)
                snprintf(buf, 32, "%lu-way associative", cache_info.dc_loop);
        seq_printf(m, "D-cache\t\t: %ld KB (%s%s, %s)\n",
                cache_info.dc_size/1024,
@@ -270,6 +260,83 @@ void disable_sr_hashing(void)
                panic("SpaceID hashing is still on!\n");
 }
 
+/* Simple function to work out if we have an existing address translation
+ * for a user space vma. */
+static inline int translation_exists(struct vm_area_struct *vma,
+                               unsigned long addr, unsigned long pfn)
+{
+       pgd_t *pgd = pgd_offset(vma->vm_mm, addr);
+       pmd_t *pmd;
+       pte_t pte;
+
+       if(pgd_none(*pgd))
+               return 0;
+
+       pmd = pmd_offset(pgd, addr);
+       if(pmd_none(*pmd) || pmd_bad(*pmd))
+               return 0;
+
+       /* We cannot take the pte lock here: flush_cache_page is usually
+        * called with pte lock already held.  Whereas flush_dcache_page
+        * takes flush_dcache_mmap_lock, which is lower in the hierarchy:
+        * the vma itself is secure, but the pte might come or go racily.
+        */
+       pte = *pte_offset_map(pmd, addr);
+       /* But pte_unmap() does nothing on this architecture */
+
+       /* Filter out coincidental file entries and swap entries */
+       if (!(pte_val(pte) & (_PAGE_FLUSH|_PAGE_PRESENT)))
+               return 0;
+
+       return pte_pfn(pte) == pfn;
+}
+
+/* Private function to flush a page from the cache of a non-current
+ * process.  cr25 contains the Page Directory of the current user
+ * process; we're going to hijack both it and the user space %sr3 to
+ * temporarily make the non-current process current.  We have to do
+ * this because cache flushing may cause a non-access tlb miss which
+ * the handlers have to fill in from the pgd of the non-current
+ * process. */
+static inline void
+flush_user_cache_page_non_current(struct vm_area_struct *vma,
+                                 unsigned long vmaddr)
+{
+       /* save the current process space and pgd */
+       unsigned long space = mfsp(3), pgd = mfctl(25);
+
+       /* we don't mind taking interrups since they may not
+        * do anything with user space, but we can't
+        * be preempted here */
+       preempt_disable();
+
+       /* make us current */
+       mtctl(__pa(vma->vm_mm->pgd), 25);
+       mtsp(vma->vm_mm->context, 3);
+
+       flush_user_dcache_page(vmaddr);
+       if(vma->vm_flags & VM_EXEC)
+               flush_user_icache_page(vmaddr);
+
+       /* put the old current process back */
+       mtsp(space, 3);
+       mtctl(pgd, 25);
+       preempt_enable();
+}
+
+
+static inline void
+__flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr)
+{
+       if (likely(vma->vm_mm->context == mfsp(3))) {
+               flush_user_dcache_page(vmaddr);
+               if (vma->vm_flags & VM_EXEC)
+                       flush_user_icache_page(vmaddr);
+       } else {
+               flush_user_cache_page_non_current(vma, vmaddr);
+       }
+}
+
 void flush_dcache_page(struct page *page)
 {
        struct address_space *mapping = page_mapping(page);
@@ -342,7 +409,7 @@ void clear_user_page_asm(void *page, unsigned long vaddr)
 #define FLUSH_THRESHOLD 0x80000 /* 0.5MB */
 int parisc_cache_flush_threshold __read_mostly = FLUSH_THRESHOLD;
 
-void parisc_setup_cache_timing(void)
+void __init parisc_setup_cache_timing(void)
 {
        unsigned long rangetime, alltime;
        unsigned long size;
@@ -366,6 +433,9 @@ void parisc_setup_cache_timing(void)
        if (!parisc_cache_flush_threshold)
                parisc_cache_flush_threshold = FLUSH_THRESHOLD;
 
+       if (parisc_cache_flush_threshold > cache_info.dc_size)
+               parisc_cache_flush_threshold = cache_info.dc_size;
+
        printk(KERN_INFO "Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus());
 }
 
@@ -410,3 +480,97 @@ void kunmap_parisc(void *addr)
 }
 EXPORT_SYMBOL(kunmap_parisc);
 #endif
+
+void __flush_tlb_range(unsigned long sid, unsigned long start,
+                      unsigned long end)
+{
+       unsigned long npages;
+
+       npages = ((end - (start & PAGE_MASK)) + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+       if (npages >= 512)  /* 2MB of space: arbitrary, should be tuned */
+               flush_tlb_all();
+       else {
+               mtsp(sid, 1);
+               purge_tlb_start();
+               if (split_tlb) {
+                       while (npages--) {
+                               pdtlb(start);
+                               pitlb(start);
+                               start += PAGE_SIZE;
+                       }
+               } else {
+                       while (npages--) {
+                               pdtlb(start);
+                               start += PAGE_SIZE;
+                       }
+               }
+               purge_tlb_end();
+       }
+}
+
+static void cacheflush_h_tmp_function(void *dummy)
+{
+       flush_cache_all_local();
+}
+
+void flush_cache_all(void)
+{
+       on_each_cpu(cacheflush_h_tmp_function, NULL, 1, 1);
+}
+
+void flush_cache_mm(struct mm_struct *mm)
+{
+#ifdef CONFIG_SMP
+       flush_cache_all();
+#else
+       flush_cache_all_local();
+#endif
+}
+
+void
+flush_user_dcache_range(unsigned long start, unsigned long end)
+{
+       if ((end - start) < parisc_cache_flush_threshold)
+               flush_user_dcache_range_asm(start,end);
+       else
+               flush_data_cache();
+}
+
+void
+flush_user_icache_range(unsigned long start, unsigned long end)
+{
+       if ((end - start) < parisc_cache_flush_threshold)
+               flush_user_icache_range_asm(start,end);
+       else
+               flush_instruction_cache();
+}
+
+
+void flush_cache_range(struct vm_area_struct *vma,
+               unsigned long start, unsigned long end)
+{
+       int sr3;
+
+       if (!vma->vm_mm->context) {
+               BUG();
+               return;
+       }
+
+       sr3 = mfsp(3);
+       if (vma->vm_mm->context == sr3) {
+               flush_user_dcache_range(start,end);
+               flush_user_icache_range(start,end);
+       } else {
+               flush_cache_all();
+       }
+}
+
+void
+flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn)
+{
+       BUG_ON(!vma->vm_mm->context);
+
+       if (likely(translation_exists(vma, vmaddr, pfn)))
+               __flush_cache_page(vma, vmaddr);
+
+}
index d6c486e9501ced09bded130f5f4049ee1d3a0c30..2ca654bd632224373cfcc28c294fc5efe783888c 100644 (file)
@@ -562,12 +562,23 @@ pa_dev_attr(rev, id.hversion_rev, "0x%x\n");
 pa_dev_attr_id(hversion, "0x%03x\n");
 pa_dev_attr_id(sversion, "0x%05x\n");
 
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct parisc_device *padev = to_parisc_device(dev);
+       struct parisc_device_id *id = &padev->id;
+
+       return sprintf(buf, "parisc:t%02Xhv%04Xrev%02Xsv%08X\n",
+               (u8)id->hw_type, (u16)id->hversion, (u8)id->hversion_rev,
+               (u32)id->sversion);
+}
+
 static struct device_attribute parisc_device_attrs[] = {
        __ATTR_RO(irq),
        __ATTR_RO(hw_type),
        __ATTR_RO(rev),
        __ATTR_RO(hversion),
        __ATTR_RO(sversion),
+       __ATTR_RO(modalias),
        __ATTR_NULL,
 };
 
@@ -689,7 +700,9 @@ parse_tree_node(struct device *parent, int index, struct hardware_path *modpath)
                .fn     = check_parent,
        };
 
-       device_for_each_child(parent, &recurse_data, descend_children);
+       if (device_for_each_child(parent, &recurse_data, descend_children))
+               /* nothing */;
+
        return d.dev;
 }
 
@@ -835,8 +848,8 @@ static void print_parisc_device(struct parisc_device *dev)
        static int count;
 
        print_pa_hwpath(dev, hw_path);
-       printk(KERN_INFO "%d. %s at 0x%lx [%s] { %d, 0x%x, 0x%.3x, 0x%.5x }",
-               ++count, dev->name, dev->hpa.start, hw_path, dev->id.hw_type,
+       printk(KERN_INFO "%d. %s at 0x%p [%s] { %d, 0x%x, 0x%.3x, 0x%.5x }",
+               ++count, dev->name, (void*) dev->hpa.start, hw_path, dev->id.hw_type,
                dev->id.hversion_rev, dev->id.hversion, dev->id.sversion);
 
        if (dev->num_addrs) {
index 340b5e8d67bad1197b75b4ec5320a932575f21e4..8474f9e5ca1032cf16eb2d3c8d8df0262dd0b173 100644 (file)
@@ -37,6 +37,8 @@
 #include <asm/unistd.h>
 #include <asm/thread_info.h>
 
+#include <linux/linkage.h>
+
 #ifdef CONFIG_64BIT
 #define CMPIB           cmpib,*
 #define CMPB            cmpb,*
         * the static part of the kernel address space.
         */
 
-       .export fault_vector_20
-
        .text
 
        .align 4096
 
-fault_vector_20:
+ENTRY(fault_vector_20)
        /* First vector is invalid (0) */
        .ascii  "cows can fly"
        .byte 0
@@ -695,14 +695,13 @@ fault_vector_20:
        def             29
        def             30
        def             31
+END(fault_vector_20)
 
 #ifndef CONFIG_64BIT
 
-       .export fault_vector_11
-       
        .align 2048
 
-fault_vector_11:
+ENTRY(fault_vector_11)
        /* First vector is invalid (0) */
        .ascii  "cows can fly"
        .byte 0
@@ -743,6 +742,7 @@ fault_vector_11:
        def             29
        def             30
        def             31
+END(fault_vector_11)
 
 #endif
 
@@ -762,9 +762,8 @@ fault_vector_11:
 #define CLONE_VM 0x100 /* Must agree with <linux/sched.h> */
 #define CLONE_UNTRACED 0x00800000
 
-       .export __kernel_thread, code
        .import do_fork
-__kernel_thread:
+ENTRY(__kernel_thread)
        STREG   %r2, -RP_OFFSET(%r30)
 
        copy    %r30, %r1
@@ -797,6 +796,7 @@ __kernel_thread:
        ldo     -PT_SZ_ALGN(%r30), %r30
        bv      %r0(%r2)
        nop
+ENDPROC(__kernel_thread)
 
        /*
         * Child Returns here
@@ -805,8 +805,7 @@ __kernel_thread:
         * into task save area.
         */
 
-       .export ret_from_kernel_thread
-ret_from_kernel_thread:
+ENTRY(ret_from_kernel_thread)
 
        /* Call schedule_tail first though */
        BL      schedule_tail, %r2
@@ -833,10 +832,10 @@ ret_from_kernel_thread:
        bv      %r0(%r1)
 #endif
        ldi     0, %r26
+ENDPROC(ret_from_kernel_thread)
 
        .import sys_execve, code
-       .export __execve, code
-__execve:
+ENTRY(__execve)
        copy    %r2, %r15
        copy    %r30, %r16
        ldo     PT_SZ_ALGN(%r30), %r30
@@ -856,16 +855,15 @@ __execve:
        copy    %r16, %r30
        bv      %r0(%r2)
        nop
+ENDPROC(__execve)
 
-       .align 4
 
        /*
         * struct task_struct *_switch_to(struct task_struct *prev,
         *      struct task_struct *next)
         *
         * switch kernel stacks and return prev */
-       .export _switch_to, code
-_switch_to:
+ENTRY(_switch_to)
        STREG    %r2, -RP_OFFSET(%r30)
 
        callee_save_float
@@ -890,6 +888,7 @@ _switch_to_ret:
        LDREG   -RP_OFFSET(%r30), %r2
        bv      %r0(%r2)
        copy    %r26, %r28
+ENDPROC(_switch_to)
 
        /*
         * Common rfi return path for interruptions, kernel execve, and
@@ -907,8 +906,7 @@ _switch_to_ret:
 
        .align 4096
 
-       .export syscall_exit_rfi
-syscall_exit_rfi:
+ENTRY(syscall_exit_rfi)
        mfctl   %cr30,%r16
        LDREG   TI_TASK(%r16), %r16     /* thread_info -> task_struct */
        ldo     TASK_REGS(%r16),%r16
@@ -978,11 +976,36 @@ intr_check_resched:
        LDREG   TI_FLAGS(%r1),%r19      /* sched.h: TIF_NEED_RESCHED */
        bb,<,n  %r19,31-TIF_NEED_RESCHED,intr_do_resched /* forward */
 
+       .import do_notify_resume,code
 intr_check_sig:
        /* As above */
        mfctl   %cr30,%r1
-       LDREG   TI_FLAGS(%r1),%r19      /* sched.h: TIF_SIGPENDING */
-       bb,<,n %r19, 31-TIF_SIGPENDING, intr_do_signal /* forward */
+       LDREG   TI_FLAGS(%r1),%r19
+       ldi     (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %r20
+       and,COND(<>)    %r19, %r20, %r0
+       b,n     intr_restore    /* skip past if we've nothing to do */
+
+       /* This check is critical to having LWS
+        * working. The IASQ is zero on the gateway
+        * page and we cannot deliver any signals until
+        * we get off the gateway page.
+        *
+        * Only do signals if we are returning to user space
+        */
+       LDREG   PT_IASQ0(%r16), %r20
+       CMPIB=,n 0,%r20,intr_restore /* backward */
+       LDREG   PT_IASQ1(%r16), %r20
+       CMPIB=,n 0,%r20,intr_restore /* backward */
+
+       copy    %r0, %r25                       /* long in_syscall = 0 */
+#ifdef CONFIG_64BIT
+       ldo     -16(%r30),%r29                  /* Reference param save area */
+#endif
+
+       BL      do_notify_resume,%r2
+       copy    %r16, %r26                      /* struct pt_regs *regs */
+
+       b,n     intr_check_sig
 
 intr_restore:
        copy            %r16,%r29
@@ -1072,35 +1095,6 @@ intr_do_preempt:
        b,n     intr_restore            /* ssm PSW_SM_I done by intr_restore */
 #endif /* CONFIG_PREEMPT */
 
-       .import do_signal,code
-intr_do_signal:
-       /* 
-               This check is critical to having LWS
-               working. The IASQ is zero on the gateway
-               page and we cannot deliver any signals until
-               we get off the gateway page.
-
-               Only do signals if we are returning to user space 
-       */
-       LDREG   PT_IASQ0(%r16), %r20
-       CMPIB= 0,%r20,intr_restore /* backward */
-       nop
-       LDREG   PT_IASQ1(%r16), %r20
-       CMPIB= 0,%r20,intr_restore /* backward */
-       nop
-
-       copy    %r0, %r24                       /* unsigned long in_syscall */
-       copy    %r16, %r25                      /* struct pt_regs *regs */
-#ifdef CONFIG_64BIT
-       ldo     -16(%r30),%r29                  /* Reference param save area */
-#endif
-
-       BL      do_signal,%r2
-       copy    %r0, %r26                       /* sigset_t *oldset = NULL */
-
-       b       intr_check_sig
-       nop
-
        /*
         * External interrupts.
         */
@@ -1115,11 +1109,7 @@ intr_extint:
        mfctl   %cr31,%r1
        copy    %r30,%r17
        /* FIXME! depi below has hardcoded idea of interrupt stack size (32k)*/
-#ifdef CONFIG_64BIT
-       depdi   0,63,15,%r17
-#else
-       depi    0,31,15,%r17
-#endif
+       DEPI    0,31,15,%r17
        CMPB=,n %r1,%r17,2f
        get_stack_use_cr31
        b,n 3f
@@ -1148,13 +1138,12 @@ intr_extint:
 
        b       do_cpu_irq_mask
        ldo     R%intr_return(%r2), %r2 /* return to intr_return, not here */
+ENDPROC(syscall_exit_rfi)
 
 
        /* Generic interruptions (illegal insn, unaligned, page fault, etc) */
 
-       .export         intr_save, code /* for os_hpmc */
-
-intr_save:
+ENTRY(intr_save)               /* for os_hpmc */
        mfsp    %sr7,%r16
        CMPIB=,n 0,%r16,1f
        get_stack_use_cr30
@@ -1229,6 +1218,7 @@ skip_save_ior:
 
        b               handle_interruption
        ldo             R%intr_check_sig(%r2), %r2
+ENDPROC(intr_save)
 
 
        /*
@@ -1814,9 +1804,7 @@ dtlb_fault:
        LDREG   PT_GR18(\regs),%r18
        .endm
 
-       .export sys_fork_wrapper
-       .export child_return
-sys_fork_wrapper:
+ENTRY(sys_fork_wrapper)
        LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
        ldo     TASK_REGS(%r1),%r1
        reg_save %r1
@@ -1853,9 +1841,10 @@ wrapper_exit:
        ldi     __NR_fork,%r20
        bv %r0(%r2)
        STREG   %r20,PT_GR20(%r1)
+ENDPROC(sys_fork_wrapper)
 
        /* Set the return value for the child */
-child_return:
+ENTRY(child_return)
        BL      schedule_tail, %r2
        nop
 
@@ -1863,10 +1852,10 @@ child_return:
        LDREG   TASK_PT_GR19(%r1),%r2
        b       wrapper_exit
        copy    %r0,%r28
+ENDPROC(child_return)
 
-       
-       .export sys_clone_wrapper
-sys_clone_wrapper:
+
+ENTRY(sys_clone_wrapper)
        LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
        ldo     TASK_REGS(%r1),%r1      /* get pt regs */
        reg_save %r1
@@ -1887,9 +1876,10 @@ sys_clone_wrapper:
 
        b       wrapper_exit
        LDREG   -RP_OFFSET-FRAME_SIZE(%r30),%r2
+ENDPROC(sys_clone_wrapper)
+
 
-       .export sys_vfork_wrapper
-sys_vfork_wrapper:
+ENTRY(sys_vfork_wrapper)
        LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
        ldo     TASK_REGS(%r1),%r1      /* get pt regs */
        reg_save %r1
@@ -1910,6 +1900,7 @@ sys_vfork_wrapper:
 
        b       wrapper_exit
        LDREG   -RP_OFFSET-FRAME_SIZE(%r30),%r2
+ENDPROC(sys_vfork_wrapper)
 
        
        .macro  execve_wrapper execve
@@ -1946,22 +1937,19 @@ error_\execve:
        nop
        .endm
 
-       .export sys_execve_wrapper
        .import sys_execve
-
-sys_execve_wrapper:
+ENTRY(sys_execve_wrapper)
        execve_wrapper sys_execve
+ENDPROC(sys_execve_wrapper)
 
 #ifdef CONFIG_64BIT
-       .export sys32_execve_wrapper
        .import sys32_execve
-
-sys32_execve_wrapper:
+ENTRY(sys32_execve_wrapper)
        execve_wrapper sys32_execve
+ENDPROC(sys32_execve_wrapper)
 #endif
 
-       .export sys_rt_sigreturn_wrapper
-sys_rt_sigreturn_wrapper:
+ENTRY(sys_rt_sigreturn_wrapper)
        LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26
        ldo     TASK_REGS(%r26),%r26    /* get pt regs */
        /* Don't save regs, we are going to restore them from sigcontext. */
@@ -1989,9 +1977,9 @@ sys_rt_sigreturn_wrapper:
         */
        bv      %r0(%r2)
        LDREG   PT_GR28(%r1),%r28  /* reload original r28 for syscall_exit */
+ENDPROC(sys_rt_sigreturn_wrapper)
 
-       .export sys_sigaltstack_wrapper
-sys_sigaltstack_wrapper:
+ENTRY(sys_sigaltstack_wrapper)
        /* Get the user stack pointer */
        LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
        ldo     TASK_REGS(%r1),%r24     /* get pt regs */
@@ -1999,10 +1987,10 @@ sys_sigaltstack_wrapper:
        STREG   %r2, -RP_OFFSET(%r30)
 #ifdef CONFIG_64BIT
        ldo     FRAME_SIZE(%r30), %r30
-       b,l     do_sigaltstack,%r2
+       BL      do_sigaltstack,%r2
        ldo     -16(%r30),%r29          /* Reference param save area */
 #else
-       bl      do_sigaltstack,%r2
+       BL      do_sigaltstack,%r2
        ldo     FRAME_SIZE(%r30), %r30
 #endif
 
@@ -2010,53 +1998,26 @@ sys_sigaltstack_wrapper:
        LDREG   -RP_OFFSET(%r30), %r2
        bv      %r0(%r2)
        nop
+ENDPROC(sys_sigaltstack_wrapper)
 
 #ifdef CONFIG_64BIT
-       .export sys32_sigaltstack_wrapper
-sys32_sigaltstack_wrapper:
+ENTRY(sys32_sigaltstack_wrapper)
        /* Get the user stack pointer */
        LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r24
        LDREG   TASK_PT_GR30(%r24),%r24
        STREG   %r2, -RP_OFFSET(%r30)
        ldo     FRAME_SIZE(%r30), %r30
-       b,l     do_sigaltstack32,%r2
+       BL      do_sigaltstack32,%r2
        ldo     -16(%r30),%r29          /* Reference param save area */
 
        ldo     -FRAME_SIZE(%r30), %r30
        LDREG   -RP_OFFSET(%r30), %r2
        bv      %r0(%r2)
        nop
+ENDPROC(sys32_sigaltstack_wrapper)
 #endif
 
-       .export sys_rt_sigsuspend_wrapper
-sys_rt_sigsuspend_wrapper:
-       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
-       ldo     TASK_REGS(%r1),%r24
-       reg_save %r24
-
-       STREG   %r2, -RP_OFFSET(%r30)
-#ifdef CONFIG_64BIT
-       ldo     FRAME_SIZE(%r30), %r30
-       b,l     sys_rt_sigsuspend,%r2
-       ldo     -16(%r30),%r29          /* Reference param save area */
-#else
-       bl      sys_rt_sigsuspend,%r2
-       ldo     FRAME_SIZE(%r30), %r30
-#endif
-
-       ldo     -FRAME_SIZE(%r30), %r30
-       LDREG   -RP_OFFSET(%r30), %r2
-
-       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
-       ldo     TASK_REGS(%r1),%r1
-       reg_restore %r1
-
-       bv      %r0(%r2)
-       nop
-
-       .export syscall_exit
-syscall_exit:
-
+ENTRY(syscall_exit)
        /* NOTE: HP-UX syscalls also come through here
         * after hpux_syscall_exit fixes up return
         * values. */
@@ -2119,9 +2080,35 @@ syscall_check_resched:
        LDREG   TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19   /* long */
        bb,<,n  %r19, 31-TIF_NEED_RESCHED, syscall_do_resched /* forward */
 
+       .import do_signal,code
 syscall_check_sig:
-       LDREG   TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19    /* get ti flags */
-       bb,<,n  %r19, 31-TIF_SIGPENDING, syscall_do_signal /* forward */
+       LDREG   TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19
+       ldi     (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %r26
+       and,COND(<>)    %r19, %r26, %r0
+       b,n     syscall_restore /* skip past if we've nothing to do */
+
+syscall_do_signal:
+       /* Save callee-save registers (for sigcontext).
+        * FIXME: After this point the process structure should be
+        * consistent with all the relevant state of the process
+        * before the syscall.  We need to verify this.
+        */
+       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
+       ldo     TASK_REGS(%r1), %r26            /* struct pt_regs *regs */
+       reg_save %r26
+
+#ifdef CONFIG_64BIT
+       ldo     -16(%r30),%r29                  /* Reference param save area */
+#endif
+
+       BL      do_notify_resume,%r2
+       ldi     1, %r25                         /* long in_syscall = 1 */
+
+       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
+       ldo     TASK_REGS(%r1), %r20            /* reload pt_regs */
+       reg_restore %r20
+
+       b,n     syscall_check_sig
 
 syscall_restore:
        /* Are we being ptraced? */
@@ -2259,31 +2246,10 @@ syscall_do_resched:
 #endif
        b       syscall_check_bh  /* if resched, we start over again */
        nop
+ENDPROC(syscall_exit)
 
-       .import do_signal,code
-syscall_do_signal:
-       /* Save callee-save registers (for sigcontext).
-          FIXME: After this point the process structure should be
-          consistent with all the relevant state of the process
-          before the syscall.  We need to verify this. */
-       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 
-       ldo     TASK_REGS(%r1), %r25            /* struct pt_regs *regs */
-       reg_save %r25
-
-       ldi     1, %r24                         /* unsigned long in_syscall */
-
-#ifdef CONFIG_64BIT
-       ldo     -16(%r30),%r29                  /* Reference param save area */
-#endif
-       BL      do_signal,%r2
-       copy    %r0, %r26                       /* sigset_t *oldset = NULL */
-
-       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
-       ldo     TASK_REGS(%r1), %r20            /* reload pt_regs */
-       reg_restore %r20
-
-       b,n     syscall_check_sig
 
+get_register:
        /*
         * get_register is used by the non access tlb miss handlers to
         * copy the value of the general register specified in r8 into
@@ -2294,8 +2260,6 @@ syscall_do_signal:
         * a -1 in it, but that is OK, it just means that we will have
         * to use the slow path instead).
         */
-
-get_register:
        blr     %r8,%r0
        nop
        bv      %r0(%r25)    /* r0 */
@@ -2363,13 +2327,13 @@ get_register:
        bv      %r0(%r25)    /* r31 */
        copy    %r31,%r1
 
+
+set_register:
        /*
         * set_register is used by the non access tlb miss handlers to
         * copy the value of r1 into the general register specified in
         * r8.
         */
-
-set_register:
        blr     %r8,%r0
        nop
        bv      %r0(%r25)    /* r0 (silly, but it is a place holder) */
@@ -2436,3 +2400,4 @@ set_register:
        copy    %r1,%r30
        bv      %r0(%r25)    /* r31 */
        copy    %r1,%r31
+
index 9158b707c0dd7a083850b16827a05eea7362efd8..39dc835bf89ed8c5e54ef2e52dd6389a44b60b07 100644 (file)
@@ -74,7 +74,7 @@ static DEFINE_SPINLOCK(pdc_lock);
 static unsigned long pdc_result[32] __attribute__ ((aligned (8)));
 static unsigned long pdc_result2[32] __attribute__ ((aligned (8)));
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 #define WIDE_FIRMWARE 0x1
 #define NARROW_FIRMWARE 0x2
 
@@ -94,12 +94,12 @@ int parisc_narrow_firmware __read_mostly = 1;
  * when running a 64-bit kernel on such boxes (e.g. C200 or C360).
  */
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 long real64_call(unsigned long function, ...);
 #endif
 long real32_call(unsigned long function, ...);
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 #   define MEM_PDC (unsigned long)(PAGE0->mem_pdc_hi) << 32 | PAGE0->mem_pdc
 #   define mem_pdc_call(args...) unlikely(parisc_narrow_firmware) ? real32_call(MEM_PDC, args) : real64_call(MEM_PDC, args)
 #else
@@ -117,7 +117,7 @@ long real32_call(unsigned long function, ...);
  */
 static unsigned long f_extend(unsigned long address)
 {
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        if(unlikely(parisc_narrow_firmware)) {
                if((address & 0xff000000) == 0xf0000000)
                        return 0xf0f0f0f000000000UL | (u32)address;
@@ -139,7 +139,7 @@ static unsigned long f_extend(unsigned long address)
  */
 static void convert_to_wide(unsigned long *addr)
 {
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        int i;
        unsigned int *p = (unsigned int *)addr;
 
@@ -158,7 +158,7 @@ static void convert_to_wide(unsigned long *addr)
  */
 void __init set_firmware_width(void)
 {
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        int retval;
        unsigned long flags;
 
@@ -238,7 +238,7 @@ int __init pdc_chassis_info(struct pdc_chassis_info *chassis_info, void *led_inf
  * 
  * Must be correctly formatted or expect system crash
  */
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 int pdc_pat_chassis_send_log(unsigned long state, unsigned long data)
 {
        int retval = 0;
@@ -949,7 +949,7 @@ int pdc_tod_set(unsigned long sec, unsigned long usec)
 }
 EXPORT_SYMBOL(pdc_tod_set);
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 int pdc_mem_mem_table(struct pdc_memory_table_raddr *r_addr,
                struct pdc_memory_table *tbl, unsigned long entries)
 {
@@ -965,7 +965,7 @@ int pdc_mem_mem_table(struct pdc_memory_table_raddr *r_addr,
 
        return retval;
 }
-#endif /* __LP64__ */
+#endif /* CONFIG_64BIT */
 
 /* FIXME: Is this pdc used?  I could not find type reference to ftc_bitmap
  * so I guessed at unsigned long.  Someone who knows what this does, can fix
@@ -1204,7 +1204,7 @@ int pdc_sti_call(unsigned long func, unsigned long flags,
 }
 EXPORT_SYMBOL(pdc_sti_call);
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 /**
  * pdc_pat_cell_get_number - Returns the cell number.
  * @cell_info: The return buffer.
@@ -1387,7 +1387,7 @@ int pdc_pat_io_pci_cfg_write(unsigned long pci_addr, int pci_size, u32 val)
 
        return retval;
 }
-#endif /* __LP64__ */
+#endif /* CONFIG_64BIT */
 
 
 /***************** 32-bit real-mode calls ***********/
@@ -1445,7 +1445,7 @@ long real32_call(unsigned long fn, ...)
        return real32_call_asm(&real_stack.sp, &real_stack.arg0, fn);
 }
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 /***************** 64-bit real-mode calls ***********/
 
 struct wide_stack {
@@ -1496,5 +1496,5 @@ long real64_call(unsigned long fn, ...)
        return real64_call_asm(&real64_stack.sp, &real64_stack.arg0, fn);
 }
 
-#endif /* __LP64__ */
+#endif /* CONFIG_64BIT */
 
index eaad2328fea14669fdd00dce7f45df8c8a9ef0d3..9676c486bb63825c59a5b4fd8f6f2420b467c03b 100644 (file)
@@ -2,7 +2,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1999 by Helge Deller
+ * Copyright (C) 1999-2007 by Helge Deller <deller@gmx.de>
  * Copyright 1999 SuSE GmbH (Philipp Rumpf)
  * Copyright 1999 Philipp Rumpf (prumpf@tux.org)
  * Copyright 2000 Hewlett Packard (Paul Bame, bame@puffin.external.hp.com)
 #include <asm/assembly.h>
 #include <asm/pgtable.h>
 
+#include <linux/linkage.h>
+
        .level  LEVEL
 
        .data
-
-       .export boot_args
-boot_args:
+ENTRY(boot_args)
        .word 0 /* arg0 */
        .word 0 /* arg1 */
        .word 0 /* arg2 */
        .word 0 /* arg3 */
+END(boot_args)
 
        .text
        .align  4
@@ -38,10 +39,9 @@ boot_args:
         .import fault_vector_11,code    /* IVA parisc 1.1 32 bit */
        .import $global$                /* forward declaration */
 #endif /*!CONFIG_64BIT*/
-       .export stext
        .export _stext,data             /* Kernel want it this way! */
 _stext:
-stext:
+ENTRY(stext)
        .proc
        .callinfo
 
@@ -343,6 +343,9 @@ smp_slave_stext:
 
        .procend
 #endif /* CONFIG_SMP */
+
+ENDPROC(stext)
+
 #ifndef CONFIG_64BIT
        .data
 
index c412c0adc4a92445f551626ac5a10a5454387526..d8baa158d8a0a37e560277ce7c550e36d95b7c1c 100644 (file)
@@ -46,6 +46,8 @@
 #include <asm/assembly.h>
 #include <asm/pdc.h>
 
+#include <linux/linkage.h>
+
        /*
         * stack for os_hpmc, the HPMC handler.
         * buffer for IODC procedures (for the HPMC handler).
@@ -69,17 +71,15 @@ hpmc_raddr:
 
 #define HPMC_PIM_DATA_SIZE 896 /* Enough to hold all architected 2.0 state */
 
-       .export hpmc_pim_data, data
        .align 8
-hpmc_pim_data:
+ENTRY(hpmc_pim_data)
        .block HPMC_PIM_DATA_SIZE
+END(hpmc_pim_data)
 
        .text
 
-       .export os_hpmc, code
        .import intr_save, code
-
-os_hpmc:
+ENTRY(os_hpmc)
 
        /*
         * registers modified:
@@ -294,11 +294,9 @@ os_hpmc_6:
 
        b .
        nop
+ENDPROC(os_hpmc)
 
        /* this label used to compute os_hpmc checksum */
-
-       .export os_hpmc_end, code
-
-os_hpmc_end:
+ENTRY(os_hpmc_end)
 
        nop
index 4e847ba53180a0641d4cdebc848359f867160984..4845a64446330d6a1e5e793a31c4c565df21a7b1 100644 (file)
@@ -47,7 +47,7 @@ void __init setup_pdc(void)
        struct pdc_system_map_mod_info module_result;
        struct pdc_module_path module_path;
        struct pdc_model model;
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        struct pdc_pat_cell_num cell_info;
 #endif
 
@@ -73,7 +73,7 @@ void __init setup_pdc(void)
         * clearer message.
         */
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        status = pdc_pat_cell_get_number(&cell_info);
        if (status == PDC_OK) {
                pdc_type = PDC_TYPE_PAT;
@@ -152,7 +152,7 @@ static void __init pagezero_memconfig(void)
        npmem_ranges = 1;
 }
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 
 /* All of the PDC PAT specific code is 64-bit only */
 
@@ -408,13 +408,13 @@ static void __init sprockets_memconfig(void)
        }
 }
 
-#else   /* !__LP64__ */
+#else   /* !CONFIG_64BIT */
 
 #define pat_inventory() do { } while (0)
 #define pat_memconfig() do { } while (0)
 #define sprockets_memconfig() pagezero_memconfig()
 
-#endif /* !__LP64__ */
+#endif /* !CONFIG_64BIT */
 
 
 #ifndef CONFIG_PA20
index b39c5b9aff463d5efcf41dda4fe2474b27b97052..e9d09b020e865ca2a2c875bc76a0d81929679a72 100644 (file)
@@ -336,11 +336,7 @@ unsigned int txn_alloc_data(unsigned int virt_irq)
 
 static inline int eirr_to_irq(unsigned long eirr)
 {
-#ifdef CONFIG_64BIT
-       int bit = fls64(eirr);
-#else
-       int bit = fls(eirr);
-#endif
+       int bit = fls_long(eirr);
        return (BITS_PER_LONG - bit) + TIMER_IRQ;
 }
 
index f50b982b0834ce8b2598d1b66d1c06b5306ca29f..fdacdd4341c9f3ccf3189afe683b7179ead823d4 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/fs.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <linux/bug.h>
 
 #include <asm/unwind.h>
 
@@ -96,7 +97,7 @@ static inline int in_local_section(struct module *me, void *loc, void *dot)
 }
 
 
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
 struct got_entry {
        Elf32_Addr addr;
 };
@@ -176,7 +177,7 @@ void *module_alloc(unsigned long size)
        return vmalloc(size);
 }
 
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
 static inline unsigned long count_gots(const Elf_Rela *rela, unsigned long n)
 {
        return 0;
@@ -319,7 +320,7 @@ int module_frob_arch_sections(CONST Elf_Ehdr *hdr,
        return 0;
 }
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 static Elf64_Word get_got(struct module *me, unsigned long value, long addend)
 {
        unsigned int i;
@@ -342,9 +343,9 @@ static Elf64_Word get_got(struct module *me, unsigned long value, long addend)
               value);
        return i * sizeof(struct got_entry);
 }
-#endif /* __LP64__ */
+#endif /* CONFIG_64BIT */
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 static Elf_Addr get_fdesc(struct module *me, unsigned long value)
 {
        Elf_Fdesc *fdesc = me->module_core + me->arch.fdesc_offset;
@@ -368,7 +369,7 @@ static Elf_Addr get_fdesc(struct module *me, unsigned long value)
        fdesc->gp = (Elf_Addr)me->module_core + me->arch.got_offset;
        return (Elf_Addr)fdesc;
 }
-#endif /* __LP64__ */
+#endif /* CONFIG_64BIT */
 
 enum elf_stub_type {
        ELF_STUB_GOT,
@@ -394,7 +395,7 @@ static Elf_Addr get_stub(struct module *me, unsigned long value, long addend,
                        i * sizeof(struct stub_entry);
        }
 
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
 /* for 32-bit the stub looks like this:
  *     ldil L'XXX,%r1
  *     be,n R'XXX(%sr4,%r1)
@@ -472,7 +473,7 @@ int apply_relocate(Elf_Shdr *sechdrs,
        return -ENOEXEC;
 }
 
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
 int apply_relocate_add(Elf_Shdr *sechdrs,
                       const char *strtab,
                       unsigned int symindex,
@@ -822,7 +823,8 @@ int module_finalize(const Elf_Ehdr *hdr,
               me->name, strtab, symhdr);
 
        if(me->arch.got_count > MAX_GOTS) {
-               printk(KERN_ERR "%s: Global Offset Table overflow (used %ld, allowed %d\n", me->name, me->arch.got_count, MAX_GOTS);
+               printk(KERN_ERR "%s: Global Offset Table overflow (used %ld, allowed %d)\n",
+                               me->name, me->arch.got_count, MAX_GOTS);
                return -EINVAL;
        }
        
@@ -850,10 +852,11 @@ int module_finalize(const Elf_Ehdr *hdr,
        nsyms = newptr - (Elf_Sym *)symhdr->sh_addr;
        DEBUGP("NEW num_symtab %lu\n", nsyms);
        symhdr->sh_size = nsyms * sizeof(Elf_Sym);
-       return 0;
+       return module_bug_finalize(hdr, sechdrs, me);
 }
 
 void module_arch_cleanup(struct module *mod)
 {
        deregister_unwind_table(mod);
+       module_bug_cleanup(mod);
 }
index e81c9937d10a30a31917fc9c2a5311c51865f41e..90b240878520b9c41f28ccbcbfc9a663f7c3e571 100644 (file)
  */
 
 #ifdef CONFIG_64BIT
-#define ADDIB  addib,*
-#define CMPB   cmpb,*
-#define ANDCM  andcm,*
-
        .level  2.0w
 #else
-#define ADDIB  addib,
-#define CMPB   cmpb,
-#define ANDCM  andcm
-
        .level  2.0
 #endif
 
-
 #include <asm/psw.h>
 #include <asm/assembly.h>
 #include <asm/pgtable.h>
 #include <asm/cache.h>
+#include <linux/linkage.h>
 
        .text
        .align  128
 
-       .export flush_tlb_all_local,code
-
-flush_tlb_all_local:
+ENTRY(flush_tlb_all_local)
        .proc
        .callinfo NO_CALLS
        .entry
@@ -200,11 +190,11 @@ fdtdone:
 
        .exit
        .procend
+ENDPROC(flush_tlb_all_local)
 
-       .export flush_instruction_cache_local,code
        .import cache_info,data
 
-flush_instruction_cache_local:
+ENTRY(flush_instruction_cache_local)
        .proc
        .callinfo NO_CALLS
        .entry
@@ -241,11 +231,11 @@ fisync:
        .exit
 
        .procend
+ENDPROC(flush_instruction_cache_local)
 
-       .export flush_data_cache_local, code
-       .import cache_info, data
 
-flush_data_cache_local:
+       .import cache_info, data
+ENTRY(flush_data_cache_local)
        .proc
        .callinfo NO_CALLS
        .entry
@@ -283,11 +273,11 @@ fdsync:
        .exit
 
        .procend
+ENDPROC(flush_data_cache_local)
 
-       .export copy_user_page_asm,code
        .align  16
 
-copy_user_page_asm:
+ENTRY(copy_user_page_asm)
        .proc
        .callinfo NO_CALLS
        .entry
@@ -409,6 +399,7 @@ copy_user_page_asm:
        .exit
 
        .procend
+ENDPROC(copy_user_page_asm)
 
 /*
  * NOTE: Code in clear_user_page has a hard coded dependency on the
@@ -446,9 +437,7 @@ copy_user_page_asm:
         * lobby for such a change.
         */
 
-       .export copy_user_page_asm,code
-
-copy_user_page_asm:
+ENTRY(copy_user_page_asm)
        .proc
        .callinfo NO_CALLS
        .entry
@@ -534,11 +523,10 @@ copy_user_page_asm:
        .exit
 
        .procend
+ENDPROC(copy_user_page_asm)
 #endif
 
-       .export __clear_user_page_asm,code
-
-__clear_user_page_asm:
+ENTRY(__clear_user_page_asm)
        .proc
        .callinfo NO_CALLS
        .entry
@@ -618,10 +606,9 @@ __clear_user_page_asm:
        .exit
 
        .procend
+ENDPROC(__clear_user_page_asm)
 
-       .export flush_kernel_dcache_page_asm
-
-flush_kernel_dcache_page_asm:
+ENTRY(flush_kernel_dcache_page_asm)
        .proc
        .callinfo NO_CALLS
        .entry
@@ -662,10 +649,9 @@ flush_kernel_dcache_page_asm:
        .exit
 
        .procend
+ENDPROC(flush_kernel_dcache_page_asm)
        
-       .export flush_user_dcache_page
-
-flush_user_dcache_page:
+ENTRY(flush_user_dcache_page)
        .proc
        .callinfo NO_CALLS
        .entry
@@ -706,10 +692,9 @@ flush_user_dcache_page:
        .exit
 
        .procend
+ENDPROC(flush_user_dcache_page)
 
-       .export flush_user_icache_page
-
-flush_user_icache_page:
+ENTRY(flush_user_icache_page)
        .proc
        .callinfo NO_CALLS
        .entry
@@ -750,11 +735,10 @@ flush_user_icache_page:
        .exit
 
        .procend
+ENDPROC(flush_user_icache_page)
 
 
-       .export purge_kernel_dcache_page
-
-purge_kernel_dcache_page:
+ENTRY(purge_kernel_dcache_page)
        .proc
        .callinfo NO_CALLS
        .entry
@@ -794,15 +778,14 @@ purge_kernel_dcache_page:
        .exit
 
        .procend
+ENDPROC(purge_kernel_dcache_page)
 
 #if 0
        /* Currently not used, but it still is a possible alternate
         * solution.
         */
 
-       .export flush_alias_page
-
-flush_alias_page:
+ENTRY(flush_alias_page)
        .proc
        .callinfo NO_CALLS
        .entry
@@ -882,10 +865,9 @@ flush_user_dcache_range_asm:
        .exit
 
        .procend
+ENDPROC(flush_alias_page)
 
-       .export flush_kernel_dcache_range_asm
-
-flush_kernel_dcache_range_asm:
+ENTRY(flush_kernel_dcache_range_asm)
        .proc
        .callinfo NO_CALLS
        .entry
@@ -905,10 +887,9 @@ flush_kernel_dcache_range_asm:
        .exit
 
        .procend
+ENDPROC(flush_kernel_dcache_range_asm)
 
-       .export flush_user_icache_range_asm
-
-flush_user_icache_range_asm:
+ENTRY(flush_user_icache_range_asm)
        .proc
        .callinfo NO_CALLS
        .entry
@@ -927,10 +908,9 @@ flush_user_icache_range_asm:
        .exit
 
        .procend
+ENDPROC(flush_user_icache_range_asm)
 
-       .export flush_kernel_icache_page
-
-flush_kernel_icache_page:
+ENTRY(flush_kernel_icache_page)
        .proc
        .callinfo NO_CALLS
        .entry
@@ -971,10 +951,9 @@ flush_kernel_icache_page:
        .exit
 
        .procend
+ENDPROC(flush_kernel_icache_page)
 
-       .export flush_kernel_icache_range_asm
-
-flush_kernel_icache_range_asm:
+ENTRY(flush_kernel_icache_range_asm)
        .proc
        .callinfo NO_CALLS
        .entry
@@ -992,14 +971,13 @@ flush_kernel_icache_range_asm:
        nop
        .exit
        .procend
+ENDPROC(flush_kernel_icache_range_asm)
 
        /* align should cover use of rfi in disable_sr_hashing_asm and
         * srdis_done.
         */
        .align  256
-       .export disable_sr_hashing_asm,code
-
-disable_sr_hashing_asm:
+ENTRY(disable_sr_hashing_asm)
        .proc
        .callinfo NO_CALLS
        .entry
@@ -1088,5 +1066,6 @@ srdis_done:
        .exit
 
        .procend
+ENDPROC(disable_sr_hashing_asm)
 
        .end
index 8f6a0b312f7a025b97d9785be851f0fb748f4e85..7aca704e96f00bceecd841f621bc3b70cf5fc895 100644 (file)
@@ -7,7 +7,7 @@
  *    Copyright (C) 2001-2003 Grant Grundler <grundler with parisc-linux.org>
  *    Copyright (C) 2002-2003 Matthew Wilcox <willy at parisc-linux.org>
  *    Copyright (C) 2002 Randolph Chung <tausq at parisc-linux.org>
- *    Copyright (C) 2002-2003 Helge Deller <deller with parisc-linux.org>
+ *    Copyright (C) 2002-2007 Helge Deller <deller with parisc-linux.org>
  * 
  *    This program is free software; you can redistribute it and/or modify
  *    it under the terms of the GNU General Public License as published by
@@ -38,7 +38,7 @@ EXPORT_SYMBOL(__cmpxchg_u32);
 #ifdef CONFIG_SMP
 EXPORT_SYMBOL(__atomic_hash);
 #endif
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 EXPORT_SYMBOL(__xchg64);
 EXPORT_SYMBOL(__cmpxchg_u64);
 #endif
@@ -58,7 +58,7 @@ EXPORT_SYMBOL(fixup_get_user_skip_2);
 EXPORT_SYMBOL(fixup_put_user_skip_1);
 EXPORT_SYMBOL(fixup_put_user_skip_2);
 
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
 /* Needed so insmod can set dp value */
 extern int $global$;
 EXPORT_SYMBOL($global$);
@@ -135,7 +135,7 @@ EXPORT_SYMBOL(__muldi3);
 asmlinkage void * __canonicalize_funcptr_for_compare(void *);
 EXPORT_SYMBOL(__canonicalize_funcptr_for_compare);
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 extern void __divdi3(void);
 extern void __udivdi3(void);
 extern void __umoddi3(void);
@@ -147,7 +147,7 @@ EXPORT_SYMBOL(__umoddi3);
 EXPORT_SYMBOL(__moddi3);
 #endif
 
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
 extern void $$dyncall(void);
 EXPORT_SYMBOL($$dyncall);
 #endif
index a6caf10730851c176dbfad4e15b32d623059a73e..0c3aecb85a5ccb344ffe8d0f391f6ebaebbf17a6 100644 (file)
@@ -342,7 +342,7 @@ pcxl_dma_init(void)
        pcxl_res_map = (char *)__get_free_pages(GFP_KERNEL,
                                            get_order(pcxl_res_size));
        memset(pcxl_res_map, 0, pcxl_res_size);
-       proc_gsc_root = proc_mkdir("gsc", 0);
+       proc_gsc_root = proc_mkdir("gsc", NULL);
        if (!proc_gsc_root)
                printk(KERN_WARNING
                        "pcxl_dma_init: Unable to create gsc /proc dir entry\n");
index 199887a61c765dea150132dc9d870b9c14a0e9f6..563df0072dee9cf5413778d068a55c4482ac2ce9 100644 (file)
@@ -200,8 +200,8 @@ static void
 pcibios_link_hba_resources( struct resource *hba_res, struct resource *r)
 {
        if (!r->parent) {
-               printk(KERN_EMERG "PCI: resource not parented! [%lx-%lx]\n",
-                               r->start, r->end);
+               printk(KERN_EMERG "PCI: resource not parented! [%p-%p]\n",
+                               (void*) r->start, (void*) r->end);
                r->parent = hba_res;
 
                /* reverse link is harder *sigh*  */
index 5e7bb90e7e08e968e765179bcd9631e55b20cc78..43874ca3ed67178505597cbe707630ffc3dfa2ba 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include <asm/assembly.h>
+#include <linux/linkage.h>
 
 #ifdef CONFIG_64BIT
        .level          2.0w
 ; starting/stopping the coprocessor with the pmenb/pmdis.
 ;
        .text
-       .align 32
 
-       .export perf_intrigue_enable_perf_counters,code
-perf_intrigue_enable_perf_counters:
+ENTRY(perf_intrigue_enable_perf_counters)
        .proc
        .callinfo  frame=0,NO_CALLS
        .entry
@@ -69,9 +68,9 @@ perf_intrigue_enable_perf_counters:
        nop
        .exit
        .procend
+ENDPROC(perf_intrigue_enable_perf_counters)
 
-       .export perf_intrigue_disable_perf_counters,code
-perf_intrigue_disable_perf_counters:
+ENTRY(perf_intrigue_disable_perf_counters)
        .proc
        .callinfo  frame=0,NO_CALLS
        .entry
@@ -86,6 +85,7 @@ perf_intrigue_disable_perf_counters:
        mtctl   %r26,ccr                 ; turn off performance coprocessor
        .exit
        .procend
+ENDPROC(perf_intrigue_disable_perf_counters)
 
 ;***********************************************************************
 ;*
@@ -117,8 +117,7 @@ perf_intrigue_disable_perf_counters:
 ;*
 ;***********************************************************************
 
-       .export perf_rdr_shift_in_W,code
-perf_rdr_shift_in_W:
+ENTRY(perf_rdr_shift_in_W)
        .proc
        .callinfo frame=0,NO_CALLS
        .entry
@@ -550,6 +549,7 @@ perf_rdr_shift_in_W_leave:
        .exit
        MTDIAG_2        (24)                    ; restore DR2
        .procend
+ENDPROC(perf_rdr_shift_in_W)
 
 
 ;***********************************************************************
@@ -575,8 +575,7 @@ perf_rdr_shift_in_W_leave:
 ;*
 ;***********************************************************************
 
-       .export perf_rdr_shift_out_W,code
-perf_rdr_shift_out_W:
+ENTRY(perf_rdr_shift_out_W)
        .proc
        .callinfo frame=0,NO_CALLS
        .entry
@@ -983,6 +982,7 @@ perf_rdr_shift_out_W_leave:
        .exit
        MTDIAG_2        (23)                    ; restore DR2
        .procend
+ENDPROC(perf_rdr_shift_out_W)
 
 
 ;***********************************************************************
@@ -1012,8 +1012,7 @@ perf_rdr_shift_out_W_leave:
 ;*
 ;***********************************************************************
 
-       .export perf_rdr_shift_in_U,code
-perf_rdr_shift_in_U:
+ENTRY(perf_rdr_shift_in_U)
        .proc
        .callinfo frame=0,NO_CALLS
        .entry
@@ -1343,6 +1342,7 @@ perf_rdr_shift_in_U_leave:
        .exit
        MTDIAG_2        (24)                    ; restore DR2
        .procend
+ENDPROC(perf_rdr_shift_in_U)
 
 ;***********************************************************************
 ;*
@@ -1369,8 +1369,7 @@ perf_rdr_shift_in_U_leave:
 ;*
 ;***********************************************************************
 
-       .export perf_rdr_shift_out_U,code
-perf_rdr_shift_out_U:
+ENTRY(perf_rdr_shift_out_U)
        .proc
        .callinfo frame=0,NO_CALLS
        .entry
@@ -1687,4 +1686,5 @@ perf_rdr_shift_out_U_leave:
        .exit
        MTDIAG_2        (23)                    ; restore DR2
        .procend
+ENDPROC(perf_rdr_shift_out_U)
 
index 2f9f9dfa66f7ba557d2a9158ffae6cfbe13a29dd..0dd3847f494c390f78563ea2c450d7e90cfa918d 100644 (file)
@@ -13,7 +13,7 @@
  *    Copyright (C) 2000 Grant Grundler <grundler with parisc-linux.org>
  *    Copyright (C) 2001 Alan Modra <amodra at parisc-linux.org>
  *    Copyright (C) 2001-2002 Ryan Bradetich <rbrad at parisc-linux.org>
- *    Copyright (C) 2001-2002 Helge Deller <deller at parisc-linux.org>
+ *    Copyright (C) 2001-2007 Helge Deller <deller at parisc-linux.org>
  *    Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
  *
  *
@@ -303,7 +303,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
                 * Copy function and argument to be called from
                 * ret_from_kernel_thread.
                 */
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
                cregs->gr[27] = pregs->gr[27];
 #endif
                cregs->gr[26] = pregs->gr[26];
@@ -355,8 +355,8 @@ asmlinkage int sys_execve(struct pt_regs *regs)
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
-       error = do_execve(filename, (char __user **) regs->gr[25],
-               (char __user **) regs->gr[24], regs);
+       error = do_execve(filename, (char __user * __user *) regs->gr[25],
+               (char __user * __user *) regs->gr[24], regs);
        if (error == 0) {
                task_lock(current);
                current->ptrace &= ~PT_DTRACE;
index fb81e5687e7c8a69c456a816c179cc26840d3239..dd5d0cb6b347365e117aa13575b19d7107ba0324 100644 (file)
@@ -48,6 +48,8 @@ EXPORT_SYMBOL(boot_cpu_data);
 
 struct cpuinfo_parisc cpu_data[NR_CPUS] __read_mostly;
 
+extern int update_cr16_clocksource(void);      /* from time.c */
+
 /*
 **     PARISC CPU driver - claim "device" and initialize CPU data structures.
 **
@@ -93,7 +95,7 @@ static int __init processor_probe(struct parisc_device *dev)
        cpuid = boot_cpu_data.cpu_count;
        txn_addr = dev->hpa.start;      /* for legacy PDC */
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        if (is_pdc_pat()) {
                ulong status;
                unsigned long bytecnt;
@@ -153,8 +155,6 @@ static int __init processor_probe(struct parisc_device *dev)
        p->cpuid = cpuid;       /* save CPU id */
        p->txn_addr = txn_addr; /* save CPU IRQ address */
 #ifdef CONFIG_SMP
-       spin_lock_init(&p->lock);
-
        /*
        ** FIXME: review if any other initialization is clobbered
        **      for boot_cpu by the above memset().
@@ -200,6 +200,12 @@ static int __init processor_probe(struct parisc_device *dev)
        }
 #endif
 
+       /* If we've registered more than one cpu,
+        * we'll use the jiffies clocksource since cr16
+        * is not synchronized between CPUs.
+        */
+       update_cr16_clocksource();
+
        return 0;
 }
 
@@ -311,11 +317,11 @@ int __init init_per_cpu(int cpunum)
        } else {
                printk(KERN_WARNING  "WARNING: No FP CoProcessor?!"
                        " (coproc_cfg.ccr_functional == 0x%lx, expected 0xc0)\n"
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
                        "Halting Machine - FP required\n"
 #endif
                        , coproc_cfg.ccr_functional);
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
                mdelay(100);    /* previous chars get pushed to console */
                panic("FP CoProc not reported");
 #endif
@@ -339,9 +345,6 @@ show_cpuinfo (struct seq_file *m, void *v)
 #ifdef CONFIG_SMP
                if (0 == cpu_data[n].hpa)
                        continue;
-#ifdef ENTRY_SYS_CPUS
-#error iCOD support wants to show CPU state here
-#endif
 #endif
                seq_printf(m, "processor\t: %d\n"
                                "cpu family\t: PA-RISC %s\n",
index 3f28de974556c838894ab5d12f40227d2c39c23e..0d0d617b6f218363794a9683ae93a4dc062ff690 100644 (file)
@@ -36,7 +36,7 @@
 #define DBG(x...)
 #endif
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 
 /* This function is needed to translate 32 bit pt_regs offsets in to
  * 64 bit pt_regs offsets.  For example, a 32 bit gdb under a 64 bit kernel
@@ -90,7 +90,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
        case PTRACE_PEEKDATA: {
                int copied;
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
                if (__is_compat_task(child)) {
                        unsigned int tmp;
 
@@ -122,7 +122,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
        case PTRACE_POKETEXT: /* write the word at location addr. */
        case PTRACE_POKEDATA:
                ret = 0;
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
                if (__is_compat_task(child)) {
                        unsigned int tmp = (unsigned int)data;
                        DBG("sys_ptrace(POKE%s, %d, %lx, %lx)\n",
@@ -145,7 +145,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
           processes, the kernel saves all regs on a syscall. */
        case PTRACE_PEEKUSR: {
                ret = -EIO;
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
                if (__is_compat_task(child)) {
                        unsigned int tmp;
 
@@ -204,7 +204,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                        ret = 0;
                        goto out_tsk;
                }
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
                if (__is_compat_task(child)) {
                        if (addr & (sizeof(int)-1))
                                goto out_tsk;
index 789061f6ceb4827b6b28c1c8fb4fa8355220d1bf..7a92695d95a6bf814a72803da7d02403953eacd4 100644 (file)
@@ -11,6 +11,8 @@
 #include <asm/psw.h>
 #include <asm/assembly.h>
 
+#include <linux/linkage.h>
+
        .section        .bss
        .export real_stack
        .export real32_stack
@@ -39,8 +41,6 @@ save_cr_end:
 
        .text
 
-       .export real32_call_asm
-
        /* unsigned long real32_call_asm(unsigned int *sp,
         *              unsigned int *arg0p,
         *              unsigned int iodc_fn)
@@ -49,7 +49,7 @@ save_cr_end:
         *      iodc_fn is the IODC function to call
         */
 
-real32_call_asm:
+ENTRY(real32_call_asm)
        STREG   %rp, -RP_OFFSET(%sp)    /* save RP */
 #ifdef CONFIG_64BIT
        callee_save
@@ -107,6 +107,7 @@ ric_ret:
        LDREG   -RP_OFFSET(%sp), %rp    /* restore RP */
        bv      0(%rp)
        nop
+ENDPROC(real32_call_asm)
 
 
 #  define PUSH_CR(r, where) mfctl r, %r1 ! STREG,ma %r1, REG_SZ(where)
@@ -218,7 +219,6 @@ rfi_r2v_1:
 /************************ 64-bit real-mode calls ***********************/
 /* This is only usable in wide kernels right now and will probably stay so */
        .text
-       .export real64_call_asm
        /* unsigned long real64_call_asm(unsigned long *sp,
         *              unsigned long *arg0p,
         *              unsigned long fn)
@@ -226,7 +226,7 @@ rfi_r2v_1:
         *      arg0p points to where saved arg values may be found
         *      iodc_fn is the IODC function to call
         */
-real64_call_asm:
+ENTRY(real64_call_asm)
        std     %rp, -0x10(%sp)         /* save RP */
        std     %sp, -8(%arg0)          /* save SP on real-mode stack */
        copy    %arg0, %sp              /* adopt the real-mode SP */
@@ -272,19 +272,21 @@ r64_ret:
        ldd     -0x10(%sp), %rp         /* restore RP */
        bv      0(%rp)
        nop
+ENDPROC(real64_call_asm)
 
 #endif
 
-       .export __canonicalize_funcptr_for_compare
        .text
        /* http://lists.parisc-linux.org/hypermail/parisc-linux/10916.html
        **      GCC 3.3 and later has a new function in libgcc.a for
        **      comparing function pointers.
        */
-__canonicalize_funcptr_for_compare:
+ENTRY(__canonicalize_funcptr_for_compare)
 #ifdef CONFIG_64BIT
        bve (%r2)
 #else
        bv %r0(%r2)
 #endif
        copy %r26,%r28
+ENDPROC(__canonicalize_funcptr_for_compare)
+
index 74b3686dd1e00c253fb7284b7d299051dc2f0ddb..9818919571fd2004cd1e01bcd53a7a56eddd1690 100644 (file)
@@ -45,7 +45,7 @@
 #include <asm/io.h>
 #include <asm/setup.h>
 
-char   __initdata command_line[COMMAND_LINE_SIZE] __read_mostly;
+char   __initdata command_line[COMMAND_LINE_SIZE];
 
 /* Intended for ccio/sba/cpu statistics under /proc/bus/{runway|gsc} */
 struct proc_dir_entry * proc_runway_root __read_mostly = NULL;
@@ -120,13 +120,13 @@ extern void collect_boot_cpu_data(void);
 
 void __init setup_arch(char **cmdline_p)
 {
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        extern int parisc_narrow_firmware;
 #endif
 
        init_per_cpu(smp_processor_id());       /* Set Modes & Enable FP */
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        printk(KERN_INFO "The 64-bit Kernel has started...\n");
 #else
        printk(KERN_INFO "The 32-bit Kernel has started...\n");
@@ -134,7 +134,7 @@ void __init setup_arch(char **cmdline_p)
 
        pdc_console_init();
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        if(parisc_narrow_firmware) {
                printk(KERN_INFO "Kernel is using PDC in 32-bit mode.\n");
        }
index ee6653edeb7a1b83da64572c03d9d0620319558f..9784e405f849ba6d066383ee82e4d7718b85a1e2 100644 (file)
  * this. */
 #define A(__x) ((unsigned long)(__x))
 
-int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall);
-
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 #include "sys32.h"
 #endif
 
-asmlinkage int
-sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
-{
-       sigset_t saveset, newset;
-#ifdef __LP64__
-       compat_sigset_t newset32;
-
-       if (is_compat_task()) {
-               /* XXX: Don't preclude handling different sized sigset_t's.  */
-               if (sigsetsize != sizeof(compat_sigset_t))
-                       return -EINVAL;
-               if (copy_from_user(&newset32, (compat_sigset_t __user *)unewset, sizeof(newset32)))
-                       return -EFAULT;
-               sigset_32to64(&newset,&newset32);
-               
-       } else 
-#endif
-       {
-               /* XXX: Don't preclude handling different sized sigset_t's.  */
-               if (sigsetsize != sizeof(sigset_t))
-                       return -EINVAL;
-       
-               if (copy_from_user(&newset, unewset, sizeof(newset)))
-                       return -EFAULT;
-       }
-
-       sigdelsetmask(&newset, ~_BLOCKABLE);
-
-       spin_lock_irq(&current->sighand->siglock);
-       saveset = current->blocked;
-       current->blocked = newset;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-
-       regs->gr[28] = -EINTR;
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               if (do_signal(&saveset, regs, 1))
-                       return -EINTR;
-       }
-}
-
 /*
  * Do a signal return - restore sigcontext.
  */
@@ -148,7 +103,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
        sigset_t set;
        unsigned long usp = (regs->gr[30] & ~(0x01UL));
        unsigned long sigframe_size = PARISC_RT_SIGFRAME_SIZE;
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        compat_sigset_t compat_set;
        struct compat_rt_sigframe __user * compat_frame;
        
@@ -162,7 +117,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
                (usp - sigframe_size);
        DBG(2,"sys_rt_sigreturn: frame is %p\n", frame);
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        compat_frame = (struct compat_rt_sigframe __user *)frame;
        
        if (is_compat_task()) {
@@ -184,7 +139,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
        spin_unlock_irq(&current->sighand->siglock);
 
        /* Good thing we saved the old gr[30], eh? */
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        if (is_compat_task()) {
                DBG(1,"sys_rt_sigreturn: compat_frame->uc.uc_mcontext 0x%p\n",
                                &compat_frame->uc.uc_mcontext);
@@ -296,7 +251,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        unsigned long rp, usp;
        unsigned long haddr, sigframe_size;
        int err = 0;
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        compat_int_t compat_val;
        struct compat_rt_sigframe __user * compat_frame;
        compat_sigset_t compat_set;
@@ -310,7 +265,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        DBG(1,"setup_rt_frame: frame %p info %p\n", frame, info);
 
        
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 
        compat_frame = (struct compat_rt_sigframe __user *)frame;
        
@@ -390,7 +345,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 
        haddr = A(ka->sa.sa_handler);
        /* The sa_handler may be a pointer to a function descriptor */
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        if (is_compat_task()) {
 #endif
                if (haddr & PA_PLABEL_FDESC) {
@@ -405,7 +360,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                        haddr = fdesc.addr;
                        regs->gr[19] = fdesc.gp;
                }
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        } else {
                Elf64_Fdesc fdesc;
                Elf64_Fdesc __user *ufdesc = (Elf64_Fdesc __user *)A(haddr & ~3);
@@ -425,19 +380,19 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        /* The syscall return path will create IAOQ values from r31.
         */
        sigframe_size = PARISC_RT_SIGFRAME_SIZE;
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        if (is_compat_task())
                sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
 #endif
        if (in_syscall) {
                regs->gr[31] = haddr;
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
                if (!test_thread_flag(TIF_32BIT))
                        sigframe_size |= 1;
 #endif
        } else {
                unsigned long psw = USER_PSW;
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
                if (!test_thread_flag(TIF_32BIT))
                        psw |= PSW_W;
 #endif
@@ -462,7 +417,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        regs->gr[2]  = rp;                /* userland return pointer */
        regs->gr[26] = sig;               /* signal number */
        
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        if (is_compat_task()) {
                regs->gr[25] = A(&compat_frame->info); /* siginfo pointer */
                regs->gr[24] = A(&compat_frame->uc);   /* ucontext pointer */
@@ -516,6 +471,97 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
        return 1;
 }
 
+static inline void
+syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
+{
+       /* Check the return code */
+       switch (regs->gr[28]) {
+       case -ERESTART_RESTARTBLOCK:
+               current_thread_info()->restart_block.fn =
+                       do_no_restart_syscall;
+       case -ERESTARTNOHAND:
+               DBG(1,"ERESTARTNOHAND: returning -EINTR\n");
+               regs->gr[28] = -EINTR;
+               break;
+
+       case -ERESTARTSYS:
+               if (!(ka->sa.sa_flags & SA_RESTART)) {
+                       DBG(1,"ERESTARTSYS: putting -EINTR\n");
+                       regs->gr[28] = -EINTR;
+                       break;
+               }
+               /* fallthrough */
+       case -ERESTARTNOINTR:
+               /* A syscall is just a branch, so all
+                * we have to do is fiddle the return pointer.
+                */
+               regs->gr[31] -= 8; /* delayed branching */
+               /* Preserve original r28. */
+               regs->gr[28] = regs->orig_r28;
+               break;
+       }
+}
+
+static inline void
+insert_restart_trampoline(struct pt_regs *regs)
+{
+       switch(regs->gr[28]) {
+       case -ERESTART_RESTARTBLOCK: {
+               /* Restart the system call - no handlers present */
+               unsigned int *usp = (unsigned int *)regs->gr[30];
+
+               /* Setup a trampoline to restart the syscall
+                * with __NR_restart_syscall
+                *
+                *  0: <return address (orig r31)>
+                *  4: <2nd half for 64-bit>
+                *  8: ldw 0(%sp), %r31
+                * 12: be 0x100(%sr2, %r0)
+                * 16: ldi __NR_restart_syscall, %r20
+                */
+#ifdef CONFIG_64BIT
+               put_user(regs->gr[31] >> 32, &usp[0]);
+               put_user(regs->gr[31] & 0xffffffff, &usp[1]);
+               put_user(0x0fc010df, &usp[2]);
+#else
+               put_user(regs->gr[31], &usp[0]);
+               put_user(0x0fc0109f, &usp[2]);
+#endif
+               put_user(0xe0008200, &usp[3]);
+               put_user(0x34140000, &usp[4]);
+
+               /* Stack is 64-byte aligned, and we only need
+                * to flush 1 cache line.
+                * Flushing one cacheline is cheap.
+                * "sync" on bigger (> 4 way) boxes is not.
+                */
+               flush_icache_range(regs->gr[30], regs->gr[30] + 4);
+
+               regs->gr[31] = regs->gr[30] + 8;
+               /* Preserve original r28. */
+               regs->gr[28] = regs->orig_r28;
+
+               return;
+       }
+       case -ERESTARTNOHAND:
+       case -ERESTARTSYS:
+       case -ERESTARTNOINTR: {
+               /* Hooray for delayed branching.  We don't
+                * have to restore %r20 (the system call
+                * number) because it gets loaded in the delay
+                * slot of the branch external instruction.
+                */
+               regs->gr[31] -= 8;
+               /* Preserve original r28. */
+               regs->gr[28] = regs->orig_r28;
+
+               return;
+       }
+       default:
+               break;
+       }
+}
+
 /*
  * Note that 'init' is a special process: it doesn't get signals it doesn't
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
@@ -527,13 +573,13 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
  * registers).  As noted below, the syscall number gets restored for
  * us due to the magic of delayed branching.
  */
-
-asmlinkage int
-do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
+asmlinkage void
+do_signal(struct pt_regs *regs, long in_syscall)
 {
        siginfo_t info;
        struct k_sigaction ka;
        int signr;
+       sigset_t *oldset;
 
        DBG(1,"\ndo_signal: oldset=0x%p, regs=0x%p, sr7 %#lx, in_syscall=%d\n",
               oldset, regs, regs->sr[7], in_syscall);
@@ -543,7 +589,9 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
           we would be called in that case, but for some reason we
           are. */
 
-       if (!oldset)
+       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+               oldset = &current->saved_sigmask;
+       else
                oldset = &current->blocked;
 
        DBG(1,"do_signal: oldset %08lx / %08lx\n", 
@@ -560,98 +608,41 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
                  break;
                
                /* Restart a system call if necessary. */
-               if (in_syscall) {
-                       /* Check the return code */
-                       switch (regs->gr[28]) {
-                       case -ERESTART_RESTARTBLOCK:
-                               current_thread_info()->restart_block.fn = do_no_restart_syscall;
-                       case -ERESTARTNOHAND:
-                               DBG(1,"ERESTARTNOHAND: returning -EINTR\n");
-                               regs->gr[28] = -EINTR;
-                               break;
-
-                       case -ERESTARTSYS:
-                               if (!(ka.sa.sa_flags & SA_RESTART)) {
-                                       DBG(1,"ERESTARTSYS: putting -EINTR\n");
-                                       regs->gr[28] = -EINTR;
-                                       break;
-                               }
-                       /* fallthrough */
-                       case -ERESTARTNOINTR:
-                               /* A syscall is just a branch, so all
-                                  we have to do is fiddle the return pointer. */
-                               regs->gr[31] -= 8; /* delayed branching */
-                               /* Preserve original r28. */
-                               regs->gr[28] = regs->orig_r28;
-                               break;
-                       }
-               }
+               if (in_syscall)
+                       syscall_restart(regs, &ka);
+
                /* Whee!  Actually deliver the signal.  If the
                   delivery failed, we need to continue to iterate in
                   this loop so we can deliver the SIGSEGV... */
-               if (handle_signal(signr, &info, &ka, oldset, regs, in_syscall)) {
+               if (handle_signal(signr, &info, &ka, oldset,
+                                 regs, in_syscall)) {
                        DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
                                regs->gr[28]);
-                       return 1;
+                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+                               clear_thread_flag(TIF_RESTORE_SIGMASK);
+                       return;
                }
        }
        /* end of while(1) looping forever if we can't force a signal */
 
        /* Did we come from a system call? */
-       if (in_syscall) {
-               /* Restart the system call - no handlers present */
-               if (regs->gr[28] == -ERESTART_RESTARTBLOCK) {
-                       unsigned int *usp = (unsigned int *)regs->gr[30];
-
-                       /* Setup a trampoline to restart the syscall
-                        * with __NR_restart_syscall
-                        *
-                        *  0: <return address (orig r31)>
-                        *  4: <2nd half for 64-bit>
-                        *  8: ldw 0(%sp), %r31
-                        * 12: be 0x100(%sr2, %r0)
-                        * 16: ldi __NR_restart_syscall, %r20
-                        */
-#ifndef __LP64__
-                       put_user(regs->gr[31], &usp[0]);
-                       put_user(0x0fc0109f, &usp[2]);
-#else
-                       put_user(regs->gr[31] >> 32, &usp[0]);
-                       put_user(regs->gr[31] & 0xffffffff, &usp[1]);
-                       put_user(0x0fc010df, &usp[2]);
-#endif
-                       put_user(0xe0008200, &usp[3]);
-                       put_user(0x34140000, &usp[4]);
-
-                       /* Stack is 64-byte aligned, and we only need
-                        * to flush 1 cache line.
-                        * Flushing one cacheline is cheap.
-                        * "sync" on bigger (> 4 way) boxes is not.
-                        */
-                       asm("fdc %%r0(%%sr3, %0)\n"
-                           "sync\n"
-                           "fic %%r0(%%sr3, %0)\n"
-                           "sync\n"
-                           : : "r"(regs->gr[30]));
-
-                       regs->gr[31] = regs->gr[30] + 8;
-                       /* Preserve original r28. */
-                       regs->gr[28] = regs->orig_r28;
-               } else if (regs->gr[28] == -ERESTARTNOHAND ||
-                          regs->gr[28] == -ERESTARTSYS ||
-                          regs->gr[28] == -ERESTARTNOINTR) {
-                       /* Hooray for delayed branching.  We don't
-                           have to restore %r20 (the system call
-                           number) because it gets loaded in the delay
-                           slot of the branch external instruction. */
-                       regs->gr[31] -= 8;
-                       /* Preserve original r28. */
-                       regs->gr[28] = regs->orig_r28;
-               }
-       }
+       if (in_syscall)
+               insert_restart_trampoline(regs);
        
        DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n", 
                regs->gr[28]);
 
-       return 0;
+       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+               clear_thread_flag(TIF_RESTORE_SIGMASK);
+               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+       }
+
+       return;
+}
+
+void do_notify_resume(struct pt_regs *regs, long in_syscall)
+{
+       if (test_thread_flag(TIF_SIGPENDING) ||
+           test_thread_flag(TIF_RESTORE_SIGMASK))
+               do_signal(regs, in_syscall);
 }
index a6b4231cafa10ece6e0595f3e06f144cdc20b0dd..1c1a37f7305332a8d069d51fd572a4de5bc971fa 100644 (file)
@@ -1,6 +1,8 @@
 /*    Signal support for 32-bit kernel builds
  *
  *    Copyright (C) 2001 Matthew Wilcox <willy at parisc-linux.org>
+ *    Copyright (C) 2006 Kyle McMartin <kyle at parisc-linux.org>
+ *
  *    Code was mostly borrowed from kernel/signal.c.
  *    See kernel/signal.c for additional Copyrights.
  *
@@ -401,7 +403,7 @@ setup_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __
 int
 copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from)
 {
-       unsigned long tmp;
+       compat_uptr_t addr;
        int err;
 
        if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
@@ -424,8 +426,8 @@ copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from)
                        err |= __get_user(to->si_uid, &from->si_uid);
                        break;
                      case __SI_FAULT >> 16:
-                       err |= __get_user(tmp, &from->si_addr);
-                       to->si_addr = (void __user *) tmp;
+                       err |= __get_user(addr, &from->si_addr);
+                       to->si_addr = compat_ptr(addr);
                        break;
                      case __SI_POLL >> 16:
                        err |= __get_user(to->si_band, &from->si_band);
@@ -445,7 +447,8 @@ copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from)
 int
 copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from)
 {
-       unsigned int addr;
+       compat_uptr_t addr;
+       compat_int_t val;
        int err;
 
        if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
@@ -474,8 +477,8 @@ copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from)
                        err |= __put_user(from->si_uid, &to->si_uid);
                        break;
                case __SI_FAULT >> 16:
-                       /* avoid type-checking warnings by copying _pad[0] in lieu of si_addr... */
-                       err |= __put_user(from->_sifields._pad[0], &to->si_addr);
+                       addr = ptr_to_compat(from->si_addr);
+                       err |= __put_user(addr, &to->si_addr);
                        break;
                case __SI_POLL >> 16:
                        err |= __put_user(from->si_band, &to->si_band);
@@ -484,17 +487,36 @@ copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from)
                case __SI_TIMER >> 16:
                        err |= __put_user(from->si_tid, &to->si_tid);
                        err |= __put_user(from->si_overrun, &to->si_overrun);
-                       addr = (unsigned long) from->si_ptr;
-                       err |= __put_user(addr, &to->si_ptr);
+                       val = (compat_int_t)from->si_int;
+                       err |= __put_user(val, &to->si_int);
                        break;
                case __SI_RT >> 16:     /* Not generated by the kernel as of now.  */
                case __SI_MESGQ >> 16:
                        err |= __put_user(from->si_uid, &to->si_uid);
                        err |= __put_user(from->si_pid, &to->si_pid);
-                       addr = (unsigned long) from->si_ptr;
-                       err |= __put_user(addr, &to->si_ptr);
+                       val = (compat_int_t)from->si_int;
+                       err |= __put_user(val, &to->si_int);
                        break;
                }
        }
        return err;
 }
+
+asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig,
+       struct compat_siginfo __user *uinfo)
+{
+       siginfo_t info;
+
+       if (copy_siginfo_from_user32(&info, uinfo))
+               return -EFAULT;
+
+       /* Not even root can pretend to send signals from the kernel.
+          Nor can they impersonate a kill(), which adds source info.  */
+       if (info.si_code >= 0)
+               return -EPERM;
+       info.si_signo = sig;
+
+       /* POSIX.1b doesn't mention process groups.  */
+       return kill_proc_info(sig, &info, pid);
+}
+
index 12cc019307adfd5b9fdef180101038954f4ac876..6ba9257fdb7f196587f1198398ee215d394a08fc 100644 (file)
@@ -16,9 +16,6 @@
 **      the Free Software Foundation; either version 2 of the License, or
 **      (at your option) any later version.
 */
-#undef ENTRY_SYS_CPUS  /* syscall support for iCOD-like functionality */
-
-
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <asm/unistd.h>
 #include <asm/cacheflush.h>
 
-#define kDEBUG 0
+#undef DEBUG_SMP
+#ifdef DEBUG_SMP
+static int smp_debug_lvl = 0;
+#define smp_debug(lvl, printargs...)           \
+               if (lvl >= smp_debug_lvl)       \
+                       printk(printargs);
+#else
+#define smp_debug(lvl, ...)
+#endif /* DEBUG_SMP */
 
 DEFINE_SPINLOCK(smp_lock);
 
@@ -76,6 +81,7 @@ cpumask_t cpu_possible_map __read_mostly = CPU_MASK_ALL;      /* Bitmap of Present CP
 EXPORT_SYMBOL(cpu_online_map);
 EXPORT_SYMBOL(cpu_possible_map);
 
+DEFINE_PER_CPU(spinlock_t, ipi_lock) = SPIN_LOCK_UNLOCKED;
 
 struct smp_call_struct {
        void (*func) (void *info);
@@ -107,13 +113,6 @@ enum ipi_message_type {
 static void
 ipi_init(int cpuid)
 {
-
-       /* If CPU is present ... */
-#ifdef ENTRY_SYS_CPUS
-       /* *and* running (not stopped) ... */
-#error iCOD support wants state checked here.
-#endif
-
 #error verify IRQ_OFFSET(IPI_IRQ) is ipi_interrupt() in new IRQ region
 
        if(cpu_online(cpuid) )
@@ -133,23 +132,12 @@ ipi_init(int cpuid)
 static void
 halt_processor(void) 
 {
-#ifdef ENTRY_SYS_CPUS
-#error halt_processor() needs rework
-/*
-** o migrate I/O interrupts off this CPU.
-** o leave IPI enabled - __cli() will disable IPI.
-** o leave CPU in online map - just change the state
-*/
-       cpu_data[this_cpu].state = STATE_STOPPED;
-       mark_bh(IPI_BH);
-#else
        /* REVISIT : redirect I/O Interrupts to another CPU? */
        /* REVISIT : does PM *know* this CPU isn't available? */
        cpu_clear(smp_processor_id(), cpu_online_map);
        local_irq_disable();
        for (;;)
                ;
-#endif
 }
 
 
@@ -167,10 +155,11 @@ ipi_interrupt(int irq, void *dev_id)
        mb();   /* Order interrupt and bit testing. */
 
        for (;;) {
-               spin_lock_irqsave(&(p->lock),flags);
+               spinlock_t *lock = &per_cpu(ipi_lock, this_cpu);
+               spin_lock_irqsave(lock, flags);
                ops = p->pending_ipi;
                p->pending_ipi = 0;
-               spin_unlock_irqrestore(&(p->lock),flags);
+               spin_unlock_irqrestore(lock, flags);
 
                mb(); /* Order bit clearing and data access. */
 
@@ -184,15 +173,11 @@ ipi_interrupt(int irq, void *dev_id)
 
                        switch (which) {
                        case IPI_NOP:
-#if (kDEBUG>=100)
-                               printk(KERN_DEBUG "CPU%d IPI_NOP\n",this_cpu);
-#endif /* kDEBUG */
+                               smp_debug(100, KERN_DEBUG "CPU%d IPI_NOP\n", this_cpu);
                                break;
                                
                        case IPI_RESCHEDULE:
-#if (kDEBUG>=100)
-                               printk(KERN_DEBUG "CPU%d IPI_RESCHEDULE\n",this_cpu);
-#endif /* kDEBUG */
+                               smp_debug(100, KERN_DEBUG "CPU%d IPI_RESCHEDULE\n", this_cpu);
                                /*
                                 * Reschedule callback.  Everything to be
                                 * done is done by the interrupt return path.
@@ -200,9 +185,7 @@ ipi_interrupt(int irq, void *dev_id)
                                break;
 
                        case IPI_CALL_FUNC:
-#if (kDEBUG>=100)
-                               printk(KERN_DEBUG "CPU%d IPI_CALL_FUNC\n",this_cpu);
-#endif /* kDEBUG */
+                               smp_debug(100, KERN_DEBUG "CPU%d IPI_CALL_FUNC\n", this_cpu);
                                {
                                        volatile struct smp_call_struct *data;
                                        void (*func)(void *info);
@@ -233,28 +216,16 @@ ipi_interrupt(int irq, void *dev_id)
                                break;
 
                        case IPI_CPU_START:
-#if (kDEBUG>=100)
-                               printk(KERN_DEBUG "CPU%d IPI_CPU_START\n",this_cpu);
-#endif /* kDEBUG */
-#ifdef ENTRY_SYS_CPUS
-                               p->state = STATE_RUNNING;
-#endif
+                               smp_debug(100, KERN_DEBUG "CPU%d IPI_CPU_START\n", this_cpu);
                                break;
 
                        case IPI_CPU_STOP:
-#if (kDEBUG>=100)
-                               printk(KERN_DEBUG "CPU%d IPI_CPU_STOP\n",this_cpu);
-#endif /* kDEBUG */
-#ifdef ENTRY_SYS_CPUS
-#else
+                               smp_debug(100, KERN_DEBUG "CPU%d IPI_CPU_STOP\n", this_cpu);
                                halt_processor();
-#endif
                                break;
 
                        case IPI_CPU_TEST:
-#if (kDEBUG>=100)
-                               printk(KERN_DEBUG "CPU%d is alive!\n",this_cpu);
-#endif /* kDEBUG */
+                               smp_debug(100, KERN_DEBUG "CPU%d is alive!\n", this_cpu);
                                break;
 
                        default:
@@ -275,12 +246,13 @@ static inline void
 ipi_send(int cpu, enum ipi_message_type op)
 {
        struct cpuinfo_parisc *p = &cpu_data[cpu];
+       spinlock_t *lock = &per_cpu(ipi_lock, cpu);
        unsigned long flags;
 
-       spin_lock_irqsave(&(p->lock),flags);
+       spin_lock_irqsave(lock, flags);
        p->pending_ipi |= 1 << op;
        gsc_writel(IPI_IRQ - CPU_IRQ_BASE, cpu_data[cpu].hpa);
-       spin_unlock_irqrestore(&(p->lock),flags);
+       spin_unlock_irqrestore(lock, flags);
 }
 
 
@@ -560,13 +532,8 @@ int __init smp_boot_one_cpu(int cpuid)
 
 alive:
        /* Remember the Slave data */
-#if (kDEBUG>=100)
-       printk(KERN_DEBUG "SMP: CPU:%d came alive after %ld _us\n",
+       smp_debug(100, KERN_DEBUG "SMP: CPU:%d came alive after %ld _us\n",
                cpuid, timeout * 100);
-#endif /* kDEBUG */
-#ifdef ENTRY_SYS_CPUS
-       cpu_data[cpuid].state = STATE_RUNNING;
-#endif
        return 0;
 }
 
@@ -574,10 +541,6 @@ void __devinit smp_prepare_boot_cpu(void)
 {
        int bootstrap_processor=cpu_data[0].cpuid;      /* CPU ID of BSP */
 
-#ifdef ENTRY_SYS_CPUS
-       cpu_data[0].state = STATE_RUNNING;
-#endif
-
        /* Setup BSP mappings */
        printk("SMP: bootstrap CPU ID is %d\n",bootstrap_processor);
 
@@ -616,101 +579,6 @@ int __cpuinit __cpu_up(unsigned int cpu)
        return cpu_online(cpu) ? 0 : -ENOSYS;
 }
 
-
-
-#ifdef ENTRY_SYS_CPUS
-/* Code goes along with:
-**    entry.s:        ENTRY_NAME(sys_cpus)   / * 215, for cpu stat * /
-*/
-int sys_cpus(int argc, char **argv)
-{
-       int i,j=0;
-       extern int current_pid(int cpu);
-
-       if( argc > 2 ) {
-               printk("sys_cpus:Only one argument supported\n");
-               return (-1);
-       }
-       if ( argc == 1 ){
-       
-#ifdef DUMP_MORE_STATE
-               for_each_online_cpu(i) {
-                       int cpus_per_line = 4;
-
-                       if (j++ % cpus_per_line)
-                               printk(" %3d",i);
-                       else
-                               printk("\n %3d",i);
-               }
-               printk("\n"); 
-#else
-               printk("\n 0\n"); 
-#endif
-       } else if((argc==2) && !(strcmp(argv[1],"-l"))) {
-               printk("\nCPUSTATE  TASK CPUNUM CPUID HARDCPU(HPA)\n");
-#ifdef DUMP_MORE_STATE
-               for_each_online_cpu(i) {
-                       if (cpu_data[i].cpuid != NO_PROC_ID) {
-                               switch(cpu_data[i].state) {
-                                       case STATE_RENDEZVOUS:
-                                               printk("RENDEZVS ");
-                                               break;
-                                       case STATE_RUNNING:
-                                               printk((current_pid(i)!=0) ? "RUNNING  " : "IDLING   ");
-                                               break;
-                                       case STATE_STOPPED:
-                                               printk("STOPPED  ");
-                                               break;
-                                       case STATE_HALTED:
-                                               printk("HALTED   ");
-                                               break;
-                                       default:
-                                               printk("%08x?", cpu_data[i].state);
-                                               break;
-                               }
-                               if(cpu_online(i)) {
-                                       printk(" %4d",current_pid(i));
-                               }       
-                               printk(" %6d",cpu_number_map(i));
-                               printk(" %5d",i);
-                               printk(" 0x%lx\n",cpu_data[i].hpa);
-                       }       
-               }
-#else
-               printk("\n%s  %4d      0     0 --------",
-                       (current->pid)?"RUNNING ": "IDLING  ",current->pid); 
-#endif
-       } else if ((argc==2) && !(strcmp(argv[1],"-s"))) { 
-#ifdef DUMP_MORE_STATE
-               printk("\nCPUSTATE   CPUID\n");
-               for_each_online_cpu(i) {
-                       if (cpu_data[i].cpuid != NO_PROC_ID) {
-                               switch(cpu_data[i].state) {
-                                       case STATE_RENDEZVOUS:
-                                               printk("RENDEZVS");break;
-                                       case STATE_RUNNING:
-                                               printk((current_pid(i)!=0) ? "RUNNING " : "IDLING");
-                                               break;
-                                       case STATE_STOPPED:
-                                               printk("STOPPED ");break;
-                                       case STATE_HALTED:
-                                               printk("HALTED  ");break;
-                                       default:
-                               }
-                               printk("  %5d\n",i);
-                       }       
-               }
-#else
-               printk("\n%s    CPU0",(current->pid==0)?"RUNNING ":"IDLING  "); 
-#endif
-       } else {
-               printk("sys_cpus:Unknown request\n");
-               return (-1);
-       }
-       return 0;
-}
-#endif /* ENTRY_SYS_CPUS */
-
 #ifdef CONFIG_PROC_FS
 int __init
 setup_profiling_timer(unsigned int multiplier)
index a05800429304983d9c3b26dea81c5deb65cccb4d..10859f53e94f363799ddd2fe504e511585af6a32 100644 (file)
 #include <asm/errno.h>
 #include <asm/psw.h>
 #include <asm/thread_info.h>
-
 #include <asm/assembly.h>
 #include <asm/processor.h>
 
+#include <linux/linkage.h>
+
        /* We fill the empty parts of the gateway page with
         * something that will kill the kernel or a
         * userspace application.
         */
 #define KILL_INSN      break   0,0
 
-#ifdef CONFIG_64BIT
-       .level          2.0w
-#else
-       .level          1.1
-#endif
+       .level          LEVEL
 
        .text
 
        .import syscall_exit,code
        .import syscall_exit_rfi,code
-       .export linux_gateway_page
 
        /* Linux gateway page is aliased to virtual page 0 in the kernel
         * address space. Since it is a gateway page it cannot be
@@ -43,7 +39,7 @@
         */
 
        .align ASM_PAGE_SIZE
-linux_gateway_page:
+ENTRY(linux_gateway_page)
 
         /* ADDRESS 0x00 to 0xb0 = 176 bytes / 4 bytes per insn = 44 insns */
        .rept 44
@@ -595,73 +591,43 @@ cas_action:
           the other for the store. Either return -EFAULT.
           Each of the entries must be relocated. */
        .section __ex_table,"aw"
-#ifdef CONFIG_64BIT
-       /* Pad the address calculation */
-       .word   0,(2b - linux_gateway_page)
-       .word   0,(3b - linux_gateway_page)
-#else
-       .word   (2b - linux_gateway_page)
-       .word   (3b - linux_gateway_page)
-#endif
+       ASM_ULONG_INSN (1b - linux_gateway_page), (3b - linux_gateway_page)
+       ASM_ULONG_INSN (2b - linux_gateway_page), (3b - linux_gateway_page)
        .previous
 
-       .section __ex_table,"aw"
-#ifdef CONFIG_64BIT
-       /* Pad the address calculation */
-       .word   0,(1b - linux_gateway_page)
-       .word   0,(3b - linux_gateway_page)
-#else
-       .word   (1b - linux_gateway_page)
-       .word   (3b - linux_gateway_page)
-#endif
-       .previous
-
-end_compare_and_swap:
 
        /* Make sure nothing else is placed on this page */
        .align ASM_PAGE_SIZE
-       .export end_linux_gateway_page
-end_linux_gateway_page:
+END(linux_gateway_page)
+ENTRY(end_linux_gateway_page)
 
        /* Relocate symbols assuming linux_gateway_page is mapped
           to virtual address 0x0 */
-#ifdef CONFIG_64BIT
-       /* FIXME: The code will always be on the gateay page
-                 and thus it will be on the first 4k, the
-                 assembler seems to think that the final
-                 subtraction result is only a word in
-                 length, so we pad the value.
-       */
-#define LWS_ENTRY(_name_) .word 0,(lws_##_name_ - linux_gateway_page)
-#else
-#define LWS_ENTRY(_name_) .word  (lws_##_name_ - linux_gateway_page)
-#endif
+
+#define LWS_ENTRY(_name_) ASM_ULONG_INSN (lws_##_name_ - linux_gateway_page)
 
        .section .rodata,"a"
 
        .align ASM_PAGE_SIZE
        /* Light-weight-syscall table */
        /* Start of lws table. */
-       .export lws_table
-.Llws_table:
-lws_table:
+ENTRY(lws_table)
        LWS_ENTRY(compare_and_swap32)   /* 0 - ELF32 Atomic compare and swap */
        LWS_ENTRY(compare_and_swap64)   /* 1 - ELF64 Atomic compare and swap */
+END(lws_table)
        /* End of lws table */
 
        .align ASM_PAGE_SIZE
-       .export sys_call_table
-.Lsys_call_table:
-sys_call_table:
+ENTRY(sys_call_table)
 #include "syscall_table.S"
+END(sys_call_table)
 
 #ifdef CONFIG_64BIT
        .align ASM_PAGE_SIZE
-       .export sys_call_table64
-.Lsys_call_table64:
-sys_call_table64:
+ENTRY(sys_call_table64)
 #define SYSCALL_TABLE_64BIT
 #include "syscall_table.S"
+END(sys_call_table64)
 #endif
 
 #ifdef CONFIG_SMP
@@ -671,9 +637,7 @@ sys_call_table64:
        */
        .section .data
        .align 4096
-       .export lws_lock_start
-.Llws_lock_start:
-lws_lock_start:
+ENTRY(lws_lock_start)
        /* lws locks */
        .align 16
        .rept 16
@@ -683,6 +647,7 @@ lws_lock_start:
        .word 0
        .word 0
        .endr
+END(lws_lock_start)
        .previous
 #endif
 /* CONFIG_SMP for lws_lock_start */
index be8eb9a0d24a7420879fc819b776870b01b21b21..8bf87e5d9c376ec6c187c8e444d377cad1484748 100644 (file)
@@ -10,7 +10,7 @@
  *    Copyright (C) 2000 Grant Grundler <grundler at parisc-linux.org>
  *    Copyright (C) 2001 Richard Hirst <rhirst with parisc-linux.org>
  *    Copyright (C) 2001-2002 Ryan Bradetich <rbrad at parisc-linux.org>
- *    Copyright (C) 2001 Helge Deller <deller at parisc-linux.org>
+ *    Copyright (C) 2001-2007 Helge Deller <deller at parisc-linux.org>
  *    Copyright (C) 2000-2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org>
  *    Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
  *    Copyright (C) 2005-2006 Kyle McMartin <kyle at parisc-linux.org>
         * to worry about faulting trying to copy in a larger 64-bit
         * struct from a 32-bit user-space app.
         */
-       ENTRY_SAME(rt_sigqueueinfo)
-       ENTRY_SAME(rt_sigsuspend_wrapper) /* not really SAME -- see the code */
+       ENTRY_COMP(rt_sigqueueinfo)
+       ENTRY_COMP(rt_sigsuspend)
        ENTRY_SAME(chown)               /* 180 */
        /* setsockopt() used by iptables: SO_SET_REPLACE/SO_SET_ADD_COUNTERS */
        ENTRY_COMP(setsockopt)
        ENTRY_SAME(inotify_init)
        ENTRY_SAME(inotify_add_watch)   /* 270 */
        ENTRY_SAME(inotify_rm_watch)
-       ENTRY_SAME(ni_syscall)          /* 271 ENTRY_COMP(pselect6) */
-       ENTRY_SAME(ni_syscall)          /* 272 ENTRY_COMP(ppoll) */
        ENTRY_SAME(migrate_pages)
+       ENTRY_COMP(pselect6)
+       ENTRY_COMP(ppoll)
        ENTRY_COMP(openat)              /* 275 */
        ENTRY_SAME(mkdirat)
        ENTRY_SAME(mknodat)
        ENTRY_SAME(splice)
        ENTRY_OURS(sync_file_range)
        ENTRY_SAME(tee)
+       ENTRY_COMP(vmsplice)
+       ENTRY_COMP(move_pages)          /* 295 */
+       ENTRY_SAME(getcpu)
+       ENTRY_SAME(epoll_pwait)
+       ENTRY_COMP(statfs64)
+       ENTRY_COMP(fstatfs64)
        /* Nothing yet */
 
index 5f1b51af06a9820ff54e57479c50543eacb0799f..07a991aa9b0c2ba6f81aa8f937c3d0039f4cf92a 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <linux/profile.h>
+#include <linux/clocksource.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -98,7 +99,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)
         * cycles after the IT fires. But it's arbitrary how much time passes
         * before we call it "late". I've picked one second.
         */
-       if (ticks_elapsed > HZ) {
+       if (unlikely(ticks_elapsed > HZ)) {
                /* Scenario 3: very long delay?  bad in any case */
                printk (KERN_CRIT "timer_interrupt(CPU %d): delayed!"
                        " cycles %lX rem %lX "
@@ -147,10 +148,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)
                write_sequnlock(&xtime_lock);
        }
 
-       /* check soft power switch status */
-       if (cpu == 0 && !atomic_read(&power_tasklet.count))
-               tasklet_schedule(&power_tasklet);
-
        return IRQ_HANDLED;
 }
 
@@ -172,121 +169,43 @@ unsigned long profile_pc(struct pt_regs *regs)
 EXPORT_SYMBOL(profile_pc);
 
 
-/*
- * Return the number of micro-seconds that elapsed since the last
- * update to wall time (aka xtime).  The xtime_lock
- * must be at least read-locked when calling this routine.
- */
-static inline unsigned long gettimeoffset (void)
-{
-#ifndef CONFIG_SMP
-       /*
-        * FIXME: This won't work on smp because jiffies are updated by cpu 0.
-        *    Once parisc-linux learns the cr16 difference between processors,
-        *    this could be made to work.
-        */
-       unsigned long now;
-       unsigned long prev_tick;
-       unsigned long next_tick;
-       unsigned long elapsed_cycles;
-       unsigned long usec;
-       unsigned long cpuid = smp_processor_id();
-       unsigned long cpt = clocktick;
-
-       next_tick = cpu_data[cpuid].it_value;
-       now = mfctl(16);        /* Read the hardware interval timer.  */
-
-       prev_tick = next_tick - cpt;
-
-       /* Assume Scenario 1: "now" is later than prev_tick.  */
-       elapsed_cycles = now - prev_tick;
-
-/* aproximate HZ with shifts. Intended math is "(elapsed/clocktick) > HZ" */
-#if HZ == 1000
-       if (elapsed_cycles > (cpt << 10) )
-#elif HZ == 250
-       if (elapsed_cycles > (cpt << 8) )
-#elif HZ == 100
-       if (elapsed_cycles > (cpt << 7) )
-#else
-#warn WTF is HZ set to anyway?
-       if (elapsed_cycles > (HZ * cpt) )
-#endif
-       {
-               /* Scenario 3: clock ticks are missing. */
-               printk (KERN_CRIT "gettimeoffset(CPU %ld): missing %ld ticks!"
-                       " cycles %lX prev/now/next %lX/%lX/%lX  clock %lX\n",
-                       cpuid, elapsed_cycles / cpt,
-                       elapsed_cycles, prev_tick, now, next_tick, cpt);
-       }
-
-       /* FIXME: Can we improve the precision? Not with PAGE0. */
-       usec = (elapsed_cycles * 10000) / PAGE0->mem_10msec;
-       return usec;
-#else
-       return 0;
-#endif
-}
+/* clock source code */
 
-void
-do_gettimeofday (struct timeval *tv)
+static cycle_t read_cr16(void)
 {
-       unsigned long flags, seq, usec, sec;
-
-       /* Hold xtime_lock and adjust timeval.  */
-       do {
-               seq = read_seqbegin_irqsave(&xtime_lock, flags);
-               usec = gettimeoffset();
-               sec = xtime.tv_sec;
-               usec += (xtime.tv_nsec / 1000);
-       } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
-
-       /* Move adjusted usec's into sec's.  */
-       while (usec >= USEC_PER_SEC) {
-               usec -= USEC_PER_SEC;
-               ++sec;
-       }
-
-       /* Return adjusted result.  */
-       tv->tv_sec = sec;
-       tv->tv_usec = usec;
+       return get_cycles();
 }
 
-EXPORT_SYMBOL(do_gettimeofday);
+static struct clocksource clocksource_cr16 = {
+       .name                   = "cr16",
+       .rating                 = 300,
+       .read                   = read_cr16,
+       .mask                   = CLOCKSOURCE_MASK(BITS_PER_LONG),
+       .mult                   = 0, /* to be set */
+       .shift                  = 22,
+       .flags                  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
 
-int
-do_settimeofday (struct timespec *tv)
+#ifdef CONFIG_SMP
+int update_cr16_clocksource(void)
 {
-       time_t wtm_sec, sec = tv->tv_sec;
-       long wtm_nsec, nsec = tv->tv_nsec;
-
-       if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
-               return -EINVAL;
-
-       write_seqlock_irq(&xtime_lock);
-       {
-               /*
-                * This is revolting. We need to set "xtime"
-                * correctly. However, the value in this location is
-                * the value at the most recent update of wall time.
-                * Discover what correction gettimeofday would have
-                * done, and then undo it!
-                */
-               nsec -= gettimeoffset() * 1000;
+       int change = 0;
 
-               wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
-               wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
-
-               set_normalized_timespec(&xtime, sec, nsec);
-               set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
-               ntp_clear();
+       /* since the cr16 cycle counters are not syncronized across CPUs,
+          we'll check if we should switch to a safe clocksource: */
+       if (clocksource_cr16.rating != 0 && num_online_cpus() > 1) {
+               clocksource_change_rating(&clocksource_cr16, 0);
+               change = 1;
        }
-       write_sequnlock_irq(&xtime_lock);
-       clock_was_set();
-       return 0;
+
+       return change;
 }
-EXPORT_SYMBOL(do_settimeofday);
+#else
+int update_cr16_clocksource(void)
+{
+       return 0; /* no change */
+}
+#endif /*CONFIG_SMP*/
 
 void __init start_cpu_itimer(void)
 {
@@ -301,11 +220,18 @@ void __init start_cpu_itimer(void)
 void __init time_init(void)
 {
        static struct pdc_tod tod_data;
+       unsigned long current_cr16_khz;
 
        clocktick = (100 * PAGE0->mem_10msec) / HZ;
 
        start_cpu_itimer();     /* get CPU 0 started */
 
+       /* register at clocksource framework */
+       current_cr16_khz = PAGE0->mem_10msec/10;  /* kHz */
+       clocksource_cr16.mult = clocksource_khz2mult(current_cr16_khz,
+                                               clocksource_cr16.shift);
+       clocksource_register(&clocksource_cr16);
+
        if (pdc_tod_read(&tod_data) == 0) {
                unsigned long flags;
 
index 65cd6ca32fed57b689f8a2dec3449dd620e3f098..55bc1471967d2221badf806b78aada441760f0c7 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/interrupt.h>
 #include <linux/console.h>
 #include <linux/kallsyms.h>
+#include <linux/bug.h>
 
 #include <asm/assembly.h>
 #include <asm/system.h>
@@ -39,6 +40,8 @@
 #include <asm/pdc.h>
 #include <asm/pdc_chassis.h>
 #include <asm/unwind.h>
+#include <asm/tlbflush.h>
+#include <asm/cacheflush.h>
 
 #include "../math-emu/math-emu.h"      /* for handle_fpe() */
 
@@ -49,7 +52,7 @@
 DEFINE_SPINLOCK(pa_dbit_lock);
 #endif
 
-int printbinary(char *buf, unsigned long x, int nbits)
+static int printbinary(char *buf, unsigned long x, int nbits)
 {
        unsigned long mask = 1UL << (nbits - 1);
        while (mask != 0) {
@@ -61,7 +64,7 @@ int printbinary(char *buf, unsigned long x, int nbits)
        return nbits;
 }
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 #define RFMT "%016lx"
 #else
 #define RFMT "%08lx"
@@ -160,13 +163,13 @@ static void do_show_stack(struct unwind_frame_info *info)
 {
        int i = 1;
 
-       printk("Backtrace:\n");
+       printk(KERN_CRIT "Backtrace:\n");
        while (i <= 16) {
                if (unwind_once(info) < 0 || info->ip == 0)
                        break;
 
                if (__kernel_text_address(info->ip)) {
-                       printk(" [<" RFMT ">] ", info->ip);
+                       printk("%s [<" RFMT ">] ", (i&0x3)==1 ? KERN_CRIT : "", info->ip);
 #ifdef CONFIG_KALLSYMS
                        print_symbol("%s\n", info->ip);
 #else
@@ -185,18 +188,19 @@ void show_stack(struct task_struct *task, unsigned long *s)
 
        if (!task) {
                unsigned long sp;
-               struct pt_regs *r;
 
 HERE:
                asm volatile ("copy %%r30, %0" : "=r"(sp));
-               r = kzalloc(sizeof(struct pt_regs), GFP_KERNEL);
-               if (!r)
-                       return;
-               r->iaoq[0] = (unsigned long)&&HERE;
-               r->gr[2] = (unsigned long)__builtin_return_address(0);
-               r->gr[30] = sp;
-               unwind_frame_init(&info, current, r);
-               kfree(r);
+               {
+                       struct pt_regs r;
+
+                       memset(&r, 0, sizeof(struct pt_regs));
+                       r.iaoq[0] = (unsigned long)&&HERE;
+                       r.gr[2] = (unsigned long)__builtin_return_address(0);
+                       r.gr[30] = sp;
+
+                       unwind_frame_init(&info, current, &r);
+               }
        } else {
                unwind_frame_init_from_blocked_task(&info, task);
        }
@@ -204,6 +208,11 @@ HERE:
        do_show_stack(&info);
 }
 
+int is_valid_bugaddr(unsigned long iaoq)
+{
+       return 1;
+}
+
 void die_if_kernel(char *str, struct pt_regs *regs, long err)
 {
        if (user_mode(regs)) {
@@ -222,15 +231,15 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)
        oops_in_progress = 1;
 
        /* Amuse the user in a SPARC fashion */
-       printk(
-"      _______________________________ \n"
-"     < Your System ate a SPARC! Gah! >\n"
-"      ------------------------------- \n"
-"             \\   ^__^\n"
-"              \\  (xx)\\_______\n"
-"                 (__)\\       )\\/\\\n"
-"                  U  ||----w |\n"
-"                     ||     ||\n");
+       if (err) printk(
+KERN_CRIT "      _______________________________ \n"
+KERN_CRIT "     < Your System ate a SPARC! Gah! >\n"
+KERN_CRIT "      ------------------------------- \n"
+KERN_CRIT "             \\   ^__^\n"
+KERN_CRIT "              \\  (xx)\\_______\n"
+KERN_CRIT "                 (__)\\       )\\/\\\n"
+KERN_CRIT "                  U  ||----w |\n"
+KERN_CRIT "                     ||     ||\n");
        
        /* unlock the pdc lock if necessary */
        pdc_emergency_unlock();
@@ -242,9 +251,20 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)
        if (!console_drivers)
                pdc_console_restart();
        
-       printk(KERN_CRIT "%s (pid %d): %s (code %ld)\n",
-               current->comm, current->pid, str, err);
+       if (err)
+               printk(KERN_CRIT "%s (pid %d): %s (code %ld)\n",
+                       current->comm, current->pid, str, err);
+
+       /* Wot's wrong wif bein' racy? */
+       if (current->thread.flags & PARISC_KERNEL_DEATH) {
+               printk(KERN_CRIT "%s() recursion detected.\n", __FUNCTION__);
+               local_irq_enable();
+               while (1);
+       }
+       current->thread.flags |= PARISC_KERNEL_DEATH;
+
        show_regs(regs);
+       dump_stack();
 
        if (in_interrupt())
                panic("Fatal exception in interrupt");
@@ -255,14 +275,6 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)
                panic("Fatal exception");
        }
 
-       /* Wot's wrong wif bein' racy? */
-       if (current->thread.flags & PARISC_KERNEL_DEATH) {
-               printk(KERN_CRIT "%s() recursion detected.\n", __FUNCTION__);
-               local_irq_enable();
-               while (1);
-       }
-
-       current->thread.flags |= PARISC_KERNEL_DEATH;
        do_exit(SIGSEGV);
 }
 
@@ -273,61 +285,45 @@ int syscall_ipi(int (*syscall) (struct pt_regs *), struct pt_regs *regs)
 
 /* gdb uses break 4,8 */
 #define GDB_BREAK_INSN 0x10004
-void handle_gdb_break(struct pt_regs *regs, int wot)
+static void handle_gdb_break(struct pt_regs *regs, int wot)
 {
        struct siginfo si;
 
-       si.si_code = wot;
-       si.si_addr = (void __user *) (regs->iaoq[0] & ~3);
        si.si_signo = SIGTRAP;
        si.si_errno = 0;
+       si.si_code = wot;
+       si.si_addr = (void __user *) (regs->iaoq[0] & ~3);
        force_sig_info(SIGTRAP, &si, current);
 }
 
-void handle_break(unsigned iir, struct pt_regs *regs)
+static void handle_break(struct pt_regs *regs)
 {
-       struct siginfo si;
-
-       switch(iir) {
-       case 0x00:
-#ifdef PRINT_USER_FAULTS
-               printk(KERN_DEBUG "break 0,0: pid=%d command='%s'\n",
-                      current->pid, current->comm);
-#endif
-               die_if_kernel("Breakpoint", regs, 0);
-#ifdef PRINT_USER_FAULTS
-               show_regs(regs);
-#endif
-               si.si_code = TRAP_BRKPT;
-               si.si_addr = (void __user *) (regs->iaoq[0] & ~3);
-               si.si_signo = SIGTRAP;
-               force_sig_info(SIGTRAP, &si, current);
-               break;
-
-       case GDB_BREAK_INSN:
-               die_if_kernel("Breakpoint", regs, 0);
-               handle_gdb_break(regs, TRAP_BRKPT);
-               break;
+       unsigned iir = regs->iir;
+
+       if (unlikely(iir == PARISC_BUG_BREAK_INSN && !user_mode(regs))) {
+               /* check if a BUG() or WARN() trapped here.  */
+               enum bug_trap_type tt;
+               tt = report_bug(regs->iaoq[0] & ~3);
+               if (tt == BUG_TRAP_TYPE_WARN) {
+                       regs->iaoq[0] += 4;
+                       regs->iaoq[1] += 4;
+                       return; /* return to next instruction when WARN_ON().  */
+               }
+               die_if_kernel("Unknown kernel breakpoint", regs,
+                       (tt == BUG_TRAP_TYPE_NONE) ? 9 : 0);
+       }
 
-       default:
 #ifdef PRINT_USER_FAULTS
-               printk(KERN_DEBUG "break %#08x: pid=%d command='%s'\n",
-                      iir, current->pid, current->comm);
+       if (unlikely(iir != GDB_BREAK_INSN)) {
+               printk(KERN_DEBUG "break %d,%d: pid=%d command='%s'\n",
+                       iir & 31, (iir>>13) & ((1<<13)-1),
+                       current->pid, current->comm);
                show_regs(regs);
-#endif
-               si.si_signo = SIGTRAP;
-               si.si_code = TRAP_BRKPT;
-               si.si_addr = (void __user *) (regs->iaoq[0] & ~3);
-               force_sig_info(SIGTRAP, &si, current);
-               return;
        }
-}
-
+#endif
 
-int handle_toc(void)
-{
-       printk(KERN_CRIT "TOC call.\n");
-       return 0;
+       /* send standard GDB signal */
+       handle_gdb_break(regs, TRAP_BRKPT);
 }
 
 static void default_trap(int code, struct pt_regs *regs)
@@ -336,7 +332,7 @@ static void default_trap(int code, struct pt_regs *regs)
        show_regs(regs);
 }
 
-void (*cpu_lpmc) (int code, struct pt_regs *regs) = default_trap;
+void (*cpu_lpmc) (int code, struct pt_regs *regs) __read_mostly = default_trap;
 
 
 void transfer_pim_to_trap_frame(struct pt_regs *regs)
@@ -554,7 +550,8 @@ void handle_interruption(int code, struct pt_regs *regs)
                /* Low-priority machine check */
                pdc_chassis_send_status(PDC_CHASSIS_DIRECT_LPMC);
                
-               flush_all_caches();
+               flush_cache_all();
+               flush_tlb_all();
                cpu_lpmc(5, regs);
                return;
 
@@ -572,7 +569,7 @@ void handle_interruption(int code, struct pt_regs *regs)
 
        case  9:
                /* Break instruction trap */
-               handle_break(regs->iir,regs);
+               handle_break(regs);
                return;
        
        case 10:
@@ -840,7 +837,7 @@ int __init check_ivt(void *iva)
        return 0;
 }
        
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
 extern const void fault_vector_11;
 #endif
 extern const void fault_vector_20;
@@ -852,7 +849,7 @@ void __init trap_init(void)
        if (boot_cpu_data.cpu_type >= pcxu)
                iva = (void *) &fault_vector_20;
        else
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
                panic("Can't boot 64-bit OS on PA1.1 processor!");
 #else
                iva = (void *) &fault_vector_11;
index bd2230d6a2a69645352eb4b1c8c71b7a4115b5a5..347bb922e6d077f717799dd2c642804dbe0f23dd 100644 (file)
  *
  */
 
+#include <linux/jiffies.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
 #include <asm/uaccess.h>
 
 /* #define DEBUG_UNALIGNED 1 */
@@ -32,7 +35,7 @@
 #define DPRINTF(fmt, args...)
 #endif
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 #define RFMT "%016lx"
 #else
 #define RFMT "%08lx"
@@ -147,15 +150,8 @@ static int emulate_ldh(struct pt_regs *regs, int toreg)
 "4:    ldi     -2, %1\n"
        FIXUP_BRANCH(3b)
 "      .previous\n"
-"      .section __ex_table,\"aw\"\n"
-#ifdef __LP64__
-"      .dword  1b,4b\n"
-"      .dword  2b,4b\n"
-#else
-"      .word   1b,4b\n"
-"      .word   2b,4b\n"
-#endif
-"      .previous\n"
+       ASM_EXCEPTIONTABLE_ENTRY(1b, 4b)
+       ASM_EXCEPTIONTABLE_ENTRY(2b, 4b)
        : "=r" (val), "=r" (ret)
        : "0" (val), "r" (saddr), "r" (regs->isr)
        : "r20", FIXUP_BRANCH_CLOBBER );
@@ -192,15 +188,8 @@ static int emulate_ldw(struct pt_regs *regs, int toreg, int flop)
 "4:    ldi     -2, %1\n"
        FIXUP_BRANCH(3b)
 "      .previous\n"
-"      .section __ex_table,\"aw\"\n"
-#ifdef __LP64__
-"      .dword  1b,4b\n"
-"      .dword  2b,4b\n"
-#else
-"      .word   1b,4b\n"
-"      .word   2b,4b\n"
-#endif
-"      .previous\n"
+       ASM_EXCEPTIONTABLE_ENTRY(1b, 4b)
+       ASM_EXCEPTIONTABLE_ENTRY(2b, 4b)
        : "=r" (val), "=r" (ret)
        : "0" (val), "r" (saddr), "r" (regs->isr)
        : "r19", "r20", FIXUP_BRANCH_CLOBBER );
@@ -224,7 +213,7 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
                regs->isr, regs->ior, toreg);
 #ifdef CONFIG_PA20
 
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
        if (!flop)
                return -1;
 #endif
@@ -243,15 +232,8 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
 "4:    ldi     -2, %1\n"
        FIXUP_BRANCH(3b)
 "      .previous\n"
-"      .section __ex_table,\"aw\"\n"
-#ifdef __LP64__
-"      .dword  1b,4b\n"
-"      .dword  2b,4b\n"
-#else
-"      .word   1b,4b\n"
-"      .word   2b,4b\n"
-#endif
-"      .previous\n"
+       ASM_EXCEPTIONTABLE_ENTRY(1b,4b)
+       ASM_EXCEPTIONTABLE_ENTRY(2b,4b)
        : "=r" (val), "=r" (ret)
        : "0" (val), "r" (saddr), "r" (regs->isr)
        : "r19", "r20", FIXUP_BRANCH_CLOBBER );
@@ -275,17 +257,9 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
 "5:    ldi     -2, %2\n"
        FIXUP_BRANCH(4b)
 "      .previous\n"
-"      .section __ex_table,\"aw\"\n"
-#ifdef __LP64__
-"      .dword  1b,5b\n"
-"      .dword  2b,5b\n"
-"      .dword  3b,5b\n"
-#else
-"      .word   1b,5b\n"
-"      .word   2b,5b\n"
-"      .word   3b,5b\n"
-#endif
-"      .previous\n"
+       ASM_EXCEPTIONTABLE_ENTRY(1b,5b)
+       ASM_EXCEPTIONTABLE_ENTRY(2b,5b)
+       ASM_EXCEPTIONTABLE_ENTRY(3b,5b)
        : "=r" (valh), "=r" (vall), "=r" (ret)
        : "0" (valh), "1" (vall), "r" (saddr), "r" (regs->isr)
        : "r19", "r20", FIXUP_BRANCH_CLOBBER );
@@ -325,15 +299,8 @@ static int emulate_sth(struct pt_regs *regs, int frreg)
 "4:    ldi     -2, %0\n"
        FIXUP_BRANCH(3b)
 "      .previous\n"
-"      .section __ex_table,\"aw\"\n"
-#ifdef __LP64__
-"      .dword  1b,4b\n"
-"      .dword  2b,4b\n"
-#else
-"      .word   1b,4b\n"
-"      .word   2b,4b\n"
-#endif
-"      .previous\n"
+       ASM_EXCEPTIONTABLE_ENTRY(1b,4b)
+       ASM_EXCEPTIONTABLE_ENTRY(2b,4b)
        : "=r" (ret)
        : "r" (val), "r" (regs->ior), "r" (regs->isr)
        : "r19", FIXUP_BRANCH_CLOBBER );
@@ -379,15 +346,8 @@ static int emulate_stw(struct pt_regs *regs, int frreg, int flop)
 "4:    ldi     -2, %0\n"
        FIXUP_BRANCH(3b)
 "      .previous\n"
-"      .section __ex_table,\"aw\"\n"
-#ifdef __LP64__
-"      .dword  1b,4b\n"
-"      .dword  2b,4b\n"
-#else
-"      .word   1b,4b\n"
-"      .word   2b,4b\n"
-#endif
-"      .previous\n"
+       ASM_EXCEPTIONTABLE_ENTRY(1b,4b)
+       ASM_EXCEPTIONTABLE_ENTRY(2b,4b)
        : "=r" (ret)
        : "r" (val), "r" (regs->ior), "r" (regs->isr)
        : "r19", "r20", "r21", "r22", "r1", FIXUP_BRANCH_CLOBBER );
@@ -410,7 +370,7 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop)
                val,  regs->isr, regs->ior);
 
 #ifdef CONFIG_PA20
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
        if (!flop)
                return -1;
 #endif
@@ -436,19 +396,10 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop)
 "6:    ldi     -2, %0\n"
        FIXUP_BRANCH(5b)
 "      .previous\n"
-"      .section __ex_table,\"aw\"\n"
-#ifdef __LP64__
-"      .dword  1b,6b\n"
-"      .dword  2b,6b\n"
-"      .dword  3b,6b\n"
-"      .dword  4b,6b\n"
-#else
-"      .word   1b,6b\n"
-"      .word   2b,6b\n"
-"      .word   3b,6b\n"
-"      .word   4b,6b\n"
-#endif
-"      .previous\n"
+       ASM_EXCEPTIONTABLE_ENTRY(1b,6b)
+       ASM_EXCEPTIONTABLE_ENTRY(2b,6b)
+       ASM_EXCEPTIONTABLE_ENTRY(3b,6b)
+       ASM_EXCEPTIONTABLE_ENTRY(4b,6b)
        : "=r" (ret)
        : "r" (val), "r" (regs->ior), "r" (regs->isr)
        : "r19", "r20", "r21", "r22", "r1", FIXUP_BRANCH_CLOBBER );
@@ -479,21 +430,11 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop)
 "7:    ldi     -2, %0\n"
        FIXUP_BRANCH(6b)
 "      .previous\n"
-"      .section __ex_table,\"aw\"\n"
-#ifdef __LP64__
-"      .dword  1b,7b\n"
-"      .dword  2b,7b\n"
-"      .dword  3b,7b\n"
-"      .dword  4b,7b\n"
-"      .dword  5b,7b\n"
-#else
-"      .word   1b,7b\n"
-"      .word   2b,7b\n"
-"      .word   3b,7b\n"
-"      .word   4b,7b\n"
-"      .word   5b,7b\n"
-#endif
-"      .previous\n"
+       ASM_EXCEPTIONTABLE_ENTRY(1b,7b)
+       ASM_EXCEPTIONTABLE_ENTRY(2b,7b)
+       ASM_EXCEPTIONTABLE_ENTRY(3b,7b)
+       ASM_EXCEPTIONTABLE_ENTRY(4b,7b)
+       ASM_EXCEPTIONTABLE_ENTRY(5b,7b)
        : "=r" (ret)
        : "r" (valh), "r" (vall), "r" (regs->ior), "r" (regs->isr)
        : "r19", "r20", "r21", "r1", FIXUP_BRANCH_CLOBBER );
index c10ab47d81fabc434f1e938194ee5a4fe92c523c..5f75b3e65986d8b9f96a7830f92fd23bde79dffd 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/kallsyms.h>
 
index 3b78c2794c369e72bfe57d2bdd461fc8754b0d63..2a8253358c6ccc6686a9a255d171c6fa3f59e229 100644 (file)
@@ -68,6 +68,8 @@ SECTIONS
 
   RODATA
 
+  BUG_TABLE
+
   /* writeable */
   . = ALIGN(ASM_PAGE_SIZE);    /* Make sure this is page aligned so
                                   that we can properly leave these
index f352666b5b2f401d096c8c53e876d5ac1c4188e6..e3eb739fab19d3eb20c6d3ae2a837abb860ed7db 100644 (file)
@@ -17,7 +17,7 @@ raw_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = {
 };
 #endif
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 unsigned long __xchg64(unsigned long x, unsigned long *ptr)
 {
        unsigned long temp, flags;
@@ -56,7 +56,7 @@ unsigned long __xchg8(char x, char *ptr)
 }
 
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 unsigned long __cmpxchg_u64(volatile unsigned long *ptr, unsigned long old, unsigned long new)
 {
        unsigned long flags;
index ecce3d35401ff87c5f0e35103fd47e3f73799c6f..d172d4245cdcfc54eabdb3758eb4ad487e8b8cf7 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/assembly.h>
 #include <asm/errno.h>
+#include <linux/linkage.h>
 
 #ifdef CONFIG_SMP
        .macro  get_fault_ip t1 t2
@@ -30,7 +31,7 @@
        /* t2 = smp_processor_id() */
        mfctl 30,\t2
        ldw TI_CPU(\t2),\t2
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        extrd,u \t2,63,32,\t2
 #endif
        /* t2 = &__per_cpu_offset[smp_processor_id()]; */
        .section .fixup, "ax"
 
        /* get_user() fixups, store -EFAULT in r8, and 0 in r9 */
-       .export fixup_get_user_skip_1
-fixup_get_user_skip_1:
+ENTRY(fixup_get_user_skip_1)
        get_fault_ip %r1,%r8
        ldo 4(%r1), %r1
        ldi -EFAULT, %r8
        bv %r0(%r1)
        copy %r0, %r9
+ENDPROC(fixup_get_user_skip_1)
 
-       .export fixup_get_user_skip_2
-fixup_get_user_skip_2:
+ENTRY(fixup_get_user_skip_2)
        get_fault_ip %r1,%r8
        ldo 8(%r1), %r1
        ldi -EFAULT, %r8
        bv %r0(%r1)
        copy %r0, %r9
+ENDPROC(fixup_get_user_skip_2)
 
        /* put_user() fixups, store -EFAULT in r8 */
-       .export fixup_put_user_skip_1
-fixup_put_user_skip_1:
+ENTRY(fixup_put_user_skip_1)
        get_fault_ip %r1,%r8
        ldo 4(%r1), %r1
        bv %r0(%r1)
        ldi -EFAULT, %r8
+ENDPROC(fixup_put_user_skip_1)
 
-       .export fixup_put_user_skip_2
-fixup_put_user_skip_2:
+ENTRY(fixup_put_user_skip_2)
        get_fault_ip %r1,%r8
        ldo 8(%r1), %r1
        bv %r0(%r1)
        ldi -EFAULT, %r8
+ENDPROC(fixup_put_user_skip_2)
+
index a0509855c9a73ca30b952082c1728d3113fb7ccc..1bd23ccec17b9a53fb838fdfdf5eb9ab62ccf739 100644 (file)
@@ -37,6 +37,7 @@
        
 #include <asm/assembly.h>
 #include <asm/errno.h>
+#include <linux/linkage.h>
 
        /*
         * get_sr gets the appropriate space value into
@@ -67,8 +68,7 @@
         *         otherwise strlen (i.e. excludes zero byte)
         */
 
-       .export lstrncpy_from_user,code
-lstrncpy_from_user:
+ENTRY(lstrncpy_from_user)
        .proc
        .callinfo NO_CALLS
        .entry
@@ -87,6 +87,7 @@ $lsfu_exit:
        bv          %r0(%r2)
        nop
        .exit
+ENDPROC(lstrncpy_from_user)
 
        .section .fixup,"ax"
 3:      fixup_branch $lsfu_exit
@@ -94,13 +95,8 @@ $lsfu_exit:
        .previous
 
        .section __ex_table,"aw"
-#ifdef __LP64__
-       .dword      1b,3b
-       .dword      2b,3b
-#else
-       .word       1b,3b
-       .word       2b,3b
-#endif
+       ASM_ULONG_INSN 1b,3b
+       ASM_ULONG_INSN 2b,3b
        .previous
 
        .procend
@@ -112,8 +108,7 @@ $lsfu_exit:
         * otherwise, returns number of bytes not transferred.
         */
 
-       .export lclear_user,code
-lclear_user:
+ENTRY(lclear_user)
        .proc
        .callinfo NO_CALLS
        .entry
@@ -127,6 +122,7 @@ $lclu_done:
        bv          %r0(%r2)
        copy        %r25,%r28
        .exit
+ENDPROC(lclear_user)
 
        .section .fixup,"ax"
 2:      fixup_branch $lclu_done
@@ -134,11 +130,7 @@ $lclu_done:
        .previous
 
        .section __ex_table,"aw"
-#ifdef __LP64__
-       .dword      1b,2b
-#else
-       .word       1b,2b
-#endif
+       ASM_ULONG_INSN 1b,2b
        .previous
 
        .procend
@@ -151,8 +143,7 @@ $lclu_done:
         *         else strlen + 1 (i.e. includes zero byte).
         */
 
-       .export lstrnlen_user,code
-lstrnlen_user:
+ENTRY(lstrnlen_user)
        .proc
        .callinfo NO_CALLS
        .entry
@@ -172,6 +163,7 @@ $lslen_done:
 $lslen_nzero:
        b           $lslen_done
        ldo         1(%r26),%r26 /* special case for N == 0 */
+ENDPROC(lstrnlen_user)
 
        .section .fixup,"ax"
 3:      fixup_branch $lslen_done
@@ -179,13 +171,8 @@ $lslen_nzero:
        .previous
 
        .section __ex_table,"aw"
-#ifdef __LP64__
-       .dword      1b,3b
-       .dword      2b,3b
-#else
-       .word       1b,3b
-       .word       2b,3b
-#endif
+       ASM_ULONG_INSN 1b,3b
+       ASM_ULONG_INSN 2b,3b
        .previous
 
        .procend
index 5575e41f9d605b0687d681934f14b763a9218061..2c43ebe99a9ce6492f53026f3530a07ebc657df1 100644 (file)
@@ -96,30 +96,18 @@ DECLARE_PER_CPU(struct exception_data, exception_data);
 #define DPRINTF(fmt, args...)
 #endif
 
-#ifndef __LP64__
-#define EXC_WORD ".word"
-#else
-#define EXC_WORD ".dword"
-#endif
-
 #define def_load_ai_insn(_insn,_sz,_tt,_s,_a,_t,_e)    \
        __asm__ __volatile__ (                          \
-       "1:\t" #_insn ",ma " #_sz "(" _s ",%1), %0\n"   \
-       "\t.section __ex_table,\"aw\"\n"                \
-       "\t" EXC_WORD "\t1b\n"                          \
-       "\t" EXC_WORD "\t" #_e "\n"                     \
-       "\t.previous\n"                                 \
+       "1:\t" #_insn ",ma " #_sz "(" _s ",%1), %0\n\t" \
+       ASM_EXCEPTIONTABLE_ENTRY(1b,_e)                 \
        : _tt(_t), "+r"(_a)                             \
        :                                               \
        : "r8")
 
 #define def_store_ai_insn(_insn,_sz,_tt,_s,_a,_t,_e)   \
        __asm__ __volatile__ (                          \
-       "1:\t" #_insn ",ma %1, " #_sz "(" _s ",%0)\n"   \
-       "\t.section __ex_table,\"aw\"\n"                \
-       "\t" EXC_WORD "\t1b\n"                          \
-       "\t" EXC_WORD "\t" #_e "\n"                     \
-       "\t.previous\n"                                 \
+       "1:\t" #_insn ",ma %1, " #_sz "(" _s ",%0)\n\t" \
+       ASM_EXCEPTIONTABLE_ENTRY(1b,_e)                 \
        : "+r"(_a)                                      \
        : _tt(_t)                                       \
        : "r8")
@@ -133,22 +121,16 @@ DECLARE_PER_CPU(struct exception_data, exception_data);
 
 #define def_load_insn(_insn,_tt,_s,_o,_a,_t,_e)        \
        __asm__ __volatile__ (                          \
-       "1:\t" #_insn " " #_o "(" _s ",%1), %0\n"       \
-       "\t.section __ex_table,\"aw\"\n"                \
-       "\t" EXC_WORD "\t1b\n"                          \
-       "\t" EXC_WORD "\t" #_e "\n"                     \
-       "\t.previous\n"                                 \
+       "1:\t" #_insn " " #_o "(" _s ",%1), %0\n\t"     \
+       ASM_EXCEPTIONTABLE_ENTRY(1b,_e)                 \
        : _tt(_t)                                       \
        : "r"(_a)                                       \
        : "r8")
 
 #define def_store_insn(_insn,_tt,_s,_t,_o,_a,_e)       \
        __asm__ __volatile__ (                          \
-       "1:\t" #_insn " %0, " #_o "(" _s ",%1)\n"       \
-       "\t.section __ex_table,\"aw\"\n"                \
-       "\t" EXC_WORD "\t1b\n"                          \
-       "\t" EXC_WORD "\t" #_e "\n"                     \
-       "\t.previous\n"                                 \
+       "1:\t" #_insn " %0, " #_o "(" _s ",%1)\n\t"     \
+       ASM_EXCEPTIONTABLE_ENTRY(1b,_e)                 \
        :                                               \
        : _tt(_t), "r"(_a)                              \
        : "r8")
@@ -167,8 +149,8 @@ extern inline void prefetch_dst(const void *addr)
        __asm__("ldd 0(" d_space ",%0), %%r0" : : "r" (addr));
 }
 #else
-#define prefetch_src(addr)
-#define prefetch_dst(addr)
+#define prefetch_src(addr) do { } while(0)
+#define prefetch_dst(addr) do { } while(0)
 #endif
 
 /* Copy from a not-aligned src to an aligned dst, using shifts. Handles 4 words
index 641f9c920eeef58e0e627467db3b6bf2c06b731a..f6f67554c6235d4aceb5c51d2c3b5c0a82051d1b 100644 (file)
                         /*  dumped to the console via printk)          */
 
 
-/* Defines for parisc_acctyp() */
-#define READ           0
-#define WRITE          1
-
 /* Various important other fields */
 #define bit22set(x)            (x & 0x00000200)
 #define bits23_25set(x)                (x & 0x000001c0)
index 12117db0043bdd0d52740bc0c42e04d3af9cb496..75ea9f2a8a41653fa8e0d31df87e924d3abc0b18 100644 (file)
@@ -6,7 +6,7 @@
  *    changed by Philipp Rumpf
  *  Copyright 1999 Philipp Rumpf (prumpf@tux.org)
  *  Copyright 2004 Randolph Chung (tausq@debian.org)
- *  Copyright 2006 Helge Deller (deller@gmx.de)
+ *  Copyright 2006-2007 Helge Deller (deller@gmx.de)
  *
  */
 
@@ -24,6 +24,7 @@
 #include <linux/pagemap.h>     /* for release_pages and page_cache_release */
 
 #include <asm/pgalloc.h>
+#include <asm/pgtable.h>
 #include <asm/tlb.h>
 #include <asm/pdc_chassis.h>
 #include <asm/mmzone.h>
@@ -65,11 +66,11 @@ static struct resource sysram_resources[MAX_PHYSMEM_RANGES] __read_mostly;
 physmem_range_t pmem_ranges[MAX_PHYSMEM_RANGES] __read_mostly;
 int npmem_ranges __read_mostly;
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 #define MAX_MEM         (~0UL)
-#else /* !__LP64__ */
+#else /* !CONFIG_64BIT */
 #define MAX_MEM         (3584U*1024U*1024U)
-#endif /* !__LP64__ */
+#endif /* !CONFIG_64BIT */
 
 static unsigned long mem_limit __read_mostly = MAX_MEM;
 
@@ -452,6 +453,8 @@ unsigned long pcxl_dma_start __read_mostly;
 
 void __init mem_init(void)
 {
+       int codesize, reservedpages, datasize, initsize;
+
        high_memory = __va((max_pfn << PAGE_SHIFT));
 
 #ifndef CONFIG_DISCONTIGMEM
@@ -466,7 +469,32 @@ void __init mem_init(void)
        }
 #endif
 
-       printk(KERN_INFO "Memory: %luk available\n", num_physpages << (PAGE_SHIFT-10));
+       codesize = (unsigned long)_etext - (unsigned long)_text;
+       datasize = (unsigned long)_edata - (unsigned long)_etext;
+       initsize = (unsigned long)__init_end - (unsigned long)__init_begin;
+
+       reservedpages = 0;
+{
+       unsigned long pfn;
+#ifdef CONFIG_DISCONTIGMEM
+       int i;
+
+       for (i = 0; i < npmem_ranges; i++) {
+               for (pfn = node_start_pfn(i); pfn < node_end_pfn(i); pfn++) {
+                       if (PageReserved(pfn_to_page(pfn)))
+                               reservedpages++;
+               }
+       }
+#else /* !CONFIG_DISCONTIGMEM */
+       for (pfn = 0; pfn < max_pfn; pfn++) {
+               /*
+                * Only count reserved RAM pages
+                */
+               if (PageReserved(pfn_to_page(pfn)))
+                       reservedpages++;
+       }
+#endif
+}
 
 #ifdef CONFIG_PA11
        if (hppa_dma_ops == &pcxl_dma_ops) {
@@ -480,6 +508,38 @@ void __init mem_init(void)
        vmalloc_start = SET_MAP_OFFSET(MAP_START);
 #endif
 
+       printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n",
+               (unsigned long)nr_free_pages() << (PAGE_SHIFT-10),
+               num_physpages << (PAGE_SHIFT-10),
+               codesize >> 10,
+               reservedpages << (PAGE_SHIFT-10),
+               datasize >> 10,
+               initsize >> 10
+       );
+
+#ifdef CONFIG_DEBUG_KERNEL /* double-sanity-check paranoia */
+       printk("virtual kernel memory layout:\n"
+              "    vmalloc : 0x%p - 0x%p   (%4ld MB)\n"
+              "    memory  : 0x%p - 0x%p   (%4ld MB)\n"
+              "      .init : 0x%p - 0x%p   (%4ld kB)\n"
+              "      .data : 0x%p - 0x%p   (%4ld kB)\n"
+              "      .text : 0x%p - 0x%p   (%4ld kB)\n",
+
+              (void*)VMALLOC_START, (void*)VMALLOC_END,
+              (VMALLOC_END - VMALLOC_START) >> 20,
+
+              __va(0), high_memory,
+              ((unsigned long)high_memory - (unsigned long)__va(0)) >> 20,
+
+              __init_begin, __init_end,
+              ((unsigned long)__init_end - (unsigned long)__init_begin) >> 10,
+
+              _etext, _edata,
+              ((unsigned long)_edata - (unsigned long)_etext) >> 10,
+
+              _text, _etext,
+              ((unsigned long)_etext - (unsigned long)_text) >> 10);
+#endif
 }
 
 unsigned long *empty_zero_page __read_mostly;
@@ -547,7 +607,7 @@ void show_mem(void)
 
                                printk("Zone list for zone %d on node %d: ", j, i);
                                for (k = 0; zl->zones[k] != NULL; k++) 
-                                       printk("[%d/%s] ", zone_to_nid(zl->zones[k]), zl->zones[k]->name);
+                                       printk("[%ld/%s] ", zone_to_nid(zl->zones[k]), zl->zones[k]->name);
                                printk("\n");
                        }
                }
index 44b42c7f639d073b0339396a8ecd8d4c908f7340..92d496ad07c97b9be730f8799bf96f7c5a538d3b 100644 (file)
@@ -26,7 +26,7 @@
  */
 void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
 {
-       void *addr;
+       void __iomem *addr;
        struct vm_struct *area;
        unsigned long offset, last_addr;
        pgprot_t pgprot;
@@ -80,14 +80,14 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
        if (!area)
                return NULL;
 
-       addr = area->addr;
+       addr = (void __iomem *) area->addr;
        if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
                               phys_addr, pgprot)) {
                vfree(addr);
                return NULL;
        }
 
-       return (void __iomem *) (offset + (char *)addr);
+       return (void __iomem *) (offset + (char __iomem *)addr);
 }
 EXPORT_SYMBOL(__ioremap);
 
diff --git a/arch/parisc/mm/kmap.c b/arch/parisc/mm/kmap.c
deleted file mode 100644 (file)
index 1b1acd5..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-/* 
- *    kmap/page table map and unmap support routines
- *
- *    Copyright 1999,2000 Hewlett-Packard Company
- *    Copyright 2000 John Marvin <jsm at hp.com>
- *    Copyright 2000 Grant Grundler <grundler at parisc-linux.org>
- *    Copyright 2000 Philipp Rumpf <prumpf@tux.org>
- *
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-/*
-** Stolen mostly from arch/parisc/kernel/pci-dma.c
-*/
-
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgalloc.h>
-
-#include <asm/io.h>
-#include <asm/page.h>          /* get_order */
-
-#undef flush_cache_all
-#define flush_cache_all flush_all_caches
-
-typedef void (*pte_iterator_t) (pte_t * pte, unsigned long arg);
-
-#if 0
-/* XXX This routine could be used with iterate_page() to replace
- * unmap_uncached_page() and save a little code space but I didn't
- * do that since I'm not certain whether this is the right path. -PB
- */
-static void unmap_cached_pte(pte_t * pte, unsigned long addr, unsigned long arg)
-{
-       pte_t page = *pte;
-       pte_clear(&init_mm, addr, pte);
-       if (!pte_none(page)) {
-               if (pte_present(page)) {
-                       unsigned long map_nr = pte_pagenr(page);
-                       if (map_nr < max_mapnr)
-                               __free_page(mem_map + map_nr);
-               } else {
-                       printk(KERN_CRIT
-                              "Whee.. Swapped out page in kernel page table\n");
-               }
-       }
-}
-#endif
-
-/* These two routines should probably check a few things... */
-static void set_uncached(pte_t * pte, unsigned long arg)
-{
-       pte_val(*pte) |= _PAGE_NO_CACHE;
-}
-
-static void set_cached(pte_t * pte, unsigned long arg)
-{
-       pte_val(*pte) &= ~_PAGE_NO_CACHE;
-}
-
-static inline void iterate_pte(pmd_t * pmd, unsigned long address,
-                              unsigned long size, pte_iterator_t op,
-                              unsigned long arg)
-{
-       pte_t *pte;
-       unsigned long end;
-
-       if (pmd_none(*pmd))
-               return;
-       if (pmd_bad(*pmd)) {
-               pmd_ERROR(*pmd);
-               pmd_clear(pmd);
-               return;
-       }
-       pte = pte_offset(pmd, address);
-       address &= ~PMD_MASK;
-       end = address + size;
-       if (end > PMD_SIZE)
-               end = PMD_SIZE;
-       do {
-               op(pte, arg);
-               address += PAGE_SIZE;
-               pte++;
-       } while (address < end);
-}
-
-static inline void iterate_pmd(pgd_t * dir, unsigned long address,
-                              unsigned long size, pte_iterator_t op,
-                              unsigned long arg)
-{
-       pmd_t *pmd;
-       unsigned long end;
-
-       if (pgd_none(*dir))
-               return;
-       if (pgd_bad(*dir)) {
-               pgd_ERROR(*dir);
-               pgd_clear(dir);
-               return;
-       }
-       pmd = pmd_offset(dir, address);
-       address &= ~PGDIR_MASK;
-       end = address + size;
-       if (end > PGDIR_SIZE)
-               end = PGDIR_SIZE;
-       do {
-               iterate_pte(pmd, address, end - address, op, arg);
-               address = (address + PMD_SIZE) & PMD_MASK;
-               pmd++;
-       } while (address < end);
-}
-
-static void iterate_pages(unsigned long address, unsigned long size,
-                         pte_iterator_t op, unsigned long arg)
-{
-       pgd_t *dir;
-       unsigned long end = address + size;
-
-       dir = pgd_offset_k(address);
-       flush_cache_all();
-       do {
-               iterate_pmd(dir, address, end - address, op, arg);
-               address = (address + PGDIR_SIZE) & PGDIR_MASK;
-               dir++;
-       } while (address && (address < end));
-       flush_tlb_all();
-}
-
-void
-kernel_set_cachemode(unsigned long vaddr, unsigned long size, int what)
-{
-       switch (what) {
-       case IOMAP_FULL_CACHING:
-               iterate_pages(vaddr, size, set_cached, 0);
-               flush_tlb_range(NULL, vaddr, size);
-               break;
-       case IOMAP_NOCACHE_SER:
-               iterate_pages(vaddr, size, set_uncached, 0);
-               flush_tlb_range(NULL, vaddr, size);
-               break;
-       default:
-               printk(KERN_CRIT
-                      "kernel_set_cachemode mode %d not understood\n",
-                      what);
-               break;
-       }
-}
index a5b898c4d0b02bc0b2b3417f51361d2050353d10..113f5139f5518e778f35f765180b28985dc6373a 100644 (file)
@@ -18,6 +18,6 @@ int __init oprofile_arch_init(struct oprofile_operations * ops)
 }
 
 
-void oprofile_arch_exit()
+void oprofile_arch_exit(void)
 {
 }
index 7ec4ac77c0fa0ee0eb24f92977d0b7740261a56b..e4006dc087ca3133b02639ea01b299d540bf56a3 100644 (file)
@@ -225,6 +225,22 @@ static struct cpu_spec cpu_specs[] = {
                .oprofile_type          = PPC_OPROFILE_POWER4,
                .platform               = "ppc970",
        },
+       {       /* PPC970MP DD1.0 - no DEEPNAP, use regular 970 init */
+               .pvr_mask               = 0xffffffff,
+               .pvr_value              = 0x00440100,
+               .cpu_name               = "PPC970MP",
+               .cpu_features           = CPU_FTRS_PPC970,
+               .cpu_user_features      = COMMON_USER_POWER4 |
+                       PPC_FEATURE_HAS_ALTIVEC_COMP,
+               .icache_bsize           = 128,
+               .dcache_bsize           = 128,
+               .num_pmcs               = 8,
+               .cpu_setup              = __setup_cpu_ppc970,
+               .cpu_restore            = __restore_cpu_ppc970,
+               .oprofile_cpu_type      = "ppc64/970MP",
+               .oprofile_type          = PPC_OPROFILE_POWER4,
+               .platform               = "ppc970",
+       },
        {       /* PPC970MP */
                .pvr_mask               = 0xffff0000,
                .pvr_value              = 0x00440000,
index 919fbf5684950f3b46073b301e8ec5b47814076c..1009308268505753fa506eba009aac6d5b92735a 100644 (file)
@@ -968,7 +968,6 @@ void pci_scan_msi_device(struct pci_dev *dev) {}
 int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) {return -1;}
 void pci_disable_msix(struct pci_dev *dev) {}
 void msi_remove_pci_irq_vectors(struct pci_dev *dev) {}
-void disable_msi_mode(struct pci_dev *dev, int pos, int type) {}
 void pci_no_msi(void) {}
 EXPORT_SYMBOL(pci_enable_msix);
 EXPORT_SYMBOL(pci_disable_msix);
index ea6fd552c7eaf8023114958e093a172e2c2b3015..91b443c9a48857239b35428a85fe86e8953f5f8d 100644 (file)
@@ -916,7 +916,7 @@ EXPORT_SYMBOL_GPL(of_irq_map_raw);
 static int of_irq_map_oldworld(struct device_node *device, int index,
                               struct of_irq *out_irq)
 {
-       const u32 *ints;
+       const u32 *ints = NULL;
        int intlen;
 
        /*
index dcc6f159fd945070050ece10f77f64df90b70edb..17724fb2067f4a2195f4e30548b62362f2c0bfd4 100644 (file)
@@ -107,12 +107,10 @@ int die(const char *str, struct pt_regs *regs, long err)
        if (machine_is(powermac) && pmac_backlight) {
                struct backlight_properties *props;
 
-               down(&pmac_backlight->sem);
-               props = pmac_backlight->props;
+               props = &pmac_backlight->props;
                props->brightness = props->max_brightness;
                props->power = FB_BLANK_UNBLANK;
-               props->update_status(pmac_backlight);
-               up(&pmac_backlight->sem);
+               backlight_update_status(pmac_backlight);
        }
        mutex_unlock(&pmac_backlight_mutex);
 #endif
index e5d819166874641f39d44e64d8c95dc56d2e8121..8aa9a93e2aa2c78a30c8920bd58c78e93799a7db 100644 (file)
@@ -55,9 +55,9 @@ static int mpc834x_usb_cfg(void)
        struct device_node *np = NULL;
        int port0_is_dr = 0;
 
-       if ((np = of_find_compatible_node(np, "usb", "fsl-usb2-dr")) != NULL)
+       if ((np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr")) != NULL)
                port0_is_dr = 1;
-       if ((np = of_find_compatible_node(np, "usb", "fsl-usb2-mph")) != NULL){
+       if ((np = of_find_compatible_node(NULL, "usb", "fsl-usb2-mph")) != NULL){
                if (port0_is_dr) {
                        printk(KERN_WARNING
                                "There is only one USB port on PB board! \n");
@@ -103,8 +103,8 @@ static int mpc834x_usb_cfg(void)
                return -1;
 
        /*
-        * if MDS board is plug into PIB board,
-        * force to use the PHY on MDS board
+        * if Processor Board is plugged into PIB board,
+        * force to use the PHY on Processor Board
         */
        bcsr5 = in_8(bcsr_regs + 5);
        if (!(bcsr5 & BCSR5_INT_USB))
index eb661ccf2dab6f80098ed485671863c5d2c66090..e764c0aced88ae6b3d7a752a6766dc6a6ef362c8 100644 (file)
@@ -47,6 +47,7 @@ config MPC85xx
        bool
        select PPC_UDBG_16550
        select PPC_INDIRECT_PCI
+       select SERIAL_8250_SHARE_IRQ if SERIAL_8250
        default y if MPC8540_ADS || MPC85xx_CDS || MPC8560_ADS || MPC85xx_MDS
 
 config PPC_INDIRECT_PCI_BE
index c11b39c3776a5565848a4e3c8d723cb314316579..fb23d53eb09c53cce17482905f95169c266de9b0 100644 (file)
 
 #define iob()  __asm__ __volatile__("eieio; sync":::"memory")
 
+static inline volatile void __iomem *celleb_epci_get_epci_base(
+                                       struct pci_controller *hose)
+{
+       /*
+        * Note:
+        * Celleb epci uses cfg_addr as a base address for
+        * epci control registers.
+        */
+
+       return hose->cfg_addr;
+}
+
+static inline volatile void __iomem *celleb_epci_get_epci_cfg(
+                                       struct pci_controller *hose)
+{
+       /*
+        * Note:
+        * Celleb epci uses cfg_data as a base address for
+        * configuration area for epci devices.
+        */
+
+       return hose->cfg_data;
+}
 
 #if 0 /* test code for epci dummy read */
 static void celleb_epci_dummy_read(struct pci_dev *dev)
 {
-       void __iomem *epci_base;
+       volatile void __iomem *epci_base;
        struct device_node *node;
        struct pci_controller *hose;
        u32 val;
@@ -58,7 +81,7 @@ static void celleb_epci_dummy_read(struct pci_dev *dev)
        if (!hose)
                return;
 
-       epci_base = hose->cfg_addr;
+       epci_base = celleb_epci_get_epci_base(hose);
 
        val = in_be32(epci_base + SCC_EPCI_WATRP);
        iosync();
@@ -70,19 +93,20 @@ static void celleb_epci_dummy_read(struct pci_dev *dev)
 static inline void clear_and_disable_master_abort_interrupt(
                                        struct pci_controller *hose)
 {
-       void __iomem *addr;
-       addr = hose->cfg_addr + PCI_COMMAND;
-       out_be32(addr, in_be32(addr) | (PCI_STATUS_REC_MASTER_ABORT << 16));
+       volatile void __iomem *epci_base, *reg;
+       epci_base = celleb_epci_get_epci_base(hose);
+       reg = epci_base + PCI_COMMAND;
+       out_be32(reg, in_be32(reg) | (PCI_STATUS_REC_MASTER_ABORT << 16));
 }
 
 static int celleb_epci_check_abort(struct pci_controller *hose,
-                                  void __iomem *addr)
+                                  volatile void __iomem *addr)
 {
-       void __iomem *reg, *epci_base;
+       volatile void __iomem *reg, *epci_base;
        u32 val;
 
        iob();
-       epci_base = hose->cfg_addr;
+       epci_base = celleb_epci_get_epci_base(hose);
 
        reg = epci_base + PCI_COMMAND;
        val = in_be32(reg);
@@ -108,20 +132,21 @@ static int celleb_epci_check_abort(struct pci_controller *hose,
        return PCIBIOS_SUCCESSFUL;
 }
 
-static void __iomem *celleb_epci_make_config_addr(struct pci_controller *hose,
+static volatile void __iomem *celleb_epci_make_config_addr(
+                                       struct pci_controller *hose,
                                        unsigned int devfn, int where)
 {
-       void __iomem *addr;
+       volatile void __iomem *addr;
        struct pci_bus *bus = hose->bus;
 
        if (bus->self)
-               addr = hose->cfg_data +
+               addr = celleb_epci_get_epci_cfg(hose) +
                       (((bus->number & 0xff) << 16)
                        | ((devfn & 0xff) << 8)
                        | (where & 0xff)
                        | 0x01000000);
        else
-               addr = hose->cfg_data +
+               addr = celleb_epci_get_epci_cfg(hose) +
                       (((devfn & 0xff) << 8) | (where & 0xff));
 
        pr_debug("EPCI: config_addr = 0x%p\n", addr);
@@ -132,7 +157,7 @@ static void __iomem *celleb_epci_make_config_addr(struct pci_controller *hose,
 static int celleb_epci_read_config(struct pci_bus *bus,
                        unsigned int devfn, int where, int size, u32 * val)
 {
-       void __iomem *addr;
+       volatile void __iomem *epci_base, *addr;
        struct device_node *node;
        struct pci_controller *hose;
 
@@ -142,13 +167,14 @@ static int celleb_epci_read_config(struct pci_bus *bus,
        node = (struct device_node *)bus->sysdata;
        hose = pci_find_hose_for_OF_device(node);
 
-       if (!hose->cfg_data)
+       if (!celleb_epci_get_epci_cfg(hose))
                return PCIBIOS_DEVICE_NOT_FOUND;
 
        if (bus->number == hose->first_busno && devfn == 0) {
                /* EPCI controller self */
 
-               addr = hose->cfg_addr + where;
+               epci_base = celleb_epci_get_epci_base(hose);
+               addr = epci_base + where;
 
                switch (size) {
                case 1:
@@ -185,7 +211,7 @@ static int celleb_epci_read_config(struct pci_bus *bus,
        }
 
        pr_debug("EPCI: "
-                "addr=0x%lx, devfn=0x%x, where=0x%x, size=0x%x, val=0x%x\n",
+                "addr=0x%p, devfn=0x%x, where=0x%x, size=0x%x, val=0x%x\n",
                 addr, devfn, where, size, *val);
 
        return celleb_epci_check_abort(hose, NULL);
@@ -194,7 +220,7 @@ static int celleb_epci_read_config(struct pci_bus *bus,
 static int celleb_epci_write_config(struct pci_bus *bus,
                        unsigned int devfn, int where, int size, u32 val)
 {
-       void __iomem *addr;
+       volatile void __iomem *epci_base, *addr;
        struct device_node *node;
        struct pci_controller *hose;
 
@@ -204,13 +230,15 @@ static int celleb_epci_write_config(struct pci_bus *bus,
        node = (struct device_node *)bus->sysdata;
        hose = pci_find_hose_for_OF_device(node);
 
-       if (!hose->cfg_data)
+
+       if (!celleb_epci_get_epci_cfg(hose))
                return PCIBIOS_DEVICE_NOT_FOUND;
 
        if (bus->number == hose->first_busno && devfn == 0) {
                /* EPCI controller self */
 
-               addr = hose->cfg_addr + where;
+               epci_base = celleb_epci_get_epci_base(hose);
+               addr = epci_base + where;
 
                switch (size) {
                case 1:
@@ -258,10 +286,10 @@ struct pci_ops celleb_epci_ops = {
 static int __devinit celleb_epci_init(struct pci_controller *hose)
 {
        u32 val;
-       void __iomem *reg, *epci_base;
+       volatile void __iomem *reg, *epci_base;
        int hwres = 0;
 
-       epci_base = hose->cfg_addr;
+       epci_base = celleb_epci_get_epci_base(hose);
 
        /* PCI core reset(Internal bus and PCI clock) */
        reg = epci_base + SCC_EPCI_CKCTRL;
@@ -382,6 +410,18 @@ int __devinit celleb_setup_epci(struct device_node *node,
 
        pr_debug("PCI: celleb_setup_epci()\n");
 
+       /*
+        * Note:
+        * Celleb epci uses cfg_addr and cfg_data member of
+        * pci_controller structure in irregular way.
+        *
+        * cfg_addr is used to map for control registers of
+        * celleb epci.
+        *
+        * cfg_data is used for configuration area of devices
+        * on Celleb epci buses.
+        */
+
        if (of_address_to_resource(node, 0, &r))
                goto error;
        hose->cfg_addr = ioremap(r.start, (r.end - r.start + 1));
index 6ad4b1a72c96b9e5aa838305e413a12b212394eb..71045677559a6b0f7deed4da21e66b925b9a2fed 100644 (file)
@@ -58,6 +58,7 @@ static struct resource mv643xx_eth0_resources[] = {
 
 
 static struct mv643xx_eth_platform_data eth0_pd = {
+       .port_number    = 0,
        .tx_sram_addr = PEGASOS2_SRAM_BASE_ETH0,
        .tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE,
        .tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16,
@@ -87,6 +88,7 @@ static struct resource mv643xx_eth1_resources[] = {
 };
 
 static struct mv643xx_eth_platform_data eth1_pd = {
+       .port_number    = 1,
        .tx_sram_addr = PEGASOS2_SRAM_BASE_ETH1,
        .tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE,
        .tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16,
index 886c522d78e94b5b9b417b8adeb104cdf333dec3..3410bcbc9dbe04030b6952ce537f1306a2186d18 100644 (file)
@@ -79,6 +79,7 @@ config LINKSTATION
        select MPIC
        select FSL_SOC
        select PPC_UDBG_16550 if SERIAL_8250
+       select DEFAULT_UIMAGE
        help
          Select LINKSTATION if configuring for one of PPC- (MPC8241)
          based NAS systems from Buffalo Technology. So far only
index c3a89414ddc099d1baf91fe28234fe87b75b02b5..de7440e62cc4fb05f0bc7b58e0d5b0ad3e81ff95 100644 (file)
@@ -37,21 +37,20 @@ static int pmac_backlight_set_legacy_queued;
  */
 static atomic_t kernel_backlight_disabled = ATOMIC_INIT(0);
 
-/* Protect the pmac_backlight variable */
+/* Protect the pmac_backlight variable below.
+   You should hold this lock when using the pmac_backlight pointer to
+   prevent its potential removal. */
 DEFINE_MUTEX(pmac_backlight_mutex);
 
 /* Main backlight storage
  *
- * Backlight drivers in this variable are required to have the "props"
+ * Backlight drivers in this variable are required to have the "ops"
  * attribute set and to have an update_status function.
  *
  * We can only store one backlight here, but since Apple laptops have only one
  * internal display, it doesn't matter. Other backlight drivers can be used
  * independently.
  *
- * Lock ordering:
- * pmac_backlight_mutex (global, main backlight)
- *   pmac_backlight->sem (backlight class)
  */
 struct backlight_device *pmac_backlight;
 
@@ -104,8 +103,7 @@ static void pmac_backlight_key_worker(struct work_struct *work)
                struct backlight_properties *props;
                int brightness;
 
-               down(&pmac_backlight->sem);
-               props = pmac_backlight->props;
+               props = &pmac_backlight->props;
 
                brightness = props->brightness +
                        ((pmac_backlight_key_queued?-1:1) *
@@ -117,9 +115,7 @@ static void pmac_backlight_key_worker(struct work_struct *work)
                        brightness = props->max_brightness;
 
                props->brightness = brightness;
-               props->update_status(pmac_backlight);
-
-               up(&pmac_backlight->sem);
+               backlight_update_status(pmac_backlight);
        }
        mutex_unlock(&pmac_backlight_mutex);
 }
@@ -145,8 +141,7 @@ static int __pmac_backlight_set_legacy_brightness(int brightness)
        if (pmac_backlight) {
                struct backlight_properties *props;
 
-               down(&pmac_backlight->sem);
-               props = pmac_backlight->props;
+               props = &pmac_backlight->props;
                props->brightness = brightness *
                        (props->max_brightness + 1) /
                        (OLD_BACKLIGHT_MAX + 1);
@@ -156,8 +151,7 @@ static int __pmac_backlight_set_legacy_brightness(int brightness)
                else if (props->brightness < 0)
                        props->brightness = 0;
 
-               props->update_status(pmac_backlight);
-               up(&pmac_backlight->sem);
+               backlight_update_status(pmac_backlight);
 
                error = 0;
        }
@@ -196,14 +190,11 @@ int pmac_backlight_get_legacy_brightness()
        if (pmac_backlight) {
                struct backlight_properties *props;
 
-               down(&pmac_backlight->sem);
-               props = pmac_backlight->props;
+               props = &pmac_backlight->props;
 
                result = props->brightness *
                        (OLD_BACKLIGHT_MAX + 1) /
                        (props->max_brightness + 1);
-
-               up(&pmac_backlight->sem);
        }
        mutex_unlock(&pmac_backlight_mutex);
 
index c29a6a064d2244e70d23464ddae9302d3b3afd25..24cc50c1774ad5131429ed27caef9e7add3ed906 100644 (file)
@@ -810,6 +810,7 @@ core99_ata100_enable(struct device_node *node, long value)
        unsigned long flags;
        struct pci_dev *pdev = NULL;
        u8 pbus, pid;
+       int rc;
 
        if (uninorth_rev < 0x24)
                return -ENODEV;
@@ -828,7 +829,9 @@ core99_ata100_enable(struct device_node *node, long value)
                        pdev = pci_find_slot(pbus, pid);
                if (pdev == NULL)
                        return 0;
-               pci_enable_device(pdev);
+               rc = pci_enable_device(pdev);
+               if (rc)
+                       return rc;
                pci_set_master(pdev);
        }
        return 0;
index f42475b27c153c324f150d9e4ff3a352c4cafba3..6fbac308ded649ffcee13fbdacfe2ea04e55959e 100644 (file)
@@ -1191,8 +1191,11 @@ void __init pmac_pcibios_after_init(void)
         * -- BenH
         */
        for_each_pci_dev(dev) {
-               if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE)
-                       pci_enable_device(dev);
+               if ((dev->class >> 16) != PCI_BASE_CLASS_STORAGE)
+                       continue;
+               if (pci_enable_device(dev))
+                       printk(KERN_WARNING
+                              "pci: Failed to enable %s\n", pci_name(dev));
        }
 #endif /* CONFIG_BLK_DEV_IDE */
 
index d270a1e374d5981662e788f10dfd9b7f07cd2aac..1a481a60a883db69f33e96a1a35c0b0de09bf19f 100644 (file)
@@ -1,9 +1,24 @@
 menu "PS3 Platform Options"
        depends on PPC_PS3
 
+config PS3_ADVANCED
+       depends on PPC_PS3
+       bool "PS3 Advanced configuration options"
+       help
+         This gives you access to some advanced options for the PS3. The
+         defaults should be fine for most users, but these options may make
+         it possible to better control the kernel configuration if you know
+         what you are doing.
+
+         Note that the answer to this question won't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about these options.
+
+         Most users should say N to this question.
+
 config PS3_HTAB_SIZE
        depends on PPC_PS3
-       int "PS3 Platform pagetable size"
+       int "PS3 Platform pagetable size" if PS3_ADVANCED
        range 18 20
        default 20
        help
@@ -42,7 +57,7 @@ config PS3_USE_LPAR_ADDR
 
 config PS3_VUART
        depends on PPC_PS3
-       bool "PS3 Virtual UART support"
+       bool "PS3 Virtual UART support" if PS3_ADVANCED
        default y
        help
          Include support for the PS3 Virtual UART.
@@ -52,9 +67,8 @@ config PS3_VUART
          general, all users will say Y.
 
 config PS3_PS3AV
-       tristate "PS3 AV settings driver"
-       depends on PPC_PS3
-       select PS3_VUART
+       tristate "PS3 AV settings driver" if PS3_ADVANCED
+       depends on PS3_VUART
        default y
        help
          Include support for the PS3 AV Settings driver.
@@ -63,8 +77,8 @@ config PS3_PS3AV
          general, all users will say Y or M.
 
 config PS3_SYS_MANAGER
-       bool "PS3 System Manager driver"
-       select PS3_VUART
+       bool "PS3 System Manager driver" if PS3_ADVANCED
+       depends on PS3_VUART
        default y
        help
          Include support for the PS3 System Manager.
index 0183e5fbaf46bc7ccb7b159b0035a94c72b23c3c..bf299b66f3fc6c0198b0f88110ea718915251769 100644 (file)
@@ -218,7 +218,7 @@ Commands:\n\
 "  ss  stop execution on all spus\n\
   sr   restore execution on stopped spus\n\
   sf  #        dump spu fields for spu # (in hex)\n\
-  sd  #        dump spu local store for spu # (in hex)\
+  sd  #        dump spu local store for spu # (in hex)\n\
   sdi #        disassemble spu local store for spu # (in hex)\n"
 #endif
 "  S   print special registers\n\
index 0df9c33629fd992159cf95406157886dff090994..ccce2a4a1522f574b49dacf261108a4b43068f09 100644 (file)
@@ -845,6 +845,21 @@ config MV64X60
        select PPC_INDIRECT_PCI
        default y
 
+config MV643XX_ETH_0
+       bool
+       depends on MV643XX_ETH && (KATANA || RADSTONE_PPC7D || EV64360 || HDPU)
+       default y
+
+config MV643XX_ETH_1
+       bool
+       depends on MV643XX_ETH && (KATANA || RADSTONE_PPC7D || EV64360)
+       default y
+
+config MV643XX_ETH_2
+       bool
+       depends on MV643XX_ETH && (KATANA || RADSTONE_PPC7D || EV64360)
+       default y
+
 menu "Set bridge options"
        depends on MV64X60
 
index 3b039c30a439adfc2b8168285bd5418f12738fff..a6f8b686ea83619f8e2a91f14c34ff0ad151c153 100644 (file)
@@ -339,7 +339,9 @@ static struct resource mv64x60_eth0_resources[] = {
        },
 };
 
-static struct mv643xx_eth_platform_data eth0_pd;
+static struct mv643xx_eth_platform_data eth0_pd = {
+       .port_number    = 0,
+};
 
 static struct platform_device eth0_device = {
        .name           = MV643XX_ETH_NAME,
@@ -362,7 +364,9 @@ static struct resource mv64x60_eth1_resources[] = {
        },
 };
 
-static struct mv643xx_eth_platform_data eth1_pd;
+static struct mv643xx_eth_platform_data eth1_pd = {
+       .port_number    = 1,
+};
 
 static struct platform_device eth1_device = {
        .name           = MV643XX_ETH_NAME,
@@ -385,7 +389,9 @@ static struct resource mv64x60_eth2_resources[] = {
        },
 };
 
-static struct mv643xx_eth_platform_data eth2_pd;
+static struct mv643xx_eth_platform_data eth2_pd = {
+       .port_number    = 2,
+};
 
 static struct platform_device eth2_device = {
        .name           = MV643XX_ETH_NAME,
index eaaac3788110ec90ad076dc92d922da452675242..0f293aa7b0fa5fd30f5dd85267267a38dcdbd96a 100644 (file)
@@ -8,8 +8,8 @@ config MMU
        default y
 
 config ZONE_DMA
-       bool
-       default y
+       def_bool y
+       depends on 64BIT
 
 config LOCKDEP_SUPPORT
        bool
@@ -376,6 +376,8 @@ config SHARED_KERNEL
          Select this option, if you want to share the text segment of the
          Linux kernel between different VM guests. This reduces memory
          usage with lots of guests but greatly increases kernel size.
+         Also if a kernel was IPL'ed from a shared segment the kexec system
+         call will not work.
          You should only select this option if you know what you are
          doing and want to exploit this feature.
 
index 6598e526857334bdf3f167cd8e9d721842e10a9d..b1e558496469c1f9074658fd6ae253b4a7fed4ff 100644 (file)
@@ -82,18 +82,18 @@ AFLAGS              += $(aflags-y)
 OBJCOPYFLAGS   := -O binary
 LDFLAGS_vmlinux := -e start
 
-head-y         := arch/$(ARCH)/kernel/head.o arch/$(ARCH)/kernel/init_task.o
+head-y         := arch/s390/kernel/head.o arch/s390/kernel/init_task.o
 
-core-y         += arch/$(ARCH)/mm/ arch/$(ARCH)/kernel/ arch/$(ARCH)/crypto/ \
-                  arch/$(ARCH)/appldata/ arch/$(ARCH)/hypfs/
-libs-y         += arch/$(ARCH)/lib/
+core-y         += arch/s390/mm/ arch/s390/kernel/ arch/s390/crypto/ \
+                  arch/s390/appldata/ arch/s390/hypfs/
+libs-y         += arch/s390/lib/
 drivers-y      += drivers/s390/
-drivers-$(CONFIG_MATHEMU) += arch/$(ARCH)/math-emu/
+drivers-$(CONFIG_MATHEMU) += arch/s390/math-emu/
 
 # must be linked after kernel
 drivers-$(CONFIG_OPROFILE)     += arch/s390/oprofile/
 
-boot           := arch/$(ARCH)/boot
+boot           := arch/s390/boot
 
 all: image
 
index 1406400bf3ea3b18a25779227e71013ea4e4a13b..741d2bbb2b37d3125f0d63626947486950db63bb 100644 (file)
@@ -1,9 +1,10 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc1
-# Fri Dec 15 16:52:28 2006
+# Linux kernel version: 2.6.21-rc1
+# Wed Feb 21 10:44:30 2007
 #
 CONFIG_MMU=y
+CONFIG_ZONE_DMA=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
@@ -11,6 +12,7 @@ CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_TIME=y
+CONFIG_NO_IOMEM=y
 CONFIG_S390=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -29,6 +31,7 @@ CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
@@ -133,6 +136,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_HOLES_IN_ZONE=y
 
 #
@@ -178,7 +182,9 @@ CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
 CONFIG_IUCV=m
 CONFIG_AFIUCV=m
 CONFIG_INET=y
@@ -195,7 +201,7 @@ CONFIG_IP_FIB_HASH=y
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_XFRM_MODE_BEET=y
@@ -313,6 +319,7 @@ CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 CONFIG_SYS_HYPERVISOR=y
 
 #
@@ -686,13 +693,13 @@ CONFIG_HEADERS_CHECK=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=17
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
 CONFIG_DEBUG_PREEMPT=y
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_LOCK_ALLOC is not set
 # CONFIG_PROVE_LOCKING is not set
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
@@ -702,10 +709,10 @@ CONFIG_DEBUG_SPINLOCK_SLEEP=y
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_FRAME_POINTER is not set
-# CONFIG_UNWIND_INFO is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_LKDTM is not set
+# CONFIG_FAULT_INJECTION is not set
 
 #
 # Security options
@@ -733,8 +740,10 @@ CONFIG_CRYPTO_MANAGER=y
 # CONFIG_CRYPTO_GF128MUL is not set
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
 # CONFIG_CRYPTO_DES is not set
+CONFIG_CRYPTO_FCRYPT=m
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
@@ -748,6 +757,7 @@ CONFIG_CRYPTO_CBC=y
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -768,4 +778,3 @@ CONFIG_BITREVERSE=m
 CONFIG_CRC32=m
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
index e518dd53eff52408f0b7427d181efd4715145e75..afca1c6f4d219e911871eae85bb4412c831b9777 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/pfn.h>
 #include <linux/uaccess.h>
+#include <asm/ipl.h>
 #include <asm/lowcore.h>
 #include <asm/processor.h>
 #include <asm/sections.h>
@@ -109,7 +110,7 @@ static inline void create_kernel_nss(void) { }
  */
 static noinline __init void clear_bss_section(void)
 {
-       memset(__bss_start, 0, _end - __bss_start);
+       memset(__bss_start, 0, __bss_stop - __bss_start);
 }
 
 /*
@@ -129,7 +130,7 @@ static noinline __init void detect_machine_type(void)
 {
        struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data;
 
-       asm volatile("stidp %0" : "=m" (S390_lowcore.cpu_data.cpu_id));
+       get_cpu_id(&S390_lowcore.cpu_data.cpu_id);
 
        /* Running under z/VM ? */
        if (cpuinfo->cpu_id.version == 0xff)
index 453fd3b4edea6e59d8a2600f43d72af32c43b43f..dc364c1419af068666e09f1e5aea0e99fe2961c1 100644 (file)
@@ -121,7 +121,7 @@ startup_continue:
        .long   .Lduct                  # cr2: dispatchable unit control table
        .long   0                       # cr3: instruction authorization
        .long   0                       # cr4: instruction authorization
-       .long   0xffffffff              # cr5: primary-aste origin
+       .long   .Lduct                  # cr5: primary-aste origin
        .long   0                       # cr6:  I/O interrupts
        .long   0                       # cr7:  secondary space segment table
        .long   0                       # cr8:  access registers translation
@@ -132,8 +132,6 @@ startup_continue:
        .long   0                       # cr13: home space segment table
        .long   0xc0000000              # cr14: machine check handling off
        .long   0                       # cr15: linkage stack operations
-.Lduct:        .long   0,0,0,0,0,0,0,0
-       .long   0,0,0,0,0,0,0,0
 .Lpcfpu:.long  0x00080000,0x80000000 + .Lchkfpu
 .Lpccsp:.long  0x00080000,0x80000000 + .Lchkcsp
 .Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg
@@ -147,21 +145,17 @@ startup_continue:
 .Linittu:   .long init_thread_union
 .Lstartup_init:
            .long startup_init
-
-       .globl ipl_schib
-ipl_schib:
-       .rept 13
-       .long 0
+       .align  64
+.Lduct:        .long   0,0,0,0,.Lduald,0,0,0
+       .long   0,0,0,0,0,0,0,0
+       .align  128
+.Lduald:.rept  8
+       .long   0x80000000,0,0,0        # invalid access-list entries
        .endr
 
-       .globl ipl_flags
-ipl_flags:
-       .long 0
-       .globl ipl_devno
-ipl_devno:
-       .word 0
-
        .org    0x12000
+       .globl  _ehead
+_ehead:
 #ifdef CONFIG_SHARED_KERNEL
        .org    0x100000
 #endif
index b8fec4e5c5d4ac3bd5e8da5b527901445ee78542..37010709fe683e934232ef9ff12d70cee2804423 100644 (file)
@@ -134,7 +134,7 @@ startup_continue:
        .quad   .Lduct                  # cr2: dispatchable unit control table
        .quad   0                       # cr3: instruction authorization
        .quad   0                       # cr4: instruction authorization
-       .quad   0xffffffffffffffff      # cr5: primary-aste origin
+       .quad   .Lduct                  # cr5: primary-aste origin
        .quad   0                       # cr6:  I/O interrupts
        .quad   0                       # cr7:  secondary space segment table
        .quad   0                       # cr8:  access registers translation
@@ -145,30 +145,23 @@ startup_continue:
        .quad   0                       # cr13: home space segment table
        .quad   0xc0000000              # cr14: machine check handling off
        .quad   0                       # cr15: linkage stack operations
-.Lduct: .long  0,0,0,0,0,0,0,0
-       .long   0,0,0,0,0,0,0,0
 .Lpcmsk:.quad  0x0000000180000000
 .L4malign:.quad 0xffffffffffc00000
 .Lscan2g:.quad 0x80000000 + 0x20000 - 8        # 2GB + 128K - 8
 .Lnop: .long   0x07000700
 .Lparmaddr:
        .quad   PARMAREA
-
-       .globl  ipl_schib
-ipl_schib:
-       .rept 13
-       .long 0
+       .align  64
+.Lduct: .long  0,0,0,0,.Lduald,0,0,0
+       .long   0,0,0,0,0,0,0,0
+       .align  128
+.Lduald:.rept  8
+       .long   0x80000000,0,0,0        # invalid access-list entries
        .endr
 
-       .globl  ipl_flags
-ipl_flags:
-       .long   0
-       .globl  ipl_devno
-ipl_devno:
-       .word 0
-
        .org    0x12000
-
+       .globl  _ehead
+_ehead:
 #ifdef CONFIG_SHARED_KERNEL
        .org    0x100000
 #endif
index 052259530651cddcd12eba6f415b4349947962f6..d125a4ead08dbdb8778854b07565986f1ce3353a 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/delay.h>
 #include <linux/reboot.h>
 #include <linux/ctype.h>
+#include <asm/ipl.h>
 #include <asm/smp.h>
 #include <asm/setup.h>
 #include <asm/cpcmd.h>
@@ -42,6 +43,13 @@ enum ipl_type {
 #define IPL_FCP_STR     "fcp"
 #define IPL_NSS_STR     "nss"
 
+/*
+ * Must be in data section since the bss section
+ * is not cleared when these are accessed.
+ */
+u16 ipl_devno __attribute__((__section__(".data"))) = 0;
+u32 ipl_flags __attribute__((__section__(".data"))) = 0;
+
 static char *ipl_type_str(enum ipl_type type)
 {
        switch (type) {
@@ -90,31 +98,10 @@ static char *shutdown_action_str(enum shutdown_action action)
        case SHUTDOWN_STOP:
                return SHUTDOWN_STOP_STR;
        default:
-               BUG();
+               return NULL;
        }
 }
 
-enum diag308_subcode  {
-       DIAG308_IPL   = 3,
-       DIAG308_DUMP  = 4,
-       DIAG308_SET   = 5,
-       DIAG308_STORE = 6,
-};
-
-enum diag308_ipl_type {
-       DIAG308_IPL_TYPE_FCP = 0,
-       DIAG308_IPL_TYPE_CCW = 2,
-};
-
-enum diag308_opt {
-       DIAG308_IPL_OPT_IPL  = 0x10,
-       DIAG308_IPL_OPT_DUMP = 0x20,
-};
-
-enum diag308_rc {
-       DIAG308_RC_OK = 1,
-};
-
 static int diag308_set_works = 0;
 
 static int reipl_capabilities = IPL_TYPE_UNKNOWN;
@@ -134,7 +121,7 @@ static struct ipl_parameter_block *dump_block_ccw;
 
 static enum shutdown_action on_panic_action = SHUTDOWN_STOP;
 
-static int diag308(unsigned long subcode, void *addr)
+int diag308(unsigned long subcode, void *addr)
 {
        register unsigned long _addr asm("0") = (unsigned long) addr;
        register unsigned long _rc asm("1") = 0;
@@ -1079,7 +1066,7 @@ static void do_reset_calls(void)
                reset->fn();
 }
 
-extern __u32 dump_prefix_page;
+u32 dump_prefix_page;
 
 void s390_reset_system(void)
 {
@@ -1091,7 +1078,7 @@ void s390_reset_system(void)
        lc->panic_stack = S390_lowcore.panic_stack;
 
        /* Save prefix page address for dump case */
-       dump_prefix_page = (unsigned long) lc;
+       dump_prefix_page = (u32)(unsigned long) lc;
 
        /* Disable prefixing */
        set_prefix(0);
index a466bab6677e15f506da1fb3d8168d5792170167..8af549e95730970ad3ed67a43ab823bf420cf24d 100644 (file)
@@ -337,21 +337,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
        }
 
        p = get_kprobe(addr);
-       if (!p) {
-               if (*addr != BREAKPOINT_INSTRUCTION) {
-                       /*
-                        * The breakpoint instruction was removed right
-                        * after we hit it.  Another cpu has removed
-                        * either a probepoint or a debugger breakpoint
-                        * at this address.  In either case, no further
-                        * handling of this interrupt is appropriate.
-                        *
-                        */
-                       ret = 1;
-               }
-               /* Not one of ours: let kernel handle it */
+       if (!p)
+               /*
+                * No kprobe at this address. The fault has not been
+                * caused by a kprobe breakpoint. The race of breakpoint
+                * vs. kprobe remove does not exist because on s390 we
+                * use stop_machine_run to arm/disarm the breakpoints.
+                */
                goto no_kprobe;
-       }
 
        kcb->kprobe_status = KPROBE_HIT_ACTIVE;
        set_current_kprobe(p, regs, kcb);
index 52f57af252b443a43418d53ae65f0f59409dc8f9..3c77dd36994cec6b71544a345a670d56353017d5 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/system.h>
 #include <asm/smp.h>
 #include <asm/reset.h>
+#include <asm/ipl.h>
 
 typedef void (*relocate_kernel_t)(kimage_entry_t *, unsigned long);
 
@@ -29,6 +30,10 @@ int machine_kexec_prepare(struct kimage *image)
 {
        void *reboot_code_buffer;
 
+       /* Can't replace kernel image since it is read-only. */
+       if (ipl_flags & IPL_NSS_VALID)
+               return -ENOSYS;
+
        /* We don't support anything but the default image type for now. */
        if (image->type != KEXEC_TYPE_DEFAULT)
                return -EINVAL;
index c3f4d9b950836442f3d1f2d53c7166b79369af01..2f481cc3d1c9c13bc5db45ad4987f51e4a07e9a5 100644 (file)
@@ -8,6 +8,10 @@
 
 #include <asm/lowcore.h>
 
+#
+# do_reipl_asm
+# Parameter: r2 = schid of reipl device
+#
                .globl  do_reipl_asm
 do_reipl_asm:  basr    %r13,0
 .Lpg0:         lpsw    .Lnewpsw-.Lpg0(%r13)
@@ -16,12 +20,12 @@ do_reipl_asm:       basr    %r13,0
                stm     %r0,%r15,__LC_GPREGS_SAVE_AREA
                stctl   %c0,%c15,__LC_CREGS_SAVE_AREA
                stam    %a0,%a15,__LC_AREGS_SAVE_AREA
-               mvc     __LC_PREFIX_SAVE_AREA(4),dump_prefix_page-.Lpg0(%r13)
+               l       %r10,.Ldump_pfx-.Lpg0(%r13)
+               mvc     __LC_PREFIX_SAVE_AREA(4),0(%r10)
                stckc   .Lclkcmp-.Lpg0(%r13)
                mvc     __LC_CLOCK_COMP_SAVE_AREA(8),.Lclkcmp-.Lpg0(%r13)
                stpt    __LC_CPU_TIMER_SAVE_AREA
                st      %r13, __LC_PSW_SAVE_AREA+4
-
                lctl    %c6,%c6,.Lall-.Lpg0(%r13)
                lr      %r1,%r2
                mvc     __LC_PGM_NEW_PSW(8),.Lpcnew-.Lpg0(%r13)
@@ -55,6 +59,7 @@ do_reipl_asm: basr    %r13,0
                .align  8
 .Lclkcmp:      .quad   0x0000000000000000
 .Lall:         .long   0xff000000
+.Ldump_pfx:    .long   dump_prefix_page
                .align  8
 .Lnewpsw:      .long   0x00080000,0x80000000+.Lpg1
 .Lpcnew:       .long   0x00080000,0x80000000+.Lecs
@@ -79,7 +84,3 @@ do_reipl_asm: basr    %r13,0
                .long   0x00000000,0x00000000
                .long   0x00000000,0x00000000
                .long   0x00000000,0x00000000
-       .globl dump_prefix_page
-dump_prefix_page:
-       .long 0x00000000
-
index dbb3eed38865fd88f8486ef4e5d63f6d62835f45..c41930499a5f1d0ca921e69e820c3810dcf4a216 100644 (file)
@@ -8,6 +8,12 @@
  */
 
 #include <asm/lowcore.h>
+
+#
+# do_reipl_asm
+# Parameter: r2 = schid of reipl device
+#
+
                .globl  do_reipl_asm
 do_reipl_asm:  basr    %r13,0
 .Lpg0:         lpswe   .Lnewpsw-.Lpg0(%r13)
@@ -20,7 +26,8 @@ do_reipl_asm: basr    %r13,0
                stg     %r0,__LC_GPREGS_SAVE_AREA-0x1000+8(%r1)
                stctg   %c0,%c15,__LC_CREGS_SAVE_AREA-0x1000(%r1)
                stam    %a0,%a15,__LC_AREGS_SAVE_AREA-0x1000(%r1)
-               mvc     __LC_PREFIX_SAVE_AREA-0x1000(4,%r1),dump_prefix_page-.Lpg0(%r13)
+               lg      %r10,.Ldump_pfx-.Lpg0(%r13)
+               mvc     __LC_PREFIX_SAVE_AREA-0x1000(4,%r1),0(%r10)
                stfpc   __LC_FP_CREG_SAVE_AREA-0x1000(%r1)
                stckc   .Lclkcmp-.Lpg0(%r13)
                mvc     __LC_CLOCK_COMP_SAVE_AREA-0x1000(8,%r1),.Lclkcmp-.Lpg0(%r13)
@@ -64,6 +71,7 @@ do_reipl_asm: basr    %r13,0
                .align  8
 .Lclkcmp:      .quad   0x0000000000000000
 .Lall:         .quad   0x00000000ff000000
+.Ldump_pfx:    .quad   dump_prefix_page
 .Lregsave:     .quad   0x0000000000000000
                .align  16
 /*
@@ -103,6 +111,3 @@ do_reipl_asm:       basr    %r13,0
                .long   0x00000000,0x00000000
                .long   0x00000000,0x00000000
                .long   0x00000000,0x00000000
-       .globl dump_prefix_page
-dump_prefix_page:
-       .long 0x00000000
index 50c5210fbc64e078683e6d58a67787df7d1c4403..863c8d08c02694815ecb611d03292c7aba160262 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/ctype.h>
 #include <linux/reboot.h>
 
+#include <asm/ipl.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/smp.h>
@@ -106,7 +107,7 @@ void __devinit cpu_init (void)
         /*
          * Store processor id in lowcore (used e.g. in timer_interrupt)
          */
-       asm volatile("stidp %0": "=m" (S390_lowcore.cpu_data.cpu_id));
+       get_cpu_id(&S390_lowcore.cpu_data.cpu_id);
         S390_lowcore.cpu_data.cpu_addr = addr;
 
         /*
@@ -689,8 +690,13 @@ setup_memory(void)
        psw_set_key(PAGE_DEFAULT_KEY);
 
        free_bootmem_with_active_regions(0, max_pfn);
-       reserve_bootmem(0, PFN_PHYS(start_pfn));
 
+       /*
+        * Reserve memory used for lowcore/command line/kernel image.
+        */
+       reserve_bootmem(0, (unsigned long)_ehead);
+       reserve_bootmem((unsigned long)_stext,
+                       PFN_PHYS(start_pfn) - (unsigned long)_stext);
        /*
         * Reserve the bootmem bitmap itself as well. We do this in two
         * steps (first step was init_bootmem()) because this catches
index 83a4ea6e3d605fb6637a845924887583a1a08910..97764f710bb7862e18f60d4a88fdd48ff87963d0 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/interrupt.h>
 #include <linux/cpu.h>
 #include <linux/timex.h>
+#include <asm/ipl.h>
 #include <asm/setup.h>
 #include <asm/sigp.h>
 #include <asm/pgalloc.h>
@@ -54,19 +55,18 @@ cpumask_t cpu_possible_map = CPU_MASK_NONE;
 static struct task_struct *current_set[NR_CPUS];
 
 static void smp_ext_bitcall(int, ec_bit_sig);
-static void smp_ext_bitcall_others(ec_bit_sig);
 
 /*
- * Structure and data for smp_call_function(). This is designed to minimise
- * static memory requirements. It also looks cleaner.
+ * Structure and data for __smp_call_function_map(). This is designed to
+ * minimise static memory requirements. It also looks cleaner.
  */
 static DEFINE_SPINLOCK(call_lock);
 
 struct call_data_struct {
        void (*func) (void *info);
        void *info;
-       atomic_t started;
-       atomic_t finished;
+       cpumask_t started;
+       cpumask_t finished;
        int wait;
 };
 
@@ -81,118 +81,114 @@ static void do_call_function(void)
        void *info = call_data->info;
        int wait = call_data->wait;
 
-       atomic_inc(&call_data->started);
+       cpu_set(smp_processor_id(), call_data->started);
        (*func)(info);
        if (wait)
-               atomic_inc(&call_data->finished);
+               cpu_set(smp_processor_id(), call_data->finished);;
 }
 
-/*
- * this function sends a 'generic call function' IPI to all other CPUs
- * in the system.
- */
-
-int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
-                       int wait)
-/*
- * [SUMMARY] Run a function on all other CPUs.
- * <func> The function to run. This must be fast and non-blocking.
- * <info> An arbitrary pointer to pass to the function.
- * <nonatomic> currently unused.
- * <wait> If true, wait (atomically) until function has completed on other CPUs.
- * [RETURNS] 0 on success, else a negative status code. Does not return until
- * remote CPUs are nearly ready to execute <<func>> or are or have executed.
- *
- * You must not call this function with disabled interrupts or from a
- * hardware interrupt handler.
- */
+static void __smp_call_function_map(void (*func) (void *info), void *info,
+                                   int nonatomic, int wait, cpumask_t map)
 {
        struct call_data_struct data;
-       int cpus = num_online_cpus()-1;
+       int cpu, local = 0;
 
-       if (cpus <= 0)
-               return 0;
-
-       /* Can deadlock when interrupts are disabled or if in wrong context */
+       /*
+        * Can deadlock when interrupts are disabled or if in wrong context.
+        */
        WARN_ON(irqs_disabled() || in_irq());
 
+       /*
+        * Check for local function call. We have to have the same call order
+        * as in on_each_cpu() because of machine_restart_smp().
+        */
+       if (cpu_isset(smp_processor_id(), map)) {
+               local = 1;
+               cpu_clear(smp_processor_id(), map);
+       }
+
+       cpus_and(map, map, cpu_online_map);
+       if (cpus_empty(map))
+               goto out;
+
        data.func = func;
        data.info = info;
-       atomic_set(&data.started, 0);
+       data.started = CPU_MASK_NONE;
        data.wait = wait;
        if (wait)
-               atomic_set(&data.finished, 0);
+               data.finished = CPU_MASK_NONE;
 
        spin_lock_bh(&call_lock);
        call_data = &data;
-       /* Send a message to all other CPUs and wait for them to respond */
-        smp_ext_bitcall_others(ec_call_function);
+
+       for_each_cpu_mask(cpu, map)
+               smp_ext_bitcall(cpu, ec_call_function);
 
        /* Wait for response */
-       while (atomic_read(&data.started) != cpus)
+       while (!cpus_equal(map, data.started))
                cpu_relax();
 
        if (wait)
-               while (atomic_read(&data.finished) != cpus)
+               while (!cpus_equal(map, data.finished))
                        cpu_relax();
+
        spin_unlock_bh(&call_lock);
 
-       return 0;
+out:
+       local_irq_disable();
+       if (local)
+               func(info);
+       local_irq_enable();
 }
 
 /*
- * Call a function on one CPU
- * cpu : the CPU the function should be executed on
+ * smp_call_function:
+ * @func: the function to run; this must be fast and non-blocking
+ * @info: an arbitrary pointer to pass to the function
+ * @nonatomic: unused
+ * @wait: if true, wait (atomically) until function has completed on other CPUs
+ *
+ * Run a function on all other CPUs.
  *
  * You must not call this function with disabled interrupts or from a
  * hardware interrupt handler. You may call it from a bottom half.
- *
- * It is guaranteed that the called function runs on the specified CPU,
- * preemption is disabled.
  */
-int smp_call_function_on(void (*func) (void *info), void *info,
-                        int nonatomic, int wait, int cpu)
+int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
+                     int wait)
 {
-       struct call_data_struct data;
-       int curr_cpu;
-
-       if (!cpu_online(cpu))
-               return -EINVAL;
-
-       /* Can deadlock when interrupts are disabled or if in wrong context */
-       WARN_ON(irqs_disabled() || in_irq());
-
-       /* disable preemption for local function call */
-       curr_cpu = get_cpu();
-
-       if (curr_cpu == cpu) {
-               /* direct call to function */
-               func(info);
-               put_cpu();
-               return 0;
-       }
-
-       data.func = func;
-       data.info = info;
-       atomic_set(&data.started, 0);
-       data.wait = wait;
-       if (wait)
-               atomic_set(&data.finished, 0);
+       cpumask_t map;
 
-       spin_lock_bh(&call_lock);
-       call_data = &data;
-       smp_ext_bitcall(cpu, ec_call_function);
-
-       /* Wait for response */
-       while (atomic_read(&data.started) != 1)
-               cpu_relax();
+       preempt_disable();
+       map = cpu_online_map;
+       cpu_clear(smp_processor_id(), map);
+       __smp_call_function_map(func, info, nonatomic, wait, map);
+       preempt_enable();
+       return 0;
+}
+EXPORT_SYMBOL(smp_call_function);
 
-       if (wait)
-               while (atomic_read(&data.finished) != 1)
-                       cpu_relax();
+/*
+ * smp_call_function_on:
+ * @func: the function to run; this must be fast and non-blocking
+ * @info: an arbitrary pointer to pass to the function
+ * @nonatomic: unused
+ * @wait: if true, wait (atomically) until function has completed on other CPUs
+ * @cpu: the CPU where func should run
+ *
+ * Run a function on one processor.
+ *
+ * You must not call this function with disabled interrupts or from a
+ * hardware interrupt handler. You may call it from a bottom half.
+ */
+int smp_call_function_on(void (*func) (void *info), void *info, int nonatomic,
+                         int wait, int cpu)
+{
+       cpumask_t map = CPU_MASK_NONE;
 
-       spin_unlock_bh(&call_lock);
-       put_cpu();
+       preempt_disable();
+       cpu_set(cpu, map);
+       __smp_call_function_map(func, info, nonatomic, wait, map);
+       preempt_enable();
        return 0;
 }
 EXPORT_SYMBOL(smp_call_function_on);
@@ -325,26 +321,6 @@ static void smp_ext_bitcall(int cpu, ec_bit_sig sig)
                udelay(10);
 }
 
-/*
- * Send an external call sigp to every other cpu in the system and
- * return without waiting for its completion.
- */
-static void smp_ext_bitcall_others(ec_bit_sig sig)
-{
-        int cpu;
-
-       for_each_online_cpu(cpu) {
-               if (cpu == smp_processor_id())
-                        continue;
-                /*
-                 * Set signaling bit in lowcore of target cpu and kick it
-                 */
-               set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast);
-               while (signal_processor(cpu, sigp_emergency_signal) == sigp_busy)
-                       udelay(10);
-        }
-}
-
 #ifndef CONFIG_64BIT
 /*
  * this function sends a 'purge tlb' signal to another CPU.
@@ -807,6 +783,5 @@ EXPORT_SYMBOL(cpu_possible_map);
 EXPORT_SYMBOL(lowcore_ptr);
 EXPORT_SYMBOL(smp_ctl_set_bit);
 EXPORT_SYMBOL(smp_ctl_clear_bit);
-EXPORT_SYMBOL(smp_call_function);
 EXPORT_SYMBOL(smp_get_cpu);
 EXPORT_SYMBOL(smp_put_cpu);
index ee9fd7b859282941db4ad38ee896ea933cc1809e..e1ad464b6f207f073e5e096931ae554aa839a75e 100644 (file)
@@ -747,6 +747,7 @@ static void etr_adjust_time(unsigned long long clock, unsigned long long delay)
        }
 }
 
+#ifdef CONFIG_SMP
 static void etr_sync_cpu_start(void *dummy)
 {
        int *in_sync = dummy;
@@ -758,8 +759,14 @@ static void etr_sync_cpu_start(void *dummy)
         * __udelay will stop the cpu on an enabled wait psw until the
         * TOD is running again.
         */
-       while (*in_sync == 0)
+       while (*in_sync == 0) {
                __udelay(1);
+               /*
+                * A different cpu changes *in_sync. Therefore use
+                * barrier() to force memory access.
+                */
+               barrier();
+       }
        if (*in_sync != 1)
                /* Didn't work. Clear per-cpu in sync bit again. */
                etr_disable_sync_clock(NULL);
@@ -773,6 +780,7 @@ static void etr_sync_cpu_start(void *dummy)
 static void etr_sync_cpu_end(void *dummy)
 {
 }
+#endif /* CONFIG_SMP */
 
 /*
  * Sync the TOD clock using the port refered to by aibp. This port
index 02854449b74ba64dea7230b606f72b63c3890218..70f2a862b670649e296d1c6e5277f01241161a11 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/delay.h>
 #include <linux/timex.h>
 #include <linux/irqflags.h>
+#include <linux/interrupt.h>
 
 void __delay(unsigned long loops)
 {
@@ -35,7 +36,11 @@ void __udelay(unsigned long usecs)
 {
        u64 end, time, jiffy_timer = 0;
        unsigned long flags, cr0, mask, dummy;
+       int irq_context;
 
+       irq_context = in_interrupt();
+       if (!irq_context)
+               local_bh_disable();
        local_irq_save(flags);
        if (raw_irqs_disabled_flags(flags)) {
                jiffy_timer = S390_lowcore.jiffy_timer;
@@ -62,6 +67,8 @@ void __udelay(unsigned long usecs)
                __ctl_load(cr0, 0, 0);
                S390_lowcore.jiffy_timer = jiffy_timer;
        }
+       if (!irq_context)
+               _local_bh_enable();
        set_clock_comparator(S390_lowcore.jiffy_timer);
        local_irq_restore(flags);
 }
index 641aef36ccc498847ee90fb42c77fa676f496d9d..7462aebd3eb638f769545f8bd723664809757563 100644 (file)
@@ -108,53 +108,40 @@ void bust_spinlocks(int yes)
 }
 
 /*
- * Check which address space is addressed by the access
- * register in S390_lowcore.exc_access_id.
- * Returns 1 for user space and 0 for kernel space.
+ * Returns the address space associated with the fault.
+ * Returns 0 for kernel space, 1 for user space and
+ * 2 for code execution in user space with noexec=on.
  */
-static int __check_access_register(struct pt_regs *regs, int error_code)
-{
-       int areg = S390_lowcore.exc_access_id;
-
-       if (areg == 0)
-               /* Access via access register 0 -> kernel address */
-               return 0;
-       save_access_regs(current->thread.acrs);
-       if (regs && areg < NUM_ACRS && current->thread.acrs[areg] <= 1)
-               /*
-                * access register contains 0 -> kernel address,
-                * access register contains 1 -> user space address
-                */
-               return current->thread.acrs[areg];
-
-       /* Something unhealthy was done with the access registers... */
-       die("page fault via unknown access register", regs, error_code);
-       do_exit(SIGKILL);
-       return 0;
-}
-
-/*
- * Check which address space the address belongs to.
- * May return 1 or 2 for user space and 0 for kernel space.
- * Returns 2 for user space in primary addressing mode with
- * CONFIG_S390_EXEC_PROTECT on and kernel parameter noexec=on.
- */
-static inline int check_user_space(struct pt_regs *regs, int error_code)
+static inline int check_space(struct task_struct *tsk)
 {
        /*
-        * The lowest two bits of S390_lowcore.trans_exc_code indicate
-        * which paging table was used:
-        *   0: Primary Segment Table Descriptor
-        *   1: STD determined via access register
-        *   2: Secondary Segment Table Descriptor
-        *   3: Home Segment Table Descriptor
+        * The lowest two bits of S390_lowcore.trans_exc_code
+        * indicate which paging table was used.
         */
-       int descriptor = S390_lowcore.trans_exc_code & 3;
-       if (unlikely(descriptor == 1))
-               return __check_access_register(regs, error_code);
-       if (descriptor == 2)
-               return current->thread.mm_segment.ar4;
-       return ((descriptor != 0) ^ (switch_amode)) << s390_noexec;
+       int desc = S390_lowcore.trans_exc_code & 3;
+
+       if (desc == 3)  /* Home Segment Table Descriptor */
+               return switch_amode == 0;
+       if (desc == 2)  /* Secondary Segment Table Descriptor */
+               return tsk->thread.mm_segment.ar4;
+#ifdef CONFIG_S390_SWITCH_AMODE
+       if (unlikely(desc == 1)) { /* STD determined via access register */
+               /* %a0 always indicates primary space. */
+               if (S390_lowcore.exc_access_id != 0) {
+                       save_access_regs(tsk->thread.acrs);
+                       /*
+                        * An alet of 0 indicates primary space.
+                        * An alet of 1 indicates secondary space.
+                        * Any other alet values generate an
+                        * alen-translation exception.
+                        */
+                       if (tsk->thread.acrs[S390_lowcore.exc_access_id])
+                               return tsk->thread.mm_segment.ar4;
+               }
+       }
+#endif
+       /* Primary Segment Table Descriptor */
+       return switch_amode << s390_noexec;
 }
 
 /*
@@ -265,16 +252,16 @@ out_fault:
  *   11       Page translation     ->  Not present       (nullification)
  *   3b       Region third trans.  ->  Not present       (nullification)
  */
-static inline void __kprobes
+static inline void
 do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection)
 {
         struct task_struct *tsk;
         struct mm_struct *mm;
         struct vm_area_struct * vma;
         unsigned long address;
-       int user_address;
        const struct exception_table_entry *fixup;
-       int si_code = SEGV_MAPERR;
+       int si_code;
+       int space;
 
         tsk = current;
         mm = tsk->mm;
@@ -294,7 +281,7 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection)
                   NULL pointer write access in kernel mode.  */
                if (!(regs->psw.mask & PSW_MASK_PSTATE)) {
                        address = 0;
-                       user_address = 0;
+                       space = 0;
                        goto no_context;
                }
 
@@ -309,15 +296,15 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection)
          * the address 
          */
         address = S390_lowcore.trans_exc_code & __FAIL_ADDR_MASK;
-       user_address = check_user_space(regs, error_code);
+       space = check_space(tsk);
 
        /*
         * Verify that the fault happened in user space, that
         * we are not in an interrupt and that there is a 
         * user context.
         */
-        if (user_address == 0 || in_atomic() || !mm)
-                goto no_context;
+       if (unlikely(space == 0 || in_atomic() || !mm))
+               goto no_context;
 
        /*
         * When we get here, the fault happened in the current
@@ -328,12 +315,13 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection)
 
         down_read(&mm->mmap_sem);
 
-        vma = find_vma(mm, address);
-        if (!vma)
-                goto bad_area;
+       si_code = SEGV_MAPERR;
+       vma = find_vma(mm, address);
+       if (!vma)
+               goto bad_area;
 
 #ifdef CONFIG_S390_EXEC_PROTECT
-       if (unlikely((user_address == 2) && !(vma->vm_flags & VM_EXEC)))
+       if (unlikely((space == 2) && !(vma->vm_flags & VM_EXEC)))
                if (!signal_return(mm, regs, address, error_code))
                        /*
                         * signal_return() has done an up_read(&mm->mmap_sem)
@@ -389,7 +377,7 @@ survive:
         * The instruction that caused the program check will
         * be repeated. Don't signal single step via SIGTRAP.
         */
-       clear_tsk_thread_flag(current, TIF_SINGLE_STEP);
+       clear_tsk_thread_flag(tsk, TIF_SINGLE_STEP);
         return;
 
 /*
@@ -419,7 +407,7 @@ no_context:
  * Oops. The kernel tried to access some bad page. We'll have to
  * terminate things with extreme prejudice.
  */
-        if (user_address == 0)
+       if (space == 0)
                 printk(KERN_ALERT "Unable to handle kernel pointer dereference"
                       " at virtual kernel address %p\n", (void *)address);
         else
@@ -462,13 +450,14 @@ do_sigbus:
                goto no_context;
 }
 
-void do_protection_exception(struct pt_regs *regs, unsigned long error_code)
+void __kprobes do_protection_exception(struct pt_regs *regs,
+                                      unsigned long error_code)
 {
        regs->psw.addr -= (error_code >> 16);
        do_exception(regs, 4, 1);
 }
 
-void do_dat_exception(struct pt_regs *regs, unsigned long error_code)
+void __kprobes do_dat_exception(struct pt_regs *regs, unsigned long error_code)
 {
        do_exception(regs, error_code & 0xff, 0);
 }
index b3e7c45efb63110f064ab77693e5349b71d081de..916b72a8cde8eea8dd21ac5e11d33af05b032f95 100644 (file)
@@ -141,7 +141,9 @@ void __init paging_init(void)
        __raw_local_irq_ssm(ssm_mask);
 
        memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+#ifdef CONFIG_ZONE_DMA
        max_zone_pfns[ZONE_DMA] = PFN_DOWN(MAX_DMA_ADDRESS);
+#endif
        max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
        free_area_init_nodes(max_zone_pfns);
 }
index 3c93012e91a33cdd36d2816e849e936bae6b0163..ed5f5a9a3b3e8c845ae9ecbb42f4323478461260 100644 (file)
@@ -2,6 +2,6 @@
 # Makefile for the R7780RP-1 specific parts of the kernel
 #
 
-obj-y   := setup.o io.o irq.o
+obj-y   := setup.o irq.o
 
 obj-$(CONFIG_PUSH_SWITCH)      += psw.o
diff --git a/arch/sh/boards/renesas/r7780rp/io.c b/arch/sh/boards/renesas/r7780rp/io.c
deleted file mode 100644 (file)
index f74d2ff..0000000
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright (C) 2001  Ian da Silva, Jeremy Siegel
- * Based largely on io_se.c.
- *
- * I/O routine for Renesas Solutions Highlander R7780RP-1
- *
- * Initial version only to support LAN access; some
- * placeholder code from io_r7780rp.c left in with the
- * expectation of later SuperIO and PCMCIA access.
- */
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/io.h>
-#include <asm/r7780rp.h>
-#include <asm/addrspace.h>
-
-static inline unsigned long port88796l(unsigned int port, int flag)
-{
-       unsigned long addr;
-
-       if (flag)
-               addr = PA_AX88796L + ((port - AX88796L_IO_BASE) << 1);
-       else
-               addr = PA_AX88796L + ((port - AX88796L_IO_BASE) << 1) + 0x1000;
-
-       return addr;
-}
-
-#if defined(CONFIG_NE2000) || defined(CONFIG_NE2000_MODULE)
-#define CHECK_AX88796L_PORT(port) \
-  ((port >= AX88796L_IO_BASE) && (port < (AX88796L_IO_BASE+0x20)))
-#else
-#define CHECK_AX88796L_PORT(port) (0)
-#endif
-
-/*
- * General outline: remap really low stuff [eventually] to SuperIO,
- * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
- * is mapped through the PCI IO window.  Stuff with high bits (PXSEG)
- * should be way beyond the window, and is used  w/o translation for
- * compatibility.
- */
-u8 r7780rp_inb(unsigned long port)
-{
-       if (CHECK_AX88796L_PORT(port))
-               return ctrl_inw(port88796l(port, 0)) & 0xff;
-       else if (is_pci_ioaddr(port))
-               return ctrl_inb(pci_ioaddr(port));
-
-       return ctrl_inw(port) & 0xff;
-}
-
-u8 r7780rp_inb_p(unsigned long port)
-{
-       u8 v;
-
-       if (CHECK_AX88796L_PORT(port))
-               v = ctrl_inw(port88796l(port, 0)) & 0xff;
-       else if (is_pci_ioaddr(port))
-               v = ctrl_inb(pci_ioaddr(port));
-       else
-               v = ctrl_inw(port) & 0xff;
-
-       ctrl_delay();
-
-       return v;
-}
-
-u16 r7780rp_inw(unsigned long port)
-{
-       if (is_pci_ioaddr(port))
-               return ctrl_inw(pci_ioaddr(port));
-
-       return ctrl_inw(port);
-}
-
-u32 r7780rp_inl(unsigned long port)
-{
-       if (is_pci_ioaddr(port))
-               return ctrl_inl(pci_ioaddr(port));
-
-       return ctrl_inl(port);
-}
-
-void r7780rp_outb(u8 value, unsigned long port)
-{
-       if (CHECK_AX88796L_PORT(port))
-               ctrl_outw(value, port88796l(port, 0));
-       else if (is_pci_ioaddr(port))
-               ctrl_outb(value, pci_ioaddr(port));
-       else
-               ctrl_outb(value, port);
-}
-
-void r7780rp_outb_p(u8 value, unsigned long port)
-{
-       if (CHECK_AX88796L_PORT(port))
-               ctrl_outw(value, port88796l(port, 0));
-       else if (is_pci_ioaddr(port))
-               ctrl_outb(value, pci_ioaddr(port));
-       else
-               ctrl_outb(value, port);
-
-       ctrl_delay();
-}
-
-void r7780rp_outw(u16 value, unsigned long port)
-{
-       if (is_pci_ioaddr(port))
-               ctrl_outw(value, pci_ioaddr(port));
-       else
-               ctrl_outw(value, port);
-}
-
-void r7780rp_outl(u32 value, unsigned long port)
-{
-       if (is_pci_ioaddr(port))
-               ctrl_outl(value, pci_ioaddr(port));
-       else
-               ctrl_outl(value, port);
-}
-
-void r7780rp_insb(unsigned long port, void *dst, unsigned long count)
-{
-       volatile u16 *p;
-       u8 *buf = dst;
-
-       if (CHECK_AX88796L_PORT(port)) {
-               p = (volatile u16 *)port88796l(port, 0);
-               while (count--)
-                       *buf++ = *p & 0xff;
-       } else if (is_pci_ioaddr(port)) {
-               volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
-
-               while (count--)
-                       *buf++ = *bp;
-       } else {
-               p = (volatile u16 *)port;
-               while (count--)
-                       *buf++ = *p & 0xff;
-       }
-}
-
-void r7780rp_insw(unsigned long port, void *dst, unsigned long count)
-{
-       volatile u16 *p;
-       u16 *buf = dst;
-
-       if (CHECK_AX88796L_PORT(port))
-               p = (volatile u16 *)port88796l(port, 1);
-       else if (is_pci_ioaddr(port))
-               p = (volatile u16 *)pci_ioaddr(port);
-       else
-               p = (volatile u16 *)port;
-
-       while (count--)
-               *buf++ = *p;
-
-       flush_dcache_all();
-}
-
-void r7780rp_insl(unsigned long port, void *dst, unsigned long count)
-{
-       if (is_pci_ioaddr(port)) {
-               volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
-               u32 *buf = dst;
-
-               while (count--)
-                       *buf++ = *p;
-       }
-}
-
-void r7780rp_outsb(unsigned long port, const void *src, unsigned long count)
-{
-       volatile u16 *p;
-       const u8 *buf = src;
-
-       if (CHECK_AX88796L_PORT(port)) {
-               p = (volatile u16 *)port88796l(port, 0);
-               while (count--)
-                       *p = *buf++;
-       } else if (is_pci_ioaddr(port)) {
-               volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
-
-               while (count--)
-                       *bp = *buf++;
-       } else
-               while (count--)
-                       ctrl_outb(*buf++, port);
-}
-
-void r7780rp_outsw(unsigned long port, const void *src, unsigned long count)
-{
-       volatile u16 *p;
-       const u16 *buf = src;
-
-       if (CHECK_AX88796L_PORT(port))
-               p = (volatile u16 *)port88796l(port, 1);
-       else if (is_pci_ioaddr(port))
-               p = (volatile u16 *)pci_ioaddr(port);
-       else
-               p = (volatile u16 *)port;
-
-       while (count--)
-               *p = *buf++;
-
-       flush_dcache_all();
-}
-
-void r7780rp_outsl(unsigned long port, const void *src, unsigned long count)
-{
-       const u32 *buf = src;
-       u32 *p;
-
-       if (is_pci_ioaddr(port))
-               p = (u32 *)pci_ioaddr(port);
-       else
-               p = (u32 *)port;
-
-       while (count--)
-               ctrl_outl(*buf++, (unsigned long)p);
-}
-
-void __iomem *r7780rp_ioport_map(unsigned long port, unsigned int size)
-{
-       if (CHECK_AX88796L_PORT(port))
-               return (void __iomem *)port88796l(port, size > 1);
-       else if (is_pci_ioaddr(port))
-               return (void __iomem *)pci_ioaddr(port);
-
-       return (void __iomem *)port;
-}
index 0d74db9f179298fcd4c86e5333d39dcf76131082..2faba6679e64cc2321874105b9b0b5ff5a8cac85 100644 (file)
@@ -187,31 +187,7 @@ static void __init r7780rp_setup(char **cmdline_p)
 struct sh_machine_vector mv_r7780rp __initmv = {
        .mv_name                = "Highlander R7780RP-1",
        .mv_setup               = r7780rp_setup,
-
        .mv_nr_irqs             = 109,
-
-       .mv_inb                 = r7780rp_inb,
-       .mv_inw                 = r7780rp_inw,
-       .mv_inl                 = r7780rp_inl,
-       .mv_outb                = r7780rp_outb,
-       .mv_outw                = r7780rp_outw,
-       .mv_outl                = r7780rp_outl,
-
-       .mv_inb_p               = r7780rp_inb_p,
-       .mv_inw_p               = r7780rp_inw,
-       .mv_inl_p               = r7780rp_inl,
-       .mv_outb_p              = r7780rp_outb_p,
-       .mv_outw_p              = r7780rp_outw,
-       .mv_outl_p              = r7780rp_outl,
-
-       .mv_insb                = r7780rp_insb,
-       .mv_insw                = r7780rp_insw,
-       .mv_insl                = r7780rp_insl,
-       .mv_outsb               = r7780rp_outsb,
-       .mv_outsw               = r7780rp_outsw,
-       .mv_outsl               = r7780rp_outsl,
-
-       .mv_ioport_map          = r7780rp_ioport_map,
        .mv_init_irq            = init_r7780rp_IRQ,
 };
 ALIAS_MV(r7780rp)
index 44b42082a0afe721a7f9776e80c327652734c15f..593f26a85e9c1b15de194a36d6abad3899fd0382 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/platform_device.h>
 #include <linux/pata_platform.h>
 #include <linux/serial_8250.h>
+#include <linux/sm501.h>
 #include <linux/pm.h>
 #include <asm/machvec.h>
 #include <asm/rts7751r2d.h>
@@ -111,10 +112,35 @@ static struct platform_device heartbeat_device = {
        .resource       = heartbeat_resources,
 };
 
+static struct resource sm501_resources[] = {
+       [0]     = {
+               .start  = 0x10000000,
+               .end    = 0x13e00000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1]     = {
+               .start  = 0x13e00000,
+               .end    = 0x13ffffff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [2]     = {
+               .start  = 32,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device sm501_device = {
+       .name           = "sm501",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(sm501_resources),
+       .resource       = sm501_resources,
+};
+
 static struct platform_device *rts7751r2d_devices[] __initdata = {
        &uart_device,
        &heartbeat_device,
        &cf_ide_device,
+       &sm501_device,
 };
 
 static int __init rts7751r2d_devices_setup(void)
index db6a02df5af680eef0b5c74dcaa4fee5e0ec1596..a59bb78bd071e01c58fec3a7c065b0b57a034870 100644 (file)
@@ -1,14 +1,13 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Thu Feb 15 17:17:29 2007
+# Linux kernel version: 2.6.21-rc1
+# Thu Mar  1 16:42:40 2007
 #
 CONFIG_SUPERH=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 # CONFIG_GENERIC_TIME is not set
@@ -33,6 +32,7 @@ CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
@@ -119,7 +119,6 @@ CONFIG_SH_RTS7751R2D=y
 # CONFIG_SH_SHMIN is not set
 # CONFIG_SH_7206_SOLUTION_ENGINE is not set
 # CONFIG_SH_7619_SOLUTION_ENGINE is not set
-# CONFIG_SH_ASDAP310 is not set
 # CONFIG_SH_UNKNOWN is not set
 
 #
@@ -281,7 +280,7 @@ CONFIG_ZERO_PAGE_OFFSET=0x00010000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
 # CONFIG_UBC_WAKEUP is not set
 CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda1"
+CONFIG_CMDLINE="console=tty0 console=ttySC0,115200 root=/dev/sda1"
 
 #
 # Bus options
@@ -433,6 +432,7 @@ CONFIG_FW_LOADER=m
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -770,7 +770,26 @@ CONFIG_NET_WIRELESS=y
 #
 # Input device support
 #
-# CONFIG_INPUT is not set
+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
@@ -781,7 +800,10 @@ CONFIG_NET_WIRELESS=y
 #
 # Character devices
 #
-# CONFIG_VT is not set
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -856,6 +878,11 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_SM501=y
+
 #
 # Multimedia devices
 #
@@ -869,9 +896,66 @@ CONFIG_HWMON=y
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
-# CONFIG_FB is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frambuffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_EPSON1355 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+CONFIG_FB_SM501=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+# CONFIG_LOGO_SUPERH_MONO is not set
+# CONFIG_LOGO_SUPERH_VGA16 is not set
+CONFIG_LOGO_SUPERH_CLUT224=y
 
 #
 # Sound
@@ -984,6 +1068,12 @@ CONFIG_SOUND_PRIME=m
 # CONFIG_SOUND_VIA82CXXX is not set
 CONFIG_AC97_BUS=m
 
+#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
 #
 # USB support
 #
@@ -1237,7 +1327,7 @@ CONFIG_LOG_BUF_SHIFT=14
 CONFIG_EARLY_SCIF_CONSOLE=y
 CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffe80000
 CONFIG_EARLY_PRINTK=y
-# CONFIG_KGDB is not set
+# CONFIG_SH_KGDB is not set
 
 #
 # Security options
index ab4ebb856c2a3cc7ca9f2e75ceb94c32ebdc1c22..b46728027195b15747b7b43f18a7e35e0a687623 100644 (file)
@@ -224,7 +224,7 @@ work_resched:
 syscall_exit_work:
        ! r0: current_thread_info->flags
        ! r8: current_thread_info
-       tst     #_TIF_SYSCALL_TRACE, r0
+       tst     #_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP, r0
        bt/s    work_pending
         tst    #_TIF_NEED_RESCHED, r0
 #ifdef CONFIG_TRACE_IRQFLAGS
index 66626c03e1eeb4b8e72f09871f6e83f1daa1b1c5..771ea42304410c7f706b95e5b59fb97da5884916 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/module.h>
 #include <linux/io.h>
 #include <asm/machvec.h>
-#include <asm/cacheflush.h>
 
 #ifdef CONFIG_CPU_SH3
 /* SH3 has a PCMCIA bug that needs a dummy read from area 6 for a
@@ -96,7 +95,6 @@ void generic_insw(unsigned long port, void *dst, unsigned long count)
        while (count--)
                *buf++ = *port_addr;
 
-       flush_dcache_all();
        dummy_read();
 }
 
@@ -171,7 +169,6 @@ void generic_outsw(unsigned long port, const void *src, unsigned long count)
        while (count--)
                *port_addr = *buf++;
 
-       flush_dcache_all();
        dummy_read();
 }
 
index 9d6a438b3eaf7a8e7692e69eab757886c9ee952d..e7607366ac4e7e2a7998b9ad793ade86d4f08c56 100644 (file)
@@ -250,12 +250,11 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
                childregs->regs[15] = usp;
                ti->addr_limit = USER_DS;
        } else {
-               childregs->regs[15] = (unsigned long)task_stack_page(p) +
-                                                       THREAD_SIZE;
+               childregs->regs[15] = (unsigned long)childregs;
                ti->addr_limit = KERNEL_DS;
        }
 
-        if (clone_flags & CLONE_SETTLS)
+       if (clone_flags & CLONE_SETTLS)
                childregs->gbr = childregs->regs[0];
 
        childregs->regs[0] = 0; /* Set return value for child */
index 04ca13a041c160127077dddab6cfd507368fb319..855f7246cfffb4a4d597a11bd5ffc654a32e348a 100644 (file)
@@ -8,7 +8,6 @@
  * SuperH version:   Copyright (C) 1999, 2000  Kaz Kojima & Niibe Yutaka
  *
  */
-
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
@@ -20,8 +19,7 @@
 #include <linux/slab.h>
 #include <linux/security.h>
 #include <linux/signal.h>
-
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -59,6 +57,23 @@ static inline int put_stack_long(struct task_struct *task, int offset,
        return 0;
 }
 
+static void ptrace_disable_singlestep(struct task_struct *child)
+{
+       clear_tsk_thread_flag(child, TIF_SINGLESTEP);
+
+       /*
+        * Ensure the UBC is not programmed at the next context switch.
+        *
+        * Normally this is not needed but there are sequences such as
+        * singlestep, signal delivery, and continue that leave the
+        * ubc_pc non-zero leading to spurious SIGTRAPs.
+        */
+       if (child->thread.ubc_pc != 0) {
+               ubc_usercnt -= 1;
+               child->thread.ubc_pc = 0;
+       }
+}
+
 /*
  * Called by kernel/ptrace.c when detaching..
  *
@@ -66,7 +81,7 @@ static inline int put_stack_long(struct task_struct *task, int offset,
  */
 void ptrace_disable(struct task_struct *child)
 {
-       /* nothing to do.. */
+       ptrace_disable_singlestep(child);
 }
 
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
@@ -76,7 +91,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 
        switch (request) {
        /* when I and D space are separate, these will need to be fixed. */
-       case PTRACE_PEEKTEXT: /* read word at location addr. */ 
+       case PTRACE_PEEKTEXT: /* read word at location addr. */
        case PTRACE_PEEKDATA: {
                unsigned long tmp;
                int copied;
@@ -94,7 +109,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                unsigned long tmp;
 
                ret = -EIO;
-               if ((addr & 3) || addr < 0 || 
+               if ((addr & 3) || addr < 0 ||
                    addr > sizeof(struct user) - 3)
                        break;
 
@@ -129,7 +144,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 
        case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
                ret = -EIO;
-               if ((addr & 3) || addr < 0 || 
+               if ((addr & 3) || addr < 0 ||
                    addr > sizeof(struct user) - 3)
                        break;
 
@@ -156,6 +171,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                        set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
                else
                        clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+
+               ptrace_disable_singlestep(child);
+
                child->exit_code = data;
                wake_up_process(child);
                ret = 0;
@@ -163,14 +181,15 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
        }
 
 /*
- * make the child exit.  Best I can do is send it a sigkill. 
- * perhaps it should be put in the status that it wants to 
+ * make the child exit.  Best I can do is send it a sigkill.
+ * perhaps it should be put in the status that it wants to
  * exit.
  */
        case PTRACE_KILL: {
                ret = 0;
                if (child->exit_state == EXIT_ZOMBIE)   /* already dead */
                        break;
+               ptrace_disable_singlestep(child);
                child->exit_code = SIGKILL;
                wake_up_process(child);
                break;
@@ -196,6 +215,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                        ubc_usercnt += 1;
                child->thread.ubc_pc = pc;
 
+               set_tsk_thread_flag(child, TIF_SINGLESTEP);
                child->exit_code = data;
                /* give it a chance to run. */
                wake_up_process(child);
@@ -248,14 +268,15 @@ asmlinkage void do_syscall_trace(void)
 {
        struct task_struct *tsk = current;
 
-       if (!test_thread_flag(TIF_SYSCALL_TRACE))
+       if (!test_thread_flag(TIF_SYSCALL_TRACE) &&
+           !test_thread_flag(TIF_SINGLESTEP))
                return;
        if (!(tsk->ptrace & PT_PTRACED))
                return;
        /* the 0x80 provides a way for the tracing parent to distinguish
           between a syscall stop and SIGTRAP delivery */
-       ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-                                ? 0x80 : 0));
+       ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) &&
+                                !test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0));
 
        /*
         * this isn't the same as continuing with a signal, but it will do
index 32f10a03fbb5e9388d27d1d889dffbff3df03b03..9f39ef1f73dae8402c115dd92e854fce972ff2f5 100644 (file)
@@ -589,6 +589,8 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
                        if (test_thread_flag(TIF_RESTORE_SIGMASK))
                                clear_thread_flag(TIF_RESTORE_SIGMASK);
                }
+
+               return;
        }
 
  no_signal:
@@ -598,7 +600,7 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
                if (regs->regs[0] == -ERESTARTNOHAND ||
                    regs->regs[0] == -ERESTARTSYS ||
                    regs->regs[0] == -ERESTARTNOINTR) {
-                       regs->regs[0] = save_r0;
+                       regs->regs[0] = save_r0;
                        regs->pc -= 2;
                } else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) {
                        regs->pc -= 2;
index 75de165867a0e75a83ac4220c493c5b10a530bfb..78a6c09875b2b6b3dc17fc18e4855a666de69668 100644 (file)
@@ -3,6 +3,7 @@
  * Written by Niibe Yutaka
  */
 #include <asm/thread_info.h>
+#include <asm/cache.h>
 #include <asm-generic/vmlinux.lds.h>
 
 #ifdef CONFIG_CPU_LITTLE_ENDIAN
@@ -53,7 +54,7 @@ SECTIONS
   . = ALIGN(PAGE_SIZE);
   .data.page_aligned : { *(.data.page_aligned) }
 
-  . = ALIGN(32);
+  . = ALIGN(L1_CACHE_BYTES);
   __per_cpu_start = .;
   .data.percpu : { *(.data.percpu) }
   __per_cpu_end = .;
index e0cd4b7f4aeb4d510ad74680b8c89aa18781f978..981b04089055cf9fc0987eb3a0f83d38f98346d1 100644 (file)
@@ -237,20 +237,10 @@ static inline void flush_cache_4096(unsigned long start,
 /*
  * Write back & invalidate the D-cache of the page.
  * (To avoid "alias" issues)
- *
- * This uses a lazy write-back on UP, which is explicitly
- * disabled on SMP.
  */
 void flush_dcache_page(struct page *page)
 {
-#ifndef CONFIG_SMP
-       struct address_space *mapping = page_mapping(page);
-
-       if (mapping && !mapping_mapped(mapping))
-               set_bit(PG_dcache_dirty, &page->flags);
-       else
-#endif
-       {
+       if (test_bit(PG_mapped, &page->flags)) {
                unsigned long phys = PHYSADDR(page_address(page));
                unsigned long addr = CACHE_OC_ADDRESS_ARRAY;
                int i, n;
index 31f8deb7a158e410b61069a2a4aa6320cb397b1f..4896d737692616146f497492b8a399ac1ef7ae3d 100644 (file)
@@ -3,11 +3,11 @@
  *
  * Copyright (C) 1999, 2000  Niibe Yutaka
  * Copyright (C) 2004  Alex Song
- * 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 <linux/init.h>
 #include <linux/mman.h>
@@ -51,6 +51,7 @@ static inline void cache_wback_all(void)
 
                        if ((data & v) == v)
                                ctrl_outl(data & ~v, addr);
+
                }
 
                addrstart += current_cpu_data.dcache.way_incr;
@@ -127,11 +128,7 @@ static void __flush_dcache_page(unsigned long phys)
  */
 void flush_dcache_page(struct page *page)
 {
-       struct address_space *mapping = page_mapping(page);
-
-       if (mapping && !mapping_mapped(mapping))
-               set_bit(PG_dcache_dirty, &page->flags);
-       else
+       if (test_bit(PG_mapped, &page->flags))
                __flush_dcache_page(PHYSADDR(page_address(page)));
 }
 
index 969efeceb9282ae1b434dfc025a9728923e696c2..df69da9ca69c7685e48a709924e58c175836ebe3 100644 (file)
@@ -23,6 +23,7 @@ extern struct mutex p3map_mutex[];
  */
 void clear_user_page(void *to, unsigned long address, struct page *page)
 {
+       __set_bit(PG_mapped, &page->flags);
        if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
                clear_page(to);
        else {
@@ -58,6 +59,7 @@ void clear_user_page(void *to, unsigned long address, struct page *page)
 void copy_user_page(void *to, void *from, unsigned long address,
                    struct page *page)
 {
+       __set_bit(PG_mapped, &page->flags);
        if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
                copy_page(to, from);
        else {
@@ -82,3 +84,23 @@ void copy_user_page(void *to, void *from, unsigned long address,
                mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]);
        }
 }
+
+/*
+ * For SH-4, we have our own implementation for ptep_get_and_clear
+ */
+inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+       pte_t pte = *ptep;
+
+       pte_clear(mm, addr, ptep);
+       if (!pte_not_present(pte)) {
+               unsigned long pfn = pte_pfn(pte);
+               if (pfn_valid(pfn)) {
+                       struct page *page = pfn_to_page(pfn);
+                       struct address_space *mapping = page_mapping(page);
+                       if (!mapping || !mapping_writably_mapped(mapping))
+                               __clear_bit(PG_mapped, &page->flags);
+               }
+       }
+       return pte;
+}
index 887ab9d18ccd25b16d4e5bc8d6d50db5f6020192..a4b015f95a3ad379b69e9f2bffe13bcce3aa1450 100644 (file)
@@ -7,7 +7,9 @@
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
+ *
  */
+
 #include <linux/init.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
@@ -74,6 +76,7 @@ void clear_user_page(void *to, unsigned long address, struct page *pg)
 {
        struct page *page = virt_to_page(to);
 
+       __set_bit(PG_mapped, &page->flags);
        if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) {
                clear_page(to);
                __flush_wback_region(to, PAGE_SIZE);
@@ -92,11 +95,12 @@ void clear_user_page(void *to, unsigned long address, struct page *pg)
  * @from: P1 address
  * @address: U0 address to be mapped
  */
-void copy_user_page(void *to, void *from, unsigned long address,
-                   struct page *pg)
+void copy_user_page(void *to, void *from, unsigned long address, struct page *pg)
 {
        struct page *page = virt_to_page(to);
 
+
+       __set_bit(PG_mapped, &page->flags);
        if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) {
                copy_page(to, from);
                __flush_wback_region(to, PAGE_SIZE);
@@ -108,3 +112,26 @@ void copy_user_page(void *to, void *from, unsigned long address,
                __flush_wback_region(to, PAGE_SIZE);
        }
 }
+
+/*
+ * For SH7705, we have our own implementation for ptep_get_and_clear
+ * Copied from pg-sh4.c
+ */
+inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+       pte_t pte = *ptep;
+
+       pte_clear(mm, addr, ptep);
+       if (!pte_not_present(pte)) {
+               unsigned long pfn = pte_pfn(pte);
+               if (pfn_valid(pfn)) {
+                       struct page *page = pfn_to_page(pfn);
+                       struct address_space *mapping = page_mapping(page);
+                       if (!mapping || !mapping_writably_mapped(mapping))
+                               __clear_bit(PG_mapped, &page->flags);
+               }
+       }
+
+       return pte;
+}
+
index d2f7b4a2eb05356339a0599638c935c08fd9d0fd..6f45c1f8a7fedd72a3d839190cfa33d5acc4d53e 100644 (file)
@@ -2,17 +2,15 @@
  * TLB flushing operations for SH with an MMU.
  *
  *  Copyright (C) 1999  Niibe Yutaka
- *  Copyright (C) 2003 - 2006  Paul Mundt
+ *  Copyright (C) 2003  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 <linux/mm.h>
-#include <linux/io.h>
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
-#include <asm/cacheflush.h>
 
 void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 {
@@ -140,54 +138,3 @@ void local_flush_tlb_all(void)
        ctrl_barrier();
        local_irq_restore(flags);
 }
-
-void update_mmu_cache(struct vm_area_struct *vma,
-                     unsigned long address, pte_t pte)
-{
-       unsigned long flags;
-       unsigned long pteval;
-       unsigned long vpn;
-       struct page *page;
-       unsigned long pfn = pte_pfn(pte);
-       struct address_space *mapping;
-
-       if (!pfn_valid(pfn))
-               return;
-
-       page = pfn_to_page(pfn);
-       mapping = page_mapping(page);
-       if (mapping) {
-               unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
-               int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
-
-               if (dirty)
-                       __flush_wback_region((void *)P1SEGADDR(phys),
-                                            PAGE_SIZE);
-       }
-
-       local_irq_save(flags);
-
-       /* Set PTEH register */
-       vpn = (address & MMU_VPN_MASK) | get_asid();
-       ctrl_outl(vpn, MMU_PTEH);
-
-       pteval = pte_val(pte);
-
-#ifdef CONFIG_CPU_HAS_PTEA
-       /* Set PTEA register */
-       /* TODO: make this look less hacky */
-       ctrl_outl(((pteval >> 28) & 0xe) | (pteval & 0x1), MMU_PTEA);
-#endif
-
-       /* Set PTEL register */
-       pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
-#if defined(CONFIG_SH_WRITETHROUGH) && defined(CONFIG_CPU_SH4)
-       pteval |= _PAGE_WT;
-#endif
-       /* conveniently, we want all the software flags to be 0 anyway */
-       ctrl_outl(pteval, MMU_PTEL);
-
-       /* Load the TLB */
-       asm volatile("ldtlb": /* no output */ : /* no input */ : "memory");
-       local_irq_restore(flags);
-}
index e5e76eb7ee09e1b2c6f118201335349847e0c4ec..7fbfd5a11ffae73860c64941240dff7ecbc03e51 100644 (file)
@@ -8,9 +8,69 @@
  *
  * Released under the terms of the GNU GPL v2.0.
  */
-#include <linux/io.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+
 #include <asm/system.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+
+void update_mmu_cache(struct vm_area_struct * vma,
+                     unsigned long address, pte_t pte)
+{
+       unsigned long flags;
+       unsigned long pteval;
+       unsigned long vpn;
+
+       /* Ptrace may call this routine. */
+       if (vma && current->active_mm != vma->vm_mm)
+               return;
+
+#if defined(CONFIG_SH7705_CACHE_32KB)
+       {
+               struct page *page = pte_page(pte);
+               unsigned long pfn = pte_pfn(pte);
+
+               if (pfn_valid(pfn) && !test_bit(PG_mapped, &page->flags)) {
+                       unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
+
+                       __flush_wback_region((void *)P1SEGADDR(phys),
+                                            PAGE_SIZE);
+                       __set_bit(PG_mapped, &page->flags);
+               }
+       }
+#endif
+
+       local_irq_save(flags);
+
+       /* Set PTEH register */
+       vpn = (address & MMU_VPN_MASK) | get_asid();
+       ctrl_outl(vpn, MMU_PTEH);
+
+       pteval = pte_val(pte);
+
+       /* Set PTEL register */
+       pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
+       /* conveniently, we want all the software flags to be 0 anyway */
+       ctrl_outl(pteval, MMU_PTEL);
+
+       /* Load the TLB */
+       asm volatile("ldtlb": /* no output */ : /* no input */ : "memory");
+       local_irq_restore(flags);
+}
 
 void local_flush_tlb_one(unsigned long asid, unsigned long page)
 {
@@ -34,3 +94,4 @@ void local_flush_tlb_one(unsigned long asid, unsigned long page)
        for (i = 0; i < ways; i++)
                ctrl_outl(data, addr + (i << 8));
 }
+
index 221e7095473d383348d57c9389f5f7be146ac34f..f74cf667c8fa8e4703d5936859c550c6a257b568 100644 (file)
@@ -8,9 +8,74 @@
  *
  * Released under the terms of the GNU GPL v2.0.
  */
-#include <linux/io.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+
 #include <asm/system.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+
+void update_mmu_cache(struct vm_area_struct * vma,
+                     unsigned long address, pte_t pte)
+{
+       unsigned long flags;
+       unsigned long pteval;
+       unsigned long vpn;
+       struct page *page;
+       unsigned long pfn;
+
+       /* Ptrace may call this routine. */
+       if (vma && current->active_mm != vma->vm_mm)
+               return;
+
+       pfn = pte_pfn(pte);
+       if (pfn_valid(pfn)) {
+               page = pfn_to_page(pfn);
+               if (!test_bit(PG_mapped, &page->flags)) {
+                       unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
+                       __flush_wback_region((void *)P1SEGADDR(phys), PAGE_SIZE);
+                       __set_bit(PG_mapped, &page->flags);
+               }
+       }
+
+       local_irq_save(flags);
+
+       /* Set PTEH register */
+       vpn = (address & MMU_VPN_MASK) | get_asid();
+       ctrl_outl(vpn, MMU_PTEH);
+
+       pteval = pte_val(pte);
+
+       /* Set PTEA register */
+       if (cpu_data->flags & CPU_HAS_PTEA)
+               /* TODO: make this look less hacky */
+               ctrl_outl(((pteval >> 28) & 0xe) | (pteval & 0x1), MMU_PTEA);
+
+       /* Set PTEL register */
+       pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
+#ifdef CONFIG_SH_WRITETHROUGH
+       pteval |= _PAGE_WT;
+#endif
+       /* conveniently, we want all the software flags to be 0 anyway */
+       ctrl_outl(pteval, MMU_PTEL);
+
+       /* Load the TLB */
+       asm volatile("ldtlb": /* no output */ : /* no input */ : "memory");
+       local_irq_restore(flags);
+}
 
 void local_flush_tlb_one(unsigned long asid, unsigned long page)
 {
@@ -28,3 +93,4 @@ void local_flush_tlb_one(unsigned long asid, unsigned long page)
        ctrl_outl(data, addr);
        back_to_P1();
 }
+
index dab6169e31ca42467a211a7570f863a08e250aff..48c24f7518c24e3ccd8c3b6ae127111c5c194518 100644 (file)
@@ -495,7 +495,7 @@ static void __init build_device_resources(struct of_device *op,
                u32 *reg = (preg + (index * ((na + ns) * 4)));
                struct device_node *dp = op->node;
                struct device_node *pp = p_op->node;
-               struct of_bus *pbus;
+               struct of_bus *pbus, *dbus;
                u64 size, result = OF_BAD_ADDR;
                unsigned long flags;
                int dna, dns;
@@ -516,6 +516,7 @@ static void __init build_device_resources(struct of_device *op,
 
                dna = na;
                dns = ns;
+               dbus = bus;
 
                while (1) {
                        dp = pp;
@@ -528,13 +529,13 @@ static void __init build_device_resources(struct of_device *op,
                        pbus = of_match_bus(pp);
                        pbus->count_cells(dp, &pna, &pns);
 
-                       if (build_one_resource(dp, bus, pbus, addr,
+                       if (build_one_resource(dp, dbus, pbus, addr,
                                               dna, dns, pna))
                                break;
 
                        dna = pna;
                        dns = pns;
-                       bus = pbus;
+                       dbus = pbus;
                }
 
        build_res:
@@ -549,9 +550,6 @@ static void __init build_device_resources(struct of_device *op,
                        r->start = result & 0xffffffff;
                        r->end = result + size - 1;
                        r->flags = flags | ((result >> 32ULL) & 0xffUL);
-               } else {
-                       r->start = ~0UL;
-                       r->end = ~0UL;
                }
                r->name = op->node->name;
        }
index 207f1b6eef5317baee833ff636488ed6fcbd36bb..3fa5f95c4614dac56b67ffc7285901588ee28cf3 100644 (file)
@@ -944,6 +944,14 @@ int pcibios_assign_resource(struct pci_dev *pdev, int resource)
        return -ENXIO;
 }
 
+struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
+{
+       struct pcidev_cookie *pc = pdev->sysdata;
+
+       return pc->prom_node;
+}
+EXPORT_SYMBOL(pci_device_to_OF_node);
+
 /*
  * This probably belongs here rather than ioport.c because
  * we do not want this crud linked into SBus kernels.
index 0f44a6a6675fa4d93a2cf9790f1f7dbf203c4953..860b8b60526c77bc4b722c6daf0a5a954e6d59f7 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Sun Feb 11 23:47:40 2007
+# Linux kernel version: 2.6.21-rc2
+# Wed Feb 28 09:50:51 2007
 #
 CONFIG_SPARC=y
 CONFIG_SPARC64=y
@@ -41,6 +41,7 @@ CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
@@ -322,6 +323,7 @@ CONFIG_CONNECTOR=m
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -787,6 +789,7 @@ CONFIG_I2C_ALGOBIT=y
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PASEMI is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
 # CONFIG_I2C_SIS5595 is not set
@@ -833,6 +836,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ADM9240 is not set
 # CONFIG_SENSORS_ASB100 is not set
@@ -873,6 +877,11 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_W83627EHF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
 #
 # Multimedia devices
 #
@@ -887,16 +896,22 @@ CONFIG_HWMON=y
 #
 # Graphics support
 #
-# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
 CONFIG_FB_DDC=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
+
+#
+# Frambuffer hardware drivers
+#
 # CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_ASILIANT is not set
@@ -908,9 +923,11 @@ CONFIG_FB_TILEBLITTING=y
 # CONFIG_FB_MATROX is not set
 CONFIG_FB_RADEON=y
 CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_RADEON_BACKLIGHT is not set
 # CONFIG_FB_RADEON_DEBUG is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
 # CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
 # CONFIG_FB_NEOMAGIC is not set
@@ -947,7 +964,6 @@ CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_VGA16 is not set
 # CONFIG_LOGO_LINUX_CLUT224 is not set
 CONFIG_LOGO_SUN_CLUT224=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -1192,6 +1208,7 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -1202,6 +1219,7 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -1445,9 +1463,11 @@ CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_LOG_BUF_SHIFT=18
 CONFIG_DETECT_SOFTLOCKUP=y
 CONFIG_SCHEDSTATS=y
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
@@ -1465,6 +1485,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_LKDTM is not set
+# CONFIG_FAULT_INJECTION is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_DEBUG_DCFLUSH is not set
 # CONFIG_STACK_DEBUG is not set
index b5ff3ee5ace1cc23d3a86cd50878568b505ea7d8..c443db1843719f9937463adea56b10ad6690f5ef 100644 (file)
@@ -109,6 +109,7 @@ static unsigned char virt_irq_alloc(unsigned int real_irq)
        return ent;
 }
 
+#ifdef CONFIG_PCI_MSI
 static void virt_irq_free(unsigned int virt_irq)
 {
        unsigned int real_irq;
@@ -121,6 +122,7 @@ static void virt_irq_free(unsigned int virt_irq)
 
        __bucket(real_irq)->virt_irq = 0;
 }
+#endif
 
 static unsigned int virt_to_real_irq(unsigned char virt_irq)
 {
index b0f3e0082a0da113fc31eedb484c44ae5c10a9b7..fb9bf1e4d036138214d418081c7c38d54340a060 100644 (file)
@@ -581,7 +581,7 @@ static void __init build_device_resources(struct of_device *op,
                u32 *reg = (preg + (index * ((na + ns) * 4)));
                struct device_node *dp = op->node;
                struct device_node *pp = p_op->node;
-               struct of_bus *pbus;
+               struct of_bus *pbus, *dbus;
                u64 size, result = OF_BAD_ADDR;
                unsigned long flags;
                int dna, dns;
@@ -599,6 +599,7 @@ static void __init build_device_resources(struct of_device *op,
 
                dna = na;
                dns = ns;
+               dbus = bus;
 
                while (1) {
                        dp = pp;
@@ -611,13 +612,13 @@ static void __init build_device_resources(struct of_device *op,
                        pbus = of_match_bus(pp);
                        pbus->count_cells(dp, &pna, &pns);
 
-                       if (build_one_resource(dp, bus, pbus, addr,
+                       if (build_one_resource(dp, dbus, pbus, addr,
                                               dna, dns, pna))
                                break;
 
                        dna = pna;
                        dns = pns;
-                       bus = pbus;
+                       dbus = pbus;
                }
 
        build_res:
@@ -635,9 +636,6 @@ static void __init build_device_resources(struct of_device *op,
                        r->start = result;
                        r->end = result + size - 1;
                        r->flags = flags;
-               } else {
-                       r->start = ~0UL;
-                       r->end = ~0UL;
                }
                r->name = op->node->name;
        }
@@ -708,7 +706,7 @@ static unsigned int __init pci_irq_swizzle(struct device_node *dp,
                                           unsigned int irq)
 {
        struct linux_prom_pci_registers *regs;
-       unsigned int devfn, slot, ret;
+       unsigned int bus, devfn, slot, ret;
 
        if (irq < 1 || irq > 4)
                return irq;
@@ -717,10 +715,46 @@ static unsigned int __init pci_irq_swizzle(struct device_node *dp,
        if (!regs)
                return irq;
 
+       bus = (regs->phys_hi >> 16) & 0xff;
        devfn = (regs->phys_hi >> 8) & 0xff;
        slot = (devfn >> 3) & 0x1f;
 
-       ret = ((irq - 1 + (slot & 3)) & 3) + 1;
+       if (pp->irq_trans) {
+               /* Derived from Table 8-3, U2P User's Manual.  This branch
+                * is handling a PCI controller that lacks a proper set of
+                * interrupt-map and interrupt-map-mask properties.  The
+                * Ultra-E450 is one example.
+                *
+                * The bit layout is BSSLL, where:
+                * B: 0 on bus A, 1 on bus B
+                * D: 2-bit slot number, derived from PCI device number as
+                *    (dev - 1) for bus A, or (dev - 2) for bus B
+                * L: 2-bit line number
+                *
+                * Actually, more "portable" way to calculate the funky
+                * slot number is to subtract pbm->pci_first_slot from the
+                * device number, and that's exactly what the pre-OF
+                * sparc64 code did, but we're building this stuff generically
+                * using the OBP tree, not in the PCI controller layer.
+                */
+               if (bus & 0x80) {
+                       /* PBM-A */
+                       bus  = 0x00;
+                       slot = (slot - 1) << 2;
+               } else {
+                       /* PBM-B */
+                       bus  = 0x10;
+                       slot = (slot - 2) << 2;
+               }
+               irq -= 1;
+
+               ret = (bus | slot | irq);
+       } else {
+               /* Going through a PCI-PCI bridge that lacks a set of
+                * interrupt-map and interrupt-map-mask properties.
+                */
+               ret = ((irq - 1 + (slot & 3)) & 3) + 1;
+       }
 
        return ret;
 }
index 6b740eb6fe7e45915a0e4372cf496036b3d3fb23..196b4b72482bd80f7f58a1caf44fcf23a3c66545 100644 (file)
@@ -668,7 +668,7 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
 
 void arch_teardown_msi_irq(unsigned int virt_irq)
 {
-       struct msi_desc *entry = get_irq_data(virt_irq);
+       struct msi_desc *entry = get_irq_msi(virt_irq);
        struct pci_dev *pdev = entry->dev;
        struct pcidev_cookie *pcp = pdev->sysdata;
        struct pci_pbm_info *pbm = pcp->pbm;
@@ -681,4 +681,12 @@ void arch_teardown_msi_irq(unsigned int virt_irq)
 }
 #endif /* !(CONFIG_PCI_MSI) */
 
+struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
+{
+       struct pcidev_cookie *pc = pdev->sysdata;
+
+       return pc->op->node;
+}
+EXPORT_SYMBOL(pci_device_to_OF_node);
+
 #endif /* !(CONFIG_PCI) */
index e03e40c7aac35472e5139152a2158b0285c76bd8..a5b079d5e8658724ae0f762cae44329f38600ff2 100644 (file)
@@ -146,6 +146,25 @@ config LEGACY_PTYS
          security.  This option enables these legacy devices; on most
          systems, it is safe to say N.
 
+config RAW_DRIVER
+        tristate "RAW driver (/dev/raw/rawN) (OBSOLETE)"
+        help
+          The raw driver permits block devices to be bound to /dev/raw/rawN.
+          Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O.
+          See the raw(8) manpage for more details.
+
+          The raw driver is deprecated and will be removed soon.
+          Applications should simply open the device (eg /dev/hda1)
+          with the O_DIRECT flag.
+
+config MAX_RAW_DEVS
+        int "Maximum number of RAW devices to support (1-8192)"
+        depends on RAW_DRIVER
+        default "256"
+        help
+          The maximum number of RAW devices that are supported.
+          Default is 256. Increase this number in case you need lots of
+          raw devices.
 
 config LEGACY_PTY_COUNT
        int "Maximum number of legacy PTY in use"
index 310af0f1e49e4a7fa2b78609ed5e46c200cba721..021b82c7a759b94eb212b90abaceb5f7618f4b31 100644 (file)
@@ -56,30 +56,31 @@ static int connect_to_switch(struct daemon_data *pri)
 
        pri->control = socket(AF_UNIX, SOCK_STREAM, 0);
        if(pri->control < 0){
+               err = -errno;
                printk("daemon_open : control socket failed, errno = %d\n", 
-                      errno);          
-               return(-errno);
+                      -err);
+               return err;
        }
 
        if(connect(pri->control, (struct sockaddr *) ctl_addr, 
                   sizeof(*ctl_addr)) < 0){
-               printk("daemon_open : control connect failed, errno = %d\n",
-                      errno);
                err = -errno;
+               printk("daemon_open : control connect failed, errno = %d\n",
+                      -err);
                goto out;
        }
 
        fd = socket(AF_UNIX, SOCK_DGRAM, 0);
        if(fd < 0){
-               printk("daemon_open : data socket failed, errno = %d\n", 
-                      errno);
                err = -errno;
+               printk("daemon_open : data socket failed, errno = %d\n",
+                      -err);
                goto out;
        }
        if(bind(fd, (struct sockaddr *) local_addr, sizeof(*local_addr)) < 0){
-               printk("daemon_open : data bind failed, errno = %d\n", 
-                      errno);
                err = -errno;
+               printk("daemon_open : data bind failed, errno = %d\n",
+                      -err);
                goto out_close;
        }
 
index 01d4ab6b0ef1889582f4d5defb4142138b0141f0..f75d7b05c4817c592dce829ec45b3f4b2de307fb 100644 (file)
@@ -370,10 +370,10 @@ static irqreturn_t line_write_interrupt(int irq, void *data)
        struct tty_struct *tty = line->tty;
        int err;
 
-       /* Interrupts are enabled here because we registered the interrupt with
+       /* Interrupts are disabled here because we registered the interrupt with
         * IRQF_DISABLED (see line_setup_irq).*/
 
-       spin_lock_irq(&line->lock);
+       spin_lock(&line->lock);
        err = flush_buffer(line);
        if (err == 0) {
                return IRQ_NONE;
@@ -381,7 +381,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data)
                line->head = line->buffer;
                line->tail = line->buffer;
        }
-       spin_unlock_irq(&line->lock);
+       spin_unlock(&line->lock);
 
        if(tty == NULL)
                return IRQ_NONE;
index 8138f5ea1bf7516272de7b086ead9ca8295306ea..b827e82884c98ad7ecf266387dd722fe6b6edede 100644 (file)
@@ -50,6 +50,14 @@ static void mcast_user_init(void *data, void *dev)
        pri->dev = dev;
 }
 
+static void mcast_remove(void *data)
+{
+       struct mcast_data *pri = data;
+
+       kfree(pri->mcast_addr);
+       pri->mcast_addr = NULL;
+}
+
 static int mcast_open(void *data)
 {
        struct mcast_data *pri = data;
@@ -157,7 +165,7 @@ const struct net_user_info mcast_user_info = {
        .init           = mcast_user_init,
        .open           = mcast_open,
        .close          = mcast_close,
-       .remove         = NULL,
+       .remove         = mcast_remove,
        .set_mtu        = mcast_set_mtu,
        .add_address    = NULL,
        .delete_address = NULL,
index fc22b9bd91530548a72cd0b6aad1afde5b00d3e6..4b382a6e710f413dfce8d054f04f60715746e2f4 100644 (file)
@@ -179,7 +179,7 @@ static struct console ssl_cons = {
        .write          = ssl_console_write,
        .device         = ssl_console_device,
        .setup          = ssl_console_setup,
-       .flags          = CON_PRINTBUFFER,
+       .flags          = CON_PRINTBUFFER|CON_ANYTIME,
        .index          = -1,
 };
 
index 7ff0b0fc37e73eff2875fe4ae0db633570181b66..76d1f1c980ef45154e717720e8a83a9ba1c2410c 100644 (file)
@@ -153,7 +153,7 @@ static struct console stdiocons = {
        .write          = uml_console_write,
        .device         = uml_console_device,
        .setup          = uml_console_setup,
-       .flags          = CON_PRINTBUFFER,
+       .flags          = CON_PRINTBUFFER|CON_ANYTIME,
        .index          = -1,
 };
 
index 8629bd1914925aba5d78f4348221c796fc323920..5c74da4104511e6faaa3821c01d3c4b7495ac730 100644 (file)
@@ -192,7 +192,9 @@ extern int os_process_parent(int pid);
 extern void os_stop_process(int pid);
 extern void os_kill_process(int pid, int reap_child);
 extern void os_kill_ptraced_process(int pid, int reap_child);
+#ifdef UML_CONFIG_MODE_TT
 extern void os_usr1_process(int pid);
+#endif
 extern long os_ptrace_ldt(long pid, long addr, long data);
 
 extern int os_getpid(void);
@@ -261,7 +263,6 @@ extern void block_signals(void);
 extern void unblock_signals(void);
 extern int get_signals(void);
 extern int set_signals(int enable);
-extern void os_usr1_signal(int on);
 
 /* trap.c */
 extern void os_fill_handlinfo(struct kern_handlers h);
index 50a288bb875a87ec10e977db3f366358c15d29d8..dbf2f5bc842f69d08026174ad6d00792c8e9b0f1 100644 (file)
@@ -142,6 +142,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
                                     .events            = events,
                                     .current_events    = 0 } );
 
+       err = -EBUSY;
        spin_lock_irqsave(&irq_lock, flags);
        for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) {
                if ((irq_fd->fd == fd) && (irq_fd->type == type)) {
index 2a32e5e8e9c963f041fe7334bda569c1c2966591..3c798cdde550e513bbf672fb8a5daedb3ed9f8b4 100644 (file)
@@ -158,12 +158,12 @@ static int kern_do_signal(struct pt_regs *regs)
                clear_thread_flag(TIF_RESTORE_SIGMASK);
                sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
        }
-       return(handled_sig);
+       return handled_sig;
 }
 
 int do_signal(void)
 {
-       return(kern_do_signal(&current->thread.regs));
+       return kern_do_signal(&current->thread.regs);
 }
 
 /*
@@ -186,5 +186,5 @@ long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
 
 long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
 {
-       return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs)));
+       return do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs));
 }
index 3a8d7e3aae0a9e2cdc70d1bc547a8b636b614d29..608784d4ec57e73f0d74a1e0ea3223c89db58cea 100644 (file)
@@ -39,6 +39,9 @@ __init void scan_elf_aux( char **envp)
                switch ( auxv->a_type ) {
                        case AT_SYSINFO:
                                __kernel_vsyscall = auxv->a_un.a_val;
+                               /* See if the page is under TASK_SIZE */
+                               if (__kernel_vsyscall < (unsigned long) envp)
+                                       __kernel_vsyscall = 0;
                                break;
                        case AT_SYSINFO_EHDR:
                                vsyscall_ehdr = auxv->a_un.a_val;
index c692a192957a80775f98097ee47d7b0d73dc6b12..76bdd671241735df114ef75cf0120674acabb163 100644 (file)
@@ -21,6 +21,7 @@
 #include "longjmp.h"
 #include "skas_ptrace.h"
 #include "kern_constants.h"
+#include "uml-config.h"
 
 #define ARBITRARY_ADDR -1
 #define FAILURE_PID    -1
@@ -131,10 +132,12 @@ void os_kill_ptraced_process(int pid, int reap_child)
                CATCH_EINTR(waitpid(pid, NULL, 0));
 }
 
+#ifdef UML_CONFIG_MODE_TT
 void os_usr1_process(int pid)
 {
        kill(pid, SIGUSR1);
 }
+#endif
 
 /* Don't use the glibc version, which caches the result in TLS. It misses some
  * syscalls, and also breaks with clone(), which does not unshare the TLS.
index b2e1fd8e35712504c1b8190acd2175f923ce7e5e..3fc43b33db667d370ceabf7e63794b43ab0df441 100644 (file)
@@ -334,8 +334,11 @@ void maybe_sigio_broken(int fd, int read)
 
        sigio_lock();
        err = need_poll(&all_sigio_fds, all_sigio_fds.used + 1);
-       if(err)
+       if(err){
+               printk("maybe_sigio_broken - failed to add pollfd for "
+                      "descriptor %d\n", fd);
                goto out;
+       }
 
        all_sigio_fds.poll[all_sigio_fds.used++] =
                ((struct pollfd) { .fd          = fd,
index b897e8592d7713c3730bfb4ab15f0b9ca716eb1d..266768629fee6de48152d0674333685a72578021 100644 (file)
@@ -243,8 +243,3 @@ int set_signals(int enable)
 
        return ret;
 }
-
-void os_usr1_signal(int on)
-{
-       change_sig(SIGUSR1, on);
-}
index 9b34fe65949a689b97fe004afe00f49f27a32b86..dda06789bcb01f7d8edf4dec2a264723a4fb7f9f 100644 (file)
@@ -419,9 +419,12 @@ void map_stub_pages(int fd, unsigned long code,
                                          .offset  = code_offset
        } } });
        n = os_write_file(fd, &mmop, sizeof(mmop));
-       if(n != sizeof(mmop))
+       if(n != sizeof(mmop)){
+               printk("mmap args - addr = 0x%lx, fd = %d, offset = %llx\n",
+                      code, code_fd, (unsigned long long) code_offset);
                panic("map_stub_pages : /proc/mm map for code failed, "
                      "err = %d\n", -n);
+       }
 
        if ( stack ) {
                __u64 map_offset;
index 1df231a26244b0ee3e95982e98e3946a60fc51e3..d221214d2ed543d1bf6ad9d4462d0ba7b907dfea 100644 (file)
@@ -16,6 +16,7 @@ void usr2_handler(int sig, union uml_pt_regs *regs)
        CHOOSE_MODE(syscall_handler_tt(sig, regs), (void) 0);
 }
 
+/* Initialized from linux_main() */
 void (*sig_info[NSIG])(int, union uml_pt_regs *);
 
 void os_fill_handlinfo(struct kern_handlers h)
index 5db7737df0ff1bc594856588b592c860a023c006..4a8b4202ef9e9f239102db00d00ba4a01391dd7b 100644 (file)
@@ -7,6 +7,7 @@
 #include "linux/slab.h"
 #include "linux/types.h"
 #include "linux/errno.h"
+#include "linux/spinlock.h"
 #include "asm/uaccess.h"
 #include "asm/smp.h"
 #include "asm/ldt.h"
@@ -386,23 +387,33 @@ static long do_modify_ldt_skas(int func, void __user *ptr,
        return ret;
 }
 
-short dummy_list[9] = {0, -1};
-short * host_ldt_entries = NULL;
+static DEFINE_SPINLOCK(host_ldt_lock);
+static short dummy_list[9] = {0, -1};
+static short * host_ldt_entries = NULL;
 
-void ldt_get_host_info(void)
+static void ldt_get_host_info(void)
 {
        long ret;
-       struct ldt_entry * ldt;
+       struct ldt_entry * ldt, *tmp;
        int i, size, k, order;
 
+       spin_lock(&host_ldt_lock);
+
+       if(host_ldt_entries != NULL){
+               spin_unlock(&host_ldt_lock);
+               return;
+       }
        host_ldt_entries = dummy_list+1;
 
+       spin_unlock(&host_ldt_lock);
+
        for(i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++);
 
        ldt = (struct ldt_entry *)
              __get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
        if(ldt == NULL) {
-               printk("ldt_get_host_info: couldn't allocate buffer for host ldt\n");
+               printk("ldt_get_host_info: couldn't allocate buffer for host "
+                      "ldt\n");
                return;
        }
 
@@ -426,11 +437,13 @@ 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);
-               if(host_ldt_entries == NULL) {
-                       printk("ldt_get_host_info: couldn't allocate host ldt list\n");
+               tmp = kmalloc(size, GFP_KERNEL);
+               if(tmp == NULL) {
+                       printk("ldt_get_host_info: couldn't allocate host ldt "
+                              "list\n");
                        goto out_free;
                }
+               host_ldt_entries = tmp;
        }
 
        for(i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++){
@@ -480,8 +493,7 @@ long init_new_ldt(struct mmu_context_skas * new_mm,
                         * inherited from the host. All ldt-entries found
                         * will be reset in the following loop
                         */
-                       if(host_ldt_entries == NULL)
-                               ldt_get_host_info();
+                       ldt_get_host_info();
                        for(num_p=host_ldt_entries; *num_p != -1; num_p++){
                                desc.entry_number = *num_p;
                                err = write_ldt_entry(&new_mm->id, 1, &desc,
@@ -560,6 +572,6 @@ void free_ldt(struct mmu_context_skas * mm)
 
 int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
 {
-       return(CHOOSE_MODE_PROC(do_modify_ldt_tt, do_modify_ldt_skas, func,
-                               ptr, bytecount));
+       return CHOOSE_MODE_PROC(do_modify_ldt_tt, do_modify_ldt_skas, func,
+                               ptr, bytecount);
 }
index 01b91f9fa7893647454f2a843f22a729197d78cb..b3f6350cac44a61cc241f2d10a69ca71cf4f10b7 100644 (file)
@@ -103,6 +103,9 @@ long arch_prctl_skas(struct task_struct *task, int code,
 
         switch(code){
        case ARCH_SET_FS:
+               current->thread.arch.fs = (unsigned long) ptr;
+               save_registers(pid, &current->thread.regs.regs);
+               break;
        case ARCH_SET_GS:
                 save_registers(pid, &current->thread.regs.regs);
                break;
@@ -140,9 +143,8 @@ long sys_clone(unsigned long clone_flags, unsigned long newsp,
 
 void arch_switch_to_skas(struct task_struct *from, struct task_struct *to)
 {
-        if(to->thread.arch.fs == 0)
+        if((to->thread.arch.fs == 0) || (to->mm == NULL))
                 return;
 
         arch_prctl_skas(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs);
 }
-
index 04566fe5de494887b510259d9a4c146e7986aefc..4de3a54318f4d6d4f3636144393ee7c88d13fea4 100644 (file)
@@ -243,6 +243,7 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
        case PTRACE_SINGLESTEP:
        case PTRACE_DETACH:
        case PTRACE_SYSCALL:
+       case PTRACE_OLDSETOPTIONS:
        case PTRACE_SETOPTIONS:
        case PTRACE_SET_THREAD_AREA:
        case PTRACE_GET_THREAD_AREA:
index 45a6a1fd14acc6d1897844e482bddeb29342c38b..ced15d06f0f3b9359d7e3d6edcdf175256d15266 100644 (file)
@@ -45,7 +45,6 @@ config X86_SPEEDSTEP_CENTRINO
 config X86_SPEEDSTEP_CENTRINO_ACPI
        bool
        depends on X86_SPEEDSTEP_CENTRINO
-       default y
 
 config X86_ACPI_CPUFREQ
        tristate "ACPI Processor P-States driver"
index 8047ea8c2ab271e9e315547e3a77450d31edcab4..dec587b293bfcf9ccfed71798279fdd8408c9a9f 100644 (file)
@@ -30,11 +30,8 @@ static void via_bugs(void)
 
 #ifdef CONFIG_ACPI
 
-static int nvidia_hpet_detected __initdata;
-
 static int __init nvidia_hpet_check(struct acpi_table_header *header)
 {
-       nvidia_hpet_detected = 1;
        return 0;
 }
 #endif
@@ -52,11 +49,7 @@ static void nvidia_bugs(void)
        if (acpi_use_timer_override)
                return;
 
-       nvidia_hpet_detected = 0;
-       if (acpi_table_parse(ACPI_SIG_HPET, nvidia_hpet_check))
-               return;
-
-       if (nvidia_hpet_detected == 0) {
+       if (acpi_table_parse(ACPI_SIG_HPET, nvidia_hpet_check)) {
                acpi_skip_timer_override = 1;
                printk(KERN_INFO "Nvidia board "
                       "detected. Ignoring ACPI "
index 9f5dac64aa8fcd6ec83b5b66efbfe10a6540ed7a..ed4350ced3d0602d681ce6cb622ec426a288ab6f 100644 (file)
@@ -675,6 +675,9 @@ END(invalidate_interrupt\num)
 ENTRY(call_function_interrupt)
        apicinterrupt CALL_FUNCTION_VECTOR,smp_call_function_interrupt
 END(call_function_interrupt)
+ENTRY(irq_move_cleanup_interrupt)
+       apicinterrupt IRQ_MOVE_CLEANUP_VECTOR,smp_irq_move_cleanup_interrupt
+END(irq_move_cleanup_interrupt)
 #endif
 
 ENTRY(apic_timer_interrupt)
index 65a0edd71a17ebd296336ef6162ff8c14590a933..8cf0b8a13778ae0e497ffd228fb24f9eef8d163d 100644 (file)
 #include <asm/timex.h>
 #include <asm/hpet.h>
 
+#define HPET_MASK      0xFFFFFFFF
+#define HPET_SHIFT     22
+
+/* FSEC = 10^-15 NSEC = 10^-9 */
+#define FSEC_PER_NSEC  1000000
+
 int nohpet __initdata;
 
 unsigned long hpet_address;
@@ -106,9 +112,31 @@ int hpet_timer_stop_set_go(unsigned long tick)
        return 0;
 }
 
+static cycle_t read_hpet(void)
+{
+       return (cycle_t)hpet_readl(HPET_COUNTER);
+}
+
+static cycle_t __vsyscall_fn vread_hpet(void)
+{
+       return readl((void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0);
+}
+
+struct clocksource clocksource_hpet = {
+       .name           = "hpet",
+       .rating         = 250,
+       .read           = read_hpet,
+       .mask           = (cycle_t)HPET_MASK,
+       .mult           = 0, /* set below */
+       .shift          = HPET_SHIFT,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+       .vread          = vread_hpet,
+};
+
 int hpet_arch_init(void)
 {
        unsigned int id;
+       u64 tmp;
 
        if (!hpet_address)
                return -1;
@@ -132,6 +160,22 @@ int hpet_arch_init(void)
 
        hpet_use_timer = (id & HPET_ID_LEGSUP);
 
+       /*
+        * hpet period is in femto seconds per cycle
+        * so we need to convert this to ns/cyc units
+        * aproximated by mult/2^shift
+        *
+        *  fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift
+        *  fsec/cyc * 1ns/1000000fsec * 2^shift = mult
+        *  fsec/cyc * 2^shift * 1nsec/1000000fsec = mult
+        *  (fsec/cyc << shift)/1000000 = mult
+        *  (hpet_period << shift)/FSEC_PER_NSEC = mult
+        */
+       tmp = (u64)hpet_period << HPET_SHIFT;
+       do_div(tmp, FSEC_PER_NSEC);
+       clocksource_hpet.mult = (u32)tmp;
+       clocksource_register(&clocksource_hpet);
+
        return hpet_timer_stop_set_go(hpet_tick);
 }
 
@@ -444,68 +488,3 @@ static int __init nohpet_setup(char *s)
 }
 
 __setup("nohpet", nohpet_setup);
-
-#define HPET_MASK      0xFFFFFFFF
-#define HPET_SHIFT     22
-
-/* FSEC = 10^-15 NSEC = 10^-9 */
-#define FSEC_PER_NSEC  1000000
-
-static void *hpet_ptr;
-
-static cycle_t read_hpet(void)
-{
-       return (cycle_t)readl(hpet_ptr);
-}
-
-static cycle_t __vsyscall_fn vread_hpet(void)
-{
-       return readl((void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0);
-}
-
-struct clocksource clocksource_hpet = {
-       .name           = "hpet",
-       .rating         = 250,
-       .read           = read_hpet,
-       .mask           = (cycle_t)HPET_MASK,
-       .mult           = 0, /* set below */
-       .shift          = HPET_SHIFT,
-       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
-       .vread          = vread_hpet,
-};
-
-static int __init init_hpet_clocksource(void)
-{
-       unsigned long hpet_period;
-       void __iomem *hpet_base;
-       u64 tmp;
-
-       if (!hpet_address)
-               return -ENODEV;
-
-       /* calculate the hpet address: */
-       hpet_base = ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
-       hpet_ptr = hpet_base + HPET_COUNTER;
-
-       /* calculate the frequency: */
-       hpet_period = readl(hpet_base + HPET_PERIOD);
-
-       /*
-        * hpet period is in femto seconds per cycle
-        * so we need to convert this to ns/cyc units
-        * aproximated by mult/2^shift
-        *
-        *  fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift
-        *  fsec/cyc * 1ns/1000000fsec * 2^shift = mult
-        *  fsec/cyc * 2^shift * 1nsec/1000000fsec = mult
-        *  (fsec/cyc << shift)/1000000 = mult
-        *  (hpet_period << shift)/FSEC_PER_NSEC = mult
-        */
-       tmp = (u64)hpet_period << HPET_SHIFT;
-       do_div(tmp, FSEC_PER_NSEC);
-       clocksource_hpet.mult = (u32)tmp;
-
-       return clocksource_register(&clocksource_hpet);
-}
-
-module_init(init_hpet_clocksource);
index 01e2cf0bdeb10a60bbfb967d9dae2880b2f9827f..21d95b7474379243cdbe4156d20a224e36364e11 100644 (file)
@@ -299,7 +299,7 @@ void init_8259A(int auto_eoi)
         * outb_p - this has to work on a wide range of PC hardware.
         */
        outb_p(0x11, 0x20);     /* ICW1: select 8259A-1 init */
-       outb_p(0x20 + 0, 0x21); /* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */
+       outb_p(IRQ0_VECTOR, 0x21);      /* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */
        outb_p(0x04, 0x21);     /* 8259A-1 (the master) has a slave on IR2 */
        if (auto_eoi)
                outb_p(0x03, 0x21);     /* master does Auto EOI */
@@ -307,7 +307,7 @@ void init_8259A(int auto_eoi)
                outb_p(0x01, 0x21);     /* master expects normal EOI */
 
        outb_p(0x11, 0xA0);     /* ICW1: select 8259A-2 init */
-       outb_p(0x20 + 8, 0xA1); /* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */
+       outb_p(IRQ8_VECTOR, 0xA1);      /* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */
        outb_p(0x02, 0xA1);     /* 8259A-2 is a slave on master's IR2 */
        outb_p(0x01, 0xA1);     /* (slave's support for AEOI in flat mode
                                    is to be investigated) */
@@ -398,24 +398,24 @@ device_initcall(i8259A_init_sysfs);
 
 static struct irqaction irq2 = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL};
 DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
-       [0 ... FIRST_EXTERNAL_VECTOR - 1] = -1,
-       [FIRST_EXTERNAL_VECTOR + 0] = 0,
-       [FIRST_EXTERNAL_VECTOR + 1] = 1,
-       [FIRST_EXTERNAL_VECTOR + 2] = 2,
-       [FIRST_EXTERNAL_VECTOR + 3] = 3,
-       [FIRST_EXTERNAL_VECTOR + 4] = 4,
-       [FIRST_EXTERNAL_VECTOR + 5] = 5,
-       [FIRST_EXTERNAL_VECTOR + 6] = 6,
-       [FIRST_EXTERNAL_VECTOR + 7] = 7,
-       [FIRST_EXTERNAL_VECTOR + 8] = 8,
-       [FIRST_EXTERNAL_VECTOR + 9] = 9,
-       [FIRST_EXTERNAL_VECTOR + 10] = 10,
-       [FIRST_EXTERNAL_VECTOR + 11] = 11,
-       [FIRST_EXTERNAL_VECTOR + 12] = 12,
-       [FIRST_EXTERNAL_VECTOR + 13] = 13,
-       [FIRST_EXTERNAL_VECTOR + 14] = 14,
-       [FIRST_EXTERNAL_VECTOR + 15] = 15,
-       [FIRST_EXTERNAL_VECTOR + 16 ... NR_VECTORS - 1] = -1
+       [0 ... IRQ0_VECTOR - 1] = -1,
+       [IRQ0_VECTOR] = 0,
+       [IRQ1_VECTOR] = 1,
+       [IRQ2_VECTOR] = 2,
+       [IRQ3_VECTOR] = 3,
+       [IRQ4_VECTOR] = 4,
+       [IRQ5_VECTOR] = 5,
+       [IRQ6_VECTOR] = 6,
+       [IRQ7_VECTOR] = 7,
+       [IRQ8_VECTOR] = 8,
+       [IRQ9_VECTOR] = 9,
+       [IRQ10_VECTOR] = 10,
+       [IRQ11_VECTOR] = 11,
+       [IRQ12_VECTOR] = 12,
+       [IRQ13_VECTOR] = 13,
+       [IRQ14_VECTOR] = 14,
+       [IRQ15_VECTOR] = 15,
+       [IRQ15_VECTOR + 1 ... NR_VECTORS - 1] = -1
 };
 
 void __init init_ISA_irqs (void)
@@ -450,6 +450,7 @@ void spurious_interrupt(void);
 void error_interrupt(void);
 void reschedule_interrupt(void);
 void call_function_interrupt(void);
+void irq_move_cleanup_interrupt(void);
 void invalidate_interrupt0(void);
 void invalidate_interrupt1(void);
 void invalidate_interrupt2(void);
@@ -519,12 +520,6 @@ void __init init_IRQ(void)
        }
 
 #ifdef CONFIG_SMP
-       /*
-        * IRQ0 must be given a fixed assignment and initialized,
-        * because it's used before the IO-APIC is set up.
-        */
-       __get_cpu_var(vector_irq)[FIRST_DEVICE_VECTOR] = 0;
-
        /*
         * The reschedule interrupt is a CPU-to-CPU reschedule-helper
         * IPI, driven by wakeup.
@@ -543,7 +538,10 @@ void __init init_IRQ(void)
 
        /* IPI for generic function call */
        set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
-#endif 
+
+       /* Low priority IPI to cleanup after moving an irq */
+       set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt);
+#endif
        set_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
        set_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt);
 
index 950682f3576697b3fa7bcc8b916be3b8a3547c8d..c6a5bc7e8118d0cb206b2185a330e925773195cc 100644 (file)
@@ -36,6 +36,7 @@
 #include <acpi/acpi_bus.h>
 #endif
 
+#include <asm/idle.h>
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/desc.h>
 #include <asm/msidef.h>
 #include <asm/hypertransport.h>
 
-static int assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result);
+struct irq_cfg {
+       cpumask_t domain;
+       cpumask_t old_domain;
+       unsigned move_cleanup_count;
+       u8 vector;
+       u8 move_in_progress : 1;
+};
+
+/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
+struct irq_cfg irq_cfg[NR_IRQS] __read_mostly = {
+       [0]  = { .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR,  },
+       [1]  = { .domain = CPU_MASK_ALL, .vector = IRQ1_VECTOR,  },
+       [2]  = { .domain = CPU_MASK_ALL, .vector = IRQ2_VECTOR,  },
+       [3]  = { .domain = CPU_MASK_ALL, .vector = IRQ3_VECTOR,  },
+       [4]  = { .domain = CPU_MASK_ALL, .vector = IRQ4_VECTOR,  },
+       [5]  = { .domain = CPU_MASK_ALL, .vector = IRQ5_VECTOR,  },
+       [6]  = { .domain = CPU_MASK_ALL, .vector = IRQ6_VECTOR,  },
+       [7]  = { .domain = CPU_MASK_ALL, .vector = IRQ7_VECTOR,  },
+       [8]  = { .domain = CPU_MASK_ALL, .vector = IRQ8_VECTOR,  },
+       [9]  = { .domain = CPU_MASK_ALL, .vector = IRQ9_VECTOR,  },
+       [10] = { .domain = CPU_MASK_ALL, .vector = IRQ10_VECTOR, },
+       [11] = { .domain = CPU_MASK_ALL, .vector = IRQ11_VECTOR, },
+       [12] = { .domain = CPU_MASK_ALL, .vector = IRQ12_VECTOR, },
+       [13] = { .domain = CPU_MASK_ALL, .vector = IRQ13_VECTOR, },
+       [14] = { .domain = CPU_MASK_ALL, .vector = IRQ14_VECTOR, },
+       [15] = { .domain = CPU_MASK_ALL, .vector = IRQ15_VECTOR, },
+};
+
+static int assign_irq_vector(int irq, cpumask_t mask);
 
 #define __apicdebuginit  __init
 
@@ -74,7 +103,7 @@ int nr_ioapic_registers[MAX_IO_APICS];
  * Rough estimation of how many shared IRQs there are, can
  * be changed anytime.
  */
-#define MAX_PLUS_SHARED_IRQS NR_IRQ_VECTORS
+#define MAX_PLUS_SHARED_IRQS NR_IRQS
 #define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
 
 /*
@@ -149,11 +178,11 @@ static inline void io_apic_sync(unsigned int apic)
                reg = io_apic_read(entry->apic, 0x10 + R + pin*2);      \
                reg ACTION;                                             \
                io_apic_modify(entry->apic, reg);                       \
+               FINAL;                                                  \
                if (!entry->next)                                       \
                        break;                                          \
                entry = irq_2_pin + entry->next;                        \
        }                                                               \
-       FINAL;                                                          \
 }
 
 union entry_union {
@@ -237,21 +266,19 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector)
 
 static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
 {
+       struct irq_cfg *cfg = irq_cfg + irq;
        unsigned long flags;
        unsigned int dest;
        cpumask_t tmp;
-       int vector;
 
        cpus_and(tmp, mask, cpu_online_map);
        if (cpus_empty(tmp))
-               tmp = TARGET_CPUS;
-
-       cpus_and(mask, tmp, CPU_MASK_ALL);
+               return;
 
-       vector = assign_irq_vector(irq, mask, &tmp);
-       if (vector < 0)
+       if (assign_irq_vector(irq, mask))
                return;
 
+       cpus_and(tmp, cfg->domain, mask);
        dest = cpu_mask_to_apicid(tmp);
 
        /*
@@ -260,8 +287,8 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
        dest = SET_APIC_LOGICAL_ID(dest);
 
        spin_lock_irqsave(&ioapic_lock, flags);
-       __target_IO_APIC_irq(irq, dest, vector);
-       set_native_irq_info(irq, mask);
+       __target_IO_APIC_irq(irq, dest, cfg->vector);
+       irq_desc[irq].affinity = mask;
        spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 #endif
@@ -615,63 +642,7 @@ static int pin_2_irq(int idx, int apic, int pin)
        return irq;
 }
 
-static inline int IO_APIC_irq_trigger(int irq)
-{
-       int apic, idx, pin;
-
-       for (apic = 0; apic < nr_ioapics; apic++) {
-               for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
-                       idx = find_irq_entry(apic,pin,mp_INT);
-                       if ((idx != -1) && (irq == pin_2_irq(idx,apic,pin)))
-                               return irq_trigger(idx);
-               }
-       }
-       /*
-        * nonexistent IRQs are edge default
-        */
-       return 0;
-}
-
-/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
-static u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = {
-       [0] = FIRST_EXTERNAL_VECTOR + 0,
-       [1] = FIRST_EXTERNAL_VECTOR + 1,
-       [2] = FIRST_EXTERNAL_VECTOR + 2,
-       [3] = FIRST_EXTERNAL_VECTOR + 3,
-       [4] = FIRST_EXTERNAL_VECTOR + 4,
-       [5] = FIRST_EXTERNAL_VECTOR + 5,
-       [6] = FIRST_EXTERNAL_VECTOR + 6,
-       [7] = FIRST_EXTERNAL_VECTOR + 7,
-       [8] = FIRST_EXTERNAL_VECTOR + 8,
-       [9] = FIRST_EXTERNAL_VECTOR + 9,
-       [10] = FIRST_EXTERNAL_VECTOR + 10,
-       [11] = FIRST_EXTERNAL_VECTOR + 11,
-       [12] = FIRST_EXTERNAL_VECTOR + 12,
-       [13] = FIRST_EXTERNAL_VECTOR + 13,
-       [14] = FIRST_EXTERNAL_VECTOR + 14,
-       [15] = FIRST_EXTERNAL_VECTOR + 15,
-};
-
-static cpumask_t irq_domain[NR_IRQ_VECTORS] __read_mostly = {
-       [0] = CPU_MASK_ALL,
-       [1] = CPU_MASK_ALL,
-       [2] = CPU_MASK_ALL,
-       [3] = CPU_MASK_ALL,
-       [4] = CPU_MASK_ALL,
-       [5] = CPU_MASK_ALL,
-       [6] = CPU_MASK_ALL,
-       [7] = CPU_MASK_ALL,
-       [8] = CPU_MASK_ALL,
-       [9] = CPU_MASK_ALL,
-       [10] = CPU_MASK_ALL,
-       [11] = CPU_MASK_ALL,
-       [12] = CPU_MASK_ALL,
-       [13] = CPU_MASK_ALL,
-       [14] = CPU_MASK_ALL,
-       [15] = CPU_MASK_ALL,
-};
-
-static int __assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result)
+static int __assign_irq_vector(int irq, cpumask_t mask)
 {
        /*
         * NOTE! The local APIC isn't very good at handling
@@ -685,20 +656,25 @@ static int __assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result)
         * 0x80, because int 0x80 is hm, kind of importantish. ;)
         */
        static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
-       int old_vector = -1;
+       unsigned int old_vector;
        int cpu;
+       struct irq_cfg *cfg;
 
-       BUG_ON((unsigned)irq >= NR_IRQ_VECTORS);
+       BUG_ON((unsigned)irq >= NR_IRQS);
+       cfg = &irq_cfg[irq];
 
        /* Only try and allocate irqs on cpus that are present */
        cpus_and(mask, mask, cpu_online_map);
 
-       if (irq_vector[irq] > 0)
-               old_vector = irq_vector[irq];
-       if (old_vector > 0) {
-               cpus_and(*result, irq_domain[irq], mask);
-               if (!cpus_empty(*result))
-                       return old_vector;
+       if ((cfg->move_in_progress) || cfg->move_cleanup_count)
+               return -EBUSY;
+
+       old_vector = cfg->vector;
+       if (old_vector) {
+               cpumask_t tmp;
+               cpus_and(tmp, cfg->domain, mask);
+               if (!cpus_empty(tmp))
+                       return 0;
        }
 
        for_each_cpu_mask(cpu, mask) {
@@ -728,48 +704,47 @@ next:
                /* Found one! */
                current_vector = vector;
                current_offset = offset;
-               if (old_vector >= 0) {
-                       cpumask_t old_mask;
-                       int old_cpu;
-                       cpus_and(old_mask, irq_domain[irq], cpu_online_map);
-                       for_each_cpu_mask(old_cpu, old_mask)
-                               per_cpu(vector_irq, old_cpu)[old_vector] = -1;
+               if (old_vector) {
+                       cfg->move_in_progress = 1;
+                       cfg->old_domain = cfg->domain;
                }
                for_each_cpu_mask(new_cpu, new_mask)
                        per_cpu(vector_irq, new_cpu)[vector] = irq;
-               irq_vector[irq] = vector;
-               irq_domain[irq] = domain;
-               cpus_and(*result, domain, mask);
-               return vector;
+               cfg->vector = vector;
+               cfg->domain = domain;
+               return 0;
        }
        return -ENOSPC;
 }
 
-static int assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result)
+static int assign_irq_vector(int irq, cpumask_t mask)
 {
-       int vector;
+       int err;
        unsigned long flags;
 
        spin_lock_irqsave(&vector_lock, flags);
-       vector = __assign_irq_vector(irq, mask, result);
+       err = __assign_irq_vector(irq, mask);
        spin_unlock_irqrestore(&vector_lock, flags);
-       return vector;
+       return err;
 }
 
 static void __clear_irq_vector(int irq)
 {
+       struct irq_cfg *cfg;
        cpumask_t mask;
        int cpu, vector;
 
-       BUG_ON(!irq_vector[irq]);
+       BUG_ON((unsigned)irq >= NR_IRQS);
+       cfg = &irq_cfg[irq];
+       BUG_ON(!cfg->vector);
 
-       vector = irq_vector[irq];
-       cpus_and(mask, irq_domain[irq], cpu_online_map);
+       vector = cfg->vector;
+       cpus_and(mask, cfg->domain, cpu_online_map);
        for_each_cpu_mask(cpu, mask)
                per_cpu(vector_irq, cpu)[vector] = -1;
 
-       irq_vector[irq] = 0;
-       irq_domain[irq] = CPU_MASK_NONE;
+       cfg->vector = 0;
+       cfg->domain = CPU_MASK_NONE;
 }
 
 void __setup_vector_irq(int cpu)
@@ -779,10 +754,10 @@ void __setup_vector_irq(int cpu)
        int irq, vector;
 
        /* Mark the inuse vectors */
-       for (irq = 0; irq < NR_IRQ_VECTORS; ++irq) {
-               if (!cpu_isset(cpu, irq_domain[irq]))
+       for (irq = 0; irq < NR_IRQS; ++irq) {
+               if (!cpu_isset(cpu, irq_cfg[irq].domain))
                        continue;
-               vector = irq_vector[irq];
+               vector = irq_cfg[irq].vector;
                per_cpu(vector_irq, cpu)[vector] = irq;
        }
        /* Mark the free vectors */
@@ -790,36 +765,45 @@ void __setup_vector_irq(int cpu)
                irq = per_cpu(vector_irq, cpu)[vector];
                if (irq < 0)
                        continue;
-               if (!cpu_isset(cpu, irq_domain[irq]))
+               if (!cpu_isset(cpu, irq_cfg[irq].domain))
                        per_cpu(vector_irq, cpu)[vector] = -1;
        }
 }
 
 
-extern void (*interrupt[NR_IRQS])(void);
-
 static struct irq_chip ioapic_chip;
 
-#define IOAPIC_AUTO    -1
-#define IOAPIC_EDGE    0
-#define IOAPIC_LEVEL   1
-
-static void ioapic_register_intr(int irq, int vector, unsigned long trigger)
+static void ioapic_register_intr(int irq, unsigned long trigger)
 {
-       if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
-                       trigger == IOAPIC_LEVEL)
+       if (trigger)
                set_irq_chip_and_handler_name(irq, &ioapic_chip,
                                              handle_fasteoi_irq, "fasteoi");
        else
                set_irq_chip_and_handler_name(irq, &ioapic_chip,
                                              handle_edge_irq, "edge");
 }
-static void __init setup_IO_APIC_irq(int apic, int pin, int idx, int irq)
+
+static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq,
+                             int trigger, int polarity)
 {
+       struct irq_cfg *cfg = irq_cfg + irq;
        struct IO_APIC_route_entry entry;
-       int vector;
-       unsigned long flags;
+       cpumask_t mask;
+
+       if (!IO_APIC_IRQ(irq))
+               return;
+
+       mask = TARGET_CPUS;
+       if (assign_irq_vector(irq, mask))
+               return;
+
+       cpus_and(mask, cfg->domain, mask);
 
+       apic_printk(APIC_VERBOSE,KERN_DEBUG
+                   "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> "
+                   "IRQ %d Mode:%i Active:%i)\n",
+                   apic, mp_ioapics[apic].mpc_apicid, pin, cfg->vector,
+                   irq, trigger, polarity);
 
        /*
         * add it to the IO-APIC irq-routing table:
@@ -828,41 +812,23 @@ static void __init setup_IO_APIC_irq(int apic, int pin, int idx, int irq)
 
        entry.delivery_mode = INT_DELIVERY_MODE;
        entry.dest_mode = INT_DEST_MODE;
+       entry.dest = cpu_mask_to_apicid(mask);
        entry.mask = 0;                         /* enable IRQ */
-       entry.dest = cpu_mask_to_apicid(TARGET_CPUS);
-
-       entry.trigger = irq_trigger(idx);
-       entry.polarity = irq_polarity(idx);
+       entry.trigger = trigger;
+       entry.polarity = polarity;
+       entry.vector = cfg->vector;
 
-       if (irq_trigger(idx)) {
-               entry.trigger = 1;
+       /* Mask level triggered irqs.
+        * Use IRQ_DELAYED_DISABLE for edge triggered irqs.
+        */
+       if (trigger)
                entry.mask = 1;
-               entry.dest = cpu_mask_to_apicid(TARGET_CPUS);
-       }
 
-       if (!apic && !IO_APIC_IRQ(irq))
-               return;
-
-       if (IO_APIC_IRQ(irq)) {
-               cpumask_t mask;
-               vector = assign_irq_vector(irq, TARGET_CPUS, &mask);
-               if (vector < 0)
-                       return;
-
-               entry.dest = cpu_mask_to_apicid(mask);
-               entry.vector = vector;
-
-               ioapic_register_intr(irq, vector, IOAPIC_AUTO);
-               if (!apic && (irq < 16))
-                       disable_8259A_irq(irq);
-       }
+       ioapic_register_intr(irq, trigger);
+       if (irq < 16)
+               disable_8259A_irq(irq);
 
        ioapic_write_entry(apic, pin, entry);
-
-       spin_lock_irqsave(&ioapic_lock, flags);
-       set_native_irq_info(irq, TARGET_CPUS);
-       spin_unlock_irqrestore(&ioapic_lock, flags);
-
 }
 
 static void __init setup_IO_APIC_irqs(void)
@@ -887,8 +853,8 @@ static void __init setup_IO_APIC_irqs(void)
                irq = pin_2_irq(idx, apic, pin);
                add_pin_to_irq(irq, apic, pin);
 
-               setup_IO_APIC_irq(apic, pin, idx, irq);
-
+               setup_IO_APIC_irq(apic, pin, irq,
+                                 irq_trigger(idx), irq_polarity(idx));
        }
        }
 
@@ -1373,16 +1339,15 @@ static unsigned int startup_ioapic_irq(unsigned int irq)
 
 static int ioapic_retrigger_irq(unsigned int irq)
 {
+       struct irq_cfg *cfg = &irq_cfg[irq];
        cpumask_t mask;
-       unsigned vector;
        unsigned long flags;
 
        spin_lock_irqsave(&vector_lock, flags);
-       vector = irq_vector[irq];
        cpus_clear(mask);
-       cpu_set(first_cpu(irq_domain[irq]), mask);
+       cpu_set(first_cpu(cfg->domain), mask);
 
-       send_IPI_mask(mask, vector);
+       send_IPI_mask(mask, cfg->vector);
        spin_unlock_irqrestore(&vector_lock, flags);
 
        return 1;
@@ -1397,8 +1362,68 @@ static int ioapic_retrigger_irq(unsigned int irq)
  * races.
  */
 
+#ifdef CONFIG_SMP
+asmlinkage void smp_irq_move_cleanup_interrupt(void)
+{
+       unsigned vector, me;
+       ack_APIC_irq();
+       exit_idle();
+       irq_enter();
+
+       me = smp_processor_id();
+       for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
+               unsigned int irq;
+               struct irq_desc *desc;
+               struct irq_cfg *cfg;
+               irq = __get_cpu_var(vector_irq)[vector];
+               if (irq >= NR_IRQS)
+                       continue;
+
+               desc = irq_desc + irq;
+               cfg = irq_cfg + irq;
+               spin_lock(&desc->lock);
+               if (!cfg->move_cleanup_count)
+                       goto unlock;
+
+               if ((vector == cfg->vector) && cpu_isset(me, cfg->domain))
+                       goto unlock;
+
+               __get_cpu_var(vector_irq)[vector] = -1;
+               cfg->move_cleanup_count--;
+unlock:
+               spin_unlock(&desc->lock);
+       }
+
+       irq_exit();
+}
+
+static void irq_complete_move(unsigned int irq)
+{
+       struct irq_cfg *cfg = irq_cfg + irq;
+       unsigned vector, me;
+
+       if (likely(!cfg->move_in_progress))
+               return;
+
+       vector = ~get_irq_regs()->orig_rax;
+       me = smp_processor_id();
+       if ((vector == cfg->vector) &&
+           cpu_isset(smp_processor_id(), cfg->domain)) {
+               cpumask_t cleanup_mask;
+
+               cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
+               cfg->move_cleanup_count = cpus_weight(cleanup_mask);
+               send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
+               cfg->move_in_progress = 0;
+       }
+}
+#else
+static inline void irq_complete_move(unsigned int irq) {}
+#endif
+
 static void ack_apic_edge(unsigned int irq)
 {
+       irq_complete_move(irq);
        move_native_irq(irq);
        ack_APIC_irq();
 }
@@ -1407,6 +1432,7 @@ static void ack_apic_level(unsigned int irq)
 {
        int do_unmask_irq = 0;
 
+       irq_complete_move(irq);
 #if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE)
        /* If we are moving the irq we need to mask it */
        if (unlikely(irq_desc[irq].status & IRQ_MOVE_PENDING)) {
@@ -1457,7 +1483,7 @@ static inline void init_IO_APIC_traps(void)
         */
        for (irq = 0; irq < NR_IRQS ; irq++) {
                int tmp = irq;
-               if (IO_APIC_IRQ(tmp) && !irq_vector[tmp]) {
+               if (IO_APIC_IRQ(tmp) && !irq_cfg[tmp].vector) {
                        /*
                         * Hmm.. We don't have an entry for this,
                         * so default to an old-fashioned 8259
@@ -1596,15 +1622,14 @@ static inline void unlock_ExtINT_logic(void)
  */
 static inline void check_timer(void)
 {
+       struct irq_cfg *cfg = irq_cfg + 0;
        int apic1, pin1, apic2, pin2;
-       int vector;
-       cpumask_t mask;
 
        /*
         * get/set the timer IRQ vector:
         */
        disable_8259A_irq(0);
-       vector = assign_irq_vector(0, TARGET_CPUS, &mask);
+       assign_irq_vector(0, TARGET_CPUS);
 
        /*
         * Subtle, code in do_timer_interrupt() expects an AEOI
@@ -1624,7 +1649,7 @@ static inline void check_timer(void)
        apic2 = ioapic_i8259.apic;
 
        apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
-               vector, apic1, pin1, apic2, pin2);
+               cfg->vector, apic1, pin1, apic2, pin2);
 
        if (pin1 != -1) {
                /*
@@ -1655,7 +1680,7 @@ static inline void check_timer(void)
                /*
                 * legacy devices should be connected to IO APIC #0
                 */
-               setup_ExtINT_IRQ0_pin(apic2, pin2, vector);
+               setup_ExtINT_IRQ0_pin(apic2, pin2, cfg->vector);
                if (timer_irq_works()) {
                        apic_printk(APIC_VERBOSE," works.\n");
                        nmi_watchdog_default();
@@ -1680,14 +1705,14 @@ static inline void check_timer(void)
 
        disable_8259A_irq(0);
        irq_desc[0].chip = &lapic_irq_type;
-       apic_write(APIC_LVT0, APIC_DM_FIXED | vector);  /* Fixed mode */
+       apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector);     /* Fixed mode */
        enable_8259A_irq(0);
 
        if (timer_irq_works()) {
                apic_printk(APIC_VERBOSE," works.\n");
                return;
        }
-       apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
+       apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
        apic_printk(APIC_VERBOSE," failed.\n");
 
        apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as ExtINT IRQ...");
@@ -1834,19 +1859,16 @@ int create_irq(void)
        /* Allocate an unused irq */
        int irq;
        int new;
-       int vector = 0;
        unsigned long flags;
-       cpumask_t mask;
 
        irq = -ENOSPC;
        spin_lock_irqsave(&vector_lock, flags);
        for (new = (NR_IRQS - 1); new >= 0; new--) {
                if (platform_legacy_irq(new))
                        continue;
-               if (irq_vector[new] != 0)
+               if (irq_cfg[new].vector != 0)
                        continue;
-               vector = __assign_irq_vector(new, TARGET_CPUS, &mask);
-               if (likely(vector > 0))
+               if (__assign_irq_vector(new, TARGET_CPUS) == 0)
                        irq = new;
                break;
        }
@@ -1875,12 +1897,15 @@ void destroy_irq(unsigned int irq)
 #ifdef CONFIG_PCI_MSI
 static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
 {
-       int vector;
+       struct irq_cfg *cfg = irq_cfg + irq;
+       int err;
        unsigned dest;
        cpumask_t tmp;
 
-       vector = assign_irq_vector(irq, TARGET_CPUS, &tmp);
-       if (vector >= 0) {
+       tmp = TARGET_CPUS;
+       err = assign_irq_vector(irq, tmp);
+       if (!err) {
+               cpus_and(tmp, cfg->domain, tmp);
                dest = cpu_mask_to_apicid(tmp);
 
                msg->address_hi = MSI_ADDR_BASE_HI;
@@ -1900,40 +1925,38 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms
                        ((INT_DELIVERY_MODE != dest_LowestPrio) ?
                                MSI_DATA_DELIVERY_FIXED:
                                MSI_DATA_DELIVERY_LOWPRI) |
-                       MSI_DATA_VECTOR(vector);
+                       MSI_DATA_VECTOR(cfg->vector);
        }
-       return vector;
+       return err;
 }
 
 #ifdef CONFIG_SMP
 static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
 {
+       struct irq_cfg *cfg = irq_cfg + irq;
        struct msi_msg msg;
        unsigned int dest;
        cpumask_t tmp;
-       int vector;
 
        cpus_and(tmp, mask, cpu_online_map);
        if (cpus_empty(tmp))
-               tmp = TARGET_CPUS;
-
-       cpus_and(mask, tmp, CPU_MASK_ALL);
+               return;
 
-       vector = assign_irq_vector(irq, mask, &tmp);
-       if (vector < 0)
+       if (assign_irq_vector(irq, mask))
                return;
 
+       cpus_and(tmp, cfg->domain, mask);
        dest = cpu_mask_to_apicid(tmp);
 
        read_msi_msg(irq, &msg);
 
        msg.data &= ~MSI_DATA_VECTOR_MASK;
-       msg.data |= MSI_DATA_VECTOR(vector);
+       msg.data |= MSI_DATA_VECTOR(cfg->vector);
        msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
        msg.address_lo |= MSI_ADDR_DEST_ID(dest);
 
        write_msi_msg(irq, &msg);
-       set_native_irq_info(irq, mask);
+       irq_desc[irq].affinity = mask;
 }
 #endif /* CONFIG_SMP */
 
@@ -2004,24 +2027,22 @@ static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector)
 
 static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask)
 {
+       struct irq_cfg *cfg = irq_cfg + irq;
        unsigned int dest;
        cpumask_t tmp;
-       int vector;
 
        cpus_and(tmp, mask, cpu_online_map);
        if (cpus_empty(tmp))
-               tmp = TARGET_CPUS;
-
-       cpus_and(mask, tmp, CPU_MASK_ALL);
+               return;
 
-       vector = assign_irq_vector(irq, mask, &tmp);
-       if (vector < 0)
+       if (assign_irq_vector(irq, mask))
                return;
 
+       cpus_and(tmp, cfg->domain, mask);
        dest = cpu_mask_to_apicid(tmp);
 
-       target_ht_irq(irq, dest, vector);
-       set_native_irq_info(irq, mask);
+       target_ht_irq(irq, dest, cfg->vector);
+       irq_desc[irq].affinity = mask;
 }
 #endif
 
@@ -2038,14 +2059,17 @@ static struct irq_chip ht_irq_chip = {
 
 int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
 {
-       int vector;
+       struct irq_cfg *cfg = irq_cfg + irq;
+       int err;
        cpumask_t tmp;
 
-       vector = assign_irq_vector(irq, TARGET_CPUS, &tmp);
-       if (vector >= 0) {
+       tmp = TARGET_CPUS;
+       err = assign_irq_vector(irq, tmp);
+       if (!err) {
                struct ht_irq_msg msg;
                unsigned dest;
 
+               cpus_and(tmp, cfg->domain, tmp);
                dest = cpu_mask_to_apicid(tmp);
 
                msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
@@ -2053,7 +2077,7 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
                msg.address_lo =
                        HT_IRQ_LOW_BASE |
                        HT_IRQ_LOW_DEST_ID(dest) |
-                       HT_IRQ_LOW_VECTOR(vector) |
+                       HT_IRQ_LOW_VECTOR(cfg->vector) |
                        ((INT_DEST_MODE == 0) ?
                                HT_IRQ_LOW_DM_PHYSICAL :
                                HT_IRQ_LOW_DM_LOGICAL) |
@@ -2068,7 +2092,7 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
                set_irq_chip_and_handler_name(irq, &ht_irq_chip,
                                              handle_edge_irq, "edge");
        }
-       return vector;
+       return err;
 }
 #endif /* CONFIG_HT_IRQ */
 
@@ -2095,11 +2119,6 @@ int __init io_apic_get_redir_entries (int ioapic)
 
 int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int polarity)
 {
-       struct IO_APIC_route_entry entry;
-       unsigned long flags;
-       int vector;
-       cpumask_t mask;
-
        if (!IO_APIC_IRQ(irq)) {
                apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
                        ioapic);
@@ -2112,42 +2131,7 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int p
        if (irq >= 16)
                add_pin_to_irq(irq, ioapic, pin);
 
-
-       vector = assign_irq_vector(irq, TARGET_CPUS, &mask);
-       if (vector < 0)
-               return vector;
-
-       /*
-        * Generate a PCI IRQ routing entry and program the IOAPIC accordingly.
-        * Note that we mask (disable) IRQs now -- these get enabled when the
-        * corresponding device driver registers for this IRQ.
-        */
-
-       memset(&entry,0,sizeof(entry));
-
-       entry.delivery_mode = INT_DELIVERY_MODE;
-       entry.dest_mode = INT_DEST_MODE;
-       entry.dest = cpu_mask_to_apicid(mask);
-       entry.trigger = triggering;
-       entry.polarity = polarity;
-       entry.mask = 1;                                  /* Disabled (masked) */
-       entry.vector = vector & 0xff;
-
-       apic_printk(APIC_VERBOSE,KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> "
-               "IRQ %d Mode:%i Active:%i)\n", ioapic, 
-              mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq,
-              triggering, polarity);
-
-       ioapic_register_intr(irq, entry.vector, triggering);
-
-       if (!ioapic && (irq < 16))
-               disable_8259A_irq(irq);
-
-       ioapic_write_entry(ioapic, pin, entry);
-
-       spin_lock_irqsave(&ioapic_lock, flags);
-       set_native_irq_info(irq, TARGET_CPUS);
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       setup_IO_APIC_irq(ioapic, pin, irq, triggering, polarity);
 
        return 0;
 }
@@ -2179,8 +2163,10 @@ void __init setup_ioapic_dest(void)
                         * when you have too many devices, because at that time only boot
                         * cpu is online.
                         */
-                       if(!irq_vector[irq])
-                               setup_IO_APIC_irq(ioapic, pin, irq_entry, irq);
+                       if (!irq_cfg[irq].vector)
+                               setup_IO_APIC_irq(ioapic, pin, irq,
+                                                 irq_trigger(irq_entry),
+                                                 irq_polarity(irq_entry));
                        else
                                set_ioapic_affinity_irq(irq, TARGET_CPUS);
                }
index 35443729aad8b5fef81caba0483d5e6ab66d5856..cd4643a3702227ac9741524aff647fd9a3c3a871 100644 (file)
@@ -923,8 +923,9 @@ void __init smp_prepare_boot_cpu(void)
  */
 int __cpuinit __cpu_up(unsigned int cpu)
 {
-       int err;
        int apicid = cpu_present_to_apicid(cpu);
+       unsigned long flags;
+       int err;
 
        WARN_ON(irqs_disabled());
 
@@ -958,7 +959,9 @@ int __cpuinit __cpu_up(unsigned int cpu)
        /*
         * Make sure and check TSC sync:
         */
+       local_irq_save(flags);
        check_tsc_sync_source(cpu);
+       local_irq_restore(flags);
 
        while (!cpu_isset(cpu, cpu_online_map))
                cpu_relax();
index c9addcfb96dc32793fc266178acc257eb4407f15..75d73a9aa9ff8aab536785f3e7ee8862d6200e69 100644 (file)
@@ -358,6 +358,8 @@ void __init time_init(void)
        set_cyc2ns_scale(cpu_khz);
        printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n",
                cpu_khz / 1000, cpu_khz % 1000);
+       init_tsc_clocksource();
+
        setup_irq(0, &irq0);
 }
 
index 8958318650190ce0260b3d63ec1742b2216c0155..1a0edbbffaa0eb0340359ece6711b9c9a36ec1f7 100644 (file)
@@ -210,7 +210,7 @@ void mark_tsc_unstable(void)
 }
 EXPORT_SYMBOL_GPL(mark_tsc_unstable);
 
-static int __init init_tsc_clocksource(void)
+void __init init_tsc_clocksource(void)
 {
        if (!notsc) {
                clocksource_tsc.mult = clocksource_khz2mult(cpu_khz,
@@ -218,9 +218,6 @@ static int __init init_tsc_clocksource(void)
                if (check_tsc_unstable())
                        clocksource_tsc.rating = 0;
 
-               return clocksource_register(&clocksource_tsc);
+               clocksource_register(&clocksource_tsc);
        }
-       return 0;
 }
-
-module_init(init_tsc_clocksource);
index 8d5f835af4819bdcba182705d8c1e1b450c8fa87..c943271783985ff56783ec0eb17b09d7f08836b7 100644 (file)
@@ -5,6 +5,7 @@
 CFLAGS_csum-partial.o := -funroll-loops
 
 obj-y := io.o iomap_copy.o
+obj-$(CONFIG_SMP)      += msr-on-cpu.o
 
 lib-y := csum-partial.o csum-copy.o csum-wrappers.o delay.o \
        usercopy.o getuser.o putuser.o  \
diff --git a/arch/x86_64/lib/msr-on-cpu.c b/arch/x86_64/lib/msr-on-cpu.c
new file mode 100644 (file)
index 0000000..47e0ec4
--- /dev/null
@@ -0,0 +1 @@
+#include "../../i386/lib/msr-on-cpu.c"
index 36bd3e12a6d4c58bdda0dde62237a50d84b93d09..050a1f0f3a8633ff90f8f89355e3b562f070ce7f 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/genhd.h>
+#include <linux/kdev_t.h>
 #include <linux/kernel.h>
 #include <linux/blkdev.h>
 #include <linux/init.h>
@@ -61,13 +62,7 @@ int register_blkdev(unsigned int major, const char *name)
        /* temporary */
        if (major == 0) {
                for (index = ARRAY_SIZE(major_names)-1; index > 0; index--) {
-                       /*
-                        * Disallow the LANANA-assigned LOCAL/EXPERIMENTAL
-                        * majors
-                        */
-                       if ((60 <= index && index <= 63) ||
-                                       (120 <= index && index <= 127) ||
-                                       (240 <= index && index <= 254))
+                       if (is_lanana_major(index))
                                continue;
                        if (major_names[index] == NULL)
                                break;
index e3f5eb9882cf4dfb403f6ca64f7262180b9db0fa..e06dbe9bc8588ac7aa6eb96b3378d16bdbaa9816 100644 (file)
@@ -82,7 +82,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
                        fsync_bdev(bdevp);
                        invalidate_bdev(bdevp, 0);
 
-                       mutex_lock(&bdev->bd_mutex);
+                       mutex_lock_nested(&bdev->bd_mutex, 1);
                        delete_partition(disk, part);
                        mutex_unlock(&bdev->bd_mutex);
                        mutex_unlock(&bdevp->bd_mutex);
index 2fa9a8bf48a0adaf5a3255e7b085201803de3688..d006c9f168d28a28d8245534a4870bd7b192ff41 100644 (file)
@@ -2,5 +2,4 @@
 # Makefile for the acorn character device drivers.
 #
 
-obj-$(CONFIG_ARCH_ACORN)       += i2c.o pcf8583.o
 obj-$(CONFIG_L7200_KEYB)       += defkeymap-l7200.o keyb_l7200.o
diff --git a/drivers/acorn/char/i2c.c b/drivers/acorn/char/i2c.c
deleted file mode 100644 (file)
index d276fd1..0000000
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- *  linux/drivers/acorn/char/i2c.c
- *
- *  Copyright (C) 2000 Russell King
- *
- * 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.
- *
- *  ARM IOC/IOMD i2c driver.
- *
- *  On Acorn machines, the following i2c devices are on the bus:
- *     - PCF8583 real time clock & static RAM
- */
-#include <linux/capability.h>
-#include <linux/init.h>
-#include <linux/time.h>
-#include <linux/miscdevice.h>
-#include <linux/rtc.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/fs.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include <asm/hardware/ioc.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-#include "pcf8583.h"
-
-extern int (*set_rtc)(void);
-
-static struct i2c_client *rtc_client;
-static const unsigned char days_in_mon[] = 
-       { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-
-#define CMOS_CHECKSUM  (63)
-
-/*
- * Acorn machines store the year in the static RAM at
- * location 128.
- */
-#define CMOS_YEAR      (64 + 128)
-
-static inline int rtc_command(int cmd, void *data)
-{
-       int ret = -EIO;
-
-       if (rtc_client)
-               ret = rtc_client->driver->command(rtc_client, cmd, data);
-
-       return ret;
-}
-
-/*
- * Update the century + year bytes in the CMOS RAM, ensuring
- * that the check byte is correctly adjusted for the change.
- */
-static int rtc_update_year(unsigned int new_year)
-{
-       unsigned char yr[2], chk;
-       struct mem cmos_year  = { CMOS_YEAR, sizeof(yr), yr };
-       struct mem cmos_check = { CMOS_CHECKSUM, 1, &chk };
-       int ret;
-
-       ret = rtc_command(MEM_READ, &cmos_check);
-       if (ret)
-               goto out;
-       ret = rtc_command(MEM_READ, &cmos_year);
-       if (ret)
-               goto out;
-
-       chk -= yr[1] + yr[0];
-
-       yr[1] = new_year / 100;
-       yr[0] = new_year % 100;
-
-       chk += yr[1] + yr[0];
-
-       ret = rtc_command(MEM_WRITE, &cmos_year);
-       if (ret == 0)
-               ret = rtc_command(MEM_WRITE, &cmos_check);
- out:
-       return ret;
-}
-
-/*
- * Read the current RTC time and date, and update xtime.
- */
-static void get_rtc_time(struct rtc_tm *rtctm, unsigned int *year)
-{
-       unsigned char ctrl, yr[2];
-       struct mem rtcmem = { CMOS_YEAR, sizeof(yr), yr };
-       int real_year, year_offset;
-
-       /*
-        * Ensure that the RTC is running.
-        */
-       rtc_command(RTC_GETCTRL, &ctrl);
-       if (ctrl & 0xc0) {
-               unsigned char new_ctrl = ctrl & ~0xc0;
-
-               printk(KERN_WARNING "RTC: resetting control %02x -> %02x\n",
-                      ctrl, new_ctrl);
-
-               rtc_command(RTC_SETCTRL, &new_ctrl);
-       }
-
-       if (rtc_command(RTC_GETDATETIME, rtctm) ||
-           rtc_command(MEM_READ, &rtcmem))
-               return;
-
-       real_year = yr[0];
-
-       /*
-        * The RTC year holds the LSB two bits of the current
-        * year, which should reflect the LSB two bits of the
-        * CMOS copy of the year.  Any difference indicates
-        * that we have to correct the CMOS version.
-        */
-       year_offset = rtctm->year_off - (real_year & 3);
-       if (year_offset < 0)
-               /*
-                * RTC year wrapped.  Adjust it appropriately.
-                */
-               year_offset += 4;
-
-       *year = real_year + year_offset + yr[1] * 100;
-}
-
-static int set_rtc_time(struct rtc_tm *rtctm, unsigned int year)
-{
-       unsigned char leap;
-       int ret;
-
-       leap = (!(year % 4) && (year % 100)) || !(year % 400);
-
-       if (rtctm->mon > 12 || rtctm->mon == 0 || rtctm->mday == 0)
-               return -EINVAL;
-
-       if (rtctm->mday > (days_in_mon[rtctm->mon] + (rtctm->mon == 2 && leap)))
-               return -EINVAL;
-
-       if (rtctm->hours >= 24 || rtctm->mins >= 60 || rtctm->secs >= 60)
-               return -EINVAL;
-
-       /*
-        * The RTC's own 2-bit year must reflect the least
-        * significant two bits of the CMOS year.
-        */
-       rtctm->year_off = (year % 100) & 3;
-
-       ret = rtc_command(RTC_SETDATETIME, rtctm);
-       if (ret == 0)
-               ret = rtc_update_year(year);
-
-       return ret;
-}
-
-/*
- * Set the RTC time only.  Note that
- * we do not touch the date.
- */
-static int k_set_rtc_time(void)
-{
-       struct rtc_tm new_rtctm, old_rtctm;
-       unsigned long nowtime = xtime.tv_sec;
-
-       if (rtc_command(RTC_GETDATETIME, &old_rtctm))
-               return 0;
-
-       new_rtctm.cs    = xtime.tv_nsec / 10000000;
-       new_rtctm.secs  = nowtime % 60; nowtime /= 60;
-       new_rtctm.mins  = nowtime % 60; nowtime /= 60;
-       new_rtctm.hours = nowtime % 24;
-
-       /*
-        * avoid writing when we're going to change the day
-        * of the month.  We will retry in the next minute.
-        * This basically means that if the RTC must not drift
-        * by more than 1 minute in 11 minutes.
-        *
-        * [ rtc: 1/1/2000 23:58:00, real 2/1/2000 00:01:00,
-        *   rtc gets set to 1/1/2000 00:01:00 ]
-        */
-       if ((old_rtctm.hours == 23 && old_rtctm.mins == 59) ||
-           (new_rtctm.hours == 23 && new_rtctm.mins == 59))
-               return 1;
-
-       return rtc_command(RTC_SETTIME, &new_rtctm);
-}
-
-static int rtc_ioctl(struct inode *inode, struct file *file,
-                    unsigned int cmd, unsigned long arg)
-{
-       unsigned int year;
-       struct rtc_time rtctm;
-       struct rtc_tm rtc_raw;
-
-       switch (cmd) {
-       case RTC_ALM_READ:
-       case RTC_ALM_SET:
-               break;
-
-       case RTC_RD_TIME:
-               memset(&rtctm, 0, sizeof(struct rtc_time));
-               get_rtc_time(&rtc_raw, &year);
-               rtctm.tm_sec  = rtc_raw.secs;
-               rtctm.tm_min  = rtc_raw.mins;
-               rtctm.tm_hour = rtc_raw.hours;
-               rtctm.tm_mday = rtc_raw.mday;
-               rtctm.tm_mon  = rtc_raw.mon - 1; /* month starts at 0 */
-               rtctm.tm_year = year - 1900; /* starts at 1900 */
-               return copy_to_user((void *)arg, &rtctm, sizeof(rtctm))
-                                ? -EFAULT : 0;
-
-       case RTC_SET_TIME:
-               if (!capable(CAP_SYS_TIME))
-                       return -EACCES;
-
-               if (copy_from_user(&rtctm, (void *)arg, sizeof(rtctm)))
-                       return -EFAULT;
-               rtc_raw.secs     = rtctm.tm_sec;
-               rtc_raw.mins     = rtctm.tm_min;
-               rtc_raw.hours    = rtctm.tm_hour;
-               rtc_raw.mday     = rtctm.tm_mday;
-               rtc_raw.mon      = rtctm.tm_mon + 1;
-               year             = rtctm.tm_year + 1900;
-               return set_rtc_time(&rtc_raw, year);
-               break;
-
-       case RTC_EPOCH_READ:
-               return put_user(1900, (unsigned long *)arg);
-
-       }
-       return -EINVAL;
-}
-
-static const struct file_operations rtc_fops = {
-       .ioctl  = rtc_ioctl,
-};
-
-static struct miscdevice rtc_dev = {
-       .minor  = RTC_MINOR,
-       .name   = "rtc",
-       .fops   = &rtc_fops,
-};
-
-/* IOC / IOMD i2c driver */
-
-#define FORCE_ONES     0xdc
-#define SCL            0x02
-#define SDA            0x01
-
-/*
- * We must preserve all non-i2c output bits in IOC_CONTROL.
- * Note also that we need to preserve the value of SCL and
- * SDA outputs as well (which may be different from the
- * values read back from IOC_CONTROL).
- */
-static u_int force_ones;
-
-static void ioc_setscl(void *data, int state)
-{
-       u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA);
-       u_int ones = force_ones;
-
-       if (state)
-               ones |= SCL;
-       else
-               ones &= ~SCL;
-
-       force_ones = ones;
-
-       ioc_writeb(ioc_control | ones, IOC_CONTROL);
-}
-
-static void ioc_setsda(void *data, int state)
-{
-       u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA);
-       u_int ones = force_ones;
-
-       if (state)
-               ones |= SDA;
-       else
-               ones &= ~SDA;
-
-       force_ones = ones;
-
-       ioc_writeb(ioc_control | ones, IOC_CONTROL);
-}
-
-static int ioc_getscl(void *data)
-{
-       return (ioc_readb(IOC_CONTROL) & SCL) != 0;
-}
-
-static int ioc_getsda(void *data)
-{
-       return (ioc_readb(IOC_CONTROL) & SDA) != 0;
-}
-
-static struct i2c_algo_bit_data ioc_data = {
-       .setsda         = ioc_setsda,
-       .setscl         = ioc_setscl,
-       .getsda         = ioc_getsda,
-       .getscl         = ioc_getscl,
-       .udelay         = 80,
-       .timeout        = 100
-};
-
-static int ioc_client_reg(struct i2c_client *client)
-{
-       if (client->driver->id == I2C_DRIVERID_PCF8583 &&
-           client->addr == 0x50) {
-               struct rtc_tm rtctm;
-               unsigned int year;
-               struct timespec tv;
-
-               rtc_client = client;
-               get_rtc_time(&rtctm, &year);
-
-               tv.tv_nsec = rtctm.cs * 10000000;
-               tv.tv_sec  = mktime(year, rtctm.mon, rtctm.mday,
-                                   rtctm.hours, rtctm.mins, rtctm.secs);
-               do_settimeofday(&tv);
-               set_rtc = k_set_rtc_time;
-       }
-
-       return 0;
-}
-
-static int ioc_client_unreg(struct i2c_client *client)
-{
-       if (client == rtc_client) {
-               set_rtc = NULL;
-               rtc_client = NULL;
-       }
-
-       return 0;
-}
-
-static struct i2c_adapter ioc_ops = {
-       .id                     = I2C_HW_B_IOC,
-       .algo_data              = &ioc_data,
-       .client_register        = ioc_client_reg,
-       .client_unregister      = ioc_client_unreg,
-};
-
-static int __init i2c_ioc_init(void)
-{
-       int ret;
-
-       force_ones = FORCE_ONES | SCL | SDA;
-
-       ret = i2c_bit_add_bus(&ioc_ops);
-
-       if (ret >= 0){
-               ret = misc_register(&rtc_dev);
-               if(ret < 0)
-                       i2c_del_adapter(&ioc_ops);
-       }
-
-       return ret;
-}
-
-__initcall(i2c_ioc_init);
diff --git a/drivers/acorn/char/pcf8583.c b/drivers/acorn/char/pcf8583.c
deleted file mode 100644 (file)
index 9b49f31..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- *  linux/drivers/acorn/char/pcf8583.c
- *
- *  Copyright (C) 2000 Russell King
- *
- * 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.
- *
- *  Driver for PCF8583 RTC & RAM chip
- */
-#include <linux/module.h>
-#include <linux/i2c.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/mc146818rtc.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/bcd.h>
-
-#include "pcf8583.h"
-
-static struct i2c_driver pcf8583_driver;
-
-static unsigned short ignore[] = { I2C_CLIENT_END };
-static unsigned short normal_addr[] = { 0x50, I2C_CLIENT_END };
-static unsigned short *forces[] = { NULL };
-
-static struct i2c_client_address_data addr_data = {
-       .normal_i2c             = normal_addr,
-       .probe                  = ignore,
-       .ignore                 = ignore,
-       .forces                 = forces,
-};
-
-#define set_ctrl(x, v) i2c_set_clientdata(x, (void *)(unsigned int)(v))
-#define get_ctrl(x)    ((unsigned int)i2c_get_clientdata(x))
-
-static int
-pcf8583_attach(struct i2c_adapter *adap, int addr, int kind)
-{
-       struct i2c_client *c;
-       unsigned char buf[1], ad[1] = { 0 };
-       struct i2c_msg msgs[2] = {
-               {
-                       .addr = addr,
-                       .flags = 0,
-                       .len = 1,
-                       .buf = ad,
-               }, {
-                       .addr = addr,
-                       .flags = I2C_M_RD,
-                       .len = 1,
-                       .buf = buf,
-               }
-       };
-
-       c = kmalloc(sizeof(*c), GFP_KERNEL);
-       if (!c)
-               return -ENOMEM;
-
-       memset(c, 0, sizeof(*c));
-       c->addr         = addr;
-       c->adapter      = adap;
-       c->driver       = &pcf8583_driver;
-
-       if (i2c_transfer(c->adapter, msgs, 2) == 2)
-               set_ctrl(c, buf[0]);
-
-       return i2c_attach_client(c);
-}
-
-static int
-pcf8583_probe(struct i2c_adapter *adap)
-{
-       return i2c_probe(adap, &addr_data, pcf8583_attach);
-}
-
-static int
-pcf8583_detach(struct i2c_client *client)
-{
-       i2c_detach_client(client);
-       kfree(client);
-       return 0;
-}
-
-static int
-pcf8583_get_datetime(struct i2c_client *client, struct rtc_tm *dt)
-{
-       unsigned char buf[8], addr[1] = { 1 };
-       struct i2c_msg msgs[2] = {
-               {
-                       .addr = client->addr,
-                       .flags = 0,
-                       .len = 1,
-                       .buf = addr,
-               }, {
-                       .addr = client->addr,
-                       .flags = I2C_M_RD,
-                       .len = 6,
-                       .buf = buf,
-               }
-       };
-       int ret = -EIO;
-
-       memset(buf, 0, sizeof(buf));
-
-       ret = i2c_transfer(client->adapter, msgs, 2);
-       if (ret == 2) {
-               dt->year_off = buf[4] >> 6;
-               dt->wday     = buf[5] >> 5;
-
-               buf[4] &= 0x3f;
-               buf[5] &= 0x1f;
-
-               dt->cs       = BCD_TO_BIN(buf[0]);
-               dt->secs     = BCD_TO_BIN(buf[1]);
-               dt->mins     = BCD_TO_BIN(buf[2]);
-               dt->hours    = BCD_TO_BIN(buf[3]);
-               dt->mday     = BCD_TO_BIN(buf[4]);
-               dt->mon      = BCD_TO_BIN(buf[5]);
-
-               ret = 0;
-       }
-
-       return ret;
-}
-
-static int
-pcf8583_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo)
-{
-       unsigned char buf[8];
-       int ret, len = 6;
-
-       buf[0] = 0;
-       buf[1] = get_ctrl(client) | 0x80;
-       buf[2] = BIN_TO_BCD(dt->cs);
-       buf[3] = BIN_TO_BCD(dt->secs);
-       buf[4] = BIN_TO_BCD(dt->mins);
-       buf[5] = BIN_TO_BCD(dt->hours);
-
-       if (datetoo) {
-               len = 8;
-               buf[6] = BIN_TO_BCD(dt->mday) | (dt->year_off << 6);
-               buf[7] = BIN_TO_BCD(dt->mon)  | (dt->wday << 5);
-       }
-
-       ret = i2c_master_send(client, (char *)buf, len);
-       if (ret == len)
-               ret = 0;
-
-       buf[1] = get_ctrl(client);
-       i2c_master_send(client, (char *)buf, 2);
-
-       return ret;
-}
-
-static int
-pcf8583_get_ctrl(struct i2c_client *client, unsigned char *ctrl)
-{
-       *ctrl = get_ctrl(client);
-       return 0;
-}
-
-static int
-pcf8583_set_ctrl(struct i2c_client *client, unsigned char *ctrl)
-{
-       unsigned char buf[2];
-
-       buf[0] = 0;
-       buf[1] = *ctrl;
-       set_ctrl(client, *ctrl);
-
-       return i2c_master_send(client, (char *)buf, 2);
-}
-
-static int
-pcf8583_read_mem(struct i2c_client *client, struct mem *mem)
-{
-       unsigned char addr[1];
-       struct i2c_msg msgs[2] = {
-               {
-                       .addr = client->addr,
-                       .flags = 0,
-                       .len = 1,
-                       .buf = addr,
-               }, {
-                       .addr = client->addr,
-                       .flags = I2C_M_RD,
-                       .len = mem->nr,
-                       .buf = mem->data,
-               }
-       };
-
-       if (mem->loc < 8)
-               return -EINVAL;
-
-       addr[0] = mem->loc;
-
-       return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
-}
-
-static int
-pcf8583_write_mem(struct i2c_client *client, struct mem *mem)
-{
-       unsigned char addr[1];
-       struct i2c_msg msgs[2] = {
-               {
-                       .addr = client->addr,
-                       .flags = 0,
-                       .len = 1,
-                       .buf = addr,
-               }, {
-                       .addr = client->addr,
-                       .flags = I2C_M_NOSTART,
-                       .len = mem->nr,
-                       .buf = mem->data,
-               }
-       };
-
-       if (mem->loc < 8)
-               return -EINVAL;
-
-       addr[0] = mem->loc;
-
-       return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
-}
-
-static int
-pcf8583_command(struct i2c_client *client, unsigned int cmd, void *arg)
-{
-       switch (cmd) {
-       case RTC_GETDATETIME:
-               return pcf8583_get_datetime(client, arg);
-               
-       case RTC_SETTIME:
-               return pcf8583_set_datetime(client, arg, 0);
-
-       case RTC_SETDATETIME:
-               return pcf8583_set_datetime(client, arg, 1);
-
-       case RTC_GETCTRL:
-               return pcf8583_get_ctrl(client, arg);
-
-       case RTC_SETCTRL:
-               return pcf8583_set_ctrl(client, arg);
-
-       case MEM_READ:
-               return pcf8583_read_mem(client, arg);
-
-       case MEM_WRITE:
-               return pcf8583_write_mem(client, arg);
-
-       default:
-               return -EINVAL;
-       }
-}
-
-static struct i2c_driver pcf8583_driver = {
-       .driver = {
-               .name   = "PCF8583",
-       },
-       .id             = I2C_DRIVERID_PCF8583,
-       .attach_adapter = pcf8583_probe,
-       .detach_client  = pcf8583_detach,
-       .command        = pcf8583_command
-};
-
-static __init int pcf8583_init(void)
-{
-       return i2c_add_driver(&pcf8583_driver);
-}
-
-static __exit void pcf8583_exit(void)
-{
-       i2c_del_driver(&pcf8583_driver);
-}
-
-module_init(pcf8583_init);
-module_exit(pcf8583_exit);
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("PCF8583 I2C RTC driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/acorn/char/pcf8583.h b/drivers/acorn/char/pcf8583.h
deleted file mode 100644 (file)
index 847f7fd..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- *  linux/drivers/acorn/char/pcf8583.h
- *
- *  Copyright (C) 2000 Russell King
- *
- * 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.
- */
-struct rtc_tm {
-       unsigned char   cs;
-       unsigned char   secs;
-       unsigned char   mins;
-       unsigned char   hours;
-       unsigned char   mday;
-       unsigned char   mon;
-       unsigned char   year_off;
-       unsigned char   wday;
-};
-
-struct mem {
-       unsigned int    loc;
-       unsigned int    nr;
-       unsigned char   *data;
-};
-
-#define RTC_GETDATETIME        0
-#define RTC_SETTIME    1
-#define RTC_SETDATETIME        2
-#define RTC_GETCTRL    3
-#define RTC_SETCTRL    4
-#define MEM_READ       5
-#define MEM_WRITE      6
-
-#define CTRL_STOP      0x80
-#define CTRL_HOLD      0x40
-#define CTRL_32KHZ     0x00
-#define CTRL_MASK      0x08
-#define CTRL_ALARMEN   0x04
-#define CTRL_ALARM     0x02
-#define CTRL_TIMER     0x01
index e942ffe8b57ee4c9a13a447bf205e3939815dfcc..e2ce4a9c1c9259adf6d16da21b0a8b313f15b906 100644 (file)
@@ -7,6 +7,7 @@ menu "ACPI (Advanced Configuration and Power Interface) Support"
        depends on !X86_VISWS
        depends on !IA64_HP_SIM
        depends on IA64 || X86
+       depends on PM
 
 config ACPI
        bool "ACPI Support"
@@ -149,6 +150,7 @@ config ACPI_DOCK
 config ACPI_BAY
        tristate "Removable Drive Bay (EXPERIMENTAL)"
        depends on EXPERIMENTAL
+       depends on ACPI_DOCK
        help
          This driver adds support for ACPI controlled removable drive
          bays such as the IBM ultrabay or the Dell Module Bay.
@@ -242,6 +244,17 @@ config ACPI_IBM_DOCK
 
          If you are not sure, say N here.
 
+config ACPI_IBM_BAY
+       bool "Legacy Removable Bay Support"
+       depends on ACPI_IBM
+       default y
+       ---help---
+         Allows the ibm_acpi driver to handle removable bays.  It will allow
+         disabling the device in the bay, and also generate notifications when
+         the bay lever is ejected or inserted.
+
+         If you are not sure, say Y here.
+
 config ACPI_TOSHIBA
        tristate "Toshiba Laptop Extras"
        depends on X86
index 772299fb5f9d97e54078f549e8241a852bbf181b..b770deab968c492322eaee25c2cbd84f0c4b92fb 100644 (file)
@@ -848,7 +848,7 @@ out:
 
 static int set_brightness_status(struct backlight_device *bd)
 {
-       return set_brightness(bd->props->brightness);
+       return set_brightness(bd->props.brightness);
 }
 
 static int
@@ -1352,11 +1352,9 @@ static int asus_hotk_remove(struct acpi_device *device, int type)
        return 0;
 }
 
-static struct backlight_properties asus_backlight_data = {
-        .owner          = THIS_MODULE,
+static struct backlight_ops asus_backlight_data = {
         .get_brightness = read_brightness,
         .update_status  = set_brightness_status,
-        .max_brightness = 15,
 };
 
 static void __exit asus_acpi_exit(void)
@@ -1410,6 +1408,7 @@ static int __init asus_acpi_init(void)
                asus_backlight_device = NULL;
                asus_acpi_exit();
        }
+        asus_backlight_device->props.max_brightness = 15;
 
        return 0;
 }
index f289fd41e77d5ef1bdb8d4d44359b08a43651930..3ec110ce00c8c3096b6f0ed7c379777b05e4822d 100644 (file)
@@ -79,11 +79,17 @@ static int __init blacklist_by_year(void)
 {
        int year = dmi_get_year(DMI_BIOS_DATE);
        /* Doesn't exist? Likely an old system */
-       if (year == -1)
+       if (year == -1) {
+               printk(KERN_ERR PREFIX "no DMI BIOS year, "
+                       "acpi=force is required to enable ACPI\n" );
                return 1;
+       }
        /* 0? Likely a buggy new BIOS */
-       if (year == 0)
+       if (year == 0) {
+               printk(KERN_ERR PREFIX "DMI BIOS year==0, "
+                       "assuming ACPI-capable machine\n" );
                return 0;
+       }
        if (year < CONFIG_ACPI_BLACKLIST_YEAR) {
                printk(KERN_ERR PREFIX "BIOS age (%d) fails cutoff (%d), "
                       "acpi=force is required to enable ACPI\n",
index ab688837379534b46ab194dacb41925215c3670b..a802962ff2b499fc2cc3489a5e28a02e58d2465d 100644 (file)
@@ -100,6 +100,7 @@ static struct acpi_ec {
        unsigned long global_lock;
        struct mutex lock;
        atomic_t query_pending;
+       atomic_t event_count;
        atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */
        wait_queue_head_t wait;
 } *ec_ecdt;
@@ -131,10 +132,12 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
        outb(data, ec->data_addr);
 }
 
-static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event)
+static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event,
+                                      unsigned old_count)
 {
        u8 status = acpi_ec_read_status(ec);
-
+       if (old_count == atomic_read(&ec->event_count))
+               return 0;
        if (event == ACPI_EC_EVENT_OBF_1) {
                if (status & ACPI_EC_FLAG_OBF)
                        return 1;
@@ -146,19 +149,19 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event)
        return 0;
 }
 
-static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event)
+static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, unsigned count)
 {
        if (acpi_ec_mode == EC_POLL) {
                unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
                while (time_before(jiffies, delay)) {
-                       if (acpi_ec_check_status(ec, event))
+                       if (acpi_ec_check_status(ec, event, 0))
                                return 0;
                }
        } else {
                if (wait_event_timeout(ec->wait,
-                                      acpi_ec_check_status(ec, event),
+                                      acpi_ec_check_status(ec, event, count),
                                       msecs_to_jiffies(ACPI_EC_DELAY)) ||
-                   acpi_ec_check_status(ec, event)) {
+                   acpi_ec_check_status(ec, event, 0)) {
                        return 0;
                } else {
                        printk(KERN_ERR PREFIX "acpi_ec_wait timeout,"
@@ -225,21 +228,22 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
                                        u8 * rdata, unsigned rdata_len)
 {
        int result = 0;
-
+       unsigned count = atomic_read(&ec->event_count);
        acpi_ec_write_cmd(ec, command);
 
        for (; wdata_len > 0; --wdata_len) {
-               result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
+               result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count);
                if (result) {
                        printk(KERN_ERR PREFIX
                               "write_cmd timeout, command = %d\n", command);
                        goto end;
                }
+               count = atomic_read(&ec->event_count);
                acpi_ec_write_data(ec, *(wdata++));
        }
 
        if (!rdata_len) {
-               result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
+               result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count);
                if (result) {
                        printk(KERN_ERR PREFIX
                               "finish-write timeout, command = %d\n", command);
@@ -250,13 +254,13 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
        }
 
        for (; rdata_len > 0; --rdata_len) {
-               result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1);
+               result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, count);
                if (result) {
                        printk(KERN_ERR PREFIX "read timeout, command = %d\n",
                               command);
                        goto end;
                }
-
+               count = atomic_read(&ec->event_count);
                *(rdata++) = acpi_ec_read_data(ec);
        }
       end:
@@ -288,7 +292,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
        /* Make sure GPE is enabled before doing transaction */
        acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
 
-       status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
+       status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0);
        if (status) {
                printk(KERN_DEBUG PREFIX
                       "input buffer is not empty, aborting transaction\n");
@@ -369,8 +373,8 @@ int ec_write(u8 addr, u8 val)
 EXPORT_SYMBOL(ec_write);
 
 int ec_transaction(u8 command,
-                         const u8 * wdata, unsigned wdata_len,
-                         u8 * rdata, unsigned rdata_len)
+                  const u8 * wdata, unsigned wdata_len,
+                  u8 * rdata, unsigned rdata_len)
 {
        struct acpi_ec *ec;
 
@@ -435,7 +439,7 @@ static u32 acpi_ec_gpe_handler(void *data)
        acpi_status status = AE_OK;
        u8 value;
        struct acpi_ec *ec = (struct acpi_ec *)data;
-
+       atomic_inc(&ec->event_count);
        if (acpi_ec_mode == EC_INTR) {
                wake_up(&ec->wait);
        }
@@ -633,6 +637,7 @@ static int acpi_ec_add(struct acpi_device *device)
        ec->uid = -1;
        mutex_init(&ec->lock);
        atomic_set(&ec->query_pending, 0);
+       atomic_set(&ec->event_count, 1);
        if (acpi_ec_mode == EC_INTR) {
                atomic_set(&ec->leaving_burst, 1);
                init_waitqueue_head(&ec->wait);
@@ -807,6 +812,7 @@ acpi_fake_ecdt_callback(acpi_handle handle,
        acpi_status status;
 
        mutex_init(&ec_ecdt->lock);
+       atomic_set(&ec_ecdt->event_count, 1);
        if (acpi_ec_mode == EC_INTR) {
                init_waitqueue_head(&ec_ecdt->wait);
        }
@@ -888,6 +894,7 @@ static int __init acpi_ec_get_real_ecdt(void)
                return -ENOMEM;
 
        mutex_init(&ec_ecdt->lock);
+       atomic_set(&ec_ecdt->event_count, 1);
        if (acpi_ec_mode == EC_INTR) {
                init_waitqueue_head(&ec_ecdt->wait);
        }
@@ -1016,8 +1023,7 @@ static int __init acpi_ec_set_intr_mode(char *str)
                acpi_ec_mode = EC_POLL;
        }
        acpi_ec_driver.ops.add = acpi_ec_add;
-       printk(KERN_NOTICE PREFIX "%s mode.\n",
-                         intr ? "interrupt" : "polling");
+       printk(KERN_NOTICE PREFIX "%s mode.\n", intr ? "interrupt" : "polling");
 
        return 1;
 }
index d572700197f309d118ff302fde56c29a2c25fb1a..8dcade63b04bad04608b29eaab97f82ea2420b15 100644 (file)
@@ -423,6 +423,8 @@ static acpi_status acpi_ev_remove_global_lock_handler(void)
  * the global lock appear as a standard mutex on the OS side.
  *
  *****************************************************************************/
+static acpi_thread_id acpi_ev_global_lock_thread_id;
+static int acpi_ev_global_lock_acquired;
 
 acpi_status acpi_ev_acquire_global_lock(u16 timeout)
 {
@@ -435,11 +437,24 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)
         * Only one thread can acquire the GL at a time, the global_lock_mutex
         * enforces this. This interface releases the interpreter if we must wait.
         */
-       status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, timeout);
+       status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, 0);
+       if (status == AE_TIME) {
+               if (acpi_ev_global_lock_thread_id == acpi_os_get_thread_id()) {
+                       acpi_ev_global_lock_acquired++;
+                       return AE_OK;
+               }
+       }
+
+       if (ACPI_FAILURE(status)) {
+               status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, timeout);
+       }
        if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
        }
 
+       acpi_ev_global_lock_thread_id = acpi_os_get_thread_id();
+       acpi_ev_global_lock_acquired++;
+
        /*
         * Make sure that a global lock actually exists. If not, just treat
         * the lock as a standard mutex.
@@ -506,6 +521,11 @@ acpi_status acpi_ev_release_global_lock(void)
                return_ACPI_STATUS(AE_NOT_ACQUIRED);
        }
 
+       acpi_ev_global_lock_acquired--;
+       if (acpi_ev_global_lock_acquired > 0) {
+               return AE_OK;
+       }
+
        if (acpi_gbl_global_lock_present) {
 
                /* Allow any thread to release the lock */
@@ -529,7 +549,8 @@ acpi_status acpi_ev_release_global_lock(void)
        acpi_gbl_global_lock_acquired = FALSE;
 
        /* Release the local GL mutex */
-
+       acpi_ev_global_lock_thread_id = 0;
+       acpi_ev_global_lock_acquired = 0;
        acpi_os_release_mutex(acpi_gbl_global_lock_mutex);
        return_ACPI_STATUS(status);
 }
index 1a0ed3dc409c8426d1e79f084a1ce0e38451bac7..36901362fd24418917ab0727f1450bd217d58967 100644 (file)
@@ -86,6 +86,7 @@
 
 #include <linux/proc_fs.h>
 #include <linux/backlight.h>
+#include <linux/fb.h>
 #include <asm/uaccess.h>
 
 #include <linux/dmi.h>
@@ -157,6 +158,7 @@ IBM_HANDLE(dock, root, "\\_SB.GDCK",        /* X30, X31, X40 */
           "\\_SB.PCI.ISA.SLCE",        /* 570 */
     );                         /* A21e,G4x,R30,R31,R32,R40,R40e,R50e */
 #endif
+#ifdef CONFIG_ACPI_IBM_BAY
 IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST",       /* 570 */
           "\\_SB.PCI0.IDE0.IDES.IDSM", /* 600e/x, 770e, 770x */
           "\\_SB.PCI0.SATA.SCND.MSTR", /* T60, X60, Z60 */ 
@@ -174,6 +176,7 @@ IBM_HANDLE(bay2, root, "\\_SB.PCI0.IDE0.PRIM.SLAV", /* A3x, R32 */
 IBM_HANDLE(bay2_ej, bay2, "_EJ3",      /* 600e/x, 770e, A3x */
           "_EJ0",              /* 770x */
     );                         /* all others */
+#endif /* CONFIG_ACPI_IBM_BAY */
 
 /* don't list other alternatives as we install a notify handler on the 570 */
 IBM_HANDLE(pci, root, "\\_SB.PCI");    /* 570 */
@@ -1044,6 +1047,7 @@ static int light_write(char *buf)
        return 0;
 }
 
+#if defined(CONFIG_ACPI_IBM_DOCK) || defined(CONFIG_ACPI_IBM_BAY)
 static int _sta(acpi_handle handle)
 {
        int status;
@@ -1053,6 +1057,7 @@ static int _sta(acpi_handle handle)
 
        return status;
 }
+#endif
 
 #ifdef CONFIG_ACPI_IBM_DOCK
 #define dock_docked() (_sta(dock_handle) & 1)
@@ -1119,6 +1124,7 @@ static void dock_notify(struct ibm_struct *ibm, u32 event)
 }
 #endif
 
+#ifdef CONFIG_ACPI_IBM_BAY
 static int bay_status_supported;
 static int bay_status2_supported;
 static int bay_eject_supported;
@@ -1194,6 +1200,7 @@ static void bay_notify(struct ibm_struct *ibm, u32 event)
 {
        acpi_bus_generate_event(ibm->device, event, 0);
 }
+#endif /* CONFIG_ACPI_IBM_BAY */
 
 static int cmos_read(char *p)
 {
@@ -1701,18 +1708,25 @@ static int brightness_write(char *buf)
 
 static int brightness_update_status(struct backlight_device *bd)
 {
-       return brightness_set(bd->props->brightness);
+       return brightness_set(
+               (bd->props.fb_blank == FB_BLANK_UNBLANK &&
+                bd->props.power == FB_BLANK_UNBLANK) ?
+                               bd->props.brightness : 0);
 }
 
-static struct backlight_properties ibm_backlight_data = {
-        .owner          = THIS_MODULE,
+static struct backlight_ops ibm_backlight_data = {
         .get_brightness = brightness_get,
         .update_status  = brightness_update_status,
-        .max_brightness = 7,
 };
 
 static int brightness_init(void)
 {
+       int b;
+
+       b = brightness_get(NULL);
+       if (b < 0)
+               return b;
+
        ibm_backlight_device = backlight_device_register("ibm", NULL, NULL,
                                                         &ibm_backlight_data);
        if (IS_ERR(ibm_backlight_device)) {
@@ -1720,6 +1734,10 @@ static int brightness_init(void)
                return PTR_ERR(ibm_backlight_device);
        }
 
+       ibm_backlight_device->props.max_brightness = 7;
+       ibm_backlight_device->props.brightness = b;
+       backlight_update_status(ibm_backlight_device);
+
        return 0;
 }
 
@@ -2353,6 +2371,7 @@ static struct ibm_struct ibms[] = {
         .type = ACPI_SYSTEM_NOTIFY,
         },
 #endif
+#ifdef CONFIG_ACPI_IBM_BAY
        {
         .name = "bay",
         .init = bay_init,
@@ -2362,6 +2381,7 @@ static struct ibm_struct ibms[] = {
         .handle = &bay_handle,
         .type = ACPI_SYSTEM_NOTIFY,
         },
+#endif /* CONFIG_ACPI_IBM_BAY */
        {
         .name = "cmos",
         .read = cmos_read,
@@ -2647,7 +2667,9 @@ IBM_PARAM(light);
 #ifdef CONFIG_ACPI_IBM_DOCK
 IBM_PARAM(dock);
 #endif
+#ifdef CONFIG_ACPI_IBM_BAY
 IBM_PARAM(bay);
+#endif /* CONFIG_ACPI_IBM_BAY */
 IBM_PARAM(cmos);
 IBM_PARAM(led);
 IBM_PARAM(beep);
@@ -2723,12 +2745,14 @@ static int __init acpi_ibm_init(void)
        IBM_HANDLE_INIT(dock);
 #endif
        IBM_HANDLE_INIT(pci);
+#ifdef CONFIG_ACPI_IBM_BAY
        IBM_HANDLE_INIT(bay);
        if (bay_handle)
                IBM_HANDLE_INIT(bay_ej);
        IBM_HANDLE_INIT(bay2);
        if (bay2_handle)
                IBM_HANDLE_INIT(bay2_ej);
+#endif /* CONFIG_ACPI_IBM_BAY */
        IBM_HANDLE_INIT(beep);
        IBM_HANDLE_INIT(ecrd);
        IBM_HANDLE_INIT(ecwr);
index 1ef338545dfef977034a490d56ae9c5f043eb948..4ffecd17970277f46967bb959bce94c15dacffe0 100644 (file)
@@ -436,8 +436,6 @@ int acpi_power_transition(struct acpi_device *device, int state)
        cl = &device->power.states[device->power.state].resources;
        tl = &device->power.states[state].resources;
 
-       device->power.state = ACPI_STATE_UNKNOWN;
-
        if (!cl->count && !tl->count) {
                result = -ENODEV;
                goto end;
@@ -468,12 +466,15 @@ int acpi_power_transition(struct acpi_device *device, int state)
                        goto end;
        }
 
-       /* We shouldn't change the state till all above operations succeed */
-       device->power.state = state;
-      end:
-       if (result)
+     end:
+       if (result) {
+               device->power.state = ACPI_STATE_UNKNOWN;
                printk(KERN_WARNING PREFIX "Transitioning device [%s] to D%d\n",
                              device->pnp.bus_id, state);
+       } else {
+       /* We shouldn't change the state till all above operations succeed */
+               device->power.state = state;
+       }
 
        return result;
 }
@@ -687,13 +688,6 @@ static int acpi_power_resume(struct acpi_device *device)
                return result;
 
        mutex_lock(&resource->resource_lock);
-       if ((resource->state == ACPI_POWER_RESOURCE_STATE_ON) &&
-           list_empty(&resource->reference)) {
-               mutex_unlock(&resource->resource_lock);
-               result = acpi_power_off_device(device->handle, NULL);
-               return result;
-       }
-
        if ((resource->state == ACPI_POWER_RESOURCE_STATE_OFF) &&
            !list_empty(&resource->reference)) {
                ref = container_of(resource->reference.next, struct acpi_power_reference, node);
index 1358c06a969c2b2d8d2a795556c4f6f3d169575f..cc48ab05676c5ccefd1b342cd8532260c48d6470 100644 (file)
@@ -191,6 +191,9 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
        user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);
 
        for (index = 0; index < number_of_elements; index++) {
+               int source_name_index = 2;
+               int source_index_index = 3;
+
                /*
                 * Point user_prt past this current structure
                 *
@@ -260,11 +263,29 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
                        return_ACPI_STATUS(AE_BAD_DATA);
                }
 
+               /*
+                * If BIOS erroneously reversed the _PRT source_name and source_index,
+                * then reverse them back.
+                */
+               if (ACPI_GET_OBJECT_TYPE (sub_object_list[3]) != ACPI_TYPE_INTEGER) {
+                       if (acpi_gbl_enable_interpreter_slack) {
+                               source_name_index = 3;
+                               source_index_index = 2;
+                               printk(KERN_WARNING "ACPI: Handling Garbled _PRT entry\n");
+                       } else {
+                               ACPI_ERROR((AE_INFO,
+                                       "(PRT[%X].source_index) Need Integer, found %s",
+                                       index,
+                                       acpi_ut_get_object_type_name(sub_object_list[3])));
+                               return_ACPI_STATUS(AE_BAD_DATA);
+                       }
+               }
+
                /*
                 * 3) Third subobject: Dereference the PRT.source_name
                 * The name may be unresolved (slack mode), so allow a null object
                 */
-               obj_desc = sub_object_list[2];
+               obj_desc = sub_object_list[source_name_index];
                if (obj_desc) {
                        switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
                        case ACPI_TYPE_LOCAL_REFERENCE:
@@ -339,7 +360,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
 
                /* 4) Fourth subobject: Dereference the PRT.source_index */
 
-               obj_desc = sub_object_list[3];
+               obj_desc = sub_object_list[source_index_index];
                if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
                        user_prt->source_index = (u32) obj_desc->integer.value;
                } else {
index faf8a5232d8e5d94d285f7c92bc4b6856ace05bb..3906d47b9783521683bcf001ad5ead9b29639c30 100644 (file)
@@ -315,7 +315,7 @@ static int set_lcd(int value)
 
 static int set_lcd_status(struct backlight_device *bd)
 {
-       return set_lcd(bd->props->brightness);
+       return set_lcd(bd->props.brightness);
 }
 
 static unsigned long write_lcd(const char *buffer, unsigned long count)
@@ -533,11 +533,9 @@ static acpi_status __exit remove_device(void)
        return AE_OK;
 }
 
-static struct backlight_properties toshiba_backlight_data = {
-        .owner          = THIS_MODULE,
+static struct backlight_ops toshiba_backlight_data = {
         .get_brightness = get_lcd,
         .update_status  = set_lcd_status,
-        .max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1,
 };
 
 static void __exit toshiba_acpi_exit(void)
@@ -597,6 +595,7 @@ static int __init toshiba_acpi_init(void)
                toshiba_backlight_device = NULL;
                toshiba_acpi_exit();
        }
+        toshiba_backlight_device->props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
 
        return (ACPI_SUCCESS(status)) ? 0 : -ENODEV;
 }
index bf525cca3b637160a3c1b28f95269ea108c1dfd3..00d25b34725549e86b739354cf5f972e6a10831f 100644 (file)
@@ -102,9 +102,9 @@ struct acpi_video_bus_cap {
 
 struct acpi_video_device_attrib {
        u32 display_index:4;    /* A zero-based instance of the Display */
-       u32 display_port_attachment:4;  /*This field differenates displays type */
+       u32 display_port_attachment:4;  /*This field differentiates the display type */
        u32 display_type:4;     /*Describe the specific type in use */
-       u32 vendor_specific:4;  /*Chipset Vendor Specifi */
+       u32 vendor_specific:4;  /*Chipset Vendor Specific */
        u32 bios_can_detect:1;  /*BIOS can detect the device */
        u32 depend_on_vga:1;    /*Non-VGA output device whose power is related to 
                                   the VGA device. */
@@ -169,7 +169,6 @@ struct acpi_video_device {
        struct acpi_device *dev;
        struct acpi_video_device_brightness *brightness;
        struct backlight_device *backlight;
-       struct backlight_properties *data;
 };
 
 /* bus */
@@ -286,13 +285,18 @@ static int acpi_video_get_brightness(struct backlight_device *bd)
 
 static int acpi_video_set_brightness(struct backlight_device *bd)
 {
-       int request_level = bd->props->brightness;
+       int request_level = bd->props.brightness;
        struct acpi_video_device *vd =
                (struct acpi_video_device *)class_get_devdata(&bd->class_dev);
        acpi_video_device_lcd_set_level(vd, request_level);
        return 0;
 }
 
+static struct backlight_ops acpi_backlight_ops = {
+       .get_brightness = acpi_video_get_brightness,
+       .update_status  = acpi_video_set_brightness,
+};
+
 /* --------------------------------------------------------------------------
                                Video Management
    -------------------------------------------------------------------------- */
@@ -480,16 +484,16 @@ acpi_video_bus_POST_options(struct acpi_video_bus *video,
  *             0.      The system BIOS should NOT automatically switch(toggle)
  *                     the active display output.
  *             1.      The system BIOS should automatically switch (toggle) the
- *                     active display output. No swich event.
+ *                     active display output. No switch event.
  *             2.      The _DGS value should be locked.
  *             3.      The system BIOS should not automatically switch (toggle) the
  *                     active display output, but instead generate the display switch
  *                     event notify code.
  *     lcd_flag        :
  *             0.      The system BIOS should automatically control the brightness level
- *                     of the LCD, when the power changes from AC to DC
+ *                     of the LCD when the power changes from AC to DC
  *             1.      The system BIOS should NOT automatically control the brightness 
- *                     level of the LCD, when the power changes from AC to DC.
+ *                     level of the LCD when the power changes from AC to DC.
  * Return Value:
  *             -1      wrong arg.
  */
@@ -521,7 +525,7 @@ acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag)
  *  Return Value:
  *     None
  *
- *  Find out all required AML method defined under the output
+ *  Find out all required AML methods defined under the output
  *  device.
  */
 
@@ -608,31 +612,18 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
                unsigned long tmp;
                static int count = 0;
                char *name;
-               struct backlight_properties *acpi_video_data;
-
                name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
                if (!name)
                        return;
 
-               acpi_video_data = kzalloc(
-                       sizeof(struct backlight_properties),
-                       GFP_KERNEL);
-               if (!acpi_video_data){
-                       kfree(name);
-                       return;
-               }
-               acpi_video_data->owner = THIS_MODULE;
-               acpi_video_data->get_brightness =
-                       acpi_video_get_brightness;
-               acpi_video_data->update_status =
-                       acpi_video_set_brightness;
                sprintf(name, "acpi_video%d", count++);
-               device->data = acpi_video_data;
-               acpi_video_data->max_brightness = max_level;
                acpi_video_device_lcd_get_level_current(device, &tmp);
-               acpi_video_data->brightness = (int)tmp;
                device->backlight = backlight_device_register(name,
-                       NULL, device, acpi_video_data);
+                       NULL, device, &acpi_backlight_ops);
+               device->backlight->props.max_brightness = max_level;
+               device->backlight->props.brightness = (int)tmp;
+               backlight_update_status(device->backlight);
+
                kfree(name);
        }
        return;
@@ -645,7 +636,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
  *  Return Value:
  *     None
  *
- *  Find out all required AML method defined under the video bus device.
+ *  Find out all required AML methods defined under the video bus device.
  */
 
 static void acpi_video_bus_find_cap(struct acpi_video_bus *video)
@@ -690,19 +681,19 @@ static int acpi_video_bus_check(struct acpi_video_bus *video)
         * to check well known required nodes.
         */
 
-       /* Does this device able to support video switching ? */
+       /* Does this device support video switching? */
        if (video->cap._DOS) {
                video->flags.multihead = 1;
                status = 0;
        }
 
-       /* Does this device able to retrieve a retrieve a video ROM ? */
+       /* Does this device support retrieving a video ROM? */
        if (video->cap._ROM) {
                video->flags.rom = 1;
                status = 0;
        }
 
-       /* Does this device able to configure which video device to POST ? */
+       /* Does this device support configuring which video device to POST? */
        if (video->cap._GPD && video->cap._SPD && video->cap._VPO) {
                video->flags.post = 1;
                status = 0;
@@ -869,7 +860,7 @@ acpi_video_device_write_brightness(struct file *file,
        if (level > 100)
                return -EFAULT;
 
-       /* validate though the list of available levels */
+       /* validate through the list of available levels */
        for (i = 0; i < dev->brightness->count; i++)
                if (level == dev->brightness->levels[i]) {
                        if (ACPI_SUCCESS
@@ -1074,10 +1065,10 @@ static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
                        printk(KERN_WARNING PREFIX
                               "The motherboard VGA device is not listed as a possible POST device.\n");
                        printk(KERN_WARNING PREFIX
-                              "This indicate a BIOS bug.  Please contact the manufacturer.\n");
+                              "This indicates a BIOS bug. Please contact the manufacturer.\n");
                }
                printk("%lx\n", options);
-               seq_printf(seq, "can POST: <intgrated video>");
+               seq_printf(seq, "can POST: <integrated video>");
                if (options & 2)
                        seq_printf(seq, " <PCI video>");
                if (options & 4)
@@ -1111,7 +1102,7 @@ static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset)
                seq_printf(seq, "<not supported>\n");
                goto end;
        }
-       seq_printf(seq, "device posted is <%s>\n", device_decode[id & 3]);
+       seq_printf(seq, "device POSTed is <%s>\n", device_decode[id & 3]);
 
       end:
        return 0;
@@ -1165,7 +1156,7 @@ acpi_video_bus_write_POST(struct file *file,
        if (opt > 3)
                return -EFAULT;
 
-       /* just in case an OEM 'forget' the motherboard... */
+       /* just in case an OEM 'forgot' the motherboard... */
        options |= 1;
 
        if (options & (1ul << opt)) {
@@ -1536,13 +1527,13 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
 /*
  *  Arg:
  *     video   : video bus device 
- *     event   : Nontify Event
+ *     event   : notify event
  *
  *  Return:
  *     < 0     : error
  *  
  *     1. Find out the current active output device.
- *     2. Identify the next output device to switch
+ *     2. Identify the next output device to switch to.
  *     3. call _DSS to do actual switch.
  */
 
@@ -1677,10 +1668,7 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
        status = acpi_remove_notify_handler(device->dev->handle,
                                            ACPI_DEVICE_NOTIFY,
                                            acpi_video_device_notify);
-       if (device->backlight){
-               backlight_device_unregister(device->backlight);
-               kfree(device->data);
-       }
+       backlight_device_unregister(device->backlight);
        return 0;
 }
 
@@ -1735,12 +1723,12 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
        device = video->device;
 
        switch (event) {
-       case ACPI_VIDEO_NOTIFY_SWITCH:  /* User request that a switch occur,
+       case ACPI_VIDEO_NOTIFY_SWITCH:  /* User requested a switch,
                                         * most likely via hotkey. */
                acpi_bus_generate_event(device, event, 0);
                break;
 
-       case ACPI_VIDEO_NOTIFY_PROBE:   /* User plug or remove a video
+       case ACPI_VIDEO_NOTIFY_PROBE:   /* User plugged in or removed a video
                                         * connector. */
                acpi_video_device_enumerate(video);
                acpi_video_device_rebind(video);
index 4af0a4bb578042fc7c58c6e4448ec01e88a1622c..d16b5b0c8b76b5d0bcacb9fbf5348e33e94492b2 100644 (file)
@@ -562,6 +562,15 @@ config PATA_IXP4XX_CF
 
          If unsure, say N.
 
+config PATA_SCC
+       tristate "Toshiba's Cell Reference Set IDE support"
+       depends on PCI && PPC_IBM_CELL_BLADE
+       help
+         This option enables support for the built-in IDE controller on
+         Toshiba Cell Reference Board.
+
+         If unsure, say N.
+
 endif
 endmenu
 
index 74298afbbaa7c354dd21fc9067a883f4326599e6..13d7397e0008080fe84dc020f69e7f10a5e2b870 100644 (file)
@@ -59,6 +59,7 @@ obj-$(CONFIG_PATA_WINBOND_VLB)        += pata_winbond.o
 obj-$(CONFIG_PATA_SIS)         += pata_sis.o
 obj-$(CONFIG_PATA_TRIFLEX)     += pata_triflex.o
 obj-$(CONFIG_PATA_IXP4XX_CF)   += pata_ixp4xx_cf.o
+obj-$(CONFIG_PATA_SCC)         += pata_scc.o
 obj-$(CONFIG_PATA_PLATFORM)    += pata_platform.o
 # Should be last but one libata driver
 obj-$(CONFIG_ATA_GENERIC)      += ata_generic.o
index 6a3543e062415cfa733e728fd327d3cbe851be14..dc7b562259232990cee4edd7b819fe88b3642658 100644 (file)
@@ -46,7 +46,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "ahci"
-#define DRV_VERSION    "2.0"
+#define DRV_VERSION    "2.1"
 
 
 enum {
@@ -198,9 +198,9 @@ struct ahci_port_priv {
        void                    *rx_fis;
        dma_addr_t              rx_fis_dma;
        /* for NCQ spurious interrupt analysis */
-       int                     ncq_saw_spurious_sdb_cnt;
        unsigned int            ncq_saw_d2h:1;
        unsigned int            ncq_saw_dmas:1;
+       unsigned int            ncq_saw_sdb:1;
 };
 
 static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg);
@@ -219,10 +219,12 @@ static void ahci_thaw(struct ata_port *ap);
 static void ahci_error_handler(struct ata_port *ap);
 static void ahci_vt8251_error_handler(struct ata_port *ap);
 static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
+#ifdef CONFIG_PM
 static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
 static int ahci_port_resume(struct ata_port *ap);
 static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
 static int ahci_pci_device_resume(struct pci_dev *pdev);
+#endif
 
 static struct scsi_host_template ahci_sht = {
        .module                 = THIS_MODULE,
@@ -241,8 +243,10 @@ static struct scsi_host_template ahci_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .suspend                = ata_scsi_device_suspend,
        .resume                 = ata_scsi_device_resume,
+#endif
 };
 
 static const struct ata_port_operations ahci_ops = {
@@ -271,8 +275,10 @@ static const struct ata_port_operations ahci_ops = {
        .error_handler          = ahci_error_handler,
        .post_internal_cmd      = ahci_post_internal_cmd,
 
+#ifdef CONFIG_PM
        .port_suspend           = ahci_port_suspend,
        .port_resume            = ahci_port_resume,
+#endif
 
        .port_start             = ahci_port_start,
        .port_stop              = ahci_port_stop,
@@ -304,8 +310,10 @@ static const struct ata_port_operations ahci_vt8251_ops = {
        .error_handler          = ahci_vt8251_error_handler,
        .post_internal_cmd      = ahci_post_internal_cmd,
 
+#ifdef CONFIG_PM
        .port_suspend           = ahci_port_suspend,
        .port_resume            = ahci_port_resume,
+#endif
 
        .port_start             = ahci_port_start,
        .port_stop              = ahci_port_stop,
@@ -381,16 +389,14 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x2929), board_ahci_pi }, /* ICH9M */
        { PCI_VDEVICE(INTEL, 0x292a), board_ahci_pi }, /* ICH9M */
        { PCI_VDEVICE(INTEL, 0x292b), board_ahci_pi }, /* ICH9M */
+       { PCI_VDEVICE(INTEL, 0x292c), board_ahci_pi }, /* ICH9M */
        { PCI_VDEVICE(INTEL, 0x292f), board_ahci_pi }, /* ICH9M */
        { PCI_VDEVICE(INTEL, 0x294d), board_ahci_pi }, /* ICH9 */
        { PCI_VDEVICE(INTEL, 0x294e), board_ahci_pi }, /* ICH9M */
 
-       /* JMicron */
-       { PCI_VDEVICE(JMICRON, 0x2360), board_ahci_ign_iferr }, /* JMB360 */
-       { PCI_VDEVICE(JMICRON, 0x2361), board_ahci_ign_iferr }, /* JMB361 */
-       { PCI_VDEVICE(JMICRON, 0x2363), board_ahci_ign_iferr }, /* JMB363 */
-       { PCI_VDEVICE(JMICRON, 0x2365), board_ahci_ign_iferr }, /* JMB365 */
-       { PCI_VDEVICE(JMICRON, 0x2366), board_ahci_ign_iferr }, /* JMB366 */
+       /* JMicron 360/1/3/5/6, match class to avoid IDE function */
+       { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+         PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },
 
        /* ATI */
        { PCI_VDEVICE(ATI, 0x4380), board_ahci }, /* ATI SB600 non-raid */
@@ -439,8 +445,10 @@ static struct pci_driver ahci_pci_driver = {
        .id_table               = ahci_pci_tbl,
        .probe                  = ahci_init_one,
        .remove                 = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend                = ahci_pci_device_suspend,
        .resume                 = ahci_pci_device_resume,
+#endif
 };
 
 
@@ -580,6 +588,7 @@ static void ahci_power_up(void __iomem *port_mmio, u32 cap)
        writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
 }
 
+#ifdef CONFIG_PM
 static void ahci_power_down(void __iomem *port_mmio, u32 cap)
 {
        u32 cmd, scontrol;
@@ -597,6 +606,7 @@ static void ahci_power_down(void __iomem *port_mmio, u32 cap)
        cmd &= ~PORT_CMD_SPIN_UP;
        writel(cmd, port_mmio + PORT_CMD);
 }
+#endif
 
 static void ahci_init_port(void __iomem *port_mmio, u32 cap,
                           dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma)
@@ -1160,23 +1170,32 @@ static void ahci_host_intr(struct ata_port *ap)
                known_irq = 1;
        }
 
-       if (status & PORT_IRQ_SDB_FIS &&
-                  pp->ncq_saw_spurious_sdb_cnt < 10) {
-               /* SDB FIS containing spurious completions might be
-                * dangerous, we need to know more about them.  Print
-                * more of it.
-                */
+       if (status & PORT_IRQ_SDB_FIS) {
                const __le32 *f = pp->rx_fis + RX_FIS_SDB;
 
-               ata_port_printk(ap, KERN_INFO, "Spurious SDB FIS during NCQ "
-                               "issue=0x%x SAct=0x%x FIS=%08x:%08x%s\n",
+               if (le32_to_cpu(f[1])) {
+                       /* SDB FIS containing spurious completions
+                        * might be dangerous, whine and fail commands
+                        * with HSM violation.  EH will turn off NCQ
+                        * after several such failures.
+                        */
+                       ata_ehi_push_desc(ehi,
+                               "spurious completions during NCQ "
+                               "issue=0x%x SAct=0x%x FIS=%08x:%08x",
                                readl(port_mmio + PORT_CMD_ISSUE),
                                readl(port_mmio + PORT_SCR_ACT),
-                               le32_to_cpu(f[0]), le32_to_cpu(f[1]),
-                               pp->ncq_saw_spurious_sdb_cnt < 10 ?
-                               "" : ", shutting up");
-
-               pp->ncq_saw_spurious_sdb_cnt++;
+                               le32_to_cpu(f[0]), le32_to_cpu(f[1]));
+                       ehi->err_mask |= AC_ERR_HSM;
+                       ehi->action |= ATA_EH_SOFTRESET;
+                       ata_port_freeze(ap);
+               } else {
+                       if (!pp->ncq_saw_sdb)
+                               ata_port_printk(ap, KERN_INFO,
+                                       "spurious SDB FIS %08x:%08x during NCQ, "
+                                       "this message won't be printed again\n",
+                                       le32_to_cpu(f[0]), le32_to_cpu(f[1]));
+                       pp->ncq_saw_sdb = 1;
+               }
                known_irq = 1;
        }
 
@@ -1329,6 +1348,7 @@ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
        }
 }
 
+#ifdef CONFIG_PM
 static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
 {
        struct ahci_host_priv *hpriv = ap->host->private_data;
@@ -1407,6 +1427,7 @@ static int ahci_pci_device_resume(struct pci_dev *pdev)
 
        return 0;
 }
+#endif
 
 static int ahci_port_start(struct ata_port *ap)
 {
@@ -1665,13 +1686,6 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (!printed_version++)
                dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
-       if (pdev->vendor == PCI_VENDOR_ID_JMICRON) {
-               /* Function 1 is the PATA controller except on the 368, where
-                  we are not AHCI anyway */
-               if (PCI_FUNC(pdev->devfn))
-                       return -ENODEV;
-       }
-
        rc = pcim_enable_device(pdev);
        if (rc)
                return rc;
index be66ea08da551f16fa76459510e8cc75fa65f0f1..d8e79882b8809a97df8eff73efd87f9e228d1bc7 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "ata_generic"
-#define DRV_VERSION "0.2.10"
+#define DRV_VERSION "0.2.11"
 
 /*
  *     A generic parallel ATA driver using libata
@@ -90,10 +90,10 @@ static int generic_set_mode(struct ata_port *ap, struct ata_device **unused)
                        /* We do need the right mode information for DMA or PIO
                           and this comes from the current configuration flags */
                        if (dma_enabled & (1 << (5 + i))) {
-                               dev->xfer_mode = XFER_MW_DMA_0;
-                               dev->xfer_shift = ATA_SHIFT_MWDMA;
+                               ata_id_to_dma_mode(dev, XFER_MW_DMA_0);
                                dev->flags &= ~ATA_DFLAG_PIO;
                        } else {
+                               ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
                                dev->xfer_mode = XFER_PIO_0;
                                dev->xfer_shift = ATA_SHIFT_PIO;
                                dev->flags |= ATA_DFLAG_PIO;
@@ -119,8 +119,10 @@ static struct scsi_host_template generic_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static struct ata_port_operations generic_port_ops = {
@@ -230,8 +232,10 @@ static struct pci_driver ata_generic_pci_driver = {
        .id_table       = ata_generic,
        .probe          = ata_generic_init_one,
        .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend        = ata_pci_device_suspend,
        .resume         = ata_pci_device_resume,
+#endif
 };
 
 static int __init ata_generic_init(void)
index 4d716c7347e70c9bf8195db78ec5377a605db57d..b952c584338fb4fe3f797435a1f720c8b6070ef4 100644 (file)
@@ -93,7 +93,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "ata_piix"
-#define DRV_VERSION    "2.00ac7"
+#define DRV_VERSION    "2.10ac1"
 
 enum {
        PIIX_IOCFG              = 0x54, /* IDE I/O configuration register */
@@ -169,8 +169,6 @@ static const struct pci_device_id piix_pci_tbl[] = {
        /* Intel PIIX4 for the 430TX/440BX/MX chipset: UDMA 33 */
        /* Also PIIX4E (fn3 rev 2) and PIIX4M (fn3 rev 3) */
        { 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 },
-       { 0x8086, 0x24db, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
-       { 0x8086, 0x25a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
        /* Intel PIIX4 */
        { 0x8086, 0x7199, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 },
        /* Intel PIIX4 */
@@ -255,8 +253,10 @@ static struct pci_driver piix_pci_driver = {
        .id_table               = piix_pci_tbl,
        .probe                  = piix_init_one,
        .remove                 = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend                = ata_pci_device_suspend,
        .resume                 = ata_pci_device_resume,
+#endif
 };
 
 static struct scsi_host_template piix_sht = {
@@ -275,8 +275,10 @@ static struct scsi_host_template piix_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static const struct ata_port_operations piix_pata_ops = {
@@ -665,14 +667,9 @@ static int ich_pata_prereset(struct ata_port *ap)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 
-       if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no])) {
-               ata_port_printk(ap, KERN_INFO, "port disabled. ignoring.\n");
-               ap->eh_context.i.action &= ~ATA_EH_RESET_MASK;
-               return 0;
-       }
-
+       if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no]))
+               return -ENOENT;
        ich_pata_cbl_detect(ap);
-
        return ata_std_prereset(ap);
 }
 
index b4e8be5d292c9293310e8a7b6fe9ead8ce2baeea..c428a56e6f315e3e7e221f82c25206129af9acab 100644 (file)
@@ -34,6 +34,13 @@ struct taskfile_array {
        u8      tfa[REGS_PER_GTF];      /* regs. 0x1f1 - 0x1f7 */
 };
 
+/*
+ *     Helper - belongs in the PCI layer somewhere eventually
+ */
+static int is_pci_dev(struct device *dev)
+{
+       return (dev->bus == &pci_bus_type);
+}
 
 /**
  * sata_get_dev_handle - finds acpi_handle and PCI device.function
@@ -53,6 +60,9 @@ static int sata_get_dev_handle(struct device *dev, acpi_handle *handle,
        struct pci_dev  *pci_dev;
        acpi_integer    addr;
 
+       if (!is_pci_dev(dev))
+               return -ENODEV;
+
        pci_dev = to_pci_dev(dev);      /* NOTE: PCI-specific */
        /* Please refer to the ACPI spec for the syntax of _ADR. */
        addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);
@@ -84,7 +94,12 @@ static int pata_get_dev_handle(struct device *dev, acpi_handle *handle,
        acpi_status status;
        struct acpi_device_info *dinfo = NULL;
        int ret = -ENODEV;
-       struct pci_dev *pdev = to_pci_dev(dev);
+       struct pci_dev *pdev;
+
+       if (!is_pci_dev(dev))
+               return -ENODEV;
+
+       pdev = to_pci_dev(dev);
 
        bus = pdev->bus->number;
        devnum = PCI_SLOT(pdev->devfn);
@@ -294,9 +309,8 @@ static int do_drive_get_GTF(struct ata_port *ap, int ix,
                return 0;
 
        if (ata_msg_probe(ap))
-               ata_dev_printk(atadev, KERN_DEBUG,
-                       "%s: ENTER: ap->id: %d, port#: %d\n",
-                       __FUNCTION__, ap->id, ap->port_no);
+               ata_dev_printk(atadev, KERN_DEBUG, "%s: ENTER: port#: %d\n",
+                              __FUNCTION__, ap->port_no);
 
        if (!ata_dev_enabled(atadev) || (ap->flags & ATA_FLAG_DISABLED)) {
                if (ata_msg_probe(ap))
@@ -456,6 +470,9 @@ static void taskfile_load_raw(struct ata_port *ap,
                                struct ata_device *atadev,
                                const struct taskfile_array *gtf)
 {
+       struct ata_taskfile tf;
+       unsigned int err;
+
        if (ata_msg_probe(ap))
                ata_dev_printk(atadev, KERN_DEBUG, "%s: (0x1f1-1f7): hex: "
                        "%02x %02x %02x %02x %02x %02x %02x\n",
@@ -468,35 +485,25 @@ static void taskfile_load_raw(struct ata_port *ap,
            && (gtf->tfa[6] == 0))
                return;
 
-       if (ap->ops->qc_issue) {
-               struct ata_taskfile tf;
-               unsigned int err;
-
-               ata_tf_init(atadev, &tf);
-
-               /* convert gtf to tf */
-               tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; /* TBD */
-               tf.protocol = atadev->class == ATA_DEV_ATAPI ?
-                       ATA_PROT_ATAPI_NODATA : ATA_PROT_NODATA;
-               tf.feature = gtf->tfa[0];       /* 0x1f1 */
-               tf.nsect   = gtf->tfa[1];       /* 0x1f2 */
-               tf.lbal    = gtf->tfa[2];       /* 0x1f3 */
-               tf.lbam    = gtf->tfa[3];       /* 0x1f4 */
-               tf.lbah    = gtf->tfa[4];       /* 0x1f5 */
-               tf.device  = gtf->tfa[5];       /* 0x1f6 */
-               tf.command = gtf->tfa[6];       /* 0x1f7 */
-
-               err = ata_exec_internal(atadev, &tf, NULL, DMA_NONE, NULL, 0);
-               if (err && ata_msg_probe(ap))
-                       ata_dev_printk(atadev, KERN_ERR,
-                               "%s: ata_exec_internal failed: %u\n",
-                               __FUNCTION__, err);
-       } else
-               if (ata_msg_warn(ap))
-                       ata_dev_printk(atadev, KERN_WARNING,
-                               "%s: SATA driver is missing qc_issue function"
-                               " entry points\n",
-                               __FUNCTION__);
+       ata_tf_init(atadev, &tf);
+
+       /* convert gtf to tf */
+       tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; /* TBD */
+       tf.protocol = atadev->class == ATA_DEV_ATAPI ?
+               ATA_PROT_ATAPI_NODATA : ATA_PROT_NODATA;
+       tf.feature = gtf->tfa[0];       /* 0x1f1 */
+       tf.nsect   = gtf->tfa[1];       /* 0x1f2 */
+       tf.lbal    = gtf->tfa[2];       /* 0x1f3 */
+       tf.lbam    = gtf->tfa[3];       /* 0x1f4 */
+       tf.lbah    = gtf->tfa[4];       /* 0x1f5 */
+       tf.device  = gtf->tfa[5];       /* 0x1f6 */
+       tf.command = gtf->tfa[6];       /* 0x1f7 */
+
+       err = ata_exec_internal(atadev, &tf, NULL, DMA_NONE, NULL, 0);
+       if (err && ata_msg_probe(ap))
+               ata_dev_printk(atadev, KERN_ERR,
+                       "%s: ata_exec_internal failed: %u\n",
+                       __FUNCTION__, err);
 }
 
 /**
@@ -521,9 +528,8 @@ static int do_drive_set_taskfiles(struct ata_port *ap,
        struct taskfile_array   *gtf;
 
        if (ata_msg_probe(ap))
-               ata_dev_printk(atadev, KERN_DEBUG,
-                       "%s: ENTER: ap->id: %d, port#: %d\n",
-                       __FUNCTION__, ap->id, ap->port_no);
+               ata_dev_printk(atadev, KERN_DEBUG, "%s: ENTER: port#: %d\n",
+                              __FUNCTION__, ap->port_no);
 
        if (noacpi || !(ap->cbl == ATA_CBL_SATA))
                return 0;
@@ -570,6 +576,13 @@ int ata_acpi_exec_tfs(struct ata_port *ap)
 
        if (noacpi)
                return 0;
+       /*
+        * TBD - implement PATA support.  For now,
+        * we should not run GTF on PATA devices since some
+        * PATA require execution of GTM/STM before GTF.
+        */
+       if (!(ap->cbl == ATA_CBL_SATA))
+               return 0;
 
        for (ix = 0; ix < ATA_MAX_DEVICES; ix++) {
                if (!ata_dev_enabled(&ap->device[ix]))
@@ -627,9 +640,8 @@ int ata_acpi_push_id(struct ata_port *ap, unsigned int ix)
                return 0;
 
        if (ata_msg_probe(ap))
-               ata_dev_printk(atadev, KERN_DEBUG,
-                       "%s: ap->id: %d, ix = %d, port#: %d\n",
-                       __FUNCTION__, ap->id, ix, ap->port_no);
+               ata_dev_printk(atadev, KERN_DEBUG, "%s: ix = %d, port#: %d\n",
+                              __FUNCTION__, ix, ap->port_no);
 
        /* Don't continue if not a SATA device. */
        if (!(ap->cbl == ATA_CBL_SATA)) {
@@ -685,9 +697,8 @@ int ata_acpi_push_id(struct ata_port *ap, unsigned int ix)
        if (err < 0) {
                if (ata_msg_probe(ap))
                        ata_dev_printk(atadev, KERN_DEBUG,
-                               "ata%u(%u): %s _SDD error: status = 0x%x\n",
-                               ap->id, ap->device->devno,
-                               __FUNCTION__, status);
+                                      "%s _SDD error: status = 0x%x\n",
+                                      __FUNCTION__, status);
        }
 
        /* always return success */
index e900c5edefc4a55af483513dddbfdbc1129d7101..3c1f8830ac8bf7dedef3d44b049beefcf695e811 100644 (file)
@@ -59,7 +59,7 @@
 
 #include "libata.h"
 
-#define DRV_VERSION    "2.10"  /* must be exactly four chars */
+#define DRV_VERSION    "2.20"  /* must be exactly four chars */
 
 
 /* debounce timing parameters in msecs { interval, duration, timeout } */
@@ -72,7 +72,7 @@ static unsigned int ata_dev_init_params(struct ata_device *dev,
 static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
 static void ata_dev_xfermask(struct ata_device *dev);
 
-static unsigned int ata_unique_id = 1;
+static unsigned int ata_print_id = 1;
 static struct workqueue_struct *ata_wq;
 
 struct workqueue_struct *ata_aux_wq;
@@ -315,9 +315,7 @@ int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
        tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
        tf->flags |= tf_flags;
 
-       if ((dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ_OFF |
-                          ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ &&
-           likely(tag != ATA_TAG_INTERNAL)) {
+       if (ata_ncq_enabled(dev) && likely(tag != ATA_TAG_INTERNAL)) {
                /* yay, NCQ */
                if (!lba_48_ok(block, n_block))
                        return -ERANGE;
@@ -600,6 +598,8 @@ void ata_dev_disable(struct ata_device *dev)
 {
        if (ata_dev_enabled(dev) && ata_msg_drv(dev->ap)) {
                ata_dev_printk(dev, KERN_WARNING, "disabled\n");
+               ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 |
+                                            ATA_DNXFER_QUIET);
                dev->class++;
        }
 }
@@ -708,7 +708,7 @@ unsigned int ata_dev_classify(const struct ata_taskfile *tf)
  *     Device type - %ATA_DEV_ATA, %ATA_DEV_ATAPI or %ATA_DEV_NONE.
  */
 
-static unsigned int
+unsigned int
 ata_dev_try_classify(struct ata_port *ap, unsigned int device, u8 *r_err)
 {
        struct ata_taskfile tf;
@@ -823,6 +823,48 @@ static u64 ata_id_n_sectors(const u16 *id)
        }
 }
 
+/**
+ *     ata_id_to_dma_mode      -       Identify DMA mode from id block
+ *     @dev: device to identify
+ *     @mode: mode to assume if we cannot tell
+ *
+ *     Set up the timing values for the device based upon the identify
+ *     reported values for the DMA mode. This function is used by drivers
+ *     which rely upon firmware configured modes, but wish to report the
+ *     mode correctly when possible.
+ *
+ *     In addition we emit similarly formatted messages to the default
+ *     ata_dev_set_mode handler, in order to provide consistency of
+ *     presentation.
+ */
+
+void ata_id_to_dma_mode(struct ata_device *dev, u8 unknown)
+{
+       unsigned int mask;
+       u8 mode;
+
+       /* Pack the DMA modes */
+       mask = ((dev->id[63] >> 8) << ATA_SHIFT_MWDMA) & ATA_MASK_MWDMA;
+       if (dev->id[53] & 0x04)
+               mask |= ((dev->id[88] >> 8) << ATA_SHIFT_UDMA) & ATA_MASK_UDMA;
+
+       /* Select the mode in use */
+       mode = ata_xfer_mask2mode(mask);
+
+       if (mode != 0) {
+               ata_dev_printk(dev, KERN_INFO, "configured for %s\n",
+                      ata_mode_string(mask));
+       } else {
+               /* SWDMA perhaps ? */
+               mode = unknown;
+               ata_dev_printk(dev, KERN_INFO, "configured for DMA\n");
+       }
+
+       /* Configure the device reporting */
+       dev->xfer_mode = mode;
+       dev->xfer_shift = ata_xfer_mode2shift(mode);
+}
+
 /**
  *     ata_noop_dev_select - Select device 0/1 on ATA bus
  *     @ap: ATA channel to manipulate
@@ -891,8 +933,8 @@ void ata_dev_select(struct ata_port *ap, unsigned int device,
                           unsigned int wait, unsigned int can_sleep)
 {
        if (ata_msg_probe(ap))
-               ata_port_printk(ap, KERN_INFO, "ata_dev_select: ENTER, ata%u: "
-                               "device %u, wait %u\n", ap->id, device, wait);
+               ata_port_printk(ap, KERN_INFO, "ata_dev_select: ENTER, "
+                               "device %u, wait %u\n", device, wait);
 
        if (wait)
                ata_wait_idle(ap);
@@ -1392,8 +1434,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
        int rc;
 
        if (ata_msg_ctl(ap))
-               ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER, host %u, dev %u\n",
-                              __FUNCTION__, ap->id, dev->devno);
+               ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__);
 
        ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
 
@@ -1430,7 +1471,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
        if (err_mask) {
                if (err_mask & AC_ERR_NODEV_HINT) {
                        DPRINTK("ata%u.%d: NODEV after polling detection\n",
-                               ap->id, dev->devno);
+                               ap->print_id, dev->devno);
                        return -ENOENT;
                }
 
@@ -1558,15 +1599,13 @@ int ata_dev_configure(struct ata_device *dev)
        int rc;
 
        if (!ata_dev_enabled(dev) && ata_msg_info(ap)) {
-               ata_dev_printk(dev, KERN_INFO,
-                              "%s: ENTER/EXIT (host %u, dev %u) -- nodev\n",
-                              __FUNCTION__, ap->id, dev->devno);
+               ata_dev_printk(dev, KERN_INFO, "%s: ENTER/EXIT -- nodev\n",
+                              __FUNCTION__);
                return 0;
        }
 
        if (ata_msg_probe(ap))
-               ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER, host %u, dev %u\n",
-                              __FUNCTION__, ap->id, dev->devno);
+               ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__);
 
        /* set _SDD */
        rc = ata_acpi_push_id(ap, dev->devno);
@@ -1610,8 +1649,9 @@ int ata_dev_configure(struct ata_device *dev)
        if (dev->class == ATA_DEV_ATA) {
                if (ata_id_is_cfa(id)) {
                        if (id[162] & 1) /* CPRM may make this media unusable */
-                               ata_dev_printk(dev, KERN_WARNING, "ata%u: device %u  supports DRM functions and may not be fully accessable.\n",
-                                       ap->id, dev->devno);
+                               ata_dev_printk(dev, KERN_WARNING,
+                                              "supports DRM functions and may "
+                                              "not be fully accessable.\n");
                        snprintf(revbuf, 7, "CFA");
                }
                else
@@ -1679,7 +1719,7 @@ int ata_dev_configure(struct ata_device *dev)
                                        "%s: %s, %s, max %s\n",
                                        revbuf, modelbuf, fwrevbuf,
                                        ata_mode_string(xfer_mask));
-                               ata_dev_printk(dev, KERN_INFO, 
+                               ata_dev_printk(dev, KERN_INFO,
                                        "%Lu sectors, multi %u, CHS %u/%u/%u\n",
                                        (unsigned long long)dev->n_sectors,
                                        dev->multi_count, dev->cylinders,
@@ -1778,7 +1818,7 @@ int ata_bus_probe(struct ata_port *ap)
 {
        unsigned int classes[ATA_MAX_DEVICES];
        int tries[ATA_MAX_DEVICES];
-       int i, rc, down_xfermask;
+       int i, rc;
        struct ata_device *dev;
 
        ata_port_probe(ap);
@@ -1787,8 +1827,6 @@ int ata_bus_probe(struct ata_port *ap)
                tries[i] = ATA_PROBE_MAX_TRIES;
 
  retry:
-       down_xfermask = 0;
-
        /* reset and determine device classes */
        ap->ops->phy_reset(ap);
 
@@ -1812,8 +1850,11 @@ int ata_bus_probe(struct ata_port *ap)
        for (i = 0; i < ATA_MAX_DEVICES; i++)
                ap->device[i].pio_mode = XFER_PIO_0;
 
-       /* read IDENTIFY page and configure devices */
-       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+       /* read IDENTIFY page and configure devices. We have to do the identify
+          specific sequence bass-ackwards so that PDIAG- is released by
+          the slave device */
+
+       for (i = ATA_MAX_DEVICES - 1; i >=  0; i--) {
                dev = &ap->device[i];
 
                if (tries[i])
@@ -1826,6 +1867,15 @@ int ata_bus_probe(struct ata_port *ap)
                                     dev->id);
                if (rc)
                        goto fail;
+       }
+
+       /* After the identify sequence we can now set up the devices. We do
+          this in the normal order so that the user doesn't get confused */
+
+       for(i = 0; i < ATA_MAX_DEVICES; i++) {
+               dev = &ap->device[i];
+               if (!ata_dev_enabled(dev))
+                       continue;
 
                ap->eh_context.i.flags |= ATA_EHI_PRINTINFO;
                rc = ata_dev_configure(dev);
@@ -1836,10 +1886,8 @@ int ata_bus_probe(struct ata_port *ap)
 
        /* configure transfer mode */
        rc = ata_set_mode(ap, &dev);
-       if (rc) {
-               down_xfermask = 1;
+       if (rc)
                goto fail;
-       }
 
        for (i = 0; i < ATA_MAX_DEVICES; i++)
                if (ata_dev_enabled(&ap->device[i]))
@@ -1851,25 +1899,29 @@ int ata_bus_probe(struct ata_port *ap)
        return -ENODEV;
 
  fail:
+       tries[dev->devno]--;
+
        switch (rc) {
        case -EINVAL:
-       case -ENODEV:
+               /* eeek, something went very wrong, give up */
                tries[dev->devno] = 0;
                break;
+
+       case -ENODEV:
+               /* give it just one more chance */
+               tries[dev->devno] = min(tries[dev->devno], 1);
        case -EIO:
-               sata_down_spd_limit(ap);
-               /* fall through */
-       default:
-               tries[dev->devno]--;
-               if (down_xfermask &&
-                   ata_down_xfermask_limit(dev, tries[dev->devno] == 1))
-                       tries[dev->devno] = 0;
+               if (tries[dev->devno] == 1) {
+                       /* This is the last chance, better to slow
+                        * down than lose it.
+                        */
+                       sata_down_spd_limit(ap);
+                       ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
+               }
        }
 
-       if (!tries[dev->devno]) {
-               ata_down_xfermask_limit(dev, 1);
+       if (!tries[dev->devno])
                ata_dev_disable(dev);
-       }
 
        goto retry;
 }
@@ -2300,7 +2352,7 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed,
 /**
  *     ata_down_xfermask_limit - adjust dev xfer masks downward
  *     @dev: Device to adjust xfer masks
- *     @force_pio0: Force PIO0
+ *     @sel: ATA_DNXFER_* selector
  *
  *     Adjust xfer masks of @dev downward.  Note that this function
  *     does not apply the change.  Invoking ata_set_mode() afterwards
@@ -2312,37 +2364,78 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed,
  *     RETURNS:
  *     0 on success, negative errno on failure
  */
-int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0)
+int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel)
 {
-       unsigned long xfer_mask;
-       int highbit;
+       char buf[32];
+       unsigned int orig_mask, xfer_mask;
+       unsigned int pio_mask, mwdma_mask, udma_mask;
+       int quiet, highbit;
 
-       xfer_mask = ata_pack_xfermask(dev->pio_mask, dev->mwdma_mask,
-                                     dev->udma_mask);
+       quiet = !!(sel & ATA_DNXFER_QUIET);
+       sel &= ~ATA_DNXFER_QUIET;
 
-       if (!xfer_mask)
-               goto fail;
-       /* don't gear down to MWDMA from UDMA, go directly to PIO */
-       if (xfer_mask & ATA_MASK_UDMA)
-               xfer_mask &= ~ATA_MASK_MWDMA;
+       xfer_mask = orig_mask = ata_pack_xfermask(dev->pio_mask,
+                                                 dev->mwdma_mask,
+                                                 dev->udma_mask);
+       ata_unpack_xfermask(xfer_mask, &pio_mask, &mwdma_mask, &udma_mask);
 
-       highbit = fls(xfer_mask) - 1;
-       xfer_mask &= ~(1 << highbit);
-       if (force_pio0)
-               xfer_mask &= 1 << ATA_SHIFT_PIO;
-       if (!xfer_mask)
-               goto fail;
+       switch (sel) {
+       case ATA_DNXFER_PIO:
+               highbit = fls(pio_mask) - 1;
+               pio_mask &= ~(1 << highbit);
+               break;
+
+       case ATA_DNXFER_DMA:
+               if (udma_mask) {
+                       highbit = fls(udma_mask) - 1;
+                       udma_mask &= ~(1 << highbit);
+                       if (!udma_mask)
+                               return -ENOENT;
+               } else if (mwdma_mask) {
+                       highbit = fls(mwdma_mask) - 1;
+                       mwdma_mask &= ~(1 << highbit);
+                       if (!mwdma_mask)
+                               return -ENOENT;
+               }
+               break;
+
+       case ATA_DNXFER_40C:
+               udma_mask &= ATA_UDMA_MASK_40C;
+               break;
+
+       case ATA_DNXFER_FORCE_PIO0:
+               pio_mask &= 1;
+       case ATA_DNXFER_FORCE_PIO:
+               mwdma_mask = 0;
+               udma_mask = 0;
+               break;
+
+       default:
+               BUG();
+       }
+
+       xfer_mask &= ata_pack_xfermask(pio_mask, mwdma_mask, udma_mask);
+
+       if (!(xfer_mask & ATA_MASK_PIO) || xfer_mask == orig_mask)
+               return -ENOENT;
+
+       if (!quiet) {
+               if (xfer_mask & (ATA_MASK_MWDMA | ATA_MASK_UDMA))
+                       snprintf(buf, sizeof(buf), "%s:%s",
+                                ata_mode_string(xfer_mask),
+                                ata_mode_string(xfer_mask & ATA_MASK_PIO));
+               else
+                       snprintf(buf, sizeof(buf), "%s",
+                                ata_mode_string(xfer_mask));
+
+               ata_dev_printk(dev, KERN_WARNING,
+                              "limiting speed to %s\n", buf);
+       }
 
        ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask,
                            &dev->udma_mask);
 
-       ata_dev_printk(dev, KERN_WARNING, "limiting speed to %s\n",
-                      ata_mode_string(xfer_mask));
-
        return 0;
-
- fail:
-       return -EINVAL;
 }
 
 static int ata_dev_set_mode(struct ata_device *dev)
@@ -2475,12 +2568,11 @@ int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev)
         * host channels are not permitted to do so.
         */
        if (used_dma && (ap->host->flags & ATA_HOST_SIMPLEX))
-               ap->host->simplex_claimed = 1;
+               ap->host->simplex_claimed = ap;
 
        /* step5: chip specific finalisation */
        if (ap->ops->post_set_mode)
                ap->ops->post_set_mode(ap);
-
  out:
        if (rc)
                *r_failed_dev = dev;
@@ -2609,7 +2701,7 @@ static unsigned int ata_bus_softreset(struct ata_port *ap,
 {
        struct ata_ioports *ioaddr = &ap->ioaddr;
 
-       DPRINTK("ata%u: bus reset via SRST\n", ap->id);
+       DPRINTK("ata%u: bus reset via SRST\n", ap->print_id);
 
        /* software reset.  causes dev0 to be selected */
        iowrite8(ap->ctl, ioaddr->ctl_addr);
@@ -2669,7 +2761,7 @@ void ata_bus_reset(struct ata_port *ap)
        u8 err;
        unsigned int dev0, dev1 = 0, devmask = 0;
 
-       DPRINTK("ENTER, host %u, port %u\n", ap->id, ap->port_no);
+       DPRINTK("ENTER, host %u, port %u\n", ap->print_id, ap->port_no);
 
        /* determine if device 0/1 are present */
        if (ap->flags & ATA_FLAG_SATA_RESET)
@@ -3256,7 +3348,6 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "WPI CDD-820",        NULL,           ATA_HORKAGE_NODMA },
        { "SAMSUNG CD-ROM SC-148C", NULL,       ATA_HORKAGE_NODMA },
        { "SAMSUNG CD-ROM SC",  NULL,           ATA_HORKAGE_NODMA },
-       { "SanDisk SDP3B-64",   NULL,           ATA_HORKAGE_NODMA },
        { "ATAPI CD-ROM DRIVE 40X MAXIMUM",NULL,ATA_HORKAGE_NODMA },
        { "_NEC DV5800A",       NULL,           ATA_HORKAGE_NODMA },
        { "SAMSUNG CD-ROM SN-124","N001",       ATA_HORKAGE_NODMA },
@@ -3266,6 +3357,8 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        /* Devices where NCQ should be avoided */
        /* NCQ is slow */
         { "WDC WD740ADFD-00",   NULL,          ATA_HORKAGE_NONCQ },
+       /* http://thread.gmane.org/gmane.linux.ide/14907 */
+       { "FUJITSU MHT2060BH",  NULL,           ATA_HORKAGE_NONCQ },
 
        /* Devices with NCQ limits */
 
@@ -3362,7 +3455,8 @@ static void ata_dev_xfermask(struct ata_device *dev)
                               "device is on DMA blacklist, disabling DMA\n");
        }
 
-       if ((host->flags & ATA_HOST_SIMPLEX) && host->simplex_claimed) {
+       if ((host->flags & ATA_HOST_SIMPLEX) &&
+            host->simplex_claimed && host->simplex_claimed != ap) {
                xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
                ata_dev_printk(dev, KERN_WARNING, "simplex DMA is claimed by "
                               "other device, disabling DMA\n");
@@ -3739,7 +3833,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
        struct scatterlist *lsg = &sg[qc->n_elem - 1];
        int n_elem, pre_n_elem, dir, trim_sg = 0;
 
-       VPRINTK("ENTER, ata%u\n", ap->id);
+       VPRINTK("ENTER, ata%u\n", ap->print_id);
        WARN_ON(!(qc->flags & ATA_QCFLAG_SG));
 
        /* we must lengthen transfers to end on a 32-bit boundary */
@@ -4140,7 +4234,7 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc)
        if (do_write != i_write)
                goto err_out;
 
-       VPRINTK("ata%u: xfering %d bytes\n", ap->id, bytes);
+       VPRINTK("ata%u: xfering %d bytes\n", ap->print_id, bytes);
 
        __atapi_pio_bytes(qc, bytes);
 
@@ -4257,7 +4351,7 @@ int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
 
 fsm_start:
        DPRINTK("ata%u: protocol %d task_state %d (dev_stat 0x%X)\n",
-               ap->id, qc->tf.protocol, ap->hsm_task_state, status);
+               ap->print_id, qc->tf.protocol, ap->hsm_task_state, status);
 
        switch (ap->hsm_task_state) {
        case HSM_ST_FIRST:
@@ -4290,8 +4384,8 @@ fsm_start:
                 * let the EH abort the command or reset the device.
                 */
                if (unlikely(status & (ATA_ERR | ATA_DF))) {
-                       printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n",
-                              ap->id, status);
+                       ata_port_printk(ap, KERN_WARNING, "DRQ=1 with device "
+                                       "error, dev_stat 0x%X\n", status);
                        qc->err_mask |= AC_ERR_HSM;
                        ap->hsm_task_state = HSM_ST_ERR;
                        goto fsm_start;
@@ -4348,8 +4442,9 @@ fsm_start:
                         * let the EH abort the command or reset the device.
                         */
                        if (unlikely(status & (ATA_ERR | ATA_DF))) {
-                               printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n",
-                                      ap->id, status);
+                               ata_port_printk(ap, KERN_WARNING, "DRQ=1 with "
+                                               "device error, dev_stat 0x%X\n",
+                                               status);
                                qc->err_mask |= AC_ERR_HSM;
                                ap->hsm_task_state = HSM_ST_ERR;
                                goto fsm_start;
@@ -4435,7 +4530,7 @@ fsm_start:
 
                /* no more data to transfer */
                DPRINTK("ata%u: dev %u command complete, drv_stat 0x%x\n",
-                       ap->id, qc->dev->devno, status);
+                       ap->print_id, qc->dev->devno, status);
 
                WARN_ON(qc->err_mask);
 
@@ -4977,7 +5072,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
        u8 status, host_stat = 0;
 
        VPRINTK("ata%u: protocol %d task_state %d\n",
-               ap->id, qc->tf.protocol, ap->hsm_task_state);
+               ap->print_id, qc->tf.protocol, ap->hsm_task_state);
 
        /* Check whether we are expecting interrupt in this state */
        switch (ap->hsm_task_state) {
@@ -4998,7 +5093,8 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
                    qc->tf.protocol == ATA_PROT_ATAPI_DMA) {
                        /* check status of DMA engine */
                        host_stat = ap->ops->bmdma_status(ap);
-                       VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat);
+                       VPRINTK("ata%u: host_stat 0x%X\n",
+                               ap->print_id, host_stat);
 
                        /* if it's not our irq... */
                        if (!(host_stat & ATA_DMA_INTR))
@@ -5259,6 +5355,7 @@ int ata_flush_cache(struct ata_device *dev)
        return 0;
 }
 
+#ifdef CONFIG_PM
 static int ata_host_request_pm(struct ata_host *host, pm_message_t mesg,
                               unsigned int action, unsigned int ehi_flags,
                               int wait)
@@ -5374,6 +5471,7 @@ void ata_host_resume(struct ata_host *host)
                            ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0);
        host->dev->power.power_state = PMSG_ON;
 }
+#endif
 
 /**
  *     ata_port_start - Set port up for dma.
@@ -5457,7 +5555,7 @@ void ata_port_init(struct ata_port *ap, struct ata_host *host,
 
        ap->lock = &host->lock;
        ap->flags = ATA_FLAG_DISABLED;
-       ap->id = ata_unique_id++;
+       ap->print_id = ata_print_id++;
        ap->ctl = ATA_DEVCTL_OBS;
        ap->host = host;
        ap->dev = ent->dev;
@@ -5528,7 +5626,7 @@ static void ata_port_init_shost(struct ata_port *ap, struct Scsi_Host *shost)
 {
        ap->scsi_host = shost;
 
-       shost->unique_id = ap->id;
+       shost->unique_id = ap->print_id;
        shost->max_id = 16;
        shost->max_lun = 1;
        shost->max_channel = 1;
@@ -5587,17 +5685,23 @@ static void ata_host_release(struct device *gendev, void *res)
        for (i = 0; i < host->n_ports; i++) {
                struct ata_port *ap = host->ports[i];
 
-               if (!ap)
-                       continue;
-
-               if (ap->ops->port_stop)
+               if (ap && ap->ops->port_stop)
                        ap->ops->port_stop(ap);
-
-               scsi_host_put(ap->scsi_host);
        }
 
        if (host->ops->host_stop)
                host->ops->host_stop(host);
+
+       for (i = 0; i < host->n_ports; i++) {
+               struct ata_port *ap = host->ports[i];
+
+               if (ap)
+                       scsi_host_put(ap->scsi_host);
+
+               host->ports[i] = NULL;
+       }
+
+       dev_set_drvdata(gendev, NULL);
 }
 
 /**
@@ -5792,9 +5896,9 @@ int ata_device_add(const struct ata_probe_ent *ent)
                        /* wait for EH to finish */
                        ata_port_wait_eh(ap);
                } else {
-                       DPRINTK("ata%u: bus probe begin\n", ap->id);
+                       DPRINTK("ata%u: bus probe begin\n", ap->print_id);
                        rc = ata_bus_probe(ap);
-                       DPRINTK("ata%u: bus probe end\n", ap->id);
+                       DPRINTK("ata%u: bus probe end\n", ap->print_id);
 
                        if (rc) {
                                /* FIXME: do something useful here?
@@ -5820,7 +5924,6 @@ int ata_device_add(const struct ata_probe_ent *ent)
 
  err_out:
        devres_release_group(dev, ata_device_add);
-       dev_set_drvdata(dev, NULL);
        VPRINTK("EXIT, returning %d\n", rc);
        return 0;
 }
@@ -5905,11 +6008,7 @@ ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port)
 {
        struct ata_probe_ent *probe_ent;
 
-       /* XXX - the following if can go away once all LLDs are managed */
-       if (!list_empty(&dev->devres_head))
-               probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL);
-       else
-               probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
+       probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL);
        if (!probe_ent) {
                printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
                       kobject_name(&(dev->kobj)));
@@ -6012,14 +6111,14 @@ int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits)
        return (tmp == bits->val) ? 1 : 0;
 }
 
+#ifdef CONFIG_PM
 void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t mesg)
 {
        pci_save_state(pdev);
+       pci_disable_device(pdev);
 
-       if (mesg.event == PM_EVENT_SUSPEND) {
-               pci_disable_device(pdev);
+       if (mesg.event == PM_EVENT_SUSPEND)
                pci_set_power_state(pdev, PCI_D3hot);
-       }
 }
 
 int ata_pci_device_do_resume(struct pci_dev *pdev)
@@ -6064,6 +6163,8 @@ int ata_pci_device_resume(struct pci_dev *pdev)
                ata_host_resume(host);
        return rc;
 }
+#endif /* CONFIG_PM */
+
 #endif /* CONFIG_PCI */
 
 
@@ -6241,6 +6342,7 @@ EXPORT_SYMBOL_GPL(ata_bmdma_drive_eh);
 EXPORT_SYMBOL_GPL(ata_bmdma_error_handler);
 EXPORT_SYMBOL_GPL(ata_bmdma_post_internal_cmd);
 EXPORT_SYMBOL_GPL(ata_port_probe);
+EXPORT_SYMBOL_GPL(ata_dev_disable);
 EXPORT_SYMBOL_GPL(sata_set_spd);
 EXPORT_SYMBOL_GPL(sata_phy_debounce);
 EXPORT_SYMBOL_GPL(sata_phy_resume);
@@ -6271,10 +6373,13 @@ EXPORT_SYMBOL_GPL(sata_scr_write);
 EXPORT_SYMBOL_GPL(sata_scr_write_flush);
 EXPORT_SYMBOL_GPL(ata_port_online);
 EXPORT_SYMBOL_GPL(ata_port_offline);
+#ifdef CONFIG_PM
 EXPORT_SYMBOL_GPL(ata_host_suspend);
 EXPORT_SYMBOL_GPL(ata_host_resume);
+#endif /* CONFIG_PM */
 EXPORT_SYMBOL_GPL(ata_id_string);
 EXPORT_SYMBOL_GPL(ata_id_c_string);
+EXPORT_SYMBOL_GPL(ata_id_to_dma_mode);
 EXPORT_SYMBOL_GPL(ata_device_blacklisted);
 EXPORT_SYMBOL_GPL(ata_scsi_simulate);
 
@@ -6287,16 +6392,20 @@ EXPORT_SYMBOL_GPL(pci_test_config_bits);
 EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
 EXPORT_SYMBOL_GPL(ata_pci_init_one);
 EXPORT_SYMBOL_GPL(ata_pci_remove_one);
+#ifdef CONFIG_PM
 EXPORT_SYMBOL_GPL(ata_pci_device_do_suspend);
 EXPORT_SYMBOL_GPL(ata_pci_device_do_resume);
 EXPORT_SYMBOL_GPL(ata_pci_device_suspend);
 EXPORT_SYMBOL_GPL(ata_pci_device_resume);
+#endif /* CONFIG_PM */
 EXPORT_SYMBOL_GPL(ata_pci_default_filter);
 EXPORT_SYMBOL_GPL(ata_pci_clear_simplex);
 #endif /* CONFIG_PCI */
 
+#ifdef CONFIG_PM
 EXPORT_SYMBOL_GPL(ata_scsi_device_suspend);
 EXPORT_SYMBOL_GPL(ata_scsi_device_resume);
+#endif /* CONFIG_PM */
 
 EXPORT_SYMBOL_GPL(ata_eng_timeout);
 EXPORT_SYMBOL_GPL(ata_port_schedule_eh);
@@ -6311,3 +6420,4 @@ EXPORT_SYMBOL_GPL(ata_irq_on);
 EXPORT_SYMBOL_GPL(ata_dummy_irq_on);
 EXPORT_SYMBOL_GPL(ata_irq_ack);
 EXPORT_SYMBOL_GPL(ata_dummy_irq_ack);
+EXPORT_SYMBOL_GPL(ata_dev_try_classify);
index 52c85af7fe9912492cd9353a4d92f78e3a600e9c..7349c3dbf774e672bfbcc8ce1ab5e8d6f2ac5ce0 100644 (file)
 
 #include "libata.h"
 
+enum {
+       ATA_EH_SPDN_NCQ_OFF             = (1 << 0),
+       ATA_EH_SPDN_SPEED_DOWN          = (1 << 1),
+       ATA_EH_SPDN_FALLBACK_TO_PIO     = (1 << 2),
+};
+
 static void __ata_port_freeze(struct ata_port *ap);
 static void ata_eh_finish(struct ata_port *ap);
+#ifdef CONFIG_PM
 static void ata_eh_handle_port_suspend(struct ata_port *ap);
 static void ata_eh_handle_port_resume(struct ata_port *ap);
+static int ata_eh_suspend(struct ata_port *ap,
+                         struct ata_device **r_failed_dev);
+static void ata_eh_prep_resume(struct ata_port *ap);
+static int ata_eh_resume(struct ata_port *ap, struct ata_device **r_failed_dev);
+#else /* CONFIG_PM */
+static void ata_eh_handle_port_suspend(struct ata_port *ap)
+{ }
+
+static void ata_eh_handle_port_resume(struct ata_port *ap)
+{ }
+
+static int ata_eh_suspend(struct ata_port *ap, struct ata_device **r_failed_dev)
+{
+       return 0;
+}
+
+static void ata_eh_prep_resume(struct ata_port *ap)
+{ }
+
+static int ata_eh_resume(struct ata_port *ap, struct ata_device **r_failed_dev)
+{
+       return 0;
+}
+#endif /* CONFIG_PM */
 
 static void ata_ering_record(struct ata_ering *ering, int is_io,
                             unsigned int err_mask)
@@ -65,12 +96,9 @@ static void ata_ering_record(struct ata_ering *ering, int is_io,
        ent->timestamp = get_jiffies_64();
 }
 
-static struct ata_ering_entry * ata_ering_top(struct ata_ering *ering)
+static void ata_ering_clear(struct ata_ering *ering)
 {
-       struct ata_ering_entry *ent = &ering->ring[ering->cursor];
-       if (!ent->err_mask)
-               return NULL;
-       return ent;
+       memset(ering, 0, sizeof(*ering));
 }
 
 static int ata_ering_map(struct ata_ering *ering,
@@ -585,7 +613,7 @@ static void __ata_port_freeze(struct ata_port *ap)
 
        ap->pflags |= ATA_PFLAG_FROZEN;
 
-       DPRINTK("ata%u port frozen\n", ap->id);
+       DPRINTK("ata%u port frozen\n", ap->print_id);
 }
 
 /**
@@ -658,7 +686,7 @@ void ata_eh_thaw_port(struct ata_port *ap)
 
        spin_unlock_irqrestore(ap->lock, flags);
 
-       DPRINTK("ata%u port thawed\n", ap->id);
+       DPRINTK("ata%u port thawed\n", ap->print_id);
 }
 
 static void ata_eh_scsidone(struct scsi_cmnd *scmd)
@@ -1159,87 +1187,99 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
        return action;
 }
 
-static int ata_eh_categorize_ering_entry(struct ata_ering_entry *ent)
+static int ata_eh_categorize_error(int is_io, unsigned int err_mask)
 {
-       if (ent->err_mask & (AC_ERR_ATA_BUS | AC_ERR_TIMEOUT))
+       if (err_mask & AC_ERR_ATA_BUS)
                return 1;
 
-       if (ent->is_io) {
-               if (ent->err_mask & AC_ERR_HSM)
-                       return 1;
-               if ((ent->err_mask &
-                    (AC_ERR_DEV|AC_ERR_MEDIA|AC_ERR_INVALID)) == AC_ERR_DEV)
+       if (err_mask & AC_ERR_TIMEOUT)
+               return 2;
+
+       if (is_io) {
+               if (err_mask & AC_ERR_HSM)
                        return 2;
+               if ((err_mask &
+                    (AC_ERR_DEV|AC_ERR_MEDIA|AC_ERR_INVALID)) == AC_ERR_DEV)
+                       return 3;
        }
 
        return 0;
 }
 
-struct speed_down_needed_arg {
+struct speed_down_verdict_arg {
        u64 since;
-       int nr_errors[3];
+       int nr_errors[4];
 };
 
-static int speed_down_needed_cb(struct ata_ering_entry *ent, void *void_arg)
+static int speed_down_verdict_cb(struct ata_ering_entry *ent, void *void_arg)
 {
-       struct speed_down_needed_arg *arg = void_arg;
+       struct speed_down_verdict_arg *arg = void_arg;
+       int cat = ata_eh_categorize_error(ent->is_io, ent->err_mask);
 
        if (ent->timestamp < arg->since)
                return -1;
 
-       arg->nr_errors[ata_eh_categorize_ering_entry(ent)]++;
+       arg->nr_errors[cat]++;
        return 0;
 }
 
 /**
- *     ata_eh_speed_down_needed - Determine wheter speed down is necessary
+ *     ata_eh_speed_down_verdict - Determine speed down verdict
  *     @dev: Device of interest
  *
  *     This function examines error ring of @dev and determines
- *     whether speed down is necessary.  Speed down is necessary if
- *     there have been more than 3 of Cat-1 errors or 10 of Cat-2
- *     errors during last 15 minutes.
+ *     whether NCQ needs to be turned off, transfer speed should be
+ *     stepped down, or falling back to PIO is necessary.
  *
- *     Cat-1 errors are ATA_BUS, TIMEOUT for any command and HSM
- *     violation for known supported commands.
+ *     Cat-1 is ATA_BUS error for any command.
  *
- *     Cat-2 errors are unclassified DEV error for known supported
+ *     Cat-2 is TIMEOUT for any command or HSM violation for known
+ *     supported commands.
+ *
+ *     Cat-3 is is unclassified DEV error for known supported
  *     command.
  *
+ *     NCQ needs to be turned off if there have been more than 3
+ *     Cat-2 + Cat-3 errors during last 10 minutes.
+ *
+ *     Speed down is necessary if there have been more than 3 Cat-1 +
+ *     Cat-2 errors or 10 Cat-3 errors during last 10 minutes.
+ *
+ *     Falling back to PIO mode is necessary if there have been more
+ *     than 10 Cat-1 + Cat-2 + Cat-3 errors during last 5 minutes.
+ *
  *     LOCKING:
  *     Inherited from caller.
  *
  *     RETURNS:
- *     1 if speed down is necessary, 0 otherwise
+ *     OR of ATA_EH_SPDN_* flags.
  */
-static int ata_eh_speed_down_needed(struct ata_device *dev)
+static unsigned int ata_eh_speed_down_verdict(struct ata_device *dev)
 {
-       const u64 interval = 15LLU * 60 * HZ;
-       static const int err_limits[3] = { -1, 3, 10 };
-       struct speed_down_needed_arg arg;
-       struct ata_ering_entry *ent;
-       int err_cat;
-       u64 j64;
+       const u64 j5mins = 5LLU * 60 * HZ, j10mins = 10LLU * 60 * HZ;
+       u64 j64 = get_jiffies_64();
+       struct speed_down_verdict_arg arg;
+       unsigned int verdict = 0;
 
-       ent = ata_ering_top(&dev->ering);
-       if (!ent)
-               return 0;
+       /* scan past 10 mins of error history */
+       memset(&arg, 0, sizeof(arg));
+       arg.since = j64 - min(j64, j10mins);
+       ata_ering_map(&dev->ering, speed_down_verdict_cb, &arg);
 
-       err_cat = ata_eh_categorize_ering_entry(ent);
-       if (err_cat == 0)
-               return 0;
+       if (arg.nr_errors[2] + arg.nr_errors[3] > 3)
+               verdict |= ATA_EH_SPDN_NCQ_OFF;
+       if (arg.nr_errors[1] + arg.nr_errors[2] > 3 || arg.nr_errors[3] > 10)
+               verdict |= ATA_EH_SPDN_SPEED_DOWN;
 
+       /* scan past 3 mins of error history */
        memset(&arg, 0, sizeof(arg));
+       arg.since = j64 - min(j64, j5mins);
+       ata_ering_map(&dev->ering, speed_down_verdict_cb, &arg);
 
-       j64 = get_jiffies_64();
-       if (j64 >= interval)
-               arg.since = j64 - interval;
-       else
-               arg.since = 0;
-
-       ata_ering_map(&dev->ering, speed_down_needed_cb, &arg);
+       if (arg.nr_errors[1] + arg.nr_errors[2] + arg.nr_errors[3] > 10)
+               verdict |= ATA_EH_SPDN_FALLBACK_TO_PIO;
 
-       return arg.nr_errors[err_cat] > err_limits[err_cat];
+       return verdict;
 }
 
 /**
@@ -1257,31 +1297,80 @@ static int ata_eh_speed_down_needed(struct ata_device *dev)
  *     Kernel thread context (may sleep).
  *
  *     RETURNS:
- *     0 on success, -errno otherwise
+ *     Determined recovery action.
  */
-static int ata_eh_speed_down(struct ata_device *dev, int is_io,
-                            unsigned int err_mask)
+static unsigned int ata_eh_speed_down(struct ata_device *dev, int is_io,
+                                     unsigned int err_mask)
 {
-       if (!err_mask)
+       unsigned int verdict;
+       unsigned int action = 0;
+
+       /* don't bother if Cat-0 error */
+       if (ata_eh_categorize_error(is_io, err_mask) == 0)
                return 0;
 
        /* record error and determine whether speed down is necessary */
        ata_ering_record(&dev->ering, is_io, err_mask);
+       verdict = ata_eh_speed_down_verdict(dev);
 
-       if (!ata_eh_speed_down_needed(dev))
-               return 0;
+       /* turn off NCQ? */
+       if ((verdict & ATA_EH_SPDN_NCQ_OFF) &&
+           (dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ |
+                          ATA_DFLAG_NCQ_OFF)) == ATA_DFLAG_NCQ) {
+               dev->flags |= ATA_DFLAG_NCQ_OFF;
+               ata_dev_printk(dev, KERN_WARNING,
+                              "NCQ disabled due to excessive errors\n");
+               goto done;
+       }
 
-       /* speed down SATA link speed if possible */
-       if (sata_down_spd_limit(dev->ap) == 0)
-               return ATA_EH_HARDRESET;
+       /* speed down? */
+       if (verdict & ATA_EH_SPDN_SPEED_DOWN) {
+               /* speed down SATA link speed if possible */
+               if (sata_down_spd_limit(dev->ap) == 0) {
+                       action |= ATA_EH_HARDRESET;
+                       goto done;
+               }
 
-       /* lower transfer mode */
-       if (ata_down_xfermask_limit(dev, 0) == 0)
-               return ATA_EH_SOFTRESET;
+               /* lower transfer mode */
+               if (dev->spdn_cnt < 2) {
+                       static const int dma_dnxfer_sel[] =
+                               { ATA_DNXFER_DMA, ATA_DNXFER_40C };
+                       static const int pio_dnxfer_sel[] =
+                               { ATA_DNXFER_PIO, ATA_DNXFER_FORCE_PIO0 };
+                       int sel;
+
+                       if (dev->xfer_shift != ATA_SHIFT_PIO)
+                               sel = dma_dnxfer_sel[dev->spdn_cnt];
+                       else
+                               sel = pio_dnxfer_sel[dev->spdn_cnt];
+
+                       dev->spdn_cnt++;
+
+                       if (ata_down_xfermask_limit(dev, sel) == 0) {
+                               action |= ATA_EH_SOFTRESET;
+                               goto done;
+                       }
+               }
+       }
+
+       /* Fall back to PIO?  Slowing down to PIO is meaningless for
+        * SATA.  Consider it only for PATA.
+        */
+       if ((verdict & ATA_EH_SPDN_FALLBACK_TO_PIO) && (dev->spdn_cnt >= 2) &&
+           (dev->ap->cbl != ATA_CBL_SATA) &&
+           (dev->xfer_shift != ATA_SHIFT_PIO)) {
+               if (ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO) == 0) {
+                       dev->spdn_cnt = 0;
+                       action |= ATA_EH_SOFTRESET;
+                       goto done;
+               }
+       }
 
-       ata_dev_printk(dev, KERN_ERR,
-                      "speed down requested but no transfer mode left\n");
        return 0;
+ done:
+       /* device has been slowed down, blow error history */
+       ata_ering_clear(&dev->ering);
+       return action;
 }
 
 /**
@@ -1726,6 +1815,7 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,
        return rc;
 }
 
+#ifdef CONFIG_PM
 /**
  *     ata_eh_suspend - handle suspend EH action
  *     @ap: target host port
@@ -1883,6 +1973,7 @@ static int ata_eh_resume(struct ata_port *ap, struct ata_device **r_failed_dev)
        DPRINTK("EXIT\n");
        return 0;
 }
+#endif /* CONFIG_PM */
 
 static int ata_port_nr_enabled(struct ata_port *ap)
 {
@@ -1964,7 +2055,7 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
 {
        struct ata_eh_context *ehc = &ap->eh_context;
        struct ata_device *dev;
-       int down_xfermask, i, rc;
+       int i, rc;
 
        DPRINTK("ENTER\n");
 
@@ -1993,7 +2084,6 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
        }
 
  retry:
-       down_xfermask = 0;
        rc = 0;
 
        /* if UNLOADING, finish immediately */
@@ -2038,10 +2128,8 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
        /* configure transfer mode if necessary */
        if (ehc->i.flags & ATA_EHI_SETMODE) {
                rc = ata_set_mode(ap, &dev);
-               if (rc) {
-                       down_xfermask = 1;
+               if (rc)
                        goto dev_fail;
-               }
                ehc->i.flags &= ~ATA_EHI_SETMODE;
        }
 
@@ -2053,20 +2141,27 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
        goto out;
 
  dev_fail:
+       ehc->tries[dev->devno]--;
+
        switch (rc) {
-       case -ENODEV:
-               /* device missing, schedule probing */
-               ehc->i.probe_mask |= (1 << dev->devno);
        case -EINVAL:
+               /* eeek, something went very wrong, give up */
                ehc->tries[dev->devno] = 0;
                break;
+
+       case -ENODEV:
+               /* device missing or wrong IDENTIFY data, schedule probing */
+               ehc->i.probe_mask |= (1 << dev->devno);
+               /* give it just one more chance */
+               ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1);
        case -EIO:
-               sata_down_spd_limit(ap);
-       default:
-               ehc->tries[dev->devno]--;
-               if (down_xfermask &&
-                   ata_down_xfermask_limit(dev, ehc->tries[dev->devno] == 1))
-                       ehc->tries[dev->devno] = 0;
+               if (ehc->tries[dev->devno] == 1) {
+                       /* This is the last chance, better to slow
+                        * down than lose it.
+                        */
+                       sata_down_spd_limit(ap);
+                       ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
+               }
        }
 
        if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) {
@@ -2181,6 +2276,7 @@ void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
        ata_eh_finish(ap);
 }
 
+#ifdef CONFIG_PM
 /**
  *     ata_eh_handle_port_suspend - perform port suspend operation
  *     @ap: port to suspend
@@ -2296,3 +2392,4 @@ static void ata_eh_handle_port_resume(struct ata_port *ap)
        }
        spin_unlock_irqrestore(ap->lock, flags);
 }
+#endif /* CONFIG_PM */
index 0009818a4306e7fb5e18c717f81d57256ebda337..6cc817a10204a89ad2615ce3bd53f111cdf267da 100644 (file)
@@ -333,6 +333,7 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
        scsi_cmd[8]  = args[3];
        scsi_cmd[10] = args[4];
        scsi_cmd[12] = args[5];
+       scsi_cmd[13] = args[6] & 0x0f;
        scsi_cmd[14] = args[0];
 
        /* Good values for timeout and retries?  Values below
@@ -509,6 +510,7 @@ static void ata_dump_status(unsigned id, struct ata_taskfile *tf)
        }
 }
 
+#ifdef CONFIG_PM
 /**
  *     ata_scsi_device_suspend - suspend ATA device associated with sdev
  *     @sdev: the SCSI device to suspend
@@ -633,6 +635,7 @@ int ata_scsi_device_resume(struct scsi_device *sdev)
        sdev->sdev_gendev.power.power_state = PMSG_ON;
        return 0;
 }
+#endif /* CONFIG_PM */
 
 /**
  *     ata_to_sense_error - convert ATA error to SCSI error
@@ -781,7 +784,7 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
         */
        if (qc->err_mask ||
            tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
-               ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
+               ata_to_sense_error(qc->ap->print_id, tf->command, tf->feature,
                                   &sb[1], &sb[2], &sb[3], verbose);
                sb[1] &= 0x0f;
        }
@@ -854,7 +857,7 @@ static void ata_gen_ata_sense(struct ata_queued_cmd *qc)
         */
        if (qc->err_mask ||
            tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
-               ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
+               ata_to_sense_error(qc->ap->print_id, tf->command, tf->feature,
                                   &sb[1], &sb[2], &sb[3], verbose);
                sb[1] &= 0x0f;
        }
@@ -986,29 +989,32 @@ int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth)
        struct ata_port *ap = ata_shost_to_port(sdev->host);
        struct ata_device *dev;
        unsigned long flags;
-       int max_depth;
 
-       if (queue_depth < 1)
+       if (queue_depth < 1 || queue_depth == sdev->queue_depth)
                return sdev->queue_depth;
 
        dev = ata_scsi_find_dev(ap, sdev);
        if (!dev || !ata_dev_enabled(dev))
                return sdev->queue_depth;
 
-       max_depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id));
-       max_depth = min(ATA_MAX_QUEUE - 1, max_depth);
-       if (queue_depth > max_depth)
-               queue_depth = max_depth;
-
-       scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, queue_depth);
-
+       /* NCQ enabled? */
        spin_lock_irqsave(ap->lock, flags);
-       if (queue_depth > 1)
-               dev->flags &= ~ATA_DFLAG_NCQ_OFF;
-       else
+       dev->flags &= ~ATA_DFLAG_NCQ_OFF;
+       if (queue_depth == 1 || !ata_ncq_enabled(dev)) {
                dev->flags |= ATA_DFLAG_NCQ_OFF;
+               queue_depth = 1;
+       }
        spin_unlock_irqrestore(ap->lock, flags);
 
+       /* limit and apply queue depth */
+       queue_depth = min(queue_depth, sdev->host->can_queue);
+       queue_depth = min(queue_depth, ata_id_queue_depth(dev->id));
+       queue_depth = min(queue_depth, ATA_MAX_QUEUE - 1);
+
+       if (sdev->queue_depth == queue_depth)
+               return -EINVAL;
+
+       scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, queue_depth);
        return queue_depth;
 }
 
@@ -1469,7 +1475,7 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
        }
 
        if (need_sense && !ap->ops->error_handler)
-               ata_dump_status(ap->id, &qc->result_tf);
+               ata_dump_status(ap->print_id, &qc->result_tf);
 
        qc->scsidone(cmd);
 
@@ -1495,11 +1501,9 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
 static int ata_scmd_need_defer(struct ata_device *dev, int is_io)
 {
        struct ata_port *ap = dev->ap;
+       int is_ncq = is_io && ata_ncq_enabled(dev);
 
-       if (!(dev->flags & ATA_DFLAG_NCQ))
-               return 0;
-
-       if (is_io) {
+       if (is_ncq) {
                if (!ata_tag_valid(ap->active_tag))
                        return 0;
        } else {
@@ -2774,7 +2778,7 @@ static inline void ata_scsi_dump_cdb(struct ata_port *ap,
        u8 *scsicmd = cmd->cmnd;
 
        DPRINTK("CDB (%u:%d,%d,%d) %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
-               ap->id,
+               ap->print_id,
                scsidev->channel, scsidev->id, scsidev->lun,
                scsicmd[0], scsicmd[1], scsicmd[2], scsicmd[3],
                scsicmd[4], scsicmd[5], scsicmd[6], scsicmd[7],
@@ -3234,7 +3238,7 @@ struct ata_port *ata_sas_port_alloc(struct ata_host *host,
 
        ata_port_init(ap, host, ent, 0);
        ap->lock = shost->host_lock;
-       kfree(ent);
+       devm_kfree(host->dev, ent);
        return ap;
 }
 EXPORT_SYMBOL_GPL(ata_sas_port_alloc);
index 16bc3e35bdd4e196eae43be264a1e758dfcf84d9..2ffcca063d80adc3405ab16c484ab7da8788a5d5 100644 (file)
@@ -175,7 +175,7 @@ void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
  */
 void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
 {
-       DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
+       DPRINTK("ata%u: cmd 0x%X\n", ap->print_id, tf->command);
 
        iowrite8(tf->command, ap->ioaddr.command_addr);
        ata_pause(ap);
@@ -521,7 +521,7 @@ void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
 static int ata_resources_present(struct pci_dev *pdev, int port)
 {
        int i;
-       
+
        /* Check the PCI resources for this channel are enabled */
        port = port * 2;
        for (i = 0; i < 2; i ++) {
@@ -531,7 +531,7 @@ static int ata_resources_present(struct pci_dev *pdev, int port)
        }
        return 1;
 }
-               
+
 /**
  *     ata_pci_init_native_mode - Initialize native-mode driver
  *     @pdev:  pci device to be initialized
@@ -576,7 +576,7 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int
 
        probe_ent->irq = pdev->irq;
        probe_ent->irq_flags = IRQF_SHARED;
-       
+
        /* Discard disabled ports. Some controllers show their
           unused channels this way */
        if (ata_resources_present(pdev, 0) == 0)
index 0ad7781d72a3b0f4e282da04dc606f48032d60cf..c42671493e8c4bf035d141b3d69b3e3702453ede 100644 (file)
@@ -41,6 +41,15 @@ struct ata_scsi_args {
 enum {
        /* flags for ata_dev_read_id() */
        ATA_READID_POSTRESET    = (1 << 0), /* reading ID after reset */
+
+       /* selector for ata_down_xfermask_limit() */
+       ATA_DNXFER_PIO          = 0,    /* speed down PIO */
+       ATA_DNXFER_DMA          = 1,    /* speed down DMA */
+       ATA_DNXFER_40C          = 2,    /* apply 40c cable limit */
+       ATA_DNXFER_FORCE_PIO    = 3,    /* force PIO */
+       ATA_DNXFER_FORCE_PIO0   = 4,    /* force PIO0 */
+
+       ATA_DNXFER_QUIET        = (1 << 31),
 };
 
 extern struct workqueue_struct *ata_aux_wq;
@@ -69,7 +78,7 @@ extern int ata_dev_revalidate(struct ata_device *dev, unsigned int flags);
 extern int ata_dev_configure(struct ata_device *dev);
 extern int sata_down_spd_limit(struct ata_port *ap);
 extern int sata_set_spd_needed(struct ata_port *ap);
-extern int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0);
+extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel);
 extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev);
 extern void ata_sg_clean(struct ata_queued_cmd *qc);
 extern void ata_qc_free(struct ata_queued_cmd *qc);
@@ -150,7 +159,5 @@ extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc);
 /* libata-sff.c */
 extern u8 ata_irq_on(struct ata_port *ap);
 
-/* pata_sis.c */
-extern struct ata_port_info sis_info133;
 
 #endif /* __LIBATA_H__ */
index ab44d18850f6eed706b0576624c8d92359ef13e0..11ea552a58cac00507f7853e1e53a598ec5afe41 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/dmi.h>
 
 #define DRV_NAME "pata_ali"
-#define DRV_VERSION "0.7.2"
+#define DRV_VERSION "0.7.3"
 
 /*
  *     Cable special cases
@@ -345,8 +345,10 @@ static struct scsi_host_template ali_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 /*
@@ -667,11 +669,13 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        return ata_pci_init_one(pdev, port_info, 2);
 }
 
+#ifdef CONFIG_PM
 static int ali_reinit_one(struct pci_dev *pdev)
 {
        ali_init_chipset(pdev);
        return ata_pci_device_resume(pdev);
 }
+#endif
 
 static const struct pci_device_id ali[] = {
        { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), },
@@ -685,8 +689,10 @@ static struct pci_driver ali_pci_driver = {
        .id_table       = ali,
        .probe          = ali_init_one,
        .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend        = ata_pci_device_suspend,
        .resume         = ali_reinit_one,
+#endif
 };
 
 static int __init ali_init(void)
index 619e44b04032ea0bada67d42ff73b81b81fb6893..18381762908bf8b474918bc5c4f93c5fcca7026c 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_amd"
-#define DRV_VERSION "0.2.7"
+#define DRV_VERSION "0.2.8"
 
 /**
  *     timing_setup            -       shared timing computation and load
@@ -128,7 +128,7 @@ static void timing_setup(struct ata_port *ap, struct ata_device *adev, int offse
 
 static int amd_pre_reset(struct ata_port *ap)
 {
-       static const u32 bitmask[2] = {0x03, 0xC0};
+       static const u32 bitmask[2] = {0x03, 0x0C};
        static const struct pci_bits amd_enable_bits[] = {
                { 0x40, 1, 0x02, 0x02 },
                { 0x40, 1, 0x01, 0x01 }
@@ -247,7 +247,7 @@ static void amd133_set_dmamode(struct ata_port *ap, struct ata_device *adev)
  */
 
 static int nv_pre_reset(struct ata_port *ap) {
-       static const u8 bitmask[2] = {0x03, 0xC0};
+       static const u8 bitmask[2] = {0x03, 0x0C};
        static const struct pci_bits nv_enable_bits[] = {
                { 0x50, 1, 0x02, 0x02 },
                { 0x50, 1, 0x01, 0x01 }
@@ -334,8 +334,10 @@ static struct scsi_host_template amd_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static struct ata_port_operations amd33_port_ops = {
@@ -663,6 +665,7 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        return ata_pci_init_one(pdev, port_info, 2);
 }
 
+#ifdef CONFIG_PM
 static int amd_reinit_one(struct pci_dev *pdev)
 {
        if (pdev->vendor == PCI_VENDOR_ID_AMD) {
@@ -679,6 +682,7 @@ static int amd_reinit_one(struct pci_dev *pdev)
        }
        return ata_pci_device_resume(pdev);
 }
+#endif
 
 static const struct pci_device_id amd[] = {
        { PCI_VDEVICE(AMD,      PCI_DEVICE_ID_AMD_COBRA_7401),          0 },
@@ -708,8 +712,10 @@ static struct pci_driver amd_pci_driver = {
        .id_table       = amd,
        .probe          = amd_init_one,
        .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend        = ata_pci_device_suspend,
        .resume         = amd_reinit_one,
+#endif
 };
 
 static int __init amd_init(void)
index c3eb40c91c80435c0fefda38c4159cd7eebec136..51d9923be02efe9e03f75b107f7ba97581f4db60 100644 (file)
@@ -224,8 +224,10 @@ static struct scsi_host_template atiixp_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static struct ata_port_operations atiixp_port_ops = {
@@ -290,8 +292,10 @@ static struct pci_driver atiixp_pci_driver = {
        .id_table       = atiixp,
        .probe          = atiixp_init_one,
        .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .resume         = ata_pci_device_resume,
        .suspend        = ata_pci_device_suspend,
+#endif
 };
 
 static int __init atiixp_init(void)
index da098282b5f6ddab91d7bb358324a1613bf02bcd..5b13bdd1edc0863049143034b7b23b8d1ef60b3a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * pata_cmd64x.c       - ATI PATA for new ATA layer
+ * pata_cmd64x.c       - CMD64x PATA for new ATA layer
  *                       (C) 2005 Red Hat Inc
  *                       Alan Cox <alan@redhat.com>
  *
@@ -285,8 +285,10 @@ static struct scsi_host_template cmd64x_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static struct ata_port_operations cmd64x_port_ops = {
@@ -479,6 +481,7 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        return ata_pci_init_one(pdev, port_info, 2);
 }
 
+#ifdef CONFIG_PM
 static int cmd64x_reinit_one(struct pci_dev *pdev)
 {
        u8 mrdmode;
@@ -492,6 +495,7 @@ static int cmd64x_reinit_one(struct pci_dev *pdev)
 #endif
        return ata_pci_device_resume(pdev);
 }
+#endif
 
 static const struct pci_device_id cmd64x[] = {
        { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_643), 0 },
@@ -507,8 +511,10 @@ static struct pci_driver cmd64x_pci_driver = {
        .id_table       = cmd64x,
        .probe          = cmd64x_init_one,
        .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend        = ata_pci_device_suspend,
        .resume         = cmd64x_reinit_one,
+#endif
 };
 
 static int __init cmd64x_init(void)
index 1ce8fcfd7826e08c32c90c130125c6013c7cb895..7ef834250a43040c3ac39656647229183efb42b8 100644 (file)
@@ -41,7 +41,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "pata_cs5520"
-#define DRV_VERSION    "0.6.3"
+#define DRV_VERSION    "0.6.4"
 
 struct pio_clocks
 {
@@ -167,8 +167,10 @@ static struct scsi_host_template cs5520_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static struct ata_port_operations cs5520_port_ops = {
@@ -306,9 +308,9 @@ static void __devexit cs5520_remove_one(struct pci_dev *pdev)
        struct ata_host *host = dev_get_drvdata(dev);
 
        ata_host_detach(host);
-       dev_set_drvdata(dev, NULL);
 }
 
+#ifdef CONFIG_PM
 /**
  *     cs5520_reinit_one       -       device resume
  *     @pdev: PCI device
@@ -325,6 +327,31 @@ static int cs5520_reinit_one(struct pci_dev *pdev)
                pci_write_config_byte(pdev, 0x60, pcicfg | 0x40);
        return ata_pci_device_resume(pdev);
 }
+
+/**
+ *     cs5520_pci_device_suspend       -       device suspend
+ *     @pdev: PCI device
+ *
+ *     We have to cut and waste bits from the standard method because
+ *     the 5520 is a bit odd and not just a pure ATA device. As a result
+ *     we must not disable it. The needed code is short and this avoids
+ *     chip specific mess in the core code.
+ */
+
+static int cs5520_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
+{
+       struct ata_host *host = dev_get_drvdata(&pdev->dev);
+       int rc = 0;
+
+       rc = ata_host_suspend(host, mesg);
+       if (rc)
+               return rc;
+
+       pci_save_state(pdev);
+       return 0;
+}
+#endif /* CONFIG_PM */
+
 /* For now keep DMA off. We can set it for all but A rev CS5510 once the
    core ATA code can handle it */
 
@@ -340,8 +367,10 @@ static struct pci_driver cs5520_pci_driver = {
        .id_table       = pata_cs5520,
        .probe          = cs5520_init_one,
        .remove         = cs5520_remove_one,
-       .suspend        = ata_pci_device_suspend,
+#ifdef CONFIG_PM
+       .suspend        = cs5520_pci_device_suspend,
        .resume         = cs5520_reinit_one,
+#endif
 };
 
 static int __init cs5520_init(void)
index 3d7b7d87ec6f3a49647a0b5a6a9ab0ff4e4703bf..db63e80e608b3b65baefaba969c2706baf92d802 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/dmi.h>
 
 #define DRV_NAME       "pata_cs5530"
-#define DRV_VERSION    "0.7.1"
+#define DRV_VERSION    "0.7.2"
 
 static void __iomem *cs5530_port_base(struct ata_port *ap)
 {
@@ -188,8 +188,10 @@ static struct scsi_host_template cs5530_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static struct ata_port_operations cs5530_port_ops = {
@@ -376,6 +378,7 @@ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        return ata_pci_init_one(pdev, port_info, 2);
 }
 
+#ifdef CONFIG_PM
 static int cs5530_reinit_one(struct pci_dev *pdev)
 {
        /* If we fail on resume we are doomed */
@@ -383,6 +386,7 @@ static int cs5530_reinit_one(struct pci_dev *pdev)
                BUG();
        return ata_pci_device_resume(pdev);
 }
+#endif /* CONFIG_PM */
 
 static const struct pci_device_id cs5530[] = {
        { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE), },
@@ -395,8 +399,10 @@ static struct pci_driver cs5530_pci_driver = {
        .id_table       = cs5530,
        .probe          = cs5530_init_one,
        .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend        = ata_pci_device_suspend,
        .resume         = cs5530_reinit_one,
+#endif
 };
 
 static int __init cs5530_init(void)
index 17bc693cc5149b34e69e74879da4635d4aeb0046..1572e5c9031af86c58c5d8a009854144e5fecc59 100644 (file)
@@ -185,8 +185,10 @@ static struct scsi_host_template cs5535_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static struct ata_port_operations cs5535_port_ops = {
@@ -270,8 +272,10 @@ static struct pci_driver cs5535_pci_driver = {
        .id_table       = cs5535,
        .probe          = cs5535_init_one,
        .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend        = ata_pci_device_suspend,
        .resume         = ata_pci_device_resume,
+#endif
 };
 
 static int __init cs5535_init(void)
index 63f48f08763db323bc7e76984f5e1a6f6a62274c..f69dde5f70665a37e2a019a23f7563177f1cbabf 100644 (file)
@@ -136,8 +136,10 @@ static struct scsi_host_template cy82c693_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static struct ata_port_operations cy82c693_port_ops = {
@@ -206,8 +208,10 @@ static struct pci_driver cy82c693_pci_driver = {
        .id_table       = cy82c693,
        .probe          = cy82c693_init_one,
        .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend        = ata_pci_device_suspend,
        .resume         = ata_pci_device_resume,
+#endif
 };
 
 static int __init cy82c693_init(void)
index c19b6a8a7dc6c5afc6b433f6e2746cffb5edfa91..dac7a6554f6c28c0febe60cb9320c61130b33bd0 100644 (file)
@@ -234,8 +234,10 @@ static struct scsi_host_template efar_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static const struct ata_port_operations efar_ops = {
@@ -317,8 +319,10 @@ static struct pci_driver efar_pci_driver = {
        .id_table               = efar_pci_tbl,
        .probe                  = efar_init_one,
        .remove                 = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend                = ata_pci_device_suspend,
        .resume                 = ata_pci_device_resume,
+#endif
 };
 
 static int __init efar_init(void)
index 27d724b5eea2c138a54c5314290f3b031fdf4a9f..baf35f87603061220fb7da4930fa0de0e7e967e3 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "pata_hpt366"
-#define DRV_VERSION    "0.5.3"
+#define DRV_VERSION    "0.6.0"
 
 struct hpt_clock {
        u8      xfer_speed;
@@ -328,8 +328,10 @@ static struct scsi_host_template hpt36x_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 /*
@@ -457,12 +459,13 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
        return ata_pci_init_one(dev, port_info, 2);
 }
 
+#ifdef CONFIG_PM
 static int hpt36x_reinit_one(struct pci_dev *dev)
 {
        hpt36x_init_chipset(dev);
        return ata_pci_device_resume(dev);
 }
-
+#endif
 
 static const struct pci_device_id hpt36x[] = {
        { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366), },
@@ -474,8 +477,10 @@ static struct pci_driver hpt36x_pci_driver = {
        .id_table       = hpt36x,
        .probe          = hpt36x_init_one,
        .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend        = ata_pci_device_suspend,
        .resume         = hpt36x_reinit_one,
+#endif
 };
 
 static int __init hpt36x_init(void)
index 4ffc392052c02f1a2dfb4769d06cace005e84abd..f331eeeafa0f39d75302023953c676910d446e64 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "pata_hpt37x"
-#define DRV_VERSION    "0.5.2"
+#define DRV_VERSION    "0.6.0"
 
 struct hpt_clock {
        u8      xfer_speed;
index 483ce7c12c9ac61da2e614e2f798ceb983abbaef..813485c8526c433a0d7931ea429351680ef7aeb5 100644 (file)
@@ -119,8 +119,10 @@ static struct scsi_host_template hpt3x3_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static struct ata_port_operations hpt3x3_port_ops = {
@@ -206,11 +208,13 @@ static int hpt3x3_init_one(struct pci_dev *dev, const struct pci_device_id *id)
        return ata_pci_init_one(dev, port_info, 2);
 }
 
+#ifdef CONFIG_PM
 static int hpt3x3_reinit_one(struct pci_dev *dev)
 {
        hpt3x3_init_chipset(dev);
        return ata_pci_device_resume(dev);
 }
+#endif
 
 static const struct pci_device_id hpt3x3[] = {
        { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT343), },
@@ -223,8 +227,10 @@ static struct pci_driver hpt3x3_pci_driver = {
        .id_table       = hpt3x3,
        .probe          = hpt3x3_init_one,
        .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend        = ata_pci_device_suspend,
        .resume         = hpt3x3_reinit_one,
+#endif
 };
 
 static int __init hpt3x3_init(void)
index 1bf5ec18b2e31490b350eb041773f04b265ad099..1a61cc89174191cb65e9e8ef6474b6cf74b633d2 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_isapnp"
-#define DRV_VERSION "0.1.5"
+#define DRV_VERSION "0.2.0"
 
 static struct scsi_host_template isapnp_sht = {
        .module                 = THIS_MODULE,
@@ -128,7 +128,6 @@ static void isapnp_remove_one(struct pnp_dev *idev)
        struct ata_host *host = dev_get_drvdata(dev);
 
        ata_host_detach(host);
-       dev_set_drvdata(dev, NULL);
 }
 
 static struct pnp_device_id isapnp_devices[] = {
index 7eac869dfcd3e984874b24773cde11852cd73d2a..ea734701555ee8d0f1ecb9810fdf561a755b33ed 100644 (file)
@@ -246,8 +246,10 @@ static struct scsi_host_template it8213_sht = {
        .dma_boundary           = ATA_DMA_BOUNDARY,
        .slave_configure        = ata_scsi_slave_config,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static const struct ata_port_operations it8213_ops = {
@@ -330,8 +332,10 @@ static struct pci_driver it8213_pci_driver = {
        .id_table               = it8213_pci_tbl,
        .probe                  = it8213_init_one,
        .remove                 = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend                = ata_pci_device_suspend,
        .resume                 = ata_pci_device_resume,
+#endif
 };
 
 static int __init it8213_init(void)
index 73394c75be4254fac5c0624c7b0ea23747279fdc..35ecb2ba067b8b09453d0236071c4bde42a51214 100644 (file)
@@ -80,7 +80,7 @@
 
 
 #define DRV_NAME "pata_it821x"
-#define DRV_VERSION "0.3.3"
+#define DRV_VERSION "0.3.4"
 
 struct it821x_dev
 {
@@ -503,10 +503,12 @@ static int it821x_smart_set_mode(struct ata_port *ap, struct ata_device **unused
                        /* We do need the right mode information for DMA or PIO
                           and this comes from the current configuration flags */
                        if (dma_enabled & (1 << (5 + i))) {
+                               ata_dev_printk(dev, KERN_INFO, "configured for DMA\n");
                                dev->xfer_mode = XFER_MW_DMA_0;
                                dev->xfer_shift = ATA_SHIFT_MWDMA;
                                dev->flags &= ~ATA_DFLAG_PIO;
                        } else {
+                               ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
                                dev->xfer_mode = XFER_PIO_0;
                                dev->xfer_shift = ATA_SHIFT_PIO;
                                dev->flags |= ATA_DFLAG_PIO;
@@ -644,8 +646,10 @@ static struct scsi_host_template it821x_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static struct ata_port_operations it821x_smart_port_ops = {
@@ -778,6 +782,7 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        return ata_pci_init_one(pdev, port_info, 2);
 }
 
+#ifdef CONFIG_PM
 static int it821x_reinit_one(struct pci_dev *pdev)
 {
        /* Resume - turn raid back off if need be */
@@ -785,6 +790,7 @@ static int it821x_reinit_one(struct pci_dev *pdev)
                it821x_disable_raid(pdev);
        return ata_pci_device_resume(pdev);
 }
+#endif
 
 static const struct pci_device_id it821x[] = {
        { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8211), },
@@ -798,8 +804,10 @@ static struct pci_driver it821x_pci_driver = {
        .id_table       = it821x,
        .probe          = it821x_init_one,
        .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend        = ata_pci_device_suspend,
        .resume         = it821x_reinit_one,
+#endif
 };
 
 static int __init it821x_init(void)
index 3222ac7b945d43637295ed8f9d349df8ce937367..9a0523b5c947ce6c73c1b17d5c49ad51c91f2518 100644 (file)
 #include <scsi/scsi_host.h>
 
 #define DRV_NAME       "pata_ixp4xx_cf"
-#define DRV_VERSION    "0.1.1ac1"
+#define DRV_VERSION    "0.1.2"
 
-static int ixp4xx_set_mode(struct ata_port *ap, struct ata_device *adev)
+static int ixp4xx_set_mode(struct ata_port *ap, struct ata_device **error)
 {
        int i;
 
        for (i = 0; i < ATA_MAX_DEVICES; i++) {
                struct ata_device *dev = &ap->device[i];
-               if (ata_dev_enabled(dev)) {
+               if (ata_dev_ready(dev)) {
+                       ata_dev_printk(dev, KERN_INFO, "configured for PIO0\n");
                        dev->pio_mode = XFER_PIO_0;
                        dev->xfer_mode = XFER_PIO_0;
                        dev->xfer_shift = ATA_SHIFT_PIO;
index 7a635dd326f85825d044a957d906a827497145c6..43763c99ea02a601b96ff8be1f943fab49d5b839 100644 (file)
@@ -137,6 +137,10 @@ static struct scsi_host_template jmicron_sht = {
        .slave_destroy          = ata_scsi_slave_destroy,
        /* Use standard CHS mapping rules */
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
+       .suspend                = ata_scsi_device_suspend,
+       .resume                 = ata_scsi_device_resume,
+#endif
 };
 
 static const struct ata_port_operations jmicron_ops = {
@@ -202,49 +206,20 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i
        };
        struct ata_port_info *port_info[2] = { &info, &info };
 
-       u32 reg;
-
-       /* PATA controller is fn 1, AHCI is fn 0 */
-       if (id->driver_data != 368 && PCI_FUNC(pdev->devfn) != 1)
-               return -ENODEV;
-
-       /* The 365/66 have two PATA channels, redirect the second */
-       if (id->driver_data == 365 || id->driver_data == 366) {
-               pci_read_config_dword(pdev, 0x80, &reg);
-               reg |= (1 << 24);       /* IDE1 to PATA IDE secondary */
-               pci_write_config_dword(pdev, 0x80, reg);
-       }
-
        return ata_pci_init_one(pdev, port_info, 2);
 }
 
-static int jmicron_reinit_one(struct pci_dev *pdev)
-{
-       u32 reg;
-
-       switch(pdev->device) {
-               case PCI_DEVICE_ID_JMICRON_JMB368:
-                       break;
-               case PCI_DEVICE_ID_JMICRON_JMB365:
-               case PCI_DEVICE_ID_JMICRON_JMB366:
-                       /* Restore mapping or disks swap and boy does it get ugly */
-                       pci_read_config_dword(pdev, 0x80, &reg);
-                       reg |= (1 << 24);       /* IDE1 to PATA IDE secondary */
-                       pci_write_config_dword(pdev, 0x80, reg);
-                       /* Fall through */
-               default:
-                       /* Make sure AHCI is turned back on */
-                       pci_write_config_byte(pdev, 0x41, 0xa1);
-       }
-       return ata_pci_device_resume(pdev);
-}
-
 static const struct pci_device_id jmicron_pci_tbl[] = {
-       { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB361), 361},
-       { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB363), 363},
-       { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB365), 365},
-       { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB366), 366},
-       { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB368), 368},
+       { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361,
+         PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 361 },
+       { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363,
+         PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 363 },
+       { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365,
+         PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 365 },
+       { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366,
+         PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 366 },
+       { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368,
+         PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 368 },
 
        { }     /* terminate list */
 };
@@ -254,8 +229,10 @@ static struct pci_driver jmicron_pci_driver = {
        .id_table               = jmicron_pci_tbl,
        .probe                  = jmicron_init_one,
        .remove                 = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend                = ata_pci_device_suspend,
-       .resume                 = jmicron_reinit_one,
+       .resume                 = ata_pci_device_resume,
+#endif
 };
 
 static int __init jmicron_init(void)
index 98c1fee4b305a92f3d92f08506010d861ee027c4..86fbcd6a742b5dbb486b471806e496ef8ebf6712 100644 (file)
 #include <linux/platform_device.h>
 
 #define DRV_NAME "pata_legacy"
-#define DRV_VERSION "0.5.3"
+#define DRV_VERSION "0.5.4"
 
 #define NR_HOST 6
 
 static int legacy_port[NR_HOST] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 };
-static int legacy_irq[NR_HOST] = { 15, 14, 11, 10, 8, 12 };
+static int legacy_irq[NR_HOST] = { 14, 15, 11, 10, 8, 12 };
 
 struct legacy_data {
        unsigned long timing;
@@ -186,7 +186,10 @@ static struct ata_port_operations legacy_port_ops = {
        .exec_command   = ata_exec_command,
        .dev_select     = ata_std_dev_select,
 
+       .freeze         = ata_bmdma_freeze,
+       .thaw           = ata_bmdma_thaw,
        .error_handler  = ata_bmdma_error_handler,
+       .post_internal_cmd = ata_bmdma_post_internal_cmd,
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
@@ -298,7 +301,10 @@ static struct ata_port_operations pdc20230_port_ops = {
        .exec_command   = ata_exec_command,
        .dev_select     = ata_std_dev_select,
 
+       .freeze         = ata_bmdma_freeze,
+       .thaw           = ata_bmdma_thaw,
        .error_handler  = ata_bmdma_error_handler,
+       .post_internal_cmd = ata_bmdma_post_internal_cmd,
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
@@ -350,7 +356,10 @@ static struct ata_port_operations ht6560a_port_ops = {
        .exec_command   = ata_exec_command,
        .dev_select     = ata_std_dev_select,
 
+       .freeze         = ata_bmdma_freeze,
+       .thaw           = ata_bmdma_thaw,
        .error_handler  = ata_bmdma_error_handler,
+       .post_internal_cmd = ata_bmdma_post_internal_cmd,
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
@@ -413,7 +422,10 @@ static struct ata_port_operations ht6560b_port_ops = {
        .exec_command   = ata_exec_command,
        .dev_select     = ata_std_dev_select,
 
+       .freeze         = ata_bmdma_freeze,
+       .thaw           = ata_bmdma_thaw,
        .error_handler  = ata_bmdma_error_handler,
+       .post_internal_cmd = ata_bmdma_post_internal_cmd,
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
@@ -531,7 +543,10 @@ static struct ata_port_operations opti82c611a_port_ops = {
        .exec_command   = ata_exec_command,
        .dev_select     = ata_std_dev_select,
 
+       .freeze         = ata_bmdma_freeze,
+       .thaw           = ata_bmdma_thaw,
        .error_handler  = ata_bmdma_error_handler,
+       .post_internal_cmd = ata_bmdma_post_internal_cmd,
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
@@ -661,7 +676,10 @@ static struct ata_port_operations opti82c46x_port_ops = {
        .exec_command   = ata_exec_command,
        .dev_select     = ata_std_dev_select,
 
+       .freeze         = ata_bmdma_freeze,
+       .thaw           = ata_bmdma_thaw,
        .error_handler  = ata_bmdma_error_handler,
+       .post_internal_cmd = ata_bmdma_post_internal_cmd,
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = opti82c46x_qc_issue_prot,
index 13a70ac6f1dc2f536b132229ac7706aa87e7d6e5..6dd7c4ef3e66bbd93832a2b4e36398a36f5756e2 100644 (file)
@@ -103,8 +103,10 @@ static struct scsi_host_template marvell_sht = {
        .slave_destroy          = ata_scsi_slave_destroy,
        /* Use standard CHS mapping rules */
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static const struct ata_port_operations marvell_ops = {
@@ -199,8 +201,10 @@ static struct pci_driver marvell_pci_driver = {
        .id_table               = marvell_pci_tbl,
        .probe                  = marvell_init_one,
        .remove                 = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend                = ata_pci_device_suspend,
        .resume                 = ata_pci_device_resume,
+#endif
 };
 
 static int __init marvell_init(void)
index 29e1809e5ecf3ce9aea4c7899d3457b64ad4716b..f5d88729ca79aba58ded4379d3a54172877277ad 100644 (file)
@@ -280,6 +280,10 @@ static struct scsi_host_template mpc52xx_ata_sht = {
        .dma_boundary           = ATA_DMA_BOUNDARY,
        .slave_configure        = ata_scsi_slave_config,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
+       .suspend                = ata_scsi_device_suspend,
+       .resume                 = ata_scsi_device_resume,
+#endif
 };
 
 static struct ata_port_operations mpc52xx_ata_port_ops = {
index f2e7115f7ab9de2aba9b0a9426e7155916c2f26f..4abe45ac19a2c121c03655875dd63b951c2c6d35 100644 (file)
@@ -165,8 +165,10 @@ static struct scsi_host_template mpiix_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static struct ata_port_operations mpiix_port_ops = {
@@ -270,8 +272,10 @@ static struct pci_driver mpiix_pci_driver = {
        .id_table       = mpiix,
        .probe          = mpiix_init_one,
        .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend        = ata_pci_device_suspend,
        .resume         = ata_pci_device_resume,
+#endif
 };
 
 static int __init mpiix_init(void)
index e8393e19be47d94b9c06b13e2a16ca157b9c9cce..38f99b38a5ea97a861e1a8cb2d1d27f324ea38cc 100644 (file)
@@ -63,8 +63,10 @@ static struct scsi_host_template netcell_sht = {
        .slave_destroy          = ata_scsi_slave_destroy,
        /* Use standard CHS mapping rules */
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static const struct ata_port_operations netcell_ops = {
@@ -153,8 +155,10 @@ static struct pci_driver netcell_pci_driver = {
        .id_table               = netcell_pci_tbl,
        .probe                  = netcell_init_one,
        .remove                 = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend                = ata_pci_device_suspend,
        .resume                 = ata_pci_device_resume,
+#endif
 };
 
 static int __init netcell_init(void)
index 3d1fa487c48606aa0ac745f4b023ad8a818aff4c..9944a28daa9c681874413ea23f8d95a938dc678a 100644 (file)
@@ -157,8 +157,10 @@ static struct scsi_host_template ns87410_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static struct ata_port_operations ns87410_port_ops = {
@@ -212,8 +214,10 @@ static struct pci_driver ns87410_pci_driver = {
        .id_table       = ns87410,
        .probe          = ns87410_init_one,
        .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend        = ata_pci_device_suspend,
        .resume         = ata_pci_device_resume,
+#endif
 };
 
 static int __init ns87410_init(void)
index 45215aa05e72b92a8b2b7d3c7be6804d5e2cbd0c..da68cd19efd612cfc5f5bde902b98605ab23683f 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/ata.h>
 
 #define DRV_NAME       "pata_oldpiix"
-#define DRV_VERSION    "0.5.3"
+#define DRV_VERSION    "0.5.4"
 
 /**
  *     oldpiix_pre_reset               -       probe begin
@@ -209,10 +209,9 @@ static unsigned int oldpiix_qc_issue_prot(struct ata_queued_cmd *qc)
        struct ata_device *adev = qc->dev;
 
        if (adev != ap->private_data) {
+               oldpiix_set_piomode(ap, adev);
                if (adev->dma_mode)
                        oldpiix_set_dmamode(ap, adev);
-               else if (adev->pio_mode)
-                       oldpiix_set_piomode(ap, adev);
        }
        return ata_qc_issue_prot(qc);
 }
@@ -234,8 +233,10 @@ static struct scsi_host_template oldpiix_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static const struct ata_port_operations oldpiix_pata_ops = {
@@ -317,8 +318,10 @@ static struct pci_driver oldpiix_pci_driver = {
        .id_table               = oldpiix_pci_tbl,
        .probe                  = oldpiix_init_one,
        .remove                 = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend                = ata_pci_device_suspend,
        .resume                 = ata_pci_device_resume,
+#endif
 };
 
 static int __init oldpiix_init(void)
index da1aa148b37d9f69b5d91c88b57608f1e7d65461..3fd3a35c2241bf1015189e25db264389480ef128 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_opti"
-#define DRV_VERSION "0.2.7"
+#define DRV_VERSION "0.2.8"
 
 enum {
        READ_REG        = 0,    /* index of Read cycle timing register */
@@ -179,8 +179,10 @@ static struct scsi_host_template opti_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static struct ata_port_operations opti_port_ops = {
@@ -244,8 +246,10 @@ static struct pci_driver opti_pci_driver = {
        .id_table       = opti,
        .probe          = opti_init_one,
        .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend        = ata_pci_device_suspend,
        .resume         = ata_pci_device_resume,
+#endif
 };
 
 static int __init opti_init(void)
index d80b36e209cc52bc6de595d414caecb32163a975..9764907e8a134e20a238478bab1f932d9f224c0e 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_optidma"
-#define DRV_VERSION "0.2.3"
+#define DRV_VERSION "0.2.4"
 
 enum {
        READ_REG        = 0,    /* index of Read cycle timing register */
@@ -360,8 +360,10 @@ static struct scsi_host_template optidma_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static struct ata_port_operations optidma_port_ops = {
@@ -524,8 +526,10 @@ static struct pci_driver optidma_pci_driver = {
        .id_table       = optidma,
        .probe          = optidma_init_one,
        .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend        = ata_pci_device_suspend,
        .resume         = ata_pci_device_resume,
+#endif
 };
 
 static int __init optidma_init(void)
index 36468ec6454cad8606a7908bb3df959997647b48..103720f873c8f31d8384b0f54b5b97975c2ad3bb 100644 (file)
@@ -42,7 +42,7 @@
 
 
 #define DRV_NAME "pata_pcmcia"
-#define DRV_VERSION "0.2.11"
+#define DRV_VERSION "0.3.0"
 
 /*
  *     Private data structure to glue stuff together
@@ -308,7 +308,6 @@ static void pcmcia_remove_one(struct pcmcia_device *pdev)
                if (info->ndev) {
                        struct ata_host *host = dev_get_drvdata(dev);
                        ata_host_detach(host);
-                       dev_set_drvdata(dev, NULL);
                }
                info->ndev = 0;
                pdev->priv = NULL;
@@ -320,14 +319,17 @@ static void pcmcia_remove_one(struct pcmcia_device *pdev)
 static struct pcmcia_device_id pcmcia_devices[] = {
        PCMCIA_DEVICE_FUNC_ID(4),
        PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000),        /* Hitachi */
+       PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000),        /* I-O Data CFA */
+       PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001),        /* Mitsubishi CFA */
        PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
-       PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),
+       PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),        /* SanDisk CFA */
        PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000),        /* Toshiba */
        PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
        PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000),        /* Samsung */
        PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000),        /* Hitachi */
        PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
-       PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200),        /* Lexar */
+       PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0100),        /* Viking CFA */
+       PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200),        /* Lexar, Viking CFA */
        PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
        PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74),
        PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
index 61537873d28ef133d4dc5efab882b7efc2c3714c..93bcdadb7be3a17c8ff82f00dc5a7425cf3c9d26 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "pata_pdc2027x"
-#define DRV_VERSION    "0.74-ac5"
+#define DRV_VERSION    "0.8"
 #undef PDC_DEBUG
 
 #ifdef PDC_DEBUG
index 6dd63413a523475c82f45cd5c03746b9b13c01b2..acdc52cbe38a0bbddcc44cca91b9592d82036f90 100644 (file)
@@ -2,13 +2,14 @@
  * pata_pdc202xx_old.c         - Promise PDC202xx PATA for new ATA layer
  *                       (C) 2005 Red Hat Inc
  *                       Alan Cox <alan@redhat.com>
+ *                       (C) 2007 Bartlomiej Zolnierkiewicz
  *
  * Based in part on linux/drivers/ide/pci/pdc202xx_old.c
  *
  * First cut with LBA48/ATAPI
  *
  * TODO:
- *     Channel interlock/reset on both required ?
+ *     Channel interlock/reset on both required
  */
 
 #include <linux/kernel.h>
@@ -21,7 +22,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_pdc202xx_old"
-#define DRV_VERSION "0.2.3"
+#define DRV_VERSION "0.4.0"
 
 /**
  *     pdc2024x_pre_reset              -       probe begin
@@ -76,7 +77,7 @@ static void pdc2026x_error_handler(struct ata_port *ap)
 static void pdc202xx_configure_piomode(struct ata_port *ap, struct ata_device *adev, int pio)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
-       int port = 0x60 + 4 * ap->port_no + 2 * adev->devno;
+       int port = 0x60 + 8 * ap->port_no + 4 * adev->devno;
        static u16 pio_timing[5] = {
                0x0913, 0x050C , 0x0308, 0x0206, 0x0104
        };
@@ -85,7 +86,7 @@ static void pdc202xx_configure_piomode(struct ata_port *ap, struct ata_device *a
        pci_read_config_byte(pdev, port, &r_ap);
        pci_read_config_byte(pdev, port + 1, &r_bp);
        r_ap &= ~0x3F;  /* Preserve ERRDY_EN, SYNC_IN */
-       r_bp &= ~0x07;
+       r_bp &= ~0x1F;
        r_ap |= (pio_timing[pio] >> 8);
        r_bp |= (pio_timing[pio] & 0xFF);
 
@@ -123,7 +124,7 @@ static void pdc202xx_set_piomode(struct ata_port *ap, struct ata_device *adev)
 static void pdc202xx_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
-       int port = 0x60 + 4 * ap->port_no + 2 * adev->devno;
+       int port = 0x60 + 8 * ap->port_no + 4 * adev->devno;
        static u8 udma_timing[6][2] = {
                { 0x60, 0x03 }, /* 33 Mhz Clock */
                { 0x40, 0x02 },
@@ -132,12 +133,17 @@ static void pdc202xx_set_dmamode(struct ata_port *ap, struct ata_device *adev)
                { 0x20, 0x01 },
                { 0x20, 0x01 }
        };
+       static u8 mdma_timing[3][2] = {
+               { 0x60, 0x03 },
+               { 0x60, 0x04 },
+               { 0xe0, 0x0f },
+       };
        u8 r_bp, r_cp;
 
        pci_read_config_byte(pdev, port + 1, &r_bp);
        pci_read_config_byte(pdev, port + 2, &r_cp);
 
-       r_bp &= ~0xF0;
+       r_bp &= ~0xE0;
        r_cp &= ~0x0F;
 
        if (adev->dma_mode >= XFER_UDMA_0) {
@@ -147,8 +153,8 @@ static void pdc202xx_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 
        } else {
                int speed = adev->dma_mode - XFER_MW_DMA_0;
-               r_bp |= 0x60;
-               r_cp |= (5 - speed);
+               r_bp |= mdma_timing[speed][0];
+               r_cp |= mdma_timing[speed][1];
        }
        pci_write_config_byte(pdev, port + 1, r_bp);
        pci_write_config_byte(pdev, port + 2, r_cp);
@@ -267,8 +273,10 @@ static struct scsi_host_template pdc202xx_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static struct ata_port_operations pdc2024x_port_ops = {
@@ -399,8 +407,10 @@ static struct pci_driver pdc202xx_pci_driver = {
        .id_table       = pdc202xx,
        .probe          = pdc202xx_init_one,
        .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend        = ata_pci_device_suspend,
        .resume         = ata_pci_device_resume,
+#endif
 };
 
 static int __init pdc202xx_init(void)
index 479a326114e0ca4132740f2e619a793a9ef5046b..4b82a5435a4ebfc1f558afa89bf088bb9d4dc565 100644 (file)
@@ -42,6 +42,7 @@ static int pata_platform_set_mode(struct ata_port *ap, struct ata_device **unuse
                        dev->pio_mode = dev->xfer_mode = XFER_PIO_0;
                        dev->xfer_shift = ATA_SHIFT_PIO;
                        dev->flags |= ATA_DFLAG_PIO;
+                       ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
                }
        }
        return 0;
@@ -227,7 +228,6 @@ static int __devexit pata_platform_remove(struct platform_device *pdev)
        struct ata_host *host = dev_get_drvdata(dev);
 
        ata_host_detach(host);
-       dev_set_drvdata(dev, NULL);
 
        return 0;
 }
index 4362141976adfa41af697adcbede81f4b1fdb44d..c3810012f3f4af7d873ecd120fda194974528dae 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/platform_device.h>
 
 #define DRV_NAME "pata_qdi"
-#define DRV_VERSION "0.2.4"
+#define DRV_VERSION "0.3.0"
 
 #define NR_HOST 4      /* Two 6580s */
 
@@ -363,7 +363,8 @@ static __init int qdi_init(void)
                                        release_region(port, 2);
                                        continue;
                                }
-                               ct += qdi_init_one(port, 6500, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04);
+                               if (qdi_init_one(port, 6500, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04) == 0)
+                                       ct++;
                        }
                        if (((r & 0xF0) == 0xA0) || (r & 0xF0) == 0x50) {
                                /* QD6580: dual channel */
@@ -375,11 +376,14 @@ static __init int qdi_init(void)
                                res = inb(port + 3);
                                if (res & 1) {
                                        /* Single channel mode */
-                                       ct += qdi_init_one(port, 6580, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04);
+                                       if (qdi_init_one(port, 6580, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04))
+                                               ct++;
                                } else {
                                        /* Dual channel mode */
-                                       ct += qdi_init_one(port, 6580, 0x1F0, 14, r & 0x04);
-                                       ct += qdi_init_one(port + 2, 6580, 0x170, 15, r & 0x04);
+                                       if (qdi_init_one(port, 6580, 0x1F0, 14, r & 0x04) == 0)
+                                               ct++;
+                                       if (qdi_init_one(port + 2, 6580, 0x170, 15, r & 0x04) == 0)
+                                               ct++;
                                }
                        }
                }
index 0d1e571ef6333572aa19df27b3588691c894cf7f..9a9132c9e3317a034ab0f402cc45ae1f6289ac39 100644 (file)
@@ -228,8 +228,10 @@ static struct scsi_host_template radisys_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static const struct ata_port_operations radisys_pata_ops = {
@@ -312,8 +314,10 @@ static struct pci_driver radisys_pci_driver = {
        .id_table               = radisys_pci_tbl,
        .probe                  = radisys_init_one,
        .remove                 = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend                = ata_pci_device_suspend,
        .resume                 = ata_pci_device_resume,
+#endif
 };
 
 static int __init radisys_init(void)
index 71a2bac09e0d90ee7638d9ecc129d7ef1141b5d7..f522daa2a6aa3c274befa168bca47fd2cd620643 100644 (file)
@@ -71,6 +71,7 @@ static int rz1000_set_mode(struct ata_port *ap, struct ata_device **unused)
                        dev->xfer_mode = XFER_PIO_0;
                        dev->xfer_shift = ATA_SHIFT_PIO;
                        dev->flags |= ATA_DFLAG_PIO;
+                       ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
                }
        }
        return 0;
@@ -93,8 +94,10 @@ static struct scsi_host_template rz1000_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static struct ata_port_operations rz1000_port_ops = {
@@ -177,6 +180,7 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en
        return -ENODEV;
 }
 
+#ifdef CONFIG_PM
 static int rz1000_reinit_one(struct pci_dev *pdev)
 {
        /* If this fails on resume (which is a "cant happen" case), we
@@ -185,6 +189,7 @@ static int rz1000_reinit_one(struct pci_dev *pdev)
                panic("rz1000 fifo");
        return ata_pci_device_resume(pdev);
 }
+#endif
 
 static const struct pci_device_id pata_rz1000[] = {
        { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000), },
@@ -198,8 +203,10 @@ static struct pci_driver rz1000_pci_driver = {
        .id_table       = pata_rz1000,
        .probe          = rz1000_init_one,
        .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend        = ata_pci_device_suspend,
        .resume         = rz1000_reinit_one,
+#endif
 };
 
 static int __init rz1000_init(void)
index 58e42fbd14f939f9104758a044cda7b2f077ee72..93b3ed0f9e8ac9a448102073535e51f04cdceacb 100644 (file)
@@ -194,8 +194,10 @@ static struct scsi_host_template sc1200_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static struct ata_port_operations sc1200_port_ops = {
@@ -210,7 +212,10 @@ static struct ata_port_operations sc1200_port_ops = {
        .exec_command   = ata_exec_command,
        .dev_select     = ata_std_dev_select,
 
+       .freeze         = ata_bmdma_freeze,
+       .thaw           = ata_bmdma_thaw,
        .error_handler  = ata_bmdma_error_handler,
+       .post_internal_cmd = ata_bmdma_post_internal_cmd,
 
        .bmdma_setup    = ata_bmdma_setup,
        .bmdma_start    = ata_bmdma_start,
@@ -266,8 +271,10 @@ static struct pci_driver sc1200_pci_driver = {
        .id_table       = sc1200,
        .probe          = sc1200_init_one,
        .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend        = ata_pci_device_suspend,
        .resume         = ata_pci_device_resume,
+#endif
 };
 
 static int __init sc1200_init(void)
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c
new file mode 100644 (file)
index 0000000..f3ed141
--- /dev/null
@@ -0,0 +1,1230 @@
+/*
+ * Support for IDE interfaces on Celleb platform
+ *
+ * (C) Copyright 2006 TOSHIBA CORPORATION
+ *
+ * This code is based on drivers/ata/ata_piix.c:
+ *  Copyright 2003-2005 Red Hat Inc
+ *  Copyright 2003-2005 Jeff Garzik
+ *  Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
+ *  Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
+ *  Copyright (C) 2003 Red Hat Inc <alan@redhat.com>
+ *
+ * and drivers/ata/ahci.c:
+ *  Copyright 2004-2005 Red Hat, Inc.
+ *
+ * and drivers/ata/libata-core.c:
+ *  Copyright 2003-2004 Red Hat, Inc.  All rights reserved.
+ *  Copyright 2003-2004 Jeff Garzik
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+
+#define DRV_NAME               "pata_scc"
+#define DRV_VERSION            "0.1"
+
+#define PCI_DEVICE_ID_TOSHIBA_SCC_ATA          0x01b4
+
+/* PCI BARs */
+#define SCC_CTRL_BAR           0
+#define SCC_BMID_BAR           1
+
+/* offset of CTRL registers */
+#define SCC_CTL_PIOSHT         0x000
+#define SCC_CTL_PIOCT          0x004
+#define SCC_CTL_MDMACT         0x008
+#define SCC_CTL_MCRCST         0x00C
+#define SCC_CTL_SDMACT         0x010
+#define SCC_CTL_SCRCST         0x014
+#define SCC_CTL_UDENVT         0x018
+#define SCC_CTL_TDVHSEL        0x020
+#define SCC_CTL_MODEREG        0x024
+#define SCC_CTL_ECMODE         0xF00
+#define SCC_CTL_MAEA0          0xF50
+#define SCC_CTL_MAEC0          0xF54
+#define SCC_CTL_CCKCTRL        0xFF0
+
+/* offset of BMID registers */
+#define SCC_DMA_CMD            0x000
+#define SCC_DMA_STATUS         0x004
+#define SCC_DMA_TABLE_OFS      0x008
+#define SCC_DMA_INTMASK        0x010
+#define SCC_DMA_INTST          0x014
+#define SCC_DMA_PTERADD        0x018
+#define SCC_REG_CMD_ADDR       0x020
+#define SCC_REG_DATA           0x000
+#define SCC_REG_ERR            0x004
+#define SCC_REG_FEATURE        0x004
+#define SCC_REG_NSECT          0x008
+#define SCC_REG_LBAL           0x00C
+#define SCC_REG_LBAM           0x010
+#define SCC_REG_LBAH           0x014
+#define SCC_REG_DEVICE         0x018
+#define SCC_REG_STATUS         0x01C
+#define SCC_REG_CMD            0x01C
+#define SCC_REG_ALTSTATUS      0x020
+
+/* register value */
+#define TDVHSEL_MASTER         0x00000001
+#define TDVHSEL_SLAVE          0x00000004
+
+#define MODE_JCUSFEN           0x00000080
+
+#define ECMODE_VALUE           0x01
+
+#define CCKCTRL_ATARESET       0x00040000
+#define CCKCTRL_BUFCNT         0x00020000
+#define CCKCTRL_CRST           0x00010000
+#define CCKCTRL_OCLKEN         0x00000100
+#define CCKCTRL_ATACLKOEN      0x00000002
+#define CCKCTRL_LCLKEN         0x00000001
+
+#define QCHCD_IOS_SS           0x00000001
+
+#define QCHSD_STPDIAG          0x00020000
+
+#define INTMASK_MSK            0xD1000012
+#define INTSTS_SERROR          0x80000000
+#define INTSTS_PRERR           0x40000000
+#define INTSTS_RERR            0x10000000
+#define INTSTS_ICERR           0x01000000
+#define INTSTS_BMSINT          0x00000010
+#define INTSTS_BMHE            0x00000008
+#define INTSTS_IOIRQS          0x00000004
+#define INTSTS_INTRQ           0x00000002
+#define INTSTS_ACTEINT         0x00000001
+
+
+/* PIO transfer mode table */
+/* JCHST */
+static const unsigned long JCHSTtbl[2][7] = {
+       {0x0E, 0x05, 0x02, 0x03, 0x02, 0x00, 0x00},     /* 100MHz */
+       {0x13, 0x07, 0x04, 0x04, 0x03, 0x00, 0x00}      /* 133MHz */
+};
+
+/* JCHHT */
+static const unsigned long JCHHTtbl[2][7] = {
+       {0x0E, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00},     /* 100MHz */
+       {0x13, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00}      /* 133MHz */
+};
+
+/* JCHCT */
+static const unsigned long JCHCTtbl[2][7] = {
+       {0x1D, 0x1D, 0x1C, 0x0B, 0x06, 0x00, 0x00},     /* 100MHz */
+       {0x27, 0x26, 0x26, 0x0E, 0x09, 0x00, 0x00}      /* 133MHz */
+};
+
+/* DMA transfer mode  table */
+/* JCHDCTM/JCHDCTS */
+static const unsigned long JCHDCTxtbl[2][7] = {
+       {0x0A, 0x06, 0x04, 0x03, 0x01, 0x00, 0x00},     /* 100MHz */
+       {0x0E, 0x09, 0x06, 0x04, 0x02, 0x01, 0x00}      /* 133MHz */
+};
+
+/* JCSTWTM/JCSTWTS  */
+static const unsigned long JCSTWTxtbl[2][7] = {
+       {0x06, 0x04, 0x03, 0x02, 0x02, 0x02, 0x00},     /* 100MHz */
+       {0x09, 0x06, 0x04, 0x02, 0x02, 0x02, 0x02}      /* 133MHz */
+};
+
+/* JCTSS */
+static const unsigned long JCTSStbl[2][7] = {
+       {0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00},     /* 100MHz */
+       {0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05}      /* 133MHz */
+};
+
+/* JCENVT */
+static const unsigned long JCENVTtbl[2][7] = {
+       {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00},     /* 100MHz */
+       {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02}      /* 133MHz */
+};
+
+/* JCACTSELS/JCACTSELM */
+static const unsigned long JCACTSELtbl[2][7] = {
+       {0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00},     /* 100MHz */
+       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}      /* 133MHz */
+};
+
+static const struct pci_device_id scc_pci_tbl[] = {
+       {PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_SCC_ATA,
+        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       { }     /* terminate list */
+};
+
+/**
+ *     scc_set_piomode - Initialize host controller PATA PIO timings
+ *     @ap: Port whose timings we are configuring
+ *     @adev: um
+ *
+ *     Set PIO mode for device.
+ *
+ *     LOCKING:
+ *     None (inherited from caller).
+ */
+
+static void scc_set_piomode (struct ata_port *ap, struct ata_device *adev)
+{
+       unsigned int pio = adev->pio_mode - XFER_PIO_0;
+       void __iomem *ctrl_base = ap->host->iomap[SCC_CTRL_BAR];
+       void __iomem *cckctrl_port = ctrl_base + SCC_CTL_CCKCTRL;
+       void __iomem *piosht_port = ctrl_base + SCC_CTL_PIOSHT;
+       void __iomem *pioct_port = ctrl_base + SCC_CTL_PIOCT;
+       unsigned long reg;
+       int offset;
+
+       reg = in_be32(cckctrl_port);
+       if (reg & CCKCTRL_ATACLKOEN)
+               offset = 1;     /* 133MHz */
+       else
+               offset = 0;     /* 100MHz */
+
+       reg = JCHSTtbl[offset][pio] << 16 | JCHHTtbl[offset][pio];
+       out_be32(piosht_port, reg);
+       reg = JCHCTtbl[offset][pio];
+       out_be32(pioct_port, reg);
+}
+
+/**
+ *     scc_set_dmamode - Initialize host controller PATA DMA timings
+ *     @ap: Port whose timings we are configuring
+ *     @adev: um
+ *     @udma: udma mode, 0 - 6
+ *
+ *     Set UDMA mode for device.
+ *
+ *     LOCKING:
+ *     None (inherited from caller).
+ */
+
+static void scc_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+{
+       unsigned int udma = adev->dma_mode;
+       unsigned int is_slave = (adev->devno != 0);
+       u8 speed = udma;
+       void __iomem *ctrl_base = ap->host->iomap[SCC_CTRL_BAR];
+       void __iomem *cckctrl_port = ctrl_base + SCC_CTL_CCKCTRL;
+       void __iomem *mdmact_port = ctrl_base + SCC_CTL_MDMACT;
+       void __iomem *mcrcst_port = ctrl_base + SCC_CTL_MCRCST;
+       void __iomem *sdmact_port = ctrl_base + SCC_CTL_SDMACT;
+       void __iomem *scrcst_port = ctrl_base + SCC_CTL_SCRCST;
+       void __iomem *udenvt_port = ctrl_base + SCC_CTL_UDENVT;
+       void __iomem *tdvhsel_port = ctrl_base + SCC_CTL_TDVHSEL;
+       int offset, idx;
+
+       if (in_be32(cckctrl_port) & CCKCTRL_ATACLKOEN)
+               offset = 1;     /* 133MHz */
+       else
+               offset = 0;     /* 100MHz */
+
+       if (speed >= XFER_UDMA_0)
+               idx = speed - XFER_UDMA_0;
+       else
+               return;
+
+       if (is_slave) {
+               out_be32(sdmact_port, JCHDCTxtbl[offset][idx]);
+               out_be32(scrcst_port, JCSTWTxtbl[offset][idx]);
+               out_be32(tdvhsel_port,
+                        (in_be32(tdvhsel_port) & ~TDVHSEL_SLAVE) | (JCACTSELtbl[offset][idx] << 2));
+       } else {
+               out_be32(mdmact_port, JCHDCTxtbl[offset][idx]);
+               out_be32(mcrcst_port, JCSTWTxtbl[offset][idx]);
+               out_be32(tdvhsel_port,
+                        (in_be32(tdvhsel_port) & ~TDVHSEL_MASTER) | JCACTSELtbl[offset][idx]);
+       }
+       out_be32(udenvt_port,
+                JCTSStbl[offset][idx] << 16 | JCENVTtbl[offset][idx]);
+}
+
+/**
+ *     scc_tf_load - send taskfile registers to host controller
+ *     @ap: Port to which output is sent
+ *     @tf: ATA taskfile register set
+ *
+ *     Note: Original code is ata_tf_load().
+ */
+
+static void scc_tf_load (struct ata_port *ap, const struct ata_taskfile *tf)
+{
+       struct ata_ioports *ioaddr = &ap->ioaddr;
+       unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+
+       if (tf->ctl != ap->last_ctl) {
+               out_be32(ioaddr->ctl_addr, tf->ctl);
+               ap->last_ctl = tf->ctl;
+               ata_wait_idle(ap);
+       }
+
+       if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
+               out_be32(ioaddr->feature_addr, tf->hob_feature);
+               out_be32(ioaddr->nsect_addr, tf->hob_nsect);
+               out_be32(ioaddr->lbal_addr, tf->hob_lbal);
+               out_be32(ioaddr->lbam_addr, tf->hob_lbam);
+               out_be32(ioaddr->lbah_addr, tf->hob_lbah);
+               VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
+                       tf->hob_feature,
+                       tf->hob_nsect,
+                       tf->hob_lbal,
+                       tf->hob_lbam,
+                       tf->hob_lbah);
+       }
+
+       if (is_addr) {
+               out_be32(ioaddr->feature_addr, tf->feature);
+               out_be32(ioaddr->nsect_addr, tf->nsect);
+               out_be32(ioaddr->lbal_addr, tf->lbal);
+               out_be32(ioaddr->lbam_addr, tf->lbam);
+               out_be32(ioaddr->lbah_addr, tf->lbah);
+               VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
+                       tf->feature,
+                       tf->nsect,
+                       tf->lbal,
+                       tf->lbam,
+                       tf->lbah);
+       }
+
+       if (tf->flags & ATA_TFLAG_DEVICE) {
+               out_be32(ioaddr->device_addr, tf->device);
+               VPRINTK("device 0x%X\n", tf->device);
+       }
+
+       ata_wait_idle(ap);
+}
+
+/**
+ *     scc_check_status - Read device status reg & clear interrupt
+ *     @ap: port where the device is
+ *
+ *     Note: Original code is ata_check_status().
+ */
+
+static u8 scc_check_status (struct ata_port *ap)
+{
+       return in_be32(ap->ioaddr.status_addr);
+}
+
+/**
+ *     scc_tf_read - input device's ATA taskfile shadow registers
+ *     @ap: Port from which input is read
+ *     @tf: ATA taskfile register set for storing input
+ *
+ *     Note: Original code is ata_tf_read().
+ */
+
+static void scc_tf_read (struct ata_port *ap, struct ata_taskfile *tf)
+{
+       struct ata_ioports *ioaddr = &ap->ioaddr;
+
+       tf->command = scc_check_status(ap);
+       tf->feature = in_be32(ioaddr->error_addr);
+       tf->nsect = in_be32(ioaddr->nsect_addr);
+       tf->lbal = in_be32(ioaddr->lbal_addr);
+       tf->lbam = in_be32(ioaddr->lbam_addr);
+       tf->lbah = in_be32(ioaddr->lbah_addr);
+       tf->device = in_be32(ioaddr->device_addr);
+
+       if (tf->flags & ATA_TFLAG_LBA48) {
+               out_be32(ioaddr->ctl_addr, tf->ctl | ATA_HOB);
+               tf->hob_feature = in_be32(ioaddr->error_addr);
+               tf->hob_nsect = in_be32(ioaddr->nsect_addr);
+               tf->hob_lbal = in_be32(ioaddr->lbal_addr);
+               tf->hob_lbam = in_be32(ioaddr->lbam_addr);
+               tf->hob_lbah = in_be32(ioaddr->lbah_addr);
+       }
+}
+
+/**
+ *     scc_exec_command - issue ATA command to host controller
+ *     @ap: port to which command is being issued
+ *     @tf: ATA taskfile register set
+ *
+ *     Note: Original code is ata_exec_command().
+ */
+
+static void scc_exec_command (struct ata_port *ap,
+                             const struct ata_taskfile *tf)
+{
+       DPRINTK("ata%u: cmd 0x%X\n", ap->print_id, tf->command);
+
+       out_be32(ap->ioaddr.command_addr, tf->command);
+       ata_pause(ap);
+}
+
+/**
+ *     scc_check_altstatus - Read device alternate status reg
+ *     @ap: port where the device is
+ */
+
+static u8 scc_check_altstatus (struct ata_port *ap)
+{
+       return in_be32(ap->ioaddr.altstatus_addr);
+}
+
+/**
+ *     scc_std_dev_select - Select device 0/1 on ATA bus
+ *     @ap: ATA channel to manipulate
+ *     @device: ATA device (numbered from zero) to select
+ *
+ *     Note: Original code is ata_std_dev_select().
+ */
+
+static void scc_std_dev_select (struct ata_port *ap, unsigned int device)
+{
+       u8 tmp;
+
+       if (device == 0)
+               tmp = ATA_DEVICE_OBS;
+       else
+               tmp = ATA_DEVICE_OBS | ATA_DEV1;
+
+       out_be32(ap->ioaddr.device_addr, tmp);
+       ata_pause(ap);
+}
+
+/**
+ *     scc_bmdma_setup - Set up PCI IDE BMDMA transaction
+ *     @qc: Info associated with this ATA transaction.
+ *
+ *     Note: Original code is ata_bmdma_setup().
+ */
+
+static void scc_bmdma_setup (struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
+       u8 dmactl;
+       void __iomem *mmio = ap->ioaddr.bmdma_addr;
+
+       /* load PRD table addr */
+       out_be32(mmio + SCC_DMA_TABLE_OFS, ap->prd_dma);
+
+       /* specify data direction, triple-check start bit is clear */
+       dmactl = in_be32(mmio + SCC_DMA_CMD);
+       dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
+       if (!rw)
+               dmactl |= ATA_DMA_WR;
+       out_be32(mmio + SCC_DMA_CMD, dmactl);
+
+       /* issue r/w command */
+       ap->ops->exec_command(ap, &qc->tf);
+}
+
+/**
+ *     scc_bmdma_start - Start a PCI IDE BMDMA transaction
+ *     @qc: Info associated with this ATA transaction.
+ *
+ *     Note: Original code is ata_bmdma_start().
+ */
+
+static void scc_bmdma_start (struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       u8 dmactl;
+       void __iomem *mmio = ap->ioaddr.bmdma_addr;
+
+       /* start host DMA transaction */
+       dmactl = in_be32(mmio + SCC_DMA_CMD);
+       out_be32(mmio + SCC_DMA_CMD, dmactl | ATA_DMA_START);
+}
+
+/**
+ *     scc_devchk - PATA device presence detection
+ *     @ap: ATA channel to examine
+ *     @device: Device to examine (starting at zero)
+ *
+ *     Note: Original code is ata_devchk().
+ */
+
+static unsigned int scc_devchk (struct ata_port *ap,
+                               unsigned int device)
+{
+       struct ata_ioports *ioaddr = &ap->ioaddr;
+       u8 nsect, lbal;
+
+       ap->ops->dev_select(ap, device);
+
+       out_be32(ioaddr->nsect_addr, 0x55);
+       out_be32(ioaddr->lbal_addr, 0xaa);
+
+       out_be32(ioaddr->nsect_addr, 0xaa);
+       out_be32(ioaddr->lbal_addr, 0x55);
+
+       out_be32(ioaddr->nsect_addr, 0x55);
+       out_be32(ioaddr->lbal_addr, 0xaa);
+
+       nsect = in_be32(ioaddr->nsect_addr);
+       lbal = in_be32(ioaddr->lbal_addr);
+
+       if ((nsect == 0x55) && (lbal == 0xaa))
+               return 1;       /* we found a device */
+
+       return 0;               /* nothing found */
+}
+
+/**
+ *     scc_bus_post_reset - PATA device post reset
+ *
+ *     Note: Original code is ata_bus_post_reset().
+ */
+
+static void scc_bus_post_reset (struct ata_port *ap, unsigned int devmask)
+{
+       struct ata_ioports *ioaddr = &ap->ioaddr;
+       unsigned int dev0 = devmask & (1 << 0);
+       unsigned int dev1 = devmask & (1 << 1);
+       unsigned long timeout;
+
+       /* if device 0 was found in ata_devchk, wait for its
+        * BSY bit to clear
+        */
+       if (dev0)
+               ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+
+       /* if device 1 was found in ata_devchk, wait for
+        * register access, then wait for BSY to clear
+        */
+       timeout = jiffies + ATA_TMOUT_BOOT;
+       while (dev1) {
+               u8 nsect, lbal;
+
+               ap->ops->dev_select(ap, 1);
+               nsect = in_be32(ioaddr->nsect_addr);
+               lbal = in_be32(ioaddr->lbal_addr);
+               if ((nsect == 1) && (lbal == 1))
+                       break;
+               if (time_after(jiffies, timeout)) {
+                       dev1 = 0;
+                       break;
+               }
+               msleep(50);     /* give drive a breather */
+       }
+       if (dev1)
+               ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+
+       /* is all this really necessary? */
+       ap->ops->dev_select(ap, 0);
+       if (dev1)
+               ap->ops->dev_select(ap, 1);
+       if (dev0)
+               ap->ops->dev_select(ap, 0);
+}
+
+/**
+ *     scc_bus_softreset - PATA device software reset
+ *
+ *     Note: Original code is ata_bus_softreset().
+ */
+
+static unsigned int scc_bus_softreset (struct ata_port *ap,
+                                      unsigned int devmask)
+{
+       struct ata_ioports *ioaddr = &ap->ioaddr;
+
+       DPRINTK("ata%u: bus reset via SRST\n", ap->print_id);
+
+       /* software reset.  causes dev0 to be selected */
+       out_be32(ioaddr->ctl_addr, ap->ctl);
+       udelay(20);
+       out_be32(ioaddr->ctl_addr, ap->ctl | ATA_SRST);
+       udelay(20);
+       out_be32(ioaddr->ctl_addr, ap->ctl);
+
+       /* spec mandates ">= 2ms" before checking status.
+        * We wait 150ms, because that was the magic delay used for
+        * ATAPI devices in Hale Landis's ATADRVR, for the period of time
+        * between when the ATA command register is written, and then
+        * status is checked.  Because waiting for "a while" before
+        * checking status is fine, post SRST, we perform this magic
+        * delay here as well.
+        *
+        * Old drivers/ide uses the 2mS rule and then waits for ready
+        */
+       msleep(150);
+
+       /* Before we perform post reset processing we want to see if
+        * the bus shows 0xFF because the odd clown forgets the D7
+        * pulldown resistor.
+        */
+       if (scc_check_status(ap) == 0xFF)
+               return 0;
+
+       scc_bus_post_reset(ap, devmask);
+
+       return 0;
+}
+
+/**
+ *     scc_std_softreset - reset host port via ATA SRST
+ *     @ap: port to reset
+ *     @classes: resulting classes of attached devices
+ *
+ *     Note: Original code is ata_std_softreset().
+ */
+
+static int scc_std_softreset (struct ata_port *ap, unsigned int *classes)
+{
+       unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
+       unsigned int devmask = 0, err_mask;
+       u8 err;
+
+       DPRINTK("ENTER\n");
+
+       if (ata_port_offline(ap)) {
+               classes[0] = ATA_DEV_NONE;
+               goto out;
+       }
+
+       /* determine if device 0/1 are present */
+       if (scc_devchk(ap, 0))
+               devmask |= (1 << 0);
+       if (slave_possible && scc_devchk(ap, 1))
+               devmask |= (1 << 1);
+
+       /* select device 0 again */
+       ap->ops->dev_select(ap, 0);
+
+       /* issue bus reset */
+       DPRINTK("about to softreset, devmask=%x\n", devmask);
+       err_mask = scc_bus_softreset(ap, devmask);
+       if (err_mask) {
+               ata_port_printk(ap, KERN_ERR, "SRST failed (err_mask=0x%x)\n",
+                               err_mask);
+               return -EIO;
+       }
+
+       /* determine by signature whether we have ATA or ATAPI devices */
+       classes[0] = ata_dev_try_classify(ap, 0, &err);
+       if (slave_possible && err != 0x81)
+               classes[1] = ata_dev_try_classify(ap, 1, &err);
+
+ out:
+       DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
+       return 0;
+}
+
+/**
+ *     scc_bmdma_stop - Stop PCI IDE BMDMA transfer
+ *     @qc: Command we are ending DMA for
+ */
+
+static void scc_bmdma_stop (struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       void __iomem *ctrl_base = ap->host->iomap[SCC_CTRL_BAR];
+       void __iomem *bmid_base = ap->host->iomap[SCC_BMID_BAR];
+       u32 reg;
+
+       while (1) {
+               reg = in_be32(bmid_base + SCC_DMA_INTST);
+
+               if (reg & INTSTS_SERROR) {
+                       printk(KERN_WARNING "%s: SERROR\n", DRV_NAME);
+                       out_be32(bmid_base + SCC_DMA_INTST, INTSTS_SERROR|INTSTS_BMSINT);
+                       out_be32(bmid_base + SCC_DMA_CMD,
+                                in_be32(bmid_base + SCC_DMA_CMD) & ~ATA_DMA_START);
+                       continue;
+               }
+
+               if (reg & INTSTS_PRERR) {
+                       u32 maea0, maec0;
+                       maea0 = in_be32(ctrl_base + SCC_CTL_MAEA0);
+                       maec0 = in_be32(ctrl_base + SCC_CTL_MAEC0);
+                       printk(KERN_WARNING "%s: PRERR [addr:%x cmd:%x]\n", DRV_NAME, maea0, maec0);
+                       out_be32(bmid_base + SCC_DMA_INTST, INTSTS_PRERR|INTSTS_BMSINT);
+                       out_be32(bmid_base + SCC_DMA_CMD,
+                                in_be32(bmid_base + SCC_DMA_CMD) & ~ATA_DMA_START);
+                       continue;
+               }
+
+               if (reg & INTSTS_RERR) {
+                       printk(KERN_WARNING "%s: Response Error\n", DRV_NAME);
+                       out_be32(bmid_base + SCC_DMA_INTST, INTSTS_RERR|INTSTS_BMSINT);
+                       out_be32(bmid_base + SCC_DMA_CMD,
+                                in_be32(bmid_base + SCC_DMA_CMD) & ~ATA_DMA_START);
+                       continue;
+               }
+
+               if (reg & INTSTS_ICERR) {
+                       out_be32(bmid_base + SCC_DMA_CMD,
+                                in_be32(bmid_base + SCC_DMA_CMD) & ~ATA_DMA_START);
+                       printk(KERN_WARNING "%s: Illegal Configuration\n", DRV_NAME);
+                       out_be32(bmid_base + SCC_DMA_INTST, INTSTS_ICERR|INTSTS_BMSINT);
+                       continue;
+               }
+
+               if (reg & INTSTS_BMSINT) {
+                       unsigned int classes;
+                       printk(KERN_WARNING "%s: Internal Bus Error\n", DRV_NAME);
+                       out_be32(bmid_base + SCC_DMA_INTST, INTSTS_BMSINT);
+                       /* TBD: SW reset */
+                       scc_std_softreset(ap, &classes);
+                       continue;
+               }
+
+               if (reg & INTSTS_BMHE) {
+                       out_be32(bmid_base + SCC_DMA_INTST, INTSTS_BMHE);
+                       continue;
+               }
+
+               if (reg & INTSTS_ACTEINT) {
+                       out_be32(bmid_base + SCC_DMA_INTST, INTSTS_ACTEINT);
+                       continue;
+               }
+
+               if (reg & INTSTS_IOIRQS) {
+                       out_be32(bmid_base + SCC_DMA_INTST, INTSTS_IOIRQS);
+                       continue;
+               }
+               break;
+       }
+
+       /* clear start/stop bit */
+       out_be32(bmid_base + SCC_DMA_CMD,
+                in_be32(bmid_base + SCC_DMA_CMD) & ~ATA_DMA_START);
+
+       /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
+       ata_altstatus(ap);      /* dummy read */
+}
+
+/**
+ *     scc_bmdma_status - Read PCI IDE BMDMA status
+ *     @ap: Port associated with this ATA transaction.
+ */
+
+static u8 scc_bmdma_status (struct ata_port *ap)
+{
+       u8 host_stat;
+       void __iomem *mmio = ap->ioaddr.bmdma_addr;
+
+       host_stat = in_be32(mmio + SCC_DMA_STATUS);
+
+       /* Workaround for PTERADD: emulate DMA_INTR when
+        * - IDE_STATUS[ERR] = 1
+        * - INT_STATUS[INTRQ] = 1
+        * - DMA_STATUS[IORACTA] = 1
+        */
+       if (!(host_stat & ATA_DMA_INTR)) {
+               u32 int_status = in_be32(mmio + SCC_DMA_INTST);
+               if (ata_altstatus(ap) & ATA_ERR &&
+                   int_status & INTSTS_INTRQ &&
+                   host_stat & ATA_DMA_ACTIVE)
+                       host_stat |= ATA_DMA_INTR;
+       }
+
+       return host_stat;
+}
+
+/**
+ *     scc_data_xfer - Transfer data by PIO
+ *     @adev: device for this I/O
+ *     @buf: data buffer
+ *     @buflen: buffer length
+ *     @write_data: read/write
+ *
+ *     Note: Original code is ata_data_xfer().
+ */
+
+static void scc_data_xfer (struct ata_device *adev, unsigned char *buf,
+                          unsigned int buflen, int write_data)
+{
+       struct ata_port *ap = adev->ap;
+       unsigned int words = buflen >> 1;
+       unsigned int i;
+       u16 *buf16 = (u16 *) buf;
+       void __iomem *mmio = ap->ioaddr.data_addr;
+
+       /* Transfer multiple of 2 bytes */
+       if (write_data) {
+               for (i = 0; i < words; i++)
+                       out_be32(mmio, cpu_to_le16(buf16[i]));
+       } else {
+               for (i = 0; i < words; i++)
+                       buf16[i] = le16_to_cpu(in_be32(mmio));
+       }
+
+       /* Transfer trailing 1 byte, if any. */
+       if (unlikely(buflen & 0x01)) {
+               u16 align_buf[1] = { 0 };
+               unsigned char *trailing_buf = buf + buflen - 1;
+
+               if (write_data) {
+                       memcpy(align_buf, trailing_buf, 1);
+                       out_be32(mmio, cpu_to_le16(align_buf[0]));
+               } else {
+                       align_buf[0] = le16_to_cpu(in_be32(mmio));
+                       memcpy(trailing_buf, align_buf, 1);
+               }
+       }
+}
+
+/**
+ *     scc_irq_on - Enable interrupts on a port.
+ *     @ap: Port on which interrupts are enabled.
+ *
+ *     Note: Original code is ata_irq_on().
+ */
+
+static u8 scc_irq_on (struct ata_port *ap)
+{
+       struct ata_ioports *ioaddr = &ap->ioaddr;
+       u8 tmp;
+
+       ap->ctl &= ~ATA_NIEN;
+       ap->last_ctl = ap->ctl;
+
+       out_be32(ioaddr->ctl_addr, ap->ctl);
+       tmp = ata_wait_idle(ap);
+
+       ap->ops->irq_clear(ap);
+
+       return tmp;
+}
+
+/**
+ *     scc_irq_ack - Acknowledge a device interrupt.
+ *     @ap: Port on which interrupts are enabled.
+ *
+ *     Note: Original code is ata_irq_ack().
+ */
+
+static u8 scc_irq_ack (struct ata_port *ap, unsigned int chk_drq)
+{
+       unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY;
+       u8 host_stat, post_stat, status;
+
+       status = ata_busy_wait(ap, bits, 1000);
+       if (status & bits)
+               if (ata_msg_err(ap))
+                       printk(KERN_ERR "abnormal status 0x%X\n", status);
+
+       /* get controller status; clear intr, err bits */
+       host_stat = in_be32(ap->ioaddr.bmdma_addr + SCC_DMA_STATUS);
+       out_be32(ap->ioaddr.bmdma_addr + SCC_DMA_STATUS,
+                host_stat | ATA_DMA_INTR | ATA_DMA_ERR);
+
+       post_stat = in_be32(ap->ioaddr.bmdma_addr + SCC_DMA_STATUS);
+
+       if (ata_msg_intr(ap))
+               printk(KERN_INFO "%s: irq ack: host_stat 0x%X, new host_stat 0x%X, drv_stat 0x%X\n",
+                      __FUNCTION__,
+                      host_stat, post_stat, status);
+
+       return status;
+}
+
+/**
+ *     scc_bmdma_freeze - Freeze BMDMA controller port
+ *     @ap: port to freeze
+ *
+ *     Note: Original code is ata_bmdma_freeze().
+ */
+
+static void scc_bmdma_freeze (struct ata_port *ap)
+{
+       struct ata_ioports *ioaddr = &ap->ioaddr;
+
+       ap->ctl |= ATA_NIEN;
+       ap->last_ctl = ap->ctl;
+
+       out_be32(ioaddr->ctl_addr, ap->ctl);
+
+       /* Under certain circumstances, some controllers raise IRQ on
+        * ATA_NIEN manipulation.  Also, many controllers fail to mask
+        * previously pending IRQ on ATA_NIEN assertion.  Clear it.
+        */
+       ata_chk_status(ap);
+
+       ap->ops->irq_clear(ap);
+}
+
+/**
+ *     scc_pata_prereset - prepare for reset
+ *     @ap: ATA port to be reset
+ */
+
+static int scc_pata_prereset (struct ata_port *ap)
+{
+       ap->cbl = ATA_CBL_PATA80;
+       return ata_std_prereset(ap);
+}
+
+/**
+ *     scc_std_postreset - standard postreset callback
+ *     @ap: the target ata_port
+ *     @classes: classes of attached devices
+ *
+ *     Note: Original code is ata_std_postreset().
+ */
+
+static void scc_std_postreset (struct ata_port *ap, unsigned int *classes)
+{
+       DPRINTK("ENTER\n");
+
+       /* re-enable interrupts */
+       if (!ap->ops->error_handler)
+               ap->ops->irq_on(ap);
+
+       /* is double-select really necessary? */
+       if (classes[0] != ATA_DEV_NONE)
+               ap->ops->dev_select(ap, 1);
+       if (classes[1] != ATA_DEV_NONE)
+               ap->ops->dev_select(ap, 0);
+
+       /* bail out if no device is present */
+       if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
+               DPRINTK("EXIT, no device\n");
+               return;
+       }
+
+       /* set up device control */
+       if (ap->ioaddr.ctl_addr)
+               out_be32(ap->ioaddr.ctl_addr, ap->ctl);
+
+       DPRINTK("EXIT\n");
+}
+
+/**
+ *     scc_error_handler - Stock error handler for BMDMA controller
+ *     @ap: port to handle error for
+ */
+
+static void scc_error_handler (struct ata_port *ap)
+{
+       ata_bmdma_drive_eh(ap, scc_pata_prereset, scc_std_softreset, NULL,
+                          scc_std_postreset);
+}
+
+/**
+ *     scc_bmdma_irq_clear - Clear PCI IDE BMDMA interrupt.
+ *     @ap: Port associated with this ATA transaction.
+ *
+ *     Note: Original code is ata_bmdma_irq_clear().
+ */
+
+static void scc_bmdma_irq_clear (struct ata_port *ap)
+{
+       void __iomem *mmio = ap->ioaddr.bmdma_addr;
+
+       if (!mmio)
+               return;
+
+       out_be32(mmio + SCC_DMA_STATUS, in_be32(mmio + SCC_DMA_STATUS));
+}
+
+/**
+ *     scc_port_start - Set port up for dma.
+ *     @ap: Port to initialize
+ *
+ *     Allocate space for PRD table using ata_port_start().
+ *     Set PRD table address for PTERADD. (PRD Transfer End Read)
+ */
+
+static int scc_port_start (struct ata_port *ap)
+{
+       void __iomem *mmio = ap->ioaddr.bmdma_addr;
+       int rc;
+
+       rc = ata_port_start(ap);
+       if (rc)
+               return rc;
+
+       out_be32(mmio + SCC_DMA_PTERADD, ap->prd_dma);
+       return 0;
+}
+
+/**
+ *     scc_port_stop - Undo scc_port_start()
+ *     @ap: Port to shut down
+ *
+ *     Reset PTERADD.
+ */
+
+static void scc_port_stop (struct ata_port *ap)
+{
+       void __iomem *mmio = ap->ioaddr.bmdma_addr;
+
+       out_be32(mmio + SCC_DMA_PTERADD, 0);
+}
+
+static struct scsi_host_template scc_sht = {
+       .module                 = THIS_MODULE,
+       .name                   = DRV_NAME,
+       .ioctl                  = ata_scsi_ioctl,
+       .queuecommand           = ata_scsi_queuecmd,
+       .can_queue              = ATA_DEF_QUEUE,
+       .this_id                = ATA_SHT_THIS_ID,
+       .sg_tablesize           = LIBATA_MAX_PRD,
+       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
+       .emulated               = ATA_SHT_EMULATED,
+       .use_clustering         = ATA_SHT_USE_CLUSTERING,
+       .proc_name              = DRV_NAME,
+       .dma_boundary           = ATA_DMA_BOUNDARY,
+       .slave_configure        = ata_scsi_slave_config,
+       .slave_destroy          = ata_scsi_slave_destroy,
+       .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
+       .resume                 = ata_scsi_device_resume,
+       .suspend                = ata_scsi_device_suspend,
+#endif
+};
+
+static const struct ata_port_operations scc_pata_ops = {
+       .port_disable           = ata_port_disable,
+       .set_piomode            = scc_set_piomode,
+       .set_dmamode            = scc_set_dmamode,
+       .mode_filter            = ata_pci_default_filter,
+
+       .tf_load                = scc_tf_load,
+       .tf_read                = scc_tf_read,
+       .exec_command           = scc_exec_command,
+       .check_status           = scc_check_status,
+       .check_altstatus        = scc_check_altstatus,
+       .dev_select             = scc_std_dev_select,
+
+       .bmdma_setup            = scc_bmdma_setup,
+       .bmdma_start            = scc_bmdma_start,
+       .bmdma_stop             = scc_bmdma_stop,
+       .bmdma_status           = scc_bmdma_status,
+       .data_xfer              = scc_data_xfer,
+
+       .qc_prep                = ata_qc_prep,
+       .qc_issue               = ata_qc_issue_prot,
+
+       .freeze                 = scc_bmdma_freeze,
+       .error_handler          = scc_error_handler,
+       .post_internal_cmd      = scc_bmdma_stop,
+
+       .irq_handler            = ata_interrupt,
+       .irq_clear              = scc_bmdma_irq_clear,
+       .irq_on                 = scc_irq_on,
+       .irq_ack                = scc_irq_ack,
+
+       .port_start             = scc_port_start,
+       .port_stop              = scc_port_stop,
+};
+
+static struct ata_port_info scc_port_info[] = {
+       {
+               .sht            = &scc_sht,
+               .flags          = ATA_FLAG_SLAVE_POSS | ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY,
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .mwdma_mask     = 0x00,
+               .udma_mask      = ATA_UDMA6,
+               .port_ops       = &scc_pata_ops,
+       },
+};
+
+/**
+ *     scc_reset_controller - initialize SCC PATA controller.
+ */
+
+static int scc_reset_controller(struct ata_probe_ent *probe_ent)
+{
+       void __iomem *ctrl_base = probe_ent->iomap[SCC_CTRL_BAR];
+       void __iomem *bmid_base = probe_ent->iomap[SCC_BMID_BAR];
+       void __iomem *cckctrl_port = ctrl_base + SCC_CTL_CCKCTRL;
+       void __iomem *mode_port = ctrl_base + SCC_CTL_MODEREG;
+       void __iomem *ecmode_port = ctrl_base + SCC_CTL_ECMODE;
+       void __iomem *intmask_port = bmid_base + SCC_DMA_INTMASK;
+       void __iomem *dmastatus_port = bmid_base + SCC_DMA_STATUS;
+       u32 reg = 0;
+
+       out_be32(cckctrl_port, reg);
+       reg |= CCKCTRL_ATACLKOEN;
+       out_be32(cckctrl_port, reg);
+       reg |= CCKCTRL_LCLKEN | CCKCTRL_OCLKEN;
+       out_be32(cckctrl_port, reg);
+       reg |= CCKCTRL_CRST;
+       out_be32(cckctrl_port, reg);
+
+       for (;;) {
+               reg = in_be32(cckctrl_port);
+               if (reg & CCKCTRL_CRST)
+                       break;
+               udelay(5000);
+       }
+
+       reg |= CCKCTRL_ATARESET;
+       out_be32(cckctrl_port, reg);
+       out_be32(ecmode_port, ECMODE_VALUE);
+       out_be32(mode_port, MODE_JCUSFEN);
+       out_be32(intmask_port, INTMASK_MSK);
+
+       if (in_be32(dmastatus_port) & QCHSD_STPDIAG) {
+               printk(KERN_WARNING "%s: failed to detect 80c cable. (PDIAG# is high)\n", DRV_NAME);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+/**
+ *     scc_setup_ports - initialize ioaddr with SCC PATA port offsets.
+ *     @ioaddr: IO address structure to be initialized
+ *     @base: base address of BMID region
+ */
+
+static void scc_setup_ports (struct ata_ioports *ioaddr, void __iomem *base)
+{
+       ioaddr->cmd_addr = base + SCC_REG_CMD_ADDR;
+       ioaddr->altstatus_addr = ioaddr->cmd_addr + SCC_REG_ALTSTATUS;
+       ioaddr->ctl_addr = ioaddr->cmd_addr + SCC_REG_ALTSTATUS;
+       ioaddr->bmdma_addr = base;
+       ioaddr->data_addr = ioaddr->cmd_addr + SCC_REG_DATA;
+       ioaddr->error_addr = ioaddr->cmd_addr + SCC_REG_ERR;
+       ioaddr->feature_addr = ioaddr->cmd_addr + SCC_REG_FEATURE;
+       ioaddr->nsect_addr = ioaddr->cmd_addr + SCC_REG_NSECT;
+       ioaddr->lbal_addr = ioaddr->cmd_addr + SCC_REG_LBAL;
+       ioaddr->lbam_addr = ioaddr->cmd_addr + SCC_REG_LBAM;
+       ioaddr->lbah_addr = ioaddr->cmd_addr + SCC_REG_LBAH;
+       ioaddr->device_addr = ioaddr->cmd_addr + SCC_REG_DEVICE;
+       ioaddr->status_addr = ioaddr->cmd_addr + SCC_REG_STATUS;
+       ioaddr->command_addr = ioaddr->cmd_addr + SCC_REG_CMD;
+}
+
+static int scc_host_init(struct ata_probe_ent *probe_ent)
+{
+       struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
+       int rc;
+
+       rc = scc_reset_controller(probe_ent);
+       if (rc)
+               return rc;
+
+       probe_ent->n_ports = 1;
+
+       rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+       if (rc)
+               return rc;
+       rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
+       if (rc)
+               return rc;
+
+       scc_setup_ports(&probe_ent->port[0], probe_ent->iomap[SCC_BMID_BAR]);
+
+       pci_set_master(pdev);
+
+       return 0;
+}
+
+/**
+ *     scc_init_one - Register SCC PATA device with kernel services
+ *     @pdev: PCI device to register
+ *     @ent: Entry in scc_pci_tbl matching with @pdev
+ *
+ *     LOCKING:
+ *     Inherited from PCI layer (may sleep).
+ *
+ *     RETURNS:
+ *     Zero on success, or -ERRNO value.
+ */
+
+static int scc_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       static int printed_version;
+       unsigned int board_idx = (unsigned int) ent->driver_data;
+       struct device *dev = &pdev->dev;
+       struct ata_probe_ent *probe_ent;
+       int rc;
+
+       if (!printed_version++)
+               dev_printk(KERN_DEBUG, &pdev->dev,
+                          "version " DRV_VERSION "\n");
+
+       rc = pcim_enable_device(pdev);
+       if (rc)
+               return rc;
+
+       rc = pcim_iomap_regions(pdev, (1 << SCC_CTRL_BAR) | (1 << SCC_BMID_BAR), DRV_NAME);
+       if (rc == -EBUSY)
+               pcim_pin_device(pdev);
+       if (rc)
+               return rc;
+
+       probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL);
+       if (!probe_ent)
+               return -ENOMEM;
+
+       probe_ent->dev = dev;
+       INIT_LIST_HEAD(&probe_ent->node);
+
+       probe_ent->sht          = scc_port_info[board_idx].sht;
+       probe_ent->port_flags   = scc_port_info[board_idx].flags;
+       probe_ent->pio_mask     = scc_port_info[board_idx].pio_mask;
+       probe_ent->udma_mask    = scc_port_info[board_idx].udma_mask;
+       probe_ent->port_ops     = scc_port_info[board_idx].port_ops;
+
+       probe_ent->irq = pdev->irq;
+       probe_ent->irq_flags = IRQF_SHARED;
+       probe_ent->iomap = pcim_iomap_table(pdev);
+
+       rc = scc_host_init(probe_ent);
+       if (rc)
+               return rc;
+
+       if (!ata_device_add(probe_ent))
+               return -ENODEV;
+
+       devm_kfree(dev, probe_ent);
+       return 0;
+}
+
+static struct pci_driver scc_pci_driver = {
+       .name                   = DRV_NAME,
+       .id_table               = scc_pci_tbl,
+       .probe                  = scc_init_one,
+       .remove                 = ata_pci_remove_one,
+#ifdef CONFIG_PM
+       .suspend                = ata_pci_device_suspend,
+       .resume                 = ata_pci_device_resume,
+#endif
+};
+
+static int __init scc_init (void)
+{
+       int rc;
+
+       DPRINTK("pci_register_driver\n");
+       rc = pci_register_driver(&scc_pci_driver);
+       if (rc)
+               return rc;
+
+       DPRINTK("done\n");
+       return 0;
+}
+
+static void __exit scc_exit (void)
+{
+       pci_unregister_driver(&scc_pci_driver);
+}
+
+module_init(scc_init);
+module_exit(scc_exit);
+
+MODULE_AUTHOR("Toshiba corp");
+MODULE_DESCRIPTION("SCSI low-level driver for Toshiba SCC PATA controller");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, scc_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
index ad5b43fef3d1a94914d090fc88476ed100a0e2a1..598eef810a74ab605001bb48e1191d42b7a99e4a 100644 (file)
@@ -41,7 +41,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_serverworks"
-#define DRV_VERSION "0.3.9"
+#define DRV_VERSION "0.4.0"
 
 #define SVWKS_CSB5_REVISION_NEW        0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */
 #define SVWKS_CSB6_REVISION    0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */
@@ -319,8 +319,10 @@ static struct scsi_host_template serverworks_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static struct ata_port_operations serverworks_osb4_port_ops = {
@@ -548,6 +550,7 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id
        return ata_pci_init_one(pdev, port_info, ports);
 }
 
+#ifdef CONFIG_PM
 static int serverworks_reinit_one(struct pci_dev *pdev)
 {
        /* Force master latency timer to 64 PCI clocks */
@@ -571,6 +574,7 @@ static int serverworks_reinit_one(struct pci_dev *pdev)
        }
        return ata_pci_device_resume(pdev);
 }
+#endif
 
 static const struct pci_device_id serverworks[] = {
        { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE), 0},
@@ -587,8 +591,10 @@ static struct pci_driver serverworks_pci_driver = {
        .id_table       = serverworks,
        .probe          = serverworks_init_one,
        .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend        = ata_pci_device_suspend,
        .resume         = serverworks_reinit_one,
+#endif
 };
 
 static int __init serverworks_init(void)
index ed79fabe025c1e5beed1811da7a447d07205f873..dab2889a556f4ab28305bfaf985f7cf7107c5f6a 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_sil680"
-#define DRV_VERSION "0.4.1"
+#define DRV_VERSION "0.4.5"
 
 /**
  *     sil680_selreg           -       return register base
@@ -139,10 +139,13 @@ static void sil680_set_piomode(struct ata_port *ap, struct ata_device *adev)
 
        unsigned long tfaddr = sil680_selreg(ap, 0x02);
        unsigned long addr = sil680_seldev(ap, adev, 0x04);
+       unsigned long addr_mask = 0x80 + 4 * ap->port_no;
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
        int pio = adev->pio_mode - XFER_PIO_0;
        int lowest_pio = pio;
+       int port_shift = 4 * adev->devno;
        u16 reg;
+       u8 mode;
 
        struct ata_device *pair = ata_dev_pair(adev);
 
@@ -153,10 +156,17 @@ static void sil680_set_piomode(struct ata_port *ap, struct ata_device *adev)
        pci_write_config_word(pdev, tfaddr, speed_t[lowest_pio]);
 
        pci_read_config_word(pdev, tfaddr-2, &reg);
+       pci_read_config_byte(pdev, addr_mask, &mode);
+
        reg &= ~0x0200;                 /* Clear IORDY */
-       if (ata_pio_need_iordy(adev))
+       mode &= ~(3 << port_shift);     /* Clear IORDY and DMA bits */
+
+       if (ata_pio_need_iordy(adev)) {
                reg |= 0x0200;          /* Enable IORDY */
+               mode |= 1 << port_shift;
+       }
        pci_write_config_word(pdev, tfaddr-2, reg);
+       pci_write_config_byte(pdev, addr_mask, mode);
 }
 
 /**
@@ -226,6 +236,10 @@ static struct scsi_host_template sil680_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
+       .suspend                = ata_scsi_device_suspend,
+       .resume                 = ata_scsi_device_resume,
+#endif
 };
 
 static struct ata_port_operations sil680_port_ops = {
@@ -367,11 +381,13 @@ static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        return ata_pci_init_one(pdev, port_info, 2);
 }
 
+#ifdef CONFIG_PM
 static int sil680_reinit_one(struct pci_dev *pdev)
 {
        sil680_init_chip(pdev);
        return ata_pci_device_resume(pdev);
 }
+#endif
 
 static const struct pci_device_id sil680[] = {
        { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680), },
@@ -384,8 +400,10 @@ static struct pci_driver sil680_pci_driver = {
        .id_table       = sil680,
        .probe          = sil680_init_one,
        .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend        = ata_pci_device_suspend,
        .resume         = sil680_reinit_one,
+#endif
 };
 
 static int __init sil680_init(void)
index 560103d55b2e9a09e784ea6882fc0d0fc5e7149a..f482078659309edb35c53b5a9ef6048f9a895130 100644 (file)
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
 #include <linux/ata.h>
-#include "libata.h"
+#include "sis.h"
 
-#undef DRV_NAME                /* already defined in libata.h, for libata-core */
 #define DRV_NAME       "pata_sis"
-#define DRV_VERSION    "0.4.5"
+#define DRV_VERSION    "0.5.0"
 
 struct sis_chipset {
        u16 device;                     /* PCI host ID */
@@ -151,7 +150,7 @@ static int sis_66_pre_reset(struct ata_port *ap)
 
        if (!pci_test_config_bits(pdev, &sis_enable_bits[ap->port_no])) {
                ata_port_disable(ap);
-               printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
+               ata_port_printk(ap, KERN_INFO, "port disabled. ignoring.\n");
                return 0;
        }
        /* Older chips keep cable detect in bits 4/5 of reg 0x48 */
@@ -197,7 +196,7 @@ static int sis_old_pre_reset(struct ata_port *ap)
 
        if (!pci_test_config_bits(pdev, &sis_enable_bits[ap->port_no])) {
                ata_port_disable(ap);
-               printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
+               ata_port_printk(ap, KERN_INFO, "port disabled. ignoring.\n");
                return 0;
        }
        ap->cbl = ATA_CBL_PATA40;
@@ -576,8 +575,10 @@ static struct scsi_host_template sis_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static const struct ata_port_operations sis_133_ops = {
@@ -1033,8 +1034,10 @@ static struct pci_driver sis_pci_driver = {
        .id_table               = sis_pci_tbl,
        .probe                  = sis_init_one,
        .remove                 = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend                = ata_pci_device_suspend,
        .resume                 = ata_pci_device_resume,
+#endif
 };
 
 static int __init sis_init(void)
index 96e890fd645b671247069881385de1c36d0abdb0..b681441cfcb96a96a17ed5492d6c985961427d07 100644 (file)
@@ -7,6 +7,13 @@
  *             SL82C105/Winbond 553 IDE driver
  *
  * and in part on the documentation and errata sheet
+ *
+ *
+ * Note: The controller like many controllers has shared timings for
+ * PIO and DMA. We thus flip to the DMA timings in dma_start and flip back
+ * in the dma_stop function. Thus we actually don't need a set_dmamode
+ * method as the PIO method is always called and will set the right PIO
+ * timing parameters.
  */
 
 #include <linux/kernel.h>
@@ -19,7 +26,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_sl82c105"
-#define DRV_VERSION "0.2.3"
+#define DRV_VERSION "0.3.0"
 
 enum {
        /*
@@ -125,33 +132,6 @@ static void sl82c105_configure_dmamode(struct ata_port *ap, struct ata_device *a
        pci_read_config_word(pdev, timing, &dummy);
 }
 
-/**
- *     sl82c105_set_dmamode    -       set initial DMA mode data
- *     @ap: ATA interface
- *     @adev: ATA device
- *
- *     Called to do the DMA mode setup. This replaces the PIO timings
- *     for the device in question. Set appropriate PIO timings not DMA
- *     timings at this point.
- */
-
-static void sl82c105_set_dmamode(struct ata_port *ap, struct ata_device *adev)
-{
-       switch(adev->dma_mode) {
-               case XFER_MW_DMA_0:
-                       sl82c105_configure_piomode(ap, adev, 0);
-                       break;
-               case XFER_MW_DMA_1:
-                       sl82c105_configure_piomode(ap, adev, 3);
-                       break;
-               case XFER_MW_DMA_2:
-                       sl82c105_configure_piomode(ap, adev, 4);
-                       break;
-               default:
-                       BUG();
-       }
-}
-
 /**
  *     sl82c105_reset_engine   -       Reset the DMA engine
  *     @ap: ATA interface
@@ -222,7 +202,7 @@ static void sl82c105_bmdma_stop(struct ata_queued_cmd *qc)
 
        /* This will redo the initial setup of the DMA device to matching
           PIO timings */
-       sl82c105_set_dmamode(ap, qc->dev);
+       sl82c105_set_piomode(ap, qc->dev);
 }
 
 static struct scsi_host_template sl82c105_sht = {
@@ -246,7 +226,6 @@ static struct scsi_host_template sl82c105_sht = {
 static struct ata_port_operations sl82c105_port_ops = {
        .port_disable   = ata_port_disable,
        .set_piomode    = sl82c105_set_piomode,
-       .set_dmamode    = sl82c105_set_dmamode,
        .mode_filter    = ata_pci_default_filter,
 
        .tf_load        = ata_tf_load,
@@ -255,7 +234,10 @@ static struct ata_port_operations sl82c105_port_ops = {
        .exec_command   = ata_exec_command,
        .dev_select     = ata_std_dev_select,
 
+       .freeze         = ata_bmdma_freeze,
+       .thaw           = ata_bmdma_thaw,
        .error_handler  = sl82c105_error_handler,
+       .post_internal_cmd = ata_bmdma_post_internal_cmd,
 
        .bmdma_setup    = ata_bmdma_setup,
        .bmdma_start    = sl82c105_bmdma_start,
index 453ab90b721e5576057ef77ee8a64cce6b1b09cc..71418f2a0cdb702408fde99a2203ddb1441106c9 100644 (file)
@@ -193,8 +193,10 @@ static struct scsi_host_template triflex_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static struct ata_port_operations triflex_port_ops = {
@@ -260,8 +262,10 @@ static struct pci_driver triflex_pci_driver = {
        .id_table       = triflex,
        .probe          = triflex_init_one,
        .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend        = ata_pci_device_suspend,
        .resume         = ata_pci_device_resume,
+#endif
 };
 
 static int __init triflex_init(void)
index 220fcd6c549296b82154b6f3d7b5a5da1953b337..946ade0e1f1b3e7a43a7a09ec5a2406afde85834 100644 (file)
@@ -170,7 +170,7 @@ static int via_pre_reset(struct ata_port *ap)
                ap->cbl = ATA_CBL_PATA40;
        else
                ap->cbl = ATA_CBL_PATA_UNK;
-               
+
 
        return ata_std_prereset(ap);
 }
@@ -305,8 +305,10 @@ static struct scsi_host_template via_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .resume                 = ata_scsi_device_resume,
        .suspend                = ata_scsi_device_suspend,
+#endif
 };
 
 static struct ata_port_operations via_port_ops = {
@@ -560,6 +562,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        return ata_pci_init_one(pdev, port_info, 2);
 }
 
+#ifdef CONFIG_PM
 /**
  *     via_reinit_one          -       reinit after resume
  *     @pdev; PCI device
@@ -592,6 +595,7 @@ static int via_reinit_one(struct pci_dev *pdev)
        }
        return ata_pci_device_resume(pdev);
 }
+#endif
 
 static const struct pci_device_id via[] = {
        { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C576_1), },
@@ -607,8 +611,10 @@ static struct pci_driver via_pci_driver = {
        .id_table       = via,
        .probe          = via_init_one,
        .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend        = ata_pci_device_suspend,
        .resume         = via_reinit_one,
+#endif
 };
 
 static int __init via_init(void)
index 0888b4f19f4c900467a158fa0d1bd6c03ad9210a..6c111035fc84da35b2ffa7e4bcf42fcb4951a960 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/platform_device.h>
 
 #define DRV_NAME "pata_winbond"
-#define DRV_VERSION "0.0.1"
+#define DRV_VERSION "0.0.2"
 
 #define NR_HOST 4      /* Two winbond controllers, two channels each */
 
index 857ac23217ab0895f095700b5db9c529a9f67fb5..5dd3ca8b5f29fb273303810d488c318d80ce7287 100644 (file)
@@ -44,7 +44,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "pdc_adma"
-#define DRV_VERSION    "0.04"
+#define DRV_VERSION    "0.05"
 
 /* macro to calculate base address for ATA regs */
 #define ADMA_ATA_REGS(base,port_no)    ((base) + ((port_no) * 0x40))
@@ -498,7 +498,7 @@ static inline unsigned int adma_intr_mmio(struct ata_host *host)
                                if ((status & ATA_BUSY))
                                        continue;
                                DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
-                                       ap->id, qc->tf.protocol, status);
+                                       ap->print_id, qc->tf.protocol, status);
 
                                /* complete taskfile transaction */
                                pp->state = adma_state_idle;
index 31b636fac98e6fa366dcc3f756d3b5e70a66ecb7..3193a603d1a159cb99b59e9f7bb705f765d28bda 100644 (file)
@@ -135,8 +135,10 @@ static struct scsi_host_template inic_sht = {
        .slave_configure        = inic_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .suspend                = ata_scsi_device_suspend,
        .resume                 = ata_scsi_device_resume,
+#endif
 };
 
 static const int scr_map[] = {
@@ -632,6 +634,7 @@ static int init_controller(void __iomem *mmio_base, u16 hctl)
        return 0;
 }
 
+#ifdef CONFIG_PM
 static int inic_pci_device_resume(struct pci_dev *pdev)
 {
        struct ata_host *host = dev_get_drvdata(&pdev->dev);
@@ -642,7 +645,6 @@ static int inic_pci_device_resume(struct pci_dev *pdev)
        ata_pci_device_do_resume(pdev);
 
        if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
-               printk("XXX\n");
                rc = init_controller(mmio_base, hpriv->cached_hctl);
                if (rc)
                        return rc;
@@ -652,6 +654,7 @@ static int inic_pci_device_resume(struct pci_dev *pdev)
 
        return 0;
 }
+#endif
 
 static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
@@ -755,8 +758,10 @@ static const struct pci_device_id inic_pci_tbl[] = {
 static struct pci_driver inic_pci_driver = {
        .name           = DRV_NAME,
        .id_table       = inic_pci_tbl,
+#ifdef CONFIG_PM
        .suspend        = ata_pci_device_suspend,
        .resume         = inic_pci_device_resume,
+#endif
        .probe          = inic_init_one,
        .remove         = ata_pci_remove_one,
 };
index d689df52eae3790a8027aaa21bc140bd3112d3ae..a65ba636aaa8eeb0ddb66b160f4a5749409c1106 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "sata_mv"
-#define DRV_VERSION    "0.7"
+#define DRV_VERSION    "0.8"
 
 enum {
        /* BAR's are enumerated in terms of pci_resource_start() terms */
@@ -137,14 +137,19 @@ enum {
        PCI_ERR                 = (1 << 18),
        TRAN_LO_DONE            = (1 << 19),    /* 6xxx: IRQ coalescing */
        TRAN_HI_DONE            = (1 << 20),    /* 6xxx: IRQ coalescing */
+       PORTS_0_3_COAL_DONE     = (1 << 8),
+       PORTS_4_7_COAL_DONE     = (1 << 17),
        PORTS_0_7_COAL_DONE     = (1 << 21),    /* 6xxx: IRQ coalescing */
        GPIO_INT                = (1 << 22),
        SELF_INT                = (1 << 23),
        TWSI_INT                = (1 << 24),
        HC_MAIN_RSVD            = (0x7f << 25), /* bits 31-25 */
+       HC_MAIN_RSVD_5          = (0x1fff << 19), /* bits 31-19 */
        HC_MAIN_MASKED_IRQS     = (TRAN_LO_DONE | TRAN_HI_DONE |
                                   PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT |
                                   HC_MAIN_RSVD),
+       HC_MAIN_MASKED_IRQS_5   = (PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE |
+                                  HC_MAIN_RSVD_5),
 
        /* SATAHC registers */
        HC_CFG_OFS              = 0,
@@ -814,23 +819,27 @@ static void mv_edma_cfg(struct mv_host_priv *hpriv, void __iomem *port_mmio)
        u32 cfg = readl(port_mmio + EDMA_CFG_OFS);
 
        /* set up non-NCQ EDMA configuration */
-       cfg &= ~0x1f;           /* clear queue depth */
-       cfg &= ~EDMA_CFG_NCQ;   /* clear NCQ mode */
        cfg &= ~(1 << 9);       /* disable equeue */
 
-       if (IS_GEN_I(hpriv))
+       if (IS_GEN_I(hpriv)) {
+               cfg &= ~0x1f;           /* clear queue depth */
                cfg |= (1 << 8);        /* enab config burst size mask */
+       }
 
-       else if (IS_GEN_II(hpriv))
+       else if (IS_GEN_II(hpriv)) {
+               cfg &= ~0x1f;           /* clear queue depth */
                cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN;
+               cfg &= ~(EDMA_CFG_NCQ | EDMA_CFG_NCQ_GO_ON_ERR); /* clear NCQ */
+       }
 
        else if (IS_GEN_IIE(hpriv)) {
-               cfg |= (1 << 23);       /* dis RX PM port mask */
-               cfg &= ~(1 << 16);      /* dis FIS-based switching (for now) */
+               cfg |= (1 << 23);       /* do not mask PM field in rx'd FIS */
+               cfg |= (1 << 22);       /* enab 4-entry host queue cache */
                cfg &= ~(1 << 19);      /* dis 128-entry queue (for now?) */
                cfg |= (1 << 18);       /* enab early completion */
-               cfg |= (1 << 17);       /* enab host q cache */
-               cfg |= (1 << 22);       /* enab cutthrough */
+               cfg |= (1 << 17);       /* enab cut-through (dis stor&forwrd) */
+               cfg &= ~(1 << 16);      /* dis FIS-based switching (for now) */
+               cfg &= ~(EDMA_CFG_NCQ | EDMA_CFG_NCQ_GO_ON_ERR); /* clear NCQ */
        }
 
        writelfl(cfg, port_mmio + EDMA_CFG_OFS);
@@ -1276,7 +1285,7 @@ static void mv_err_intr(struct ata_port *ap, int reset_allowed)
                pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
        }
        DPRINTK(KERN_ERR "ata%u: port error; EDMA err cause: 0x%08x "
-               "SERR: 0x%08x\n", ap->id, edma_err_cause, serr);
+               "SERR: 0x%08x\n", ap->print_id, edma_err_cause, serr);
 
        /* Clear EDMA now that SERR cleanup done */
        writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
@@ -2052,7 +2061,7 @@ static void mv_port_init(struct ata_ioports *port,  void __iomem *port_mmio)
        port->altstatus_addr = port->ctl_addr = shd_base + SHD_CTL_AST_OFS;
 
        /* unused: */
-       port->cmd_addr = port->bmdma_addr = port->scr_addr = 0;
+       port->cmd_addr = port->bmdma_addr = port->scr_addr = NULL;
 
        /* Clear any currently outstanding port interrupt conditions */
        serr_ofs = mv_scr_offset(SCR_ERROR);
@@ -2240,7 +2249,11 @@ static int mv_init_host(struct pci_dev *pdev, struct ata_probe_ent *probe_ent,
 
        /* and unmask interrupt generation for host regs */
        writelfl(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS);
-       writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
+
+       if (IS_50XX(hpriv))
+               writelfl(~HC_MAIN_MASKED_IRQS_5, mmio + HC_MAIN_IRQ_MASK_OFS);
+       else
+               writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
 
        VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
                "PCI int cause/mask=0x%08x/0x%08x\n",
@@ -2347,7 +2360,7 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                return rc;
 
        /* Enable interrupts */
-       if (msi && !pci_enable_msi(pdev))
+       if (msi && pci_enable_msi(pdev))
                pci_intx(pdev, 1);
 
        mv_dump_pci_cfg(pdev, 0x68);
index ab92f208dae2f955b9aef79d214707e90c1b10f0..9d9670a9b117e67d3689b8f5b2a1aa4b586f9ac6 100644 (file)
@@ -219,6 +219,7 @@ struct nv_adma_port_priv {
        void __iomem *          gen_block;
        void __iomem *          notifier_clear_block;
        u8                      flags;
+       int                     last_issue_ncq;
 };
 
 struct nv_host_priv {
@@ -229,7 +230,9 @@ struct nv_host_priv {
 
 static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
 static void nv_remove_one (struct pci_dev *pdev);
+#ifdef CONFIG_PM
 static int nv_pci_device_resume(struct pci_dev *pdev);
+#endif
 static void nv_ck804_host_stop(struct ata_host *host);
 static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance);
 static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance);
@@ -250,14 +253,13 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance);
 static void nv_adma_irq_clear(struct ata_port *ap);
 static int nv_adma_port_start(struct ata_port *ap);
 static void nv_adma_port_stop(struct ata_port *ap);
+#ifdef CONFIG_PM
 static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg);
 static int nv_adma_port_resume(struct ata_port *ap);
+#endif
 static void nv_adma_error_handler(struct ata_port *ap);
 static void nv_adma_host_stop(struct ata_host *host);
-static void nv_adma_bmdma_setup(struct ata_queued_cmd *qc);
-static void nv_adma_bmdma_start(struct ata_queued_cmd *qc);
-static void nv_adma_bmdma_stop(struct ata_queued_cmd *qc);
-static u8 nv_adma_bmdma_status(struct ata_port *ap);
+static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc);
 
 enum nv_host_type
 {
@@ -297,8 +299,10 @@ static struct pci_driver nv_pci_driver = {
        .name                   = DRV_NAME,
        .id_table               = nv_pci_tbl,
        .probe                  = nv_init_one,
+#ifdef CONFIG_PM
        .suspend                = ata_pci_device_suspend,
        .resume                 = nv_pci_device_resume,
+#endif
        .remove                 = nv_remove_one,
 };
 
@@ -318,8 +322,10 @@ static struct scsi_host_template nv_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .suspend                = ata_scsi_device_suspend,
        .resume                 = ata_scsi_device_resume,
+#endif
 };
 
 static struct scsi_host_template nv_adma_sht = {
@@ -338,8 +344,10 @@ static struct scsi_host_template nv_adma_sht = {
        .slave_configure        = nv_adma_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .suspend                = ata_scsi_device_suspend,
        .resume                 = ata_scsi_device_resume,
+#endif
 };
 
 static const struct ata_port_operations nv_generic_ops = {
@@ -432,16 +440,16 @@ static const struct ata_port_operations nv_adma_ops = {
        .exec_command           = ata_exec_command,
        .check_status           = ata_check_status,
        .dev_select             = ata_std_dev_select,
-       .bmdma_setup            = nv_adma_bmdma_setup,
-       .bmdma_start            = nv_adma_bmdma_start,
-       .bmdma_stop             = nv_adma_bmdma_stop,
-       .bmdma_status           = nv_adma_bmdma_status,
+       .bmdma_setup            = ata_bmdma_setup,
+       .bmdma_start            = ata_bmdma_start,
+       .bmdma_stop             = ata_bmdma_stop,
+       .bmdma_status           = ata_bmdma_status,
        .qc_prep                = nv_adma_qc_prep,
        .qc_issue               = nv_adma_qc_issue,
        .freeze                 = nv_ck804_freeze,
        .thaw                   = nv_ck804_thaw,
        .error_handler          = nv_adma_error_handler,
-       .post_internal_cmd      = nv_adma_bmdma_stop,
+       .post_internal_cmd      = nv_adma_post_internal_cmd,
        .data_xfer              = ata_data_xfer,
        .irq_handler            = nv_adma_interrupt,
        .irq_clear              = nv_adma_irq_clear,
@@ -451,8 +459,10 @@ static const struct ata_port_operations nv_adma_ops = {
        .scr_write              = nv_scr_write,
        .port_start             = nv_adma_port_start,
        .port_stop              = nv_adma_port_stop,
+#ifdef CONFIG_PM
        .port_suspend           = nv_adma_port_suspend,
        .port_resume            = nv_adma_port_resume,
+#endif
        .host_stop              = nv_adma_host_stop,
 };
 
@@ -661,30 +671,31 @@ static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, __le16 *cpb)
 {
        unsigned int idx = 0;
 
-       cpb[idx++] = cpu_to_le16((ATA_REG_DEVICE << 8) | tf->device | WNB);
-
-       if ((tf->flags & ATA_TFLAG_LBA48) == 0) {
-               cpb[idx++] = cpu_to_le16(IGN);
-               cpb[idx++] = cpu_to_le16(IGN);
-               cpb[idx++] = cpu_to_le16(IGN);
-               cpb[idx++] = cpu_to_le16(IGN);
-               cpb[idx++] = cpu_to_le16(IGN);
-       }
-       else {
-               cpb[idx++] = cpu_to_le16((ATA_REG_ERR   << 8) | tf->hob_feature);
-               cpb[idx++] = cpu_to_le16((ATA_REG_NSECT << 8) | tf->hob_nsect);
-               cpb[idx++] = cpu_to_le16((ATA_REG_LBAL  << 8) | tf->hob_lbal);
-               cpb[idx++] = cpu_to_le16((ATA_REG_LBAM  << 8) | tf->hob_lbam);
-               cpb[idx++] = cpu_to_le16((ATA_REG_LBAH  << 8) | tf->hob_lbah);
+       if(tf->flags & ATA_TFLAG_ISADDR) {
+               if (tf->flags & ATA_TFLAG_LBA48) {
+                       cpb[idx++] = cpu_to_le16((ATA_REG_ERR   << 8) | tf->hob_feature | WNB);
+                       cpb[idx++] = cpu_to_le16((ATA_REG_NSECT << 8) | tf->hob_nsect);
+                       cpb[idx++] = cpu_to_le16((ATA_REG_LBAL  << 8) | tf->hob_lbal);
+                       cpb[idx++] = cpu_to_le16((ATA_REG_LBAM  << 8) | tf->hob_lbam);
+                       cpb[idx++] = cpu_to_le16((ATA_REG_LBAH  << 8) | tf->hob_lbah);
+                       cpb[idx++] = cpu_to_le16((ATA_REG_ERR    << 8) | tf->feature);
+               } else
+                       cpb[idx++] = cpu_to_le16((ATA_REG_ERR    << 8) | tf->feature | WNB);
+
+               cpb[idx++] = cpu_to_le16((ATA_REG_NSECT  << 8) | tf->nsect);
+               cpb[idx++] = cpu_to_le16((ATA_REG_LBAL   << 8) | tf->lbal);
+               cpb[idx++] = cpu_to_le16((ATA_REG_LBAM   << 8) | tf->lbam);
+               cpb[idx++] = cpu_to_le16((ATA_REG_LBAH   << 8) | tf->lbah);
        }
-       cpb[idx++] = cpu_to_le16((ATA_REG_ERR    << 8) | tf->feature);
-       cpb[idx++] = cpu_to_le16((ATA_REG_NSECT  << 8) | tf->nsect);
-       cpb[idx++] = cpu_to_le16((ATA_REG_LBAL   << 8) | tf->lbal);
-       cpb[idx++] = cpu_to_le16((ATA_REG_LBAM   << 8) | tf->lbam);
-       cpb[idx++] = cpu_to_le16((ATA_REG_LBAH   << 8) | tf->lbah);
+
+       if(tf->flags & ATA_TFLAG_DEVICE)
+               cpb[idx++] = cpu_to_le16((ATA_REG_DEVICE << 8) | tf->device);
 
        cpb[idx++] = cpu_to_le16((ATA_REG_CMD    << 8) | tf->command | CMDEND);
 
+       while(idx < 12)
+               cpb[idx++] = cpu_to_le16(IGN);
+
        return idx;
 }
 
@@ -741,6 +752,17 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
                        DPRINTK("Completing qc from tag %d with err_mask %u\n",cpb_num,
                                qc->err_mask);
                        ata_qc_complete(qc);
+               } else {
+                       struct ata_eh_info *ehi = &ap->eh_info;
+                       /* Notifier bits set without a command may indicate the drive
+                          is misbehaving. Raise host state machine violation on this
+                          condition. */
+                       ata_port_printk(ap, KERN_ERR, "notifier for tag %d with no command?\n",
+                               cpb_num);
+                       ehi->err_mask |= AC_ERR_HSM;
+                       ehi->action |= ATA_EH_SOFTRESET;
+                       ata_port_freeze(ap);
+                       return 1;
                }
        }
        return 0;
@@ -852,22 +874,20 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
 
                        if (status & (NV_ADMA_STAT_DONE |
                                      NV_ADMA_STAT_CPBERR)) {
-                               /** Check CPBs for completed commands */
+                               u32 check_commands;
+                               int pos, error = 0;
+
+                               if(ata_tag_valid(ap->active_tag))
+                                       check_commands = 1 << ap->active_tag;
+                               else
+                                       check_commands = ap->sactive;
 
-                               if (ata_tag_valid(ap->active_tag)) {
-                                       /* Non-NCQ command */
-                                       nv_adma_check_cpb(ap, ap->active_tag,
-                                               notifier_error & (1 << ap->active_tag));
-                               } else {
-                                       int pos, error = 0;
-                                       u32 active = ap->sactive;
-
-                                       while ((pos = ffs(active)) && !error) {
-                                               pos--;
-                                               error = nv_adma_check_cpb(ap, pos,
-                                                       notifier_error & (1 << pos) );
-                                               active &= ~(1 << pos );
-                                       }
+                               /** Check CPBs for completed commands */
+                               while ((pos = ffs(check_commands)) && !error) {
+                                       pos--;
+                                       error = nv_adma_check_cpb(ap, pos,
+                                               notifier_error & (1 << pos) );
+                                       check_commands &= ~(1 << pos );
                                }
                        }
                }
@@ -905,73 +925,12 @@ static void nv_adma_irq_clear(struct ata_port *ap)
        iowrite8(ioread8(dma_stat_addr), dma_stat_addr);
 }
 
-static void nv_adma_bmdma_setup(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
-       struct nv_adma_port_priv *pp = ap->private_data;
-       u8 dmactl;
-
-       if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) {
-               WARN_ON(1);
-               return;
-       }
-
-       /* load PRD table addr. */
-       iowrite32(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
-
-       /* specify data direction, triple-check start bit is clear */
-       dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
-       dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
-       if (!rw)
-               dmactl |= ATA_DMA_WR;
-
-       iowrite8(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
-
-       /* issue r/w command */
-       ata_exec_command(ap, &qc->tf);
-}
-
-static void nv_adma_bmdma_start(struct ata_queued_cmd *qc)
+static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc)
 {
-       struct ata_port *ap = qc->ap;
-       struct nv_adma_port_priv *pp = ap->private_data;
-       u8 dmactl;
-
-       if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) {
-               WARN_ON(1);
-               return;
-       }
-
-       /* start host DMA transaction */
-       dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
-       iowrite8(dmactl | ATA_DMA_START,
-                ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
-}
-
-static void nv_adma_bmdma_stop(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       struct nv_adma_port_priv *pp = ap->private_data;
-
-       if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE))
-               return;
-
-       /* clear start/stop bit */
-       iowrite8(ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START,
-                ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
-
-       /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
-       ata_altstatus(ap);        /* dummy read */
-}
-
-static u8 nv_adma_bmdma_status(struct ata_port *ap)
-{
-       struct nv_adma_port_priv *pp = ap->private_data;
-
-       WARN_ON(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE));
+       struct nv_adma_port_priv *pp = qc->ap->private_data;
 
-       return ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+       if(pp->flags & NV_ADMA_PORT_REGISTER_MODE)
+               ata_bmdma_post_internal_cmd(qc);
 }
 
 static int nv_adma_port_start(struct ata_port *ap)
@@ -1040,14 +999,15 @@ static int nv_adma_port_start(struct ata_port *ap)
 
        /* clear GO for register mode, enable interrupt */
        tmp = readw(mmio + NV_ADMA_CTL);
-       writew( (tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN, mmio + NV_ADMA_CTL);
+       writew( (tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN |
+                NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL);
 
        tmp = readw(mmio + NV_ADMA_CTL);
        writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
-       readl( mmio + NV_ADMA_CTL );    /* flush posted write */
+       readw( mmio + NV_ADMA_CTL );    /* flush posted write */
        udelay(1);
        writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
-       readl( mmio + NV_ADMA_CTL );    /* flush posted write */
+       readw( mmio + NV_ADMA_CTL );    /* flush posted write */
 
        return 0;
 }
@@ -1061,6 +1021,7 @@ static void nv_adma_port_stop(struct ata_port *ap)
        writew(0, mmio + NV_ADMA_CTL);
 }
 
+#ifdef CONFIG_PM
 static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg)
 {
        struct nv_adma_port_priv *pp = ap->private_data;
@@ -1099,17 +1060,19 @@ static int nv_adma_port_resume(struct ata_port *ap)
 
        /* clear GO for register mode, enable interrupt */
        tmp = readw(mmio + NV_ADMA_CTL);
-       writew((tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN, mmio + NV_ADMA_CTL);
+       writew( (tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN |
+                NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL);
 
        tmp = readw(mmio + NV_ADMA_CTL);
        writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
-       readl( mmio + NV_ADMA_CTL );    /* flush posted write */
+       readw( mmio + NV_ADMA_CTL );    /* flush posted write */
        udelay(1);
        writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
-       readl( mmio + NV_ADMA_CTL );    /* flush posted write */
+       readw( mmio + NV_ADMA_CTL );    /* flush posted write */
 
        return 0;
 }
+#endif
 
 static void nv_adma_setup_port(struct ata_probe_ent *probe_ent, unsigned int port)
 {
@@ -1163,11 +1126,7 @@ static void nv_adma_fill_aprd(struct ata_queued_cmd *qc,
                              int idx,
                              struct nv_adma_prd *aprd)
 {
-       u8 flags;
-
-       memset(aprd, 0, sizeof(struct nv_adma_prd));
-
-       flags = 0;
+       u8 flags = 0;
        if (qc->tf.flags & ATA_TFLAG_WRITE)
                flags |= NV_APRD_WRITE;
        if (idx == qc->n_elem - 1)
@@ -1178,6 +1137,7 @@ static void nv_adma_fill_aprd(struct ata_queued_cmd *qc,
        aprd->addr  = cpu_to_le64(((u64)sg_dma_address(sg)));
        aprd->len   = cpu_to_le32(((u32)sg_dma_len(sg))); /* len in bytes */
        aprd->flags = flags;
+       aprd->packet_len = 0;
 }
 
 static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb)
@@ -1198,6 +1158,8 @@ static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb)
        }
        if (idx > 5)
                cpb->next_aprd = cpu_to_le64(((u64)(pp->aprd_dma + NV_ADMA_SGTBL_SZ * qc->tag)));
+       else
+               cpb->next_aprd = cpu_to_le64(0);
 }
 
 static int nv_adma_use_reg_mode(struct ata_queued_cmd *qc)
@@ -1230,7 +1192,10 @@ static void nv_adma_qc_prep(struct ata_queued_cmd *qc)
                return;
        }
 
-       memset(cpb, 0, sizeof(struct nv_adma_cpb));
+       cpb->resp_flags = NV_CPB_RESP_DONE;
+       wmb();
+       cpb->ctl_flags = 0;
+       wmb();
 
        cpb->len                = 3;
        cpb->tag                = qc->tag;
@@ -1254,12 +1219,15 @@ static void nv_adma_qc_prep(struct ata_queued_cmd *qc)
           finished filling in all of the contents */
        wmb();
        cpb->ctl_flags = ctl_flags;
+       wmb();
+       cpb->resp_flags = 0;
 }
 
 static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc)
 {
        struct nv_adma_port_priv *pp = qc->ap->private_data;
        void __iomem *mmio = pp->ctl_block;
+       int curr_ncq = (qc->tf.protocol == ATA_PROT_NCQ);
 
        VPRINTK("ENTER\n");
 
@@ -1274,6 +1242,14 @@ static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc)
        /* write append register, command tag in lower 8 bits
           and (number of cpbs to append -1) in top 8 bits */
        wmb();
+
+       if(curr_ncq != pp->last_issue_ncq) {
+               /* Seems to need some delay before switching between NCQ and non-NCQ
+                  commands, else we get command timeouts and such. */
+               udelay(20);
+               pp->last_issue_ncq = curr_ncq;
+       }
+
        writew(qc->tag, mmio + NV_ADMA_APPEND);
 
        DPRINTK("Issued tag %u\n",qc->tag);
@@ -1447,6 +1423,30 @@ static void nv_adma_error_handler(struct ata_port *ap)
                int i;
                u16 tmp;
 
+               if(ata_tag_valid(ap->active_tag) || ap->sactive) {
+                       u32 notifier = readl(mmio + NV_ADMA_NOTIFIER);
+                       u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR);
+                       u32 gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL);
+                       u32 status = readw(mmio + NV_ADMA_STAT);
+                       u8 cpb_count = readb(mmio + NV_ADMA_CPB_COUNT);
+                       u8 next_cpb_idx = readb(mmio + NV_ADMA_NEXT_CPB_IDX);
+
+                       ata_port_printk(ap, KERN_ERR, "EH in ADMA mode, notifier 0x%X "
+                               "notifier_error 0x%X gen_ctl 0x%X status 0x%X "
+                               "next cpb count 0x%X next cpb idx 0x%x\n",
+                               notifier, notifier_error, gen_ctl, status,
+                               cpb_count, next_cpb_idx);
+
+                       for( i=0;i<NV_ADMA_MAX_CPBS;i++) {
+                               struct nv_adma_cpb *cpb = &pp->cpb[i];
+                               if( (ata_tag_valid(ap->active_tag) && i == ap->active_tag) ||
+                                   ap->sactive & (1 << i) )
+                                       ata_port_printk(ap, KERN_ERR,
+                                               "CPB %d: ctl_flags 0x%x, resp_flags 0x%x\n",
+                                               i, cpb->ctl_flags, cpb->resp_flags);
+                       }
+               }
+
                /* Push us back into port register mode for error handling. */
                nv_adma_register_mode(ap);
 
@@ -1460,10 +1460,10 @@ static void nv_adma_error_handler(struct ata_port *ap)
                /* Reset channel */
                tmp = readw(mmio + NV_ADMA_CTL);
                writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
-               readl( mmio + NV_ADMA_CTL );    /* flush posted write */
+               readw( mmio + NV_ADMA_CTL );    /* flush posted write */
                udelay(1);
                writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
-               readl( mmio + NV_ADMA_CTL );    /* flush posted write */
+               readw( mmio + NV_ADMA_CTL );    /* flush posted write */
        }
 
        ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
@@ -1575,6 +1575,7 @@ static void nv_remove_one (struct pci_dev *pdev)
        kfree(hpriv);
 }
 
+#ifdef CONFIG_PM
 static int nv_pci_device_resume(struct pci_dev *pdev)
 {
        struct ata_host *host = dev_get_drvdata(&pdev->dev);
@@ -1622,6 +1623,7 @@ static int nv_pci_device_resume(struct pci_dev *pdev)
 
        return 0;
 }
+#endif
 
 static void nv_ck804_host_stop(struct ata_host *host)
 {
index cf9ed8c3930155bf87cd0d08c63c1ee84d977539..2339813ce9f646caf678172bbb85e045d157f2c7 100644 (file)
@@ -45,7 +45,7 @@
 #include "sata_promise.h"
 
 #define DRV_NAME       "sata_promise"
-#define DRV_VERSION    "1.05"
+#define DRV_VERSION    "2.00"
 
 
 enum {
@@ -218,6 +218,7 @@ static const struct ata_port_operations pdc_pata_ops = {
        .freeze                 = pdc_freeze,
        .thaw                   = pdc_thaw,
        .error_handler          = pdc_error_handler,
+       .post_internal_cmd      = pdc_post_internal_cmd,
        .data_xfer              = ata_data_xfer,
        .irq_handler            = pdc_interrupt,
        .irq_clear              = pdc_irq_clear,
@@ -776,7 +777,8 @@ static int pdc_old_check_atapi_dma(struct ata_queued_cmd *qc)
        return pdc_check_atapi_dma(qc);
 }
 
-static void pdc_ata_setup_port(struct ata_ioports *port, void __iomem *base)
+static void pdc_ata_setup_port(struct ata_ioports *port, void __iomem *base,
+                              void __iomem *scr_addr)
 {
        port->cmd_addr          = base;
        port->data_addr         = base;
@@ -791,6 +793,7 @@ static void pdc_ata_setup_port(struct ata_ioports *port, void __iomem *base)
        port->status_addr       = base + 0x1c;
        port->altstatus_addr    =
        port->ctl_addr          = base + 0x38;
+       port->scr_addr          = scr_addr;
 }
 
 
@@ -903,11 +906,8 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
 
        base = probe_ent->iomap[PDC_MMIO_BAR];
 
-       pdc_ata_setup_port(&probe_ent->port[0], base + 0x200);
-       pdc_ata_setup_port(&probe_ent->port[1], base + 0x280);
-
-       probe_ent->port[0].scr_addr = base + 0x400;
-       probe_ent->port[1].scr_addr = base + 0x500;
+       pdc_ata_setup_port(&probe_ent->port[0], base + 0x200, base + 0x400);
+       pdc_ata_setup_port(&probe_ent->port[1], base + 0x280, base + 0x500);
 
        /* notice 4-port boards */
        switch (board_idx) {
@@ -916,12 +916,8 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
                /* Fall through */
        case board_20319:
                        probe_ent->n_ports = 4;
-
-               pdc_ata_setup_port(&probe_ent->port[2], base + 0x300);
-               pdc_ata_setup_port(&probe_ent->port[3], base + 0x380);
-
-               probe_ent->port[2].scr_addr = base + 0x600;
-               probe_ent->port[3].scr_addr = base + 0x700;
+               pdc_ata_setup_port(&probe_ent->port[2], base + 0x300, base + 0x600);
+               pdc_ata_setup_port(&probe_ent->port[3], base + 0x380, base + 0x700);
                break;
        case board_2057x:
                hp->flags |= PDC_FLAG_GEN_II;
@@ -931,7 +927,7 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
                tmp = readb(base + PDC_FLASH_CTL+1);
                if (!(tmp & 0x80)) {
                        probe_ent->n_ports = 3;
-                       pdc_ata_setup_port(&probe_ent->port[2], base + 0x300);
+                       pdc_ata_setup_port(&probe_ent->port[2], base + 0x300, NULL);
                        hp->port_flags[2] = ATA_FLAG_SLAVE_POSS;
                        printk(KERN_INFO DRV_NAME " PATA port found\n");
                } else
@@ -941,12 +937,8 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
                break;
        case board_20619:
                probe_ent->n_ports = 4;
-
-               pdc_ata_setup_port(&probe_ent->port[2], base + 0x300);
-               pdc_ata_setup_port(&probe_ent->port[3], base + 0x380);
-
-               probe_ent->port[2].scr_addr = base + 0x600;
-               probe_ent->port[3].scr_addr = base + 0x700;
+               pdc_ata_setup_port(&probe_ent->port[2], base + 0x300, NULL);
+               pdc_ata_setup_port(&probe_ent->port[3], base + 0x380, NULL);
                break;
        default:
                BUG();
index 6097d8f2a0c0aea71891bbff9c9c7b5b1fa11e47..8786b45f291b8d62af9ddb6fd3bc585d7c659201 100644 (file)
@@ -39,7 +39,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "sata_qstor"
-#define DRV_VERSION    "0.06"
+#define DRV_VERSION    "0.07"
 
 enum {
        QS_MMIO_BAR             = 4,
@@ -446,7 +446,7 @@ static inline unsigned int qs_intr_mmio(struct ata_host *host)
                                if ((status & ATA_BUSY))
                                        continue;
                                DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
-                                       ap->id, qc->tf.protocol, status);
+                                       ap->print_id, qc->tf.protocol, status);
 
                                /* complete taskfile transaction */
                                pp->state = qs_state_idle;
index dca3d3749f0626cbc2d79798ecda01502b1452e3..917b7ea4ef7c203b0bd4ebc5abd83aad5ceb4420 100644 (file)
@@ -46,7 +46,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "sata_sil"
-#define DRV_VERSION    "2.0"
+#define DRV_VERSION    "2.1"
 
 enum {
        SIL_MMIO_BAR            = 5,
@@ -183,8 +183,10 @@ static struct scsi_host_template sil_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .suspend                = ata_scsi_device_suspend,
        .resume                 = ata_scsi_device_resume,
+#endif
 };
 
 static const struct ata_port_operations sil_ops = {
@@ -339,7 +341,7 @@ static inline void __iomem *sil_scr_addr(struct ata_port *ap, unsigned int sc_re
                break;
        }
 
-       return 0;
+       return NULL;
 }
 
 static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg)
@@ -386,9 +388,15 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
                goto freeze;
        }
 
-       if (unlikely(!qc || qc->tf.ctl & ATA_NIEN))
+       if (unlikely(!qc))
                goto freeze;
 
+       if (unlikely(qc->tf.flags & ATA_TFLAG_POLLING)) {
+               /* this sometimes happens, just clear IRQ */
+               ata_chk_status(ap);
+               return;
+       }
+
        /* Check whether we are expecting interrupt in this state */
        switch (ap->hsm_task_state) {
        case HSM_ST_FIRST:
index e65e8d55da3e9b36dea407bc6993b724a8ebf1db..75d961599651b8198b9e4eb6b613cdf3d6cb00d4 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "sata_sil24"
-#define DRV_VERSION    "0.3"
+#define DRV_VERSION    "0.8"
 
 /*
  * Port request block (PRB) 32 bytes
@@ -380,8 +380,10 @@ static struct scsi_host_template sil24_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .suspend                = ata_scsi_device_suspend,
        .resume                 = ata_scsi_device_resume,
+#endif
 };
 
 static const struct ata_port_operations sil24_ops = {
@@ -647,7 +649,6 @@ static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
                                 struct sil24_sge *sge)
 {
        struct scatterlist *sg;
-       unsigned int idx = 0;
 
        ata_for_each_sg(sg, qc) {
                sge->addr = cpu_to_le64(sg_dma_address(sg));
@@ -656,9 +657,7 @@ static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
                        sge->flags = cpu_to_le32(SGE_TRM);
                else
                        sge->flags = 0;
-
                sge++;
-               idx++;
        }
 }
 
index 49c9e2bd706f9ad1f9367f78d481c1fb8139f668..1879e0cd56aab7cac280d54d674c6acd8a03e07b 100644 (file)
@@ -40,9 +40,8 @@
 #include <linux/device.h>
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
-#include "libata.h"
+#include "sis.h"
 
-#undef DRV_NAME                /* already defined in libata.h, for libata-core */
 #define DRV_NAME       "sata_sis"
 #define DRV_VERSION    "0.7"
 
@@ -310,7 +309,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
                case 0x10:
                        ppi[1] = &sis_info133;
                        break;
-                       
+
                case 0x30:
                        ppi[0] = &sis_info133;
                        break;
index 4e4289994204ea0409c982ae66cc15a9862051fd..b121195cc598c6a9f4dccd6bbe21580e187ad7c9 100644 (file)
@@ -53,7 +53,7 @@
 #endif /* CONFIG_PPC_OF */
 
 #define DRV_NAME       "sata_svw"
-#define DRV_VERSION    "2.0"
+#define DRV_VERSION    "2.1"
 
 enum {
        K2_FLAG_NO_ATAPI_DMA            = (1 << 29),
index 0ebd77b080d68396b4bc37987b45037004374a8e..1a081c3a8c06a24b3cd4ba51e6d643435ed2ca21 100644 (file)
@@ -44,7 +44,7 @@
 #include "sata_promise.h"
 
 #define DRV_NAME       "sata_sx4"
-#define DRV_VERSION    "0.9"
+#define DRV_VERSION    "0.10"
 
 
 enum {
@@ -421,7 +421,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
 
        WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
 
-       VPRINTK("ata%u: ENTER\n", ap->id);
+       VPRINTK("ata%u: ENTER\n", ap->print_id);
 
        /* hard-code chip #0 */
        mmio += PDC_CHIP0_OFS;
@@ -478,7 +478,7 @@ static void pdc20621_nodata_prep(struct ata_queued_cmd *qc)
        unsigned int portno = ap->port_no;
        unsigned int i;
 
-       VPRINTK("ata%u: ENTER\n", ap->id);
+       VPRINTK("ata%u: ENTER\n", ap->print_id);
 
        /* hard-code chip #0 */
        mmio += PDC_CHIP0_OFS;
@@ -605,7 +605,7 @@ static void pdc20621_packet_start(struct ata_queued_cmd *qc)
        /* hard-code chip #0 */
        mmio += PDC_CHIP0_OFS;
 
-       VPRINTK("ata%u: ENTER\n", ap->id);
+       VPRINTK("ata%u: ENTER\n", ap->print_id);
 
        wmb();                  /* flush PRD, pkt writes */
 
@@ -672,7 +672,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
 
                /* step two - DMA from DIMM to host */
                if (doing_hdma) {
-                       VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
+                       VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->print_id,
                                readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
                        /* get drive status; clear intr; complete txn */
                        qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
@@ -683,7 +683,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
                /* step one - exec ATA command */
                else {
                        u8 seq = (u8) (port_no + 1 + 4);
-                       VPRINTK("ata%u: read ata, 0x%x 0x%x\n", ap->id,
+                       VPRINTK("ata%u: read ata, 0x%x 0x%x\n", ap->print_id,
                                readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
 
                        /* submit hdma pkt */
@@ -698,7 +698,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
                /* step one - DMA from host to DIMM */
                if (doing_hdma) {
                        u8 seq = (u8) (port_no + 1);
-                       VPRINTK("ata%u: write hdma, 0x%x 0x%x\n", ap->id,
+                       VPRINTK("ata%u: write hdma, 0x%x 0x%x\n", ap->print_id,
                                readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
 
                        /* submit ata pkt */
@@ -711,7 +711,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
 
                /* step two - execute ATA command */
                else {
-                       VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id,
+                       VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->print_id,
                                readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
                        /* get drive status; clear intr; complete txn */
                        qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
index 80131eec68f4cfe95aa028c2533b9cc883f92d87..d659ace80f4f6c985f6da071a61b9d42ff93b8a5 100644 (file)
@@ -36,7 +36,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "sata_uli"
-#define DRV_VERSION    "1.0"
+#define DRV_VERSION    "1.1"
 
 enum {
        uli_5289                = 0,
index baca6d79bb0bc426eda80fe358555a35c246981e..598e6a26a481a7934d8ae14121e395844c1f22dd 100644 (file)
@@ -46,7 +46,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "sata_via"
-#define DRV_VERSION    "2.0"
+#define DRV_VERSION    "2.1"
 
 enum board_ids_enum {
        vt6420,
@@ -60,7 +60,7 @@ enum {
        SATA_PATA_SHARING       = 0x49, /* PATA/SATA sharing func ctrl */
        PATA_UDMA_TIMING        = 0xB3, /* PATA timing for DMA/ cable detect */
        PATA_PIO_TIMING         = 0xAB, /* PATA timing register */
-       
+
        PORT0                   = (1 << 1),
        PORT1                   = (1 << 0),
        ALL_PORTS               = PORT0 | PORT1,
@@ -151,7 +151,7 @@ static const struct ata_port_operations vt6420_sata_ops = {
 
 static const struct ata_port_operations vt6421_pata_ops = {
        .port_disable           = ata_port_disable,
-       
+
        .set_piomode            = vt6421_set_pio_mode,
        .set_dmamode            = vt6421_set_dma_mode,
 
@@ -185,7 +185,7 @@ static const struct ata_port_operations vt6421_pata_ops = {
 
 static const struct ata_port_operations vt6421_sata_ops = {
        .port_disable           = ata_port_disable,
-       
+
        .tf_load                = ata_tf_load,
        .tf_read                = ata_tf_read,
        .check_status           = ata_check_status,
@@ -423,16 +423,21 @@ static struct ata_probe_ent *vt6420_init_probe_ent(struct pci_dev *pdev)
 {
        struct ata_probe_ent *probe_ent;
        struct ata_port_info *ppi[2];
-       void __iomem * const *iomap;
+       void __iomem *bar5;
 
        ppi[0] = ppi[1] = &vt6420_port_info;
        probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
        if (!probe_ent)
                return NULL;
 
-       iomap = pcim_iomap_table(pdev);
-       probe_ent->port[0].scr_addr = svia_scr_addr(iomap[5], 0);
-       probe_ent->port[1].scr_addr = svia_scr_addr(iomap[5], 1);
+       bar5 = pcim_iomap(pdev, 5, 0);
+       if (!bar5) {
+               dev_printk(KERN_ERR, &pdev->dev, "failed to iomap PCI BAR 5\n");
+               return NULL;
+       }
+
+       probe_ent->port[0].scr_addr = svia_scr_addr(bar5, 0);
+       probe_ent->port[1].scr_addr = svia_scr_addr(bar5, 1);
 
        return probe_ent;
 }
@@ -460,6 +465,13 @@ static struct ata_probe_ent *vt6421_init_probe_ent(struct pci_dev *pdev)
        probe_ent->mwdma_mask   = 0x07;
        probe_ent->udma_mask    = 0x7f;
 
+       for (i = 0; i < 6; i++)
+               if (!pcim_iomap(pdev, i, 0)) {
+                       dev_printk(KERN_ERR, &pdev->dev,
+                                  "failed to iomap PCI BAR %d\n", i);
+                       return NULL;
+               }
+
        for (i = 0; i < N_PORTS; i++)
                vt6421_init_addrs(probe_ent, pcim_iomap_table(pdev), i);
 
@@ -522,7 +534,7 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        if (rc)
                return rc;
 
-       rc = pcim_iomap_regions(pdev, 0x1f, DRV_NAME);
+       rc = pci_request_regions(pdev, DRV_NAME);
        if (rc) {
                pcim_pin_device(pdev);
                return rc;
index 2fd037bde090d92641a954d82d2017ce3aa375ca..170bad1b415b01765276b7578f6675804e7afb6d 100644 (file)
@@ -47,7 +47,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "sata_vsc"
-#define DRV_VERSION    "2.0"
+#define DRV_VERSION    "2.1"
 
 enum {
        VSC_MMIO_BAR                    = 0,
@@ -98,10 +98,6 @@ enum {
                              VSC_SATA_INT_PHY_CHANGE),
 };
 
-#define is_vsc_sata_int_err(port_idx, int_status) \
-        (int_status & (VSC_SATA_INT_ERROR << (8 * port_idx)))
-
-
 static u32 vsc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
 {
        if (sc_reg > SCR_CONTROL)
@@ -119,6 +115,28 @@ static void vsc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
 }
 
 
+static void vsc_freeze(struct ata_port *ap)
+{
+       void __iomem *mask_addr;
+
+       mask_addr = ap->host->iomap[VSC_MMIO_BAR] +
+               VSC_SATA_INT_MASK_OFFSET + ap->port_no;
+
+       writeb(0, mask_addr);
+}
+
+
+static void vsc_thaw(struct ata_port *ap)
+{
+       void __iomem *mask_addr;
+
+       mask_addr = ap->host->iomap[VSC_MMIO_BAR] +
+               VSC_SATA_INT_MASK_OFFSET + ap->port_no;
+
+       writeb(0xff, mask_addr);
+}
+
+
 static void vsc_intr_mask_update(struct ata_port *ap, u8 ctl)
 {
        void __iomem *mask_addr;
@@ -203,6 +221,36 @@ static void vsc_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
         }
 }
 
+static inline void vsc_error_intr(u8 port_status, struct ata_port *ap)
+{
+       if (port_status & (VSC_SATA_INT_PHY_CHANGE | VSC_SATA_INT_ERROR_M))
+               ata_port_freeze(ap);
+       else
+               ata_port_abort(ap);
+}
+
+static void vsc_port_intr(u8 port_status, struct ata_port *ap)
+{
+       struct ata_queued_cmd *qc;
+       int handled = 0;
+
+       if (unlikely(port_status & VSC_SATA_INT_ERROR)) {
+               vsc_error_intr(port_status, ap);
+               return;
+       }
+
+       qc = ata_qc_from_tag(ap, ap->active_tag);
+       if (qc && likely(!(qc->tf.flags & ATA_TFLAG_POLLING)))
+               handled = ata_host_intr(ap, qc);
+
+       /* We received an interrupt during a polled command,
+        * or some other spurious condition.  Interrupt reporting
+        * with this hardware is fairly reliable so it is safe to
+        * simply clear the interrupt
+        */
+       if (unlikely(!handled))
+               ata_chk_status(ap);
+}
 
 /*
  * vsc_sata_interrupt
@@ -214,59 +262,36 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance)
        struct ata_host *host = dev_instance;
        unsigned int i;
        unsigned int handled = 0;
-       u32 int_status;
-
-       spin_lock(&host->lock);
+       u32 status;
 
-       int_status = readl(host->iomap[VSC_MMIO_BAR] +
-                          VSC_SATA_INT_STAT_OFFSET);
+       status = readl(host->iomap[VSC_MMIO_BAR] + VSC_SATA_INT_STAT_OFFSET);
 
-       for (i = 0; i < host->n_ports; i++) {
-               if (int_status & ((u32) 0xFF << (8 * i))) {
-                       struct ata_port *ap;
+       if (unlikely(status == 0xffffffff || status == 0)) {
+               if (status)
+                       dev_printk(KERN_ERR, host->dev,
+                               ": IRQ status == 0xffffffff, "
+                               "PCI fault or device removal?\n");
+               goto out;
+       }
 
-                       ap = host->ports[i];
+       spin_lock(&host->lock);
 
-                       if (is_vsc_sata_int_err(i, int_status)) {
-                               u32 err_status;
-                               printk(KERN_DEBUG "%s: ignoring interrupt(s)\n", __FUNCTION__);
-                               err_status = ap ? vsc_sata_scr_read(ap, SCR_ERROR) : 0;
-                               vsc_sata_scr_write(ap, SCR_ERROR, err_status);
-                               handled++;
-                       }
+       for (i = 0; i < host->n_ports; i++) {
+               u8 port_status = (status >> (8 * i)) & 0xff;
+               if (port_status) {
+                       struct ata_port *ap = host->ports[i];
 
                        if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
-                               struct ata_queued_cmd *qc;
-
-                               qc = ata_qc_from_tag(ap, ap->active_tag);
-                               if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
-                                       handled += ata_host_intr(ap, qc);
-                               else if (is_vsc_sata_int_err(i, int_status)) {
-                                       /*
-                                        * On some chips (i.e. Intel 31244), an error
-                                        * interrupt will sneak in at initialization
-                                        * time (phy state changes).  Clearing the SCR
-                                        * error register is not required, but it prevents
-                                        * the phy state change interrupts from recurring
-                                        * later.
-                                        */
-                                       u32 err_status;
-                                       err_status = vsc_sata_scr_read(ap, SCR_ERROR);
-                                       printk(KERN_DEBUG "%s: clearing interrupt, "
-                                              "status %x; sata err status %x\n",
-                                              __FUNCTION__,
-                                              int_status, err_status);
-                                       vsc_sata_scr_write(ap, SCR_ERROR, err_status);
-                                       /* Clear interrupt status */
-                                       ata_chk_status(ap);
-                                       handled++;
-                               }
-                       }
+                               vsc_port_intr(port_status, ap);
+                               handled++;
+                       } else
+                               dev_printk(KERN_ERR, host->dev,
+                                       ": interrupt from disabled port %d\n", i);
                }
        }
 
        spin_unlock(&host->lock);
-
+out:
        return IRQ_RETVAL(handled);
 }
 
@@ -304,8 +329,8 @@ static const struct ata_port_operations vsc_sata_ops = {
        .qc_prep                = ata_qc_prep,
        .qc_issue               = ata_qc_issue_prot,
        .data_xfer              = ata_data_xfer,
-       .freeze                 = ata_bmdma_freeze,
-       .thaw                   = ata_bmdma_thaw,
+       .freeze                 = vsc_freeze,
+       .thaw                   = vsc_thaw,
        .error_handler          = ata_bmdma_error_handler,
        .post_internal_cmd      = ata_bmdma_post_internal_cmd,
        .irq_handler            = vsc_sata_interrupt,
diff --git a/drivers/ata/sis.h b/drivers/ata/sis.h
new file mode 100644 (file)
index 0000000..231da8f
--- /dev/null
@@ -0,0 +1,5 @@
+
+struct ata_port_info;
+
+/* pata_sis.c */
+extern struct ata_port_info sis_info133;
index 889583dfc1a6652be25486d394d80f9c16d44c8e..cb44cb4f6a47bf25c38a37f0a15832517f2d0c26 100644 (file)
@@ -311,6 +311,17 @@ EXPORT_SYMBOL_GPL(cfag12864b_enable);
 EXPORT_SYMBOL_GPL(cfag12864b_disable);
 EXPORT_SYMBOL_GPL(cfag12864b_isenabled);
 
+/*
+ * Is the module inited?
+ */
+
+static unsigned char cfag12864b_inited;
+unsigned char cfag12864b_isinited(void)
+{
+       return cfag12864b_inited;
+}
+EXPORT_SYMBOL_GPL(cfag12864b_isinited);
+
 /*
  * Module Init & Exit
  */
@@ -319,6 +330,13 @@ static int __init cfag12864b_init(void)
 {
        int ret = -EINVAL;
 
+       /* ks0108_init() must be called first */
+       if (!ks0108_isinited()) {
+               printk(KERN_ERR CFAG12864B_NAME ": ERROR: "
+                       "ks0108 is not initialized\n");
+               goto none;
+       }
+
        if (PAGE_SIZE < CFAG12864B_SIZE) {
                printk(KERN_ERR CFAG12864B_NAME ": ERROR: "
                        "page size (%i) < cfag12864b size (%i)\n",
@@ -354,6 +372,7 @@ static int __init cfag12864b_init(void)
        cfag12864b_clear();
        cfag12864b_on();
 
+       cfag12864b_inited = 1;
        return 0;
 
 cachealloced:
index 94765e78315f07d01b2625bf131916ac837614d8..66fafbb1d0871896ebf36d0d5c78debcc17a8f2b 100644 (file)
@@ -137,7 +137,14 @@ static struct platform_device *cfag12864bfb_device;
 
 static int __init cfag12864bfb_init(void)
 {
-       int ret;
+       int ret = -EINVAL;
+
+       /* cfag12864b_init() must be called first */
+       if (!cfag12864b_isinited()) {
+               printk(KERN_ERR CFAG12864BFB_NAME ": ERROR: "
+                       "cfag12864b is not initialized\n");
+               goto none;
+       }
 
        if (cfag12864b_enable()) {
                printk(KERN_ERR CFAG12864BFB_NAME ": ERROR: "
@@ -162,6 +169,7 @@ static int __init cfag12864bfb_init(void)
                }
        }
 
+none:
        return ret;
 }
 
index a637575b9106191ebd7ed1ce57e772bccad6a0ae..e6c3646ef18ce007c4446b6d96738202d0cf0874 100644 (file)
@@ -110,6 +110,17 @@ EXPORT_SYMBOL_GPL(ks0108_startline);
 EXPORT_SYMBOL_GPL(ks0108_address);
 EXPORT_SYMBOL_GPL(ks0108_page);
 
+/*
+ * Is the module inited?
+ */
+
+static unsigned char ks0108_inited;
+unsigned char ks0108_isinited(void)
+{
+       return ks0108_inited;
+}
+EXPORT_SYMBOL_GPL(ks0108_isinited);
+
 /*
  * Module Init & Exit
  */
@@ -142,6 +153,7 @@ static int __init ks0108_init(void)
                goto registered;
        }
 
+       ks0108_inited = 1;
        return 0;
 
 registered:
index 1417e5cd4c6f539544ebc686a81d7b51592e0331..d5968128be2b89c02202d9bdd5d87e64322656be 100644 (file)
@@ -840,48 +840,6 @@ void class_device_destroy(struct class *cls, dev_t devt)
                class_device_unregister(class_dev);
 }
 
-int class_device_rename(struct class_device *class_dev, char *new_name)
-{
-       int error = 0;
-       char *old_class_name = NULL, *new_class_name = NULL;
-
-       class_dev = class_device_get(class_dev);
-       if (!class_dev)
-               return -EINVAL;
-
-       pr_debug("CLASS: renaming '%s' to '%s'\n", class_dev->class_id,
-                new_name);
-
-#ifdef CONFIG_SYSFS_DEPRECATED
-       if (class_dev->dev)
-               old_class_name = make_class_name(class_dev->class->name,
-                                                &class_dev->kobj);
-#endif
-
-       strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN);
-
-       error = kobject_rename(&class_dev->kobj, new_name);
-
-#ifdef CONFIG_SYSFS_DEPRECATED
-       if (class_dev->dev) {
-               new_class_name = make_class_name(class_dev->class->name,
-                                                &class_dev->kobj);
-               if (new_class_name)
-                       sysfs_create_link(&class_dev->dev->kobj,
-                                         &class_dev->kobj, new_class_name);
-               if (old_class_name)
-                       sysfs_remove_link(&class_dev->dev->kobj,
-                                               old_class_name);
-       }
-#endif
-       class_device_put(class_dev);
-
-       kfree(old_class_name);
-       kfree(new_class_name);
-
-       return error;
-}
-
 struct class_device * class_device_get(struct class_device *class_dev)
 {
        if (class_dev)
index a8ac34ba610716a4fc5c4193920a3d44a4697ccd..f191afe62b4d06633dc84490ec6e630d983c6a1a 100644 (file)
 int (*platform_notify)(struct device * dev) = NULL;
 int (*platform_notify_remove)(struct device * dev) = NULL;
 
+/*
+ * Detect the LANANA-assigned LOCAL/EXPERIMENTAL majors
+ */
+bool is_lanana_major(unsigned int major)
+{
+       if (major >= 60 && major <= 63)
+               return 1;
+       if (major >= 120 && major <= 127)
+               return 1;
+       if (major >= 240 && major <= 254)
+               return 1;
+       return 0;
+}
+
 /*
  * sysfs bindings for devices.
  */
@@ -570,17 +584,17 @@ int device_add(struct device *dev)
                if (dev->kobj.parent != &dev->class->subsys.kset.kobj)
                        sysfs_create_link(&dev->class->subsys.kset.kobj,
                                          &dev->kobj, dev->bus_id);
-#ifdef CONFIG_SYSFS_DEPRECATED
                if (parent) {
                        sysfs_create_link(&dev->kobj, &dev->parent->kobj,
                                                        "device");
+#ifdef CONFIG_SYSFS_DEPRECATED
                        class_name = make_class_name(dev->class->name,
                                                        &dev->kobj);
                        if (class_name)
                                sysfs_create_link(&dev->parent->kobj,
                                                  &dev->kobj, class_name);
-               }
 #endif
+               }
        }
 
        if ((error = device_add_attrs(dev)))
@@ -623,12 +637,41 @@ int device_add(struct device *dev)
                                             BUS_NOTIFY_DEL_DEVICE, dev);
        device_remove_groups(dev);
  GroupError:
-       device_remove_attrs(dev);
+       device_remove_attrs(dev);
  AttrsError:
        if (dev->devt_attr) {
                device_remove_file(dev, dev->devt_attr);
                kfree(dev->devt_attr);
        }
+
+       if (dev->class) {
+               sysfs_remove_link(&dev->kobj, "subsystem");
+               /* If this is not a "fake" compatible device, remove the
+                * symlink from the class to the device. */
+               if (dev->kobj.parent != &dev->class->subsys.kset.kobj)
+                       sysfs_remove_link(&dev->class->subsys.kset.kobj,
+                                         dev->bus_id);
+               if (parent) {
+#ifdef CONFIG_SYSFS_DEPRECATED
+                       char *class_name = make_class_name(dev->class->name,
+                                                          &dev->kobj);
+                       if (class_name)
+                               sysfs_remove_link(&dev->parent->kobj,
+                                                 class_name);
+                       kfree(class_name);
+#endif
+                       sysfs_remove_link(&dev->kobj, "device");
+               }
+
+               down(&dev->class->sem);
+               /* notify any interfaces that the device is now gone */
+               list_for_each_entry(class_intf, &dev->class->interfaces, node)
+                       if (class_intf->remove_dev)
+                               class_intf->remove_dev(dev, class_intf);
+               /* remove the device from the class list */
+               list_del_init(&dev->node);
+               up(&dev->class->sem);
+       }
  ueventattrError:
        device_remove_file(dev, &dev->uevent_attr);
  attrError:
@@ -718,17 +761,17 @@ void device_del(struct device * dev)
                if (dev->kobj.parent != &dev->class->subsys.kset.kobj)
                        sysfs_remove_link(&dev->class->subsys.kset.kobj,
                                          dev->bus_id);
-#ifdef CONFIG_SYSFS_DEPRECATED
                if (parent) {
+#ifdef CONFIG_SYSFS_DEPRECATED
                        char *class_name = make_class_name(dev->class->name,
                                                           &dev->kobj);
                        if (class_name)
                                sysfs_remove_link(&dev->parent->kobj,
                                                  class_name);
                        kfree(class_name);
+#endif
                        sysfs_remove_link(&dev->kobj, "device");
                }
-#endif
 
                down(&dev->class->sem);
                /* notify any interfaces that the device is now gone */
@@ -744,6 +787,13 @@ void device_del(struct device * dev)
        device_remove_attrs(dev);
        bus_remove_device(dev);
 
+       /*
+        * Some platform devices are driven without driver attached
+        * and managed resources may have been acquired.  Make sure
+        * all resources are released.
+        */
+       devres_release_all(dev);
+
        /* Notify the platform of the removal, in case they
         * need to do anything...
         */
@@ -1015,14 +1065,14 @@ int device_rename(struct device *dev, char *new_name)
 
        return error;
 }
-
+EXPORT_SYMBOL_GPL(device_rename);
 
 static int device_move_class_links(struct device *dev,
                                   struct device *old_parent,
                                   struct device *new_parent)
 {
+       int error = 0;
 #ifdef CONFIG_SYSFS_DEPRECATED
-       int error;
        char *class_name;
 
        class_name = make_class_name(dev->class->name, &dev->kobj);
@@ -1050,7 +1100,12 @@ out:
        kfree(class_name);
        return error;
 #else
-       return 0;
+       if (old_parent)
+               sysfs_remove_link(&dev->kobj, "device");
+       if (new_parent)
+               error = sysfs_create_link(&dev->kobj, &new_parent->kobj,
+                                         "device");
+       return error;
 #endif
 }
 
index cacb1c816e355503757c84c745d00f9a3c81e185..17ee97f3a99b59900bd6b89f373e871a3662c6ce 100644 (file)
@@ -406,22 +406,6 @@ config BLK_DEV_RAM_BLOCKSIZE
          setups function - apparently needed by the rd_load_image routine
          that supposes the filesystem in the image uses a 1024 blocksize.
 
-config BLK_DEV_INITRD
-       bool "Initial RAM filesystem and RAM disk (initramfs/initrd) support"
-       depends on BROKEN || !FRV
-       help
-         The initial RAM filesystem is a ramfs which is loaded by the
-         boot loader (loadlin or lilo) and that is mounted as root
-         before the normal boot procedure. It is typically used to
-         load modules needed to mount the "real" root file system,
-         etc. See <file:Documentation/initrd.txt> for details.
-
-         If RAM disk support (BLK_DEV_RAM) is also included, this
-         also enables initial RAM disk (initrd) support and adds
-         15 Kbytes (more on some other architectures) to the kernel size.
-
-         If unsure say Y.
-
 config CDROM_PKTCDVD
        tristate "Packet writing on CD/DVD media"
        depends on !UML
index bb022ed4a8667936288ac328bde688a4dfbe16be..8d17d8df36621e479e3c2b7d4760ecc2baee2346 100644 (file)
@@ -530,7 +530,7 @@ aoecmd_ata_rsp(struct sk_buff *skb)
        u16 aoemajor;
 
        hin = (struct aoe_hdr *) skb->mac.raw;
-       aoemajor = be16_to_cpu(hin->major);
+       aoemajor = be16_to_cpu(get_unaligned(&hin->major));
        d = aoedev_by_aoeaddr(aoemajor, hin->minor);
        if (d == NULL) {
                snprintf(ebuf, sizeof ebuf, "aoecmd_ata_rsp: ata response "
@@ -542,7 +542,7 @@ aoecmd_ata_rsp(struct sk_buff *skb)
 
        spin_lock_irqsave(&d->lock, flags);
 
-       n = be32_to_cpu(hin->tag);
+       n = be32_to_cpu(get_unaligned(&hin->tag));
        f = getframe(d, n);
        if (f == NULL) {
                calc_rttavg(d, -tsince(n));
@@ -550,9 +550,9 @@ aoecmd_ata_rsp(struct sk_buff *skb)
                snprintf(ebuf, sizeof ebuf,
                        "%15s e%d.%d    tag=%08x@%08lx\n",
                        "unexpected rsp",
-                       be16_to_cpu(hin->major),
+                       be16_to_cpu(get_unaligned(&hin->major)),
                        hin->minor,
-                       be32_to_cpu(hin->tag),
+                       be32_to_cpu(get_unaligned(&hin->tag)),
                        jiffies);
                aoechr_error(ebuf);
                return;
@@ -631,7 +631,7 @@ aoecmd_ata_rsp(struct sk_buff *skb)
                        printk(KERN_INFO
                                "aoe: unrecognized ata command %2.2Xh for %d.%d\n",
                                ahout->cmdstat,
-                               be16_to_cpu(hin->major),
+                               be16_to_cpu(get_unaligned(&hin->major)),
                                hin->minor);
                }
        }
@@ -733,7 +733,7 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
         * Enough people have their dip switches set backwards to
         * warrant a loud message for this special case.
         */
-       aoemajor = be16_to_cpu(h->major);
+       aoemajor = be16_to_cpu(get_unaligned(&h->major));
        if (aoemajor == 0xfff) {
                printk(KERN_ERR "aoe: Warning: shelf address is all ones.  "
                        "Check shelf dip switches.\n");
index 9626e0f5da9dd4edc73d7ab559b3aa6d233e0836..aab6d91a2c2285b03c50a1249b49d333f70dfb20 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/blkdev.h>
 #include <linux/netdevice.h>
 #include <linux/moduleparam.h>
+#include <asm/unaligned.h>
 #include "aoe.h"
 
 #define NECODES 5
@@ -123,7 +124,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
        skb_push(skb, ETH_HLEN);        /* (1) */
 
        h = (struct aoe_hdr *) skb->mac.raw;
-       n = be32_to_cpu(h->tag);
+       n = be32_to_cpu(get_unaligned(&h->tag));
        if ((h->verfl & AOEFL_RSP) == 0 || (n & 1<<31))
                goto exit;
 
@@ -133,7 +134,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
                        n = 0;
                if (net_ratelimit())
                        printk(KERN_ERR "aoe: error packet from %d.%d; ecode=%d '%s'\n",
-                              be16_to_cpu(h->major), h->minor, 
+                              be16_to_cpu(get_unaligned(&h->major)), h->minor,
                               h->err, aoe_errlist[n]);
                goto exit;
        }
index 05dfe357527c231037365be190baef05b39ef5f3..0c716ee905d74273c92362f28b29abd74264858b 100644 (file)
@@ -1291,13 +1291,19 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
        if (inq_buff == NULL)
                goto mem_msg;
 
+       /* testing to see if 16-byte CDBs are already being used */
+       if (h->cciss_read == CCISS_READ_16) {
+               cciss_read_capacity_16(h->ctlr, drv_index, 1,
+                       &total_size, &block_size);
+               goto geo_inq;
+       }
+
        cciss_read_capacity(ctlr, drv_index, 1,
                            &total_size, &block_size);
 
-       /* total size = last LBA + 1 */
-       /* FFFFFFFF + 1 = 0, cannot have a logical volume of size 0 */
-       /* so we assume this volume this must be >2TB in size */
-       if (total_size == (__u32) 0) {
+       /* if read_capacity returns all F's this volume is >2TB in size */
+       /* so we switch to 16-byte CDB's for all read/write ops */
+       if (total_size == 0xFFFFFFFFULL) {
                cciss_read_capacity_16(ctlr, drv_index, 1,
                &total_size, &block_size);
                h->cciss_read = CCISS_READ_16;
@@ -1306,6 +1312,7 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
                h->cciss_read = CCISS_READ_10;
                h->cciss_write = CCISS_WRITE_10;
        }
+geo_inq:
        cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size,
                               inq_buff, &h->drv[drv_index]);
 
@@ -1917,13 +1924,14 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
                        drv->raid_level = inq_buff->data_byte[8];
                }
                drv->block_size = block_size;
-               drv->nr_blocks = total_size;
+               drv->nr_blocks = total_size + 1;
                t = drv->heads * drv->sectors;
                if (t > 1) {
-                       unsigned rem = sector_div(total_size, t);
+                       sector_t real_size = total_size + 1;
+                       unsigned long rem = sector_div(real_size, t);
                        if (rem)
-                               total_size++;
-                       drv->cylinders = total_size;
+                               real_size++;
+                       drv->cylinders = real_size;
                }
        } else {                /* Get geometry failed */
                printk(KERN_WARNING "cciss: reading geometry failed\n");
@@ -1953,16 +1961,16 @@ cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size,
                                ctlr, buf, sizeof(ReadCapdata_struct),
                                        1, logvol, 0, NULL, TYPE_CMD);
        if (return_code == IO_OK) {
-               *total_size = be32_to_cpu(*(__u32 *) buf->total_size)+1;
+               *total_size = be32_to_cpu(*(__u32 *) buf->total_size);
                *block_size = be32_to_cpu(*(__u32 *) buf->block_size);
        } else {                /* read capacity command failed */
                printk(KERN_WARNING "cciss: read capacity failed\n");
                *total_size = 0;
                *block_size = BLOCK_SIZE;
        }
-       if (*total_size != (__u32) 0)
+       if (*total_size != 0)
                printk(KERN_INFO "      blocks= %llu block_size= %d\n",
-               (unsigned long long)*total_size, *block_size);
+               (unsigned long long)*total_size+1, *block_size);
        kfree(buf);
        return;
 }
@@ -1989,7 +1997,7 @@ cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size,
                                1, logvol, 0, NULL, TYPE_CMD);
        }
        if (return_code == IO_OK) {
-               *total_size = be64_to_cpu(*(__u64 *) buf->total_size)+1;
+               *total_size = be64_to_cpu(*(__u64 *) buf->total_size);
                *block_size = be32_to_cpu(*(__u32 *) buf->block_size);
        } else {                /* read capacity command failed */
                printk(KERN_WARNING "cciss: read capacity failed\n");
@@ -1997,7 +2005,7 @@ cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size,
                *block_size = BLOCK_SIZE;
        }
        printk(KERN_INFO "      blocks= %llu block_size= %d\n",
-              (unsigned long long)*total_size, *block_size);
+              (unsigned long long)*total_size+1, *block_size);
        kfree(buf);
        return;
 }
@@ -3119,8 +3127,9 @@ static void cciss_getgeometry(int cntl_num)
                }
                cciss_read_capacity(cntl_num, i, 0, &total_size, &block_size);
 
-               /* total_size = last LBA + 1 */
-               if(total_size == (__u32) 0) {
+               /* If read_capacity returns all F's the logical is >2TB */
+               /* so we switch to 16-byte CDBs for all read/write ops */
+               if(total_size == 0xFFFFFFFFULL) {
                        cciss_read_capacity_16(cntl_num, i, 0,
                        &total_size, &block_size);
                        hba[cntl_num]->cciss_read = CCISS_READ_16;
@@ -3395,7 +3404,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
        return -1;
 }
 
-static void __devexit cciss_remove_one(struct pci_dev *pdev)
+static void cciss_remove_one(struct pci_dev *pdev)
 {
        ctlr_info_t *tmp_ptr;
        int i, j;
@@ -3419,9 +3428,10 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
        memset(flush_buf, 0, 4);
        return_code = sendcmd(CCISS_CACHE_FLUSH, i, flush_buf, 4, 0, 0, 0, NULL,
                              TYPE_CMD);
-       if (return_code != IO_OK) {
-               printk(KERN_WARNING "Error Flushing cache on controller %d\n",
-                      i);
+       if (return_code == IO_OK) {
+               printk(KERN_INFO "Completed flushing cache on controller %d\n", i);
+       } else {
+               printk(KERN_WARNING "Error flushing cache on controller %d\n", i);
        }
        free_irq(hba[i]->intr[2], hba[i]);
 
@@ -3472,6 +3482,7 @@ static struct pci_driver cciss_pci_driver = {
        .probe = cciss_init_one,
        .remove = __devexit_p(cciss_remove_one),
        .id_table = cciss_pci_device_id,        /* id_table */
+       .shutdown = cciss_remove_one,
 };
 
 /*
index 3f1b38276e96e123e6ec772cb08a605dd8d08032..5231ed7e723f0a1ef34ca61684e0ef563b2bc468 100644 (file)
@@ -297,17 +297,17 @@ static int initialising = 1;
 #define DRS (&drive_state[current_drive])
 #define DRWE (&write_errors[current_drive])
 #define FDCS (&fdc_state[fdc])
-#define CLEARF(x) (clear_bit(x##_BIT, &DRS->flags))
-#define SETF(x) (set_bit(x##_BIT, &DRS->flags))
-#define TESTF(x) (test_bit(x##_BIT, &DRS->flags))
+#define CLEARF(x) clear_bit(x##_BIT, &DRS->flags)
+#define SETF(x) set_bit(x##_BIT, &DRS->flags)
+#define TESTF(x) test_bit(x##_BIT, &DRS->flags)
 
 #define UDP (&drive_params[drive])
 #define UDRS (&drive_state[drive])
 #define UDRWE (&write_errors[drive])
 #define UFDCS (&fdc_state[FDC(drive)])
-#define UCLEARF(x) (clear_bit(x##_BIT, &UDRS->flags))
-#define USETF(x) (set_bit(x##_BIT, &UDRS->flags))
-#define UTESTF(x) (test_bit(x##_BIT, &UDRS->flags))
+#define UCLEARF(x) clear_bit(x##_BIT, &UDRS->flags)
+#define USETF(x) set_bit(x##_BIT, &UDRS->flags)
+#define UTESTF(x) test_bit(x##_BIT, &UDRS->flags)
 
 #define DPRINT(format, args...) printk(DEVICE_NAME "%d: " format, current_drive , ## args)
 
index 93fb6ed4ed522da8b53c3dcc96a915bf80e027eb..a4fb7038318817d02b6d39f83c5ccf8e004408dd 100644 (file)
@@ -765,7 +765,7 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
                        goto out;
        }
 
-       rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
+       rq->cmd_len = COMMAND_SIZE(cgc->cmd[0]);
        memcpy(rq->cmd, cgc->cmd, CDROM_PACKET_SIZE);
        if (sizeof(rq->cmd) > CDROM_PACKET_SIZE)
                memset(rq->cmd + CDROM_PACKET_SIZE, 0, sizeof(rq->cmd) - CDROM_PACKET_SIZE);
index dff3766f117f3307fdc52fbb46a9126db32d4a14..5872036e8ae6b90f36b2c29789c826755f0d7903 100644 (file)
@@ -1179,8 +1179,10 @@ static int __init mm_init(void)
                return -ENOMEM;
 
        err = major_nr = register_blkdev(0, "umem");
-       if (err < 0)
+       if (err < 0) {
+               pci_unregister_driver(&mm_pci_driver);
                return -EIO;
+       }
 
        for (i = 0; i < num_cards; i++) {
                mm_gendisk[i] = alloc_disk(1 << MM_SHIFT);
@@ -1207,6 +1209,7 @@ static int __init mm_init(void)
        return 0;
 
 out:
+       pci_unregister_driver(&mm_pci_driver);
        unregister_blkdev(major_nr, "umem");
        while (i--)
                put_disk(mm_gendisk[i]);
index 9256985cbe36c727af74aec9333a8c0c5049dc05..8919ccf8274b3141c4fc240f7b83fc12b7203708 100644 (file)
@@ -307,3 +307,5 @@ MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
 MODULE_DESCRIPTION("Broadcom Blutonium firmware driver ver " VERSION);
 MODULE_VERSION(VERSION);
 MODULE_LICENSE("GPL");
+MODULE_FIRMWARE("BCM2033-MD.hex");
+MODULE_FIRMWARE("BCM2033-FW.bin");
index 27cceb6f5652ca4f0a694411273966fbfcfb09a4..4c766f36d8844c05cf4a07fcd198bb2ba14b0fcb 100644 (file)
@@ -801,3 +801,4 @@ MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
 MODULE_DESCRIPTION("BlueFRITZ! USB driver ver " VERSION);
 MODULE_VERSION(VERSION);
 MODULE_LICENSE("GPL");
+MODULE_FIRMWARE("bfubase.frm");
index 34e5555cb917d999b33f54815b7baf4d2426c8fa..18b0f3992c5ba54ce710b85784141f22885ee987 100644 (file)
@@ -63,6 +63,7 @@
 MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>, Jose Orlando Pereira <jop@di.uminho.pt>");
 MODULE_DESCRIPTION("Bluetooth driver for the 3Com Bluetooth PCMCIA card");
 MODULE_LICENSE("GPL");
+MODULE_FIRMWARE("BT3CPCC.bin");
 
 
 
index dc13ebacedfb4446bc788e72804641e404eeb4a7..44cd7b2ddf09ca786446bb8c8adfc7f52bf6d503 100644 (file)
@@ -376,6 +376,25 @@ static int send_request(struct request *req)
        return 0;
 }
 
+static void viocd_end_request(struct request *req, int uptodate)
+{
+       int nsectors = req->hard_nr_sectors;
+
+       /*
+        * Make sure it's fully ended, and ensure that we process
+        * at least one sector.
+        */
+       if (blk_pc_request(req))
+               nsectors = (req->data_len + 511) >> 9;
+       if (!nsectors)
+               nsectors = 1;
+
+       if (end_that_request_first(req, uptodate, nsectors))
+               BUG();
+       add_disk_randomness(req->rq_disk);
+       blkdev_dequeue_request(req);
+       end_that_request_last(req, uptodate);
+}
 
 static int rwreq;
 
@@ -385,11 +404,11 @@ static void do_viocd_request(request_queue_t *q)
 
        while ((rwreq == 0) && ((req = elv_next_request(q)) != NULL)) {
                if (!blk_fs_request(req))
-                       end_request(req, 0);
+                       viocd_end_request(req, 0);
                else if (send_request(req) < 0) {
                        printk(VIOCD_KERN_WARNING
                                        "unable to send message to OS/400!");
-                       end_request(req, 0);
+                       viocd_end_request(req, 0);
                } else
                        rwreq++;
        }
@@ -601,9 +620,9 @@ return_complete:
                                        "with rc %d:0x%04X: %s\n",
                                        req, event->xRc,
                                        bevent->sub_result, err->msg);
-                       end_request(req, 0);
+                       viocd_end_request(req, 0);
                } else
-                       end_request(req, 1);
+                       viocd_end_request(req, 1);
 
                /* restart handling of incoming requests */
                spin_unlock_irqrestore(&viocd_reqlock, flags);
index d0a6dc53213c00ecb5e22c7b5933c9789c195e30..3429ece4ef92513abe134a3555f331d8673a36be 100644 (file)
@@ -1026,16 +1026,17 @@ config MMTIMER
 source "drivers/char/tpm/Kconfig"
 
 config TELCLOCK
-       tristate "Telecom clock driver for MPBL0010 ATCA SBC"
+       tristate "Telecom clock driver for ATCA SBC"
        depends on EXPERIMENTAL && X86
        default n
        help
-         The telecom clock device is specific to the MPBL0010 ATCA computer and
-         allows direct userspace access to the configuration of the telecom clock
-         configuration settings.  This device is used for hardware synchronization
-         across the ATCA backplane fabric.  Upon loading, the driver exports a
-         sysfs directory, /sys/devices/platform/telco_clock, with a number of
-         files for controlling the behavior of this hardware.
+         The telecom clock device is specific to the MPCBL0010 and MPCBL0050
+         ATCA computers and allows direct userspace access to the
+         configuration of the telecom clock configuration settings.  This
+         device is used for hardware synchronization across the ATCA backplane
+         fabric.  Upon loading, the driver exports a sysfs directory,
+         /sys/devices/platform/telco_clock, with a number of files for
+         controlling the behavior of this hardware.
 
 endmenu
 
index a0d04a23dacd2f3c809118244c60d7a1bd9ec969..627f542827c7069b4352bb1692d0baae2af63d38 100644 (file)
@@ -1,7 +1,8 @@
 agpgart-y := backend.o frontend.o generic.o isoch.o
 
+agpgart-$(CONFIG_COMPAT)       += compat_ioctl.o
+
 obj-$(CONFIG_AGP)              += agpgart.o
-obj-$(CONFIG_COMPAT)           += compat_ioctl.o
 obj-$(CONFIG_AGP_ALI)          += ali-agp.o
 obj-$(CONFIG_AGP_ATI)          += ati-agp.o
 obj-$(CONFIG_AGP_AMD)          += amd-k7-agp.o
index 9bd68d9f0f5989105b6349ba98004d9cff381b2e..fdbca25a3948a14437181d2bd4b89567dfcdcf2e 100644 (file)
@@ -93,12 +93,12 @@ struct aper_size_info_fixed {
 
 struct agp_bridge_driver {
        struct module *owner;
-       void *aperture_sizes;
+       const void *aperture_sizes;
        int num_aperture_sizes;
        enum aper_size_type size_type;
        int cant_use_aperture;
        int needs_scratch_page;
-       struct gatt_mask *masks;
+       const struct gatt_mask *masks;
        int (*fetch_size)(void);
        int (*configure)(void);
        void (*agp_enable)(struct agp_bridge_data *, u32);
@@ -119,7 +119,7 @@ struct agp_bridge_driver {
 
 struct agp_bridge_data {
        const struct agp_version *version;
-       struct agp_bridge_driver *driver;
+       const struct agp_bridge_driver *driver;
        struct vm_operations_struct *vm_ops;
        void *previous_size;
        void *current_size;
@@ -290,7 +290,7 @@ void agp3_generic_cleanup(void);
 
 /* aperture sizes have been standardised since v3 */
 #define AGP_GENERIC_SIZES_ENTRIES 11
-extern struct aper_size_info_16 agp3_generic_sizes[];
+extern const struct aper_size_info_16 agp3_generic_sizes[];
 
 #define virt_to_gart(x) (phys_to_gart(virt_to_phys(x)))
 #define gart_to_virt(x) (phys_to_virt(gart_to_phys(x)))
index 98177a93076f5c7d4f7959b93b37ae0b99617120..5b684fddcc0338bc5f55b074cf01e8fb0e5e6a9b 100644 (file)
@@ -182,7 +182,7 @@ static void m1541_destroy_page(void * addr)
 
 /* Setup function */
 
-static struct aper_size_info_32 ali_generic_sizes[7] =
+static const struct aper_size_info_32 ali_generic_sizes[7] =
 {
        {256, 65536, 6, 10},
        {128, 32768, 5, 9},
@@ -193,7 +193,7 @@ static struct aper_size_info_32 ali_generic_sizes[7] =
        {4, 1024, 0, 3}
 };
 
-static struct agp_bridge_driver ali_generic_bridge = {
+static const struct agp_bridge_driver ali_generic_bridge = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = ali_generic_sizes,
        .size_type              = U32_APER_SIZE,
@@ -217,7 +217,7 @@ static struct agp_bridge_driver ali_generic_bridge = {
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_bridge_driver ali_m1541_bridge = {
+static const struct agp_bridge_driver ali_m1541_bridge = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = ali_generic_sizes,
        .size_type              = U32_APER_SIZE,
index 3d8d448bf394a181afcd4fc7319b87471aede4a7..e6c534e6284638a610d8a1549b52530d6d4225af 100644 (file)
@@ -344,7 +344,7 @@ static int amd_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
        return 0;
 }
 
-static struct aper_size_info_lvl2 amd_irongate_sizes[7] =
+static const struct aper_size_info_lvl2 amd_irongate_sizes[7] =
 {
        {2048, 524288, 0x0000000c},
        {1024, 262144, 0x0000000a},
@@ -355,12 +355,12 @@ static struct aper_size_info_lvl2 amd_irongate_sizes[7] =
        {32, 8192, 0x00000000}
 };
 
-static struct gatt_mask amd_irongate_masks[] =
+static const struct gatt_mask amd_irongate_masks[] =
 {
        {.mask = 1, .type = 0}
 };
 
-static struct agp_bridge_driver amd_irongate_driver = {
+static const struct agp_bridge_driver amd_irongate_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = amd_irongate_sizes,
        .size_type              = LVL2_APER_SIZE,
index 636d984ed4a62598dc1e11f174f9e9a90262bfee..485720486d600931dd526d5ff6415d1f19886bb9 100644 (file)
@@ -192,7 +192,7 @@ static u64 amd64_configure (struct pci_dev *hammer, u64 gatt_table)
 }
 
 
-static struct aper_size_info_32 amd_8151_sizes[7] =
+static const struct aper_size_info_32 amd_8151_sizes[7] =
 {
        {2048, 524288, 9, 0x00000000 }, /* 0 0 0 0 0 0 */
        {1024, 262144, 8, 0x00000400 }, /* 1 0 0 0 0 0 */
@@ -232,7 +232,7 @@ static void amd64_cleanup(void)
 }
 
 
-static struct agp_bridge_driver amd_8151_driver = {
+static const struct agp_bridge_driver amd_8151_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = amd_8151_sizes,
        .size_type              = U32_APER_SIZE,
index 77c9ad68fba919b09cd72013639622149164d382..780e59e588ad968c82f6b1a7b15df14925ff35fa 100644 (file)
@@ -24,7 +24,7 @@
 #define ATI_GART_CACHE_ENTRY_CNTRL     0x10
 
 
-static struct aper_size_info_lvl2 ati_generic_sizes[7] =
+static const struct aper_size_info_lvl2 ati_generic_sizes[7] =
 {
        {2048, 524288, 0x0000000c},
        {1024, 262144, 0x0000000a},
@@ -410,7 +410,7 @@ static int ati_free_gatt_table(struct agp_bridge_data *bridge)
        return 0;
 }
 
-static struct agp_bridge_driver ati_generic_bridge = {
+static const struct agp_bridge_driver ati_generic_bridge = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = ati_generic_sizes,
        .size_type              = LVL2_APER_SIZE,
index 658cb1a72d2cf65d9c5244775ecdf1b696313b02..df8da7262853d8d3320f8561ee8a378930e99b37 100644 (file)
@@ -59,7 +59,7 @@ static struct _efficeon_private {
        unsigned long l1_table[EFFICEON_L1_SIZE];
 } efficeon_private;
 
-static struct gatt_mask efficeon_generic_masks[] =
+static const struct gatt_mask efficeon_generic_masks[] =
 {
        {.mask = 0x00000001, .type = 0}
 };
@@ -70,7 +70,7 @@ static inline unsigned long efficeon_mask_memory(unsigned long addr)
        return addr | 0x00000001;
 }
 
-static struct aper_size_info_lvl2 efficeon_generic_sizes[4] =
+static const struct aper_size_info_lvl2 efficeon_generic_sizes[4] =
 {
        {256, 65536, 0},
        {128, 32768, 32},
@@ -309,7 +309,7 @@ static int efficeon_remove_memory(struct agp_memory * mem, off_t pg_start, int t
 }
 
 
-static struct agp_bridge_driver efficeon_driver = {
+static const struct agp_bridge_driver efficeon_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = efficeon_generic_sizes,
        .size_type              = LVL2_APER_SIZE,
index 7923337c3d26ae3db5a3aea6496eae8dd4836df6..f902d71947ba9914507c6b900bffc17aa6915d53 100644 (file)
@@ -1340,7 +1340,7 @@ void agp3_generic_cleanup(void)
 }
 EXPORT_SYMBOL(agp3_generic_cleanup);
 
-struct aper_size_info_16 agp3_generic_sizes[AGP_GENERIC_SIZES_ENTRIES] =
+const struct aper_size_info_16 agp3_generic_sizes[AGP_GENERIC_SIZES_ENTRIES] =
 {
        {4096, 1048576, 10,0x000},
        {2048,  524288, 9, 0x800},
index 847deabf7f9b6b110f694d68856cb82c7fab9f56..bcdb149c8179cec8beeb15fe22394428504c467b 100644 (file)
@@ -419,7 +419,7 @@ hp_zx1_enable (struct agp_bridge_data *bridge, u32 mode)
        agp_device_command(command, (mode & AGP8X_MODE) != 0);
 }
 
-struct agp_bridge_driver hp_zx1_driver = {
+const struct agp_bridge_driver hp_zx1_driver = {
        .owner                  = THIS_MODULE,
        .size_type              = FIXED_APER_SIZE,
        .configure              = hp_zx1_configure,
index 3e7618653abd05ca4f74b12788e018251dd88b74..53354bf83af76389ba56c09b2c9a047e87460dd7 100644 (file)
@@ -78,7 +78,7 @@ static struct {
        } *lp_desc;
 } i460;
 
-static struct aper_size_info_8 i460_sizes[3] =
+static const struct aper_size_info_8 i460_sizes[3] =
 {
        /*
         * The 32GB aperture is only available with a 4M GART page size.  Due to the
@@ -550,7 +550,7 @@ static unsigned long i460_mask_memory (struct agp_bridge_data *bridge,
                | (((addr & ~((1 << I460_IO_PAGE_SHIFT) - 1)) & 0xfffff000) >> 12);
 }
 
-struct agp_bridge_driver intel_i460_driver = {
+const struct agp_bridge_driver intel_i460_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = i460_sizes,
        .size_type              = U8_APER_SIZE,
index 06b0bb6d982fca6486a928b98f7e84898a515579..e542a628f1c7dca18def0e5e62ec40e15cac6b84 100644 (file)
@@ -63,7 +63,7 @@ extern int agp_memory_reserved;
 #define INTEL_I7505_AGPCTRL    0x70
 #define INTEL_I7505_MCHCFG     0x50
 
-static struct aper_size_info_fixed intel_i810_sizes[] =
+static const struct aper_size_info_fixed intel_i810_sizes[] =
 {
        {64, 16384, 4},
        /* The 32M mode still requires a 64k gatt */
@@ -1365,18 +1365,18 @@ static int intel_7505_configure(void)
 }
 
 /* Setup function */
-static struct gatt_mask intel_generic_masks[] =
+static const struct gatt_mask intel_generic_masks[] =
 {
        {.mask = 0x00000017, .type = 0}
 };
 
-static struct aper_size_info_8 intel_815_sizes[2] =
+static const struct aper_size_info_8 intel_815_sizes[2] =
 {
        {64, 16384, 4, 0},
        {32, 8192, 3, 8},
 };
 
-static struct aper_size_info_8 intel_8xx_sizes[7] =
+static const struct aper_size_info_8 intel_8xx_sizes[7] =
 {
        {256, 65536, 6, 0},
        {128, 32768, 5, 32},
@@ -1387,7 +1387,7 @@ static struct aper_size_info_8 intel_8xx_sizes[7] =
        {4, 1024, 0, 63}
 };
 
-static struct aper_size_info_16 intel_generic_sizes[7] =
+static const struct aper_size_info_16 intel_generic_sizes[7] =
 {
        {256, 65536, 6, 0},
        {128, 32768, 5, 32},
@@ -1398,7 +1398,7 @@ static struct aper_size_info_16 intel_generic_sizes[7] =
        {4, 1024, 0, 63}
 };
 
-static struct aper_size_info_8 intel_830mp_sizes[4] =
+static const struct aper_size_info_8 intel_830mp_sizes[4] =
 {
        {256, 65536, 6, 0},
        {128, 32768, 5, 32},
@@ -1406,7 +1406,7 @@ static struct aper_size_info_8 intel_830mp_sizes[4] =
        {32, 8192, 3, 56}
 };
 
-static struct agp_bridge_driver intel_generic_driver = {
+static const struct agp_bridge_driver intel_generic_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = intel_generic_sizes,
        .size_type              = U16_APER_SIZE,
@@ -1430,7 +1430,7 @@ static struct agp_bridge_driver intel_generic_driver = {
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_bridge_driver intel_810_driver = {
+static const struct agp_bridge_driver intel_810_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = intel_i810_sizes,
        .size_type              = FIXED_APER_SIZE,
@@ -1455,7 +1455,7 @@ static struct agp_bridge_driver intel_810_driver = {
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_bridge_driver intel_815_driver = {
+static const struct agp_bridge_driver intel_815_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = intel_815_sizes,
        .size_type              = U8_APER_SIZE,
@@ -1479,7 +1479,7 @@ static struct agp_bridge_driver intel_815_driver = {
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_bridge_driver intel_830_driver = {
+static const struct agp_bridge_driver intel_830_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = intel_i830_sizes,
        .size_type              = FIXED_APER_SIZE,
@@ -1504,7 +1504,7 @@ static struct agp_bridge_driver intel_830_driver = {
        .agp_type_to_mask_type  = intel_i830_type_to_mask_type,
 };
 
-static struct agp_bridge_driver intel_820_driver = {
+static const struct agp_bridge_driver intel_820_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = intel_8xx_sizes,
        .size_type              = U8_APER_SIZE,
@@ -1528,7 +1528,7 @@ static struct agp_bridge_driver intel_820_driver = {
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_bridge_driver intel_830mp_driver = {
+static const struct agp_bridge_driver intel_830mp_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = intel_830mp_sizes,
        .size_type              = U8_APER_SIZE,
@@ -1552,7 +1552,7 @@ static struct agp_bridge_driver intel_830mp_driver = {
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_bridge_driver intel_840_driver = {
+static const struct agp_bridge_driver intel_840_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = intel_8xx_sizes,
        .size_type              = U8_APER_SIZE,
@@ -1576,7 +1576,7 @@ static struct agp_bridge_driver intel_840_driver = {
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_bridge_driver intel_845_driver = {
+static const struct agp_bridge_driver intel_845_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = intel_8xx_sizes,
        .size_type              = U8_APER_SIZE,
@@ -1600,7 +1600,7 @@ static struct agp_bridge_driver intel_845_driver = {
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_bridge_driver intel_850_driver = {
+static const struct agp_bridge_driver intel_850_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = intel_8xx_sizes,
        .size_type              = U8_APER_SIZE,
@@ -1624,7 +1624,7 @@ static struct agp_bridge_driver intel_850_driver = {
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_bridge_driver intel_860_driver = {
+static const struct agp_bridge_driver intel_860_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = intel_8xx_sizes,
        .size_type              = U8_APER_SIZE,
@@ -1648,7 +1648,7 @@ static struct agp_bridge_driver intel_860_driver = {
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_bridge_driver intel_915_driver = {
+static const struct agp_bridge_driver intel_915_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = intel_i830_sizes,
        .size_type              = FIXED_APER_SIZE,
@@ -1673,7 +1673,7 @@ static struct agp_bridge_driver intel_915_driver = {
        .agp_type_to_mask_type  = intel_i830_type_to_mask_type,
 };
 
-static struct agp_bridge_driver intel_i965_driver = {
+static const struct agp_bridge_driver intel_i965_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = intel_i830_sizes,
        .size_type              = FIXED_APER_SIZE,
@@ -1698,7 +1698,7 @@ static struct agp_bridge_driver intel_i965_driver = {
        .agp_type_to_mask_type  = intel_i830_type_to_mask_type,
 };
 
-static struct agp_bridge_driver intel_7505_driver = {
+static const struct agp_bridge_driver intel_7505_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = intel_8xx_sizes,
        .size_type              = U8_APER_SIZE,
index 2563286b2fcf3db9a112a986147cd0d23c2c5ed0..0c9dab557c947601bc35c102159150c2469a4736 100644 (file)
@@ -272,7 +272,7 @@ static void nvidia_tlbflush(struct agp_memory *mem)
 }
 
 
-static struct aper_size_info_8 nvidia_generic_sizes[5] =
+static const struct aper_size_info_8 nvidia_generic_sizes[5] =
 {
        {512, 131072, 7, 0},
        {256, 65536, 6, 8},
@@ -283,13 +283,13 @@ static struct aper_size_info_8 nvidia_generic_sizes[5] =
 };
 
 
-static struct gatt_mask nvidia_generic_masks[] =
+static const struct gatt_mask nvidia_generic_masks[] =
 {
        { .mask = 1, .type = 0}
 };
 
 
-static struct agp_bridge_driver nvidia_driver = {
+static const struct agp_bridge_driver nvidia_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = nvidia_generic_sizes,
        .size_type              = U8_APER_SIZE,
index b7b4590673ae977d67231ffb5eeb381b2243bcfb..3d83b461ccadef926c80f8217de6e2688840557d 100644 (file)
@@ -210,7 +210,7 @@ parisc_agp_enable(struct agp_bridge_data *bridge, u32 mode)
        agp_device_command(command, (mode & AGP8X_MODE) != 0);
 }
 
-struct agp_bridge_driver parisc_agp_driver = {
+static const struct agp_bridge_driver parisc_agp_driver = {
        .owner                  = THIS_MODULE,
        .size_type              = FIXED_APER_SIZE,
        .configure              = parisc_agp_configure,
@@ -236,7 +236,7 @@ static int __init
 agp_ioc_init(void __iomem *ioc_regs)
 {
        struct _parisc_agp_info *info = &parisc_agp_info;
-        u64 *iova_base, *io_pdir, io_tlb_ps;
+        u64 iova_base, *io_pdir, io_tlb_ps;
         int io_tlb_shift;
 
         printk(KERN_INFO DRVPFX "IO PDIR shared with sba_iommu\n");
index 92d1dc45b9be05d53fa04fde3c21c2dae4097488..ee8f50edde1bd1f320c7ce15002e035be81883b2 100644 (file)
@@ -247,7 +247,7 @@ static struct agp_bridge_data *sgi_tioca_find_bridge(struct pci_dev *pdev)
        return bridge;
 }
 
-struct agp_bridge_driver sgi_tioca_driver = {
+const struct agp_bridge_driver sgi_tioca_driver = {
        .owner = THIS_MODULE,
        .size_type = U16_APER_SIZE,
        .configure = sgi_tioca_configure,
index 60342b708152d25ccd06bbf097b438f179017bb3..125f4282d9553697b091152bc040c40a6985ef4e 100644 (file)
@@ -108,7 +108,7 @@ static void sis_delayed_enable(struct agp_bridge_data *bridge, u32 mode)
        }
 }
 
-static struct aper_size_info_8 sis_generic_sizes[7] =
+static const struct aper_size_info_8 sis_generic_sizes[7] =
 {
        {256, 65536, 6, 99},
        {128, 32768, 5, 83},
index 9f5ae7714f85e1c8e30e7ff3ae2440f24e5ea91e..55212a3811fd9568767fc533d6308a77262254cc 100644 (file)
@@ -385,12 +385,12 @@ static int serverworks_remove_memory(struct agp_memory *mem, off_t pg_start,
        return 0;
 }
 
-static struct gatt_mask serverworks_masks[] =
+static const struct gatt_mask serverworks_masks[] =
 {
        {.mask = 1, .type = 0}
 };
 
-static struct aper_size_info_lvl2 serverworks_sizes[7] =
+static const struct aper_size_info_lvl2 serverworks_sizes[7] =
 {
        {2048, 524288, 0x80000000},
        {1024, 262144, 0xc0000000},
@@ -423,7 +423,7 @@ static void serverworks_agp_enable(struct agp_bridge_data *bridge, u32 mode)
        agp_device_command(command, 0);
 }
 
-static struct agp_bridge_driver sworks_driver = {
+static const struct agp_bridge_driver sworks_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = serverworks_sizes,
        .size_type              = LVL2_APER_SIZE,
index 6c45702e542cc7394ee5596b0d06ef3a2d49047b..91b062126a686edd0af2c2e2e564c2f4a9181d81 100644 (file)
@@ -460,7 +460,7 @@ void null_cache_flush(void)
 
 /* Setup function */
 
-static struct aper_size_info_32 uninorth_sizes[7] =
+static const struct aper_size_info_32 uninorth_sizes[7] =
 {
 #if 0 /* Not sure uninorth supports that high aperture sizes */
        {256, 65536, 6, 64},
@@ -477,7 +477,7 @@ static struct aper_size_info_32 uninorth_sizes[7] =
  * Not sure that u3 supports that high aperture sizes but it
  * would strange if it did not :)
  */
-static struct aper_size_info_32 u3_sizes[8] =
+static const struct aper_size_info_32 u3_sizes[8] =
 {
        {512, 131072, 7, 128},
        {256, 65536, 6, 64},
@@ -489,7 +489,7 @@ static struct aper_size_info_32 u3_sizes[8] =
        {4, 1024, 0, 1}
 };
 
-struct agp_bridge_driver uninorth_agp_driver = {
+const struct agp_bridge_driver uninorth_agp_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = (void *)uninorth_sizes,
        .size_type              = U32_APER_SIZE,
@@ -514,7 +514,7 @@ struct agp_bridge_driver uninorth_agp_driver = {
        .cant_use_aperture      = 1,
 };
 
-struct agp_bridge_driver u3_agp_driver = {
+const struct agp_bridge_driver u3_agp_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = (void *)u3_sizes,
        .size_type              = U32_APER_SIZE,
index 2e7c04370cd9e16340ed51da02f38ac30cbce086..a2bb4eccaab4c08fbbf24049ee1a7b1d5d64cf4e 100644 (file)
@@ -89,7 +89,7 @@ static void via_tlbflush(struct agp_memory *mem)
 }
 
 
-static struct aper_size_info_8 via_generic_sizes[9] =
+static const struct aper_size_info_8 via_generic_sizes[9] =
 {
        {256, 65536, 6, 0},
        {128, 32768, 5, 128},
@@ -170,7 +170,7 @@ static void via_tlbflush_agp3(struct agp_memory *mem)
 }
 
 
-static struct agp_bridge_driver via_agp3_driver = {
+static const struct agp_bridge_driver via_agp3_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = agp3_generic_sizes,
        .size_type              = U8_APER_SIZE,
@@ -194,7 +194,7 @@ static struct agp_bridge_driver via_agp3_driver = {
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_bridge_driver via_driver = {
+static const struct agp_bridge_driver via_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = via_generic_sizes,
        .size_type              = U8_APER_SIZE,
index 54df35527bc50b0d946fd1c7993d6aa84afed6b8..16dc5d1d3cb4f2715be9889d3e2a8bf822dfefec 100644 (file)
@@ -3501,6 +3501,7 @@ get_serial_info(struct cyclades_port *info,
        tmp.irq = cinfo->irq;
        tmp.flags = info->flags;
        tmp.close_delay = info->close_delay;
+       tmp.closing_wait = info->closing_wait;
        tmp.baud_base = info->baud;
        tmp.custom_divisor = info->custom_divisor;
        tmp.hub6 = 0;           /*!!! */
index 6d58b037080234431b49f6cacde669998ab749a7..59146e3365bac8bbda37b45d33297c0c9d071b7e 100644 (file)
@@ -197,6 +197,7 @@ static int ds1286_ioctl(struct inode *inode, struct file *file,
 
                hrs = alm_tm.tm_hour;
                min = alm_tm.tm_min;
+               sec = alm_tm.tm_sec;
 
                if (hrs >= 24)
                        hrs = 0xff;
@@ -204,9 +205,11 @@ static int ds1286_ioctl(struct inode *inode, struct file *file,
                if (min >= 60)
                        min = 0xff;
 
-               BIN_TO_BCD(sec);
-               BIN_TO_BCD(min);
-               BIN_TO_BCD(hrs);
+               if (sec != 0)
+                       return -EINVAL;
+
+               min = BIN2BCD(min);
+               min = BIN2BCD(hrs);
 
                spin_lock(&ds1286_lock);
                rtc_write(hrs, RTC_HOURS_ALARM);
index 88fc24fc43928674ef24647a394a2348cd18c082..de5be30484ad3d9f8b91b8f0699ca39c97647d99 100644 (file)
@@ -209,7 +209,6 @@ static void digi_send_break(struct channel *ch, int msec);
 static void setup_empty_event(struct tty_struct *tty, struct channel *ch);
 void epca_setup(char *, int *);
 
-static int get_termio(struct tty_struct *, struct termio __user *);
 static int pc_write(struct tty_struct *, const unsigned char *, int);
 static int pc_init(void);
 static int init_PCI(void);
@@ -2362,15 +2361,6 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
 
        switch (cmd) 
        { /* Begin switch cmd */
-
-#if 0  /* Handled by calling layer properly */
-               case TCGETS:
-                       if (copy_to_user(argp, tty->termios, sizeof(struct ktermios)))
-                               return -EFAULT;
-                       return 0;
-               case TCGETA:
-                       return get_termio(tty, argp);
-#endif
                case TCSBRK:    /* SVID version: non-zero arg --> no break */
                        retval = tty_check_change(tty);
                        if (retval)
@@ -2735,13 +2725,6 @@ static void setup_empty_event(struct tty_struct *tty, struct channel *ch)
        memoff(ch);
 } /* End setup_empty_event */
 
-/* --------------------- Begin get_termio ----------------------- */
-
-static int get_termio(struct tty_struct * tty, struct termio __user * termio)
-{ /* Begin get_termio */
-       return kernel_termios_to_user_termio(termio, tty->termios);
-} /* End get_termio */
-
 /* ---------------------- Begin epca_setup  -------------------------- */
 void epca_setup(char *str, int *ints)
 { /* Begin epca_setup */
index cc2cd46bedc6ac6dac8dd7d256a3605c784128cf..a0a88aa23f5b751457e01470afbe6f06068678c9 100644 (file)
@@ -316,7 +316,7 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
 {
        struct hvc_struct *hp;
        unsigned long flags;
-       int irq = NO_IRQ;
+       int irq = 0;
        int rc = 0;
        struct kobject *kobjp;
 
@@ -338,14 +338,14 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
        hp->tty = tty;
        /* Save for request_irq outside of spin_lock. */
        irq = hp->irq;
-       if (irq != NO_IRQ)
+       if (irq)
                hp->irq_requested = 1;
 
        kobjp = &hp->kobj;
 
        spin_unlock_irqrestore(&hp->lock, flags);
        /* check error, fallback to non-irq */
-       if (irq != NO_IRQ)
+       if (irq)
                rc = request_irq(irq, hvc_handle_interrupt, IRQF_DISABLED, "hvc_console", hp);
 
        /*
@@ -373,7 +373,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
 {
        struct hvc_struct *hp;
        struct kobject *kobjp;
-       int irq = NO_IRQ;
+       int irq = 0;
        unsigned long flags;
 
        if (tty_hung_up_p(filp))
@@ -407,7 +407,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
                 */
                tty_wait_until_sent(tty, HVC_CLOSE_WAIT);
 
-               if (irq != NO_IRQ)
+               if (irq)
                        free_irq(irq, hp);
 
        } else {
@@ -424,7 +424,7 @@ static void hvc_hangup(struct tty_struct *tty)
 {
        struct hvc_struct *hp = tty->driver_data;
        unsigned long flags;
-       int irq = NO_IRQ;
+       int irq = 0;
        int temp_open_count;
        struct kobject *kobjp;
 
@@ -453,7 +453,7 @@ static void hvc_hangup(struct tty_struct *tty)
                irq = hp->irq;
        hp->irq_requested = 0;
        spin_unlock_irqrestore(&hp->lock, flags);
-       if (irq != NO_IRQ)
+       if (irq)
                free_irq(irq, hp);
        while(temp_open_count) {
                --temp_open_count;
@@ -583,7 +583,7 @@ static int hvc_poll(struct hvc_struct *hp)
        /* If we aren't interrupt driven and aren't throttled, we always
         * request a reschedule
         */
-       if (hp->irq == NO_IRQ)
+       if (hp->irq == 0)
                poll_mask |= HVC_POLL_READ;
 
        /* Read data if any */
index f86fa0c55d364b05131574d6b48a73be996d5872..e46120d05b689af32f855e68a1656fd1d9794fd0 100644 (file)
@@ -80,7 +80,7 @@ static int i2RetryFlushOutput(i2ChanStrPtr);
 // Not a documented part of the library routines (careful...) but the Diagnostic
 // i2diag.c finds them useful to help the throughput in certain limited
 // single-threaded operations.
-static inline void iiSendPendingMail(i2eBordStrPtr);
+static void iiSendPendingMail(i2eBordStrPtr);
 static void serviceOutgoingFifo(i2eBordStrPtr);
 
 // Functions defined in ip2.c as part of interrupt handling
@@ -166,7 +166,7 @@ static void iiSendPendingMail_t(unsigned long data)
 // If any outgoing mail bits are set and there is outgoing mailbox is empty,
 // send the mail and clear the bits.
 //******************************************************************************
-static inline void
+static void
 iiSendPendingMail(i2eBordStrPtr pB)
 {
        if (pB->i2eOutMailWaiting && (!pB->i2eWaitingForEmptyFifo) )
index a7b33d2f5991c84fd332ff15dab1145161c1c089..e22146546adde92de6b01f15f98ebcf1ff02767c 100644 (file)
@@ -2478,6 +2478,11 @@ static __devinit void default_find_bmc(void)
                if (!info)
                        return;
 
+#ifdef CONFIG_PPC_MERGE
+               if (check_legacy_ioport(ipmi_defaults[i].port))
+                       continue;
+#endif
+
                info->addr_source = NULL;
 
                info->si_type = ipmi_defaults[i].type;
index d649abbf08574595d2e270cd488ea478c2405ac9..5f4fdcf7c96e50124404e3e1fa16963bf9da9480 100644 (file)
@@ -409,138 +409,6 @@ static int lcd_ioctl(struct inode *inode, struct file *file,
                        break;
                }
 
-//  Erase the flash
-
-       case FLASH_Erase:{
-
-                       int ctr = 0;
-
-                       if ( !capable(CAP_SYS_ADMIN) ) return -EPERM;
-
-                       pr_info(LCD "Erasing Flash\n");
-
-                       // Chip Erase Sequence
-                       WRITE_FLASH(kFlash_Addr1, kFlash_Data1);
-                       WRITE_FLASH(kFlash_Addr2, kFlash_Data2);
-                       WRITE_FLASH(kFlash_Addr1, kFlash_Erase3);
-                       WRITE_FLASH(kFlash_Addr1, kFlash_Data1);
-                       WRITE_FLASH(kFlash_Addr2, kFlash_Data2);
-                       WRITE_FLASH(kFlash_Addr1, kFlash_Erase6);
-
-                       while ((!dqpoll(0x00000000, 0xFF))
-                              && (!timeout(0x00000000))) {
-                               ctr++;
-                       }
-
-                       if (READ_FLASH(0x07FFF0) == 0xFF) {
-                               pr_info(LCD "Erase Successful\n");
-                       } else if (timeout) {
-                               pr_info(LCD "Erase Timed Out\n");
-                       }
-
-                       break;
-               }
-
-// burn the flash
-
-       case FLASH_Burn:{
-
-                       volatile unsigned long burn_addr;
-                       unsigned long flags;
-                       unsigned int i, index;
-                       unsigned char *rom;
-
-
-                       struct lcd_display display;
-
-                       if ( !capable(CAP_SYS_ADMIN) ) return -EPERM;
-
-                       if (copy_from_user
-                           (&display, (struct lcd_display *) arg,
-                            sizeof(struct lcd_display)))
-                               return -EFAULT;
-                       rom = kmalloc((128), GFP_ATOMIC);
-                       if (rom == NULL) {
-                               printk(KERN_ERR LCD "kmalloc() failed in %s\n",
-                                               __FUNCTION__);
-                               return -ENOMEM;
-                       }
-
-                       pr_info(LCD "Starting Flash burn\n");
-                       for (i = 0; i < FLASH_SIZE; i = i + 128) {
-
-                               if (copy_from_user
-                                   (rom, display.RomImage + i, 128)) {
-                                       kfree(rom);
-                                       return -EFAULT;
-                               }
-                               burn_addr = kFlashBase + i;
-                               spin_lock_irqsave(&lcd_lock, flags);
-                               for (index = 0; index < (128); index++) {
-
-                                       WRITE_FLASH(kFlash_Addr1,
-                                                   kFlash_Data1);
-                                       WRITE_FLASH(kFlash_Addr2,
-                                                   kFlash_Data2);
-                                       WRITE_FLASH(kFlash_Addr1,
-                                                   kFlash_Prog);
-                                       *((volatile unsigned char *)burn_addr) =
-                                         (volatile unsigned char) rom[index];
-
-                                       while ((!dqpoll (burn_addr,
-                                               (volatile unsigned char)
-                                               rom[index])) &&
-                                               (!timeout(burn_addr))) { }
-                                       burn_addr++;
-                               }
-                               spin_unlock_irqrestore(&lcd_lock, flags);
-                               if (* ((volatile unsigned char *)
-                                       (burn_addr - 1)) ==
-                                       (volatile unsigned char)
-                                       rom[index - 1]) {
-                               } else if (timeout) {
-                                       pr_info(LCD "Flash burn timed out\n");
-                               }
-
-
-                       }
-                       kfree(rom);
-
-                       pr_info(LCD "Flash successfully burned\n");
-
-                       break;
-               }
-
-//  read the flash all at once
-
-       case FLASH_Read:{
-
-                       unsigned char *user_bytes;
-                       volatile unsigned long read_addr;
-                       unsigned int i;
-
-                       user_bytes =
-                           &(((struct lcd_display *) arg)->RomImage[0]);
-
-                       if (!access_ok
-                           (VERIFY_WRITE, user_bytes, FLASH_SIZE))
-                               return -EFAULT;
-
-                       pr_info(LCD "Reading Flash");
-                       for (i = 0; i < FLASH_SIZE; i++) {
-                               unsigned char tmp_byte;
-                               read_addr = kFlashBase + i;
-                               tmp_byte =
-                                   *((volatile unsigned char *)
-                                     read_addr);
-                               if (__put_user(tmp_byte, &user_bytes[i]))
-                                       return -EFAULT;
-                       }
-
-
-                       break;
-               }
-
        default:
                return -EINVAL;
 
@@ -644,42 +512,6 @@ static void __exit lcd_exit(void)
        misc_deregister(&lcd_dev);
 }
 
-//
-// Function: dqpoll
-//
-// Description:  Polls the data lines to see if the flash is busy
-//
-// In: address, byte data
-//
-// Out: 0 = busy, 1 = write or erase complete
-//
-//
-
-static int dqpoll(volatile unsigned long address, volatile unsigned char data)
-{
-       volatile unsigned char dq7;
-
-       dq7 = data & 0x80;
-
-       return ((READ_FLASH(address) & 0x80) == dq7);
-}
-
-//
-// Function: timeout
-//
-// Description: Checks to see if erase or write has timed out
-//              By polling dq5
-//
-// In: address
-//
-//
-// Out: 0 = not timed out, 1 = timed out
-
-static int timeout(volatile unsigned long address)
-{
-       return (READ_FLASH(address) & 0x20) == 0x20;
-}
-
 module_init(lcd_init);
 module_exit(lcd_exit);
 
index a8d4ae737158b4905f6f3c3acb079f9bbc04091a..290b3ff23b0353905d129d6848c60065cccf273a 100644 (file)
 
 // function headers
 
-static int dqpoll(volatile unsigned long, volatile unsigned char );
-static int timeout(volatile unsigned long);
-
 #define LCD_CHARS_PER_LINE 40
-#define FLASH_SIZE 524288
 #define MAX_IDLE_TIME 120
 
 struct lcd_display {
@@ -54,26 +50,6 @@ struct lcd_display {
 #define LCDTimeoutValue        0xfff
 
 
-// Flash definitions AMD 29F040
-#define kFlashBase     0x0FC00000
-
-#define kFlash_Addr1    0x5555
-#define kFlash_Addr2    0x2AAA
-#define kFlash_Data1    0xAA
-#define kFlash_Data2    0x55
-#define kFlash_Prog     0xA0
-#define kFlash_Erase3   0x80
-#define kFlash_Erase6   0x10
-#define kFlash_Read     0xF0
-
-#define kFlash_ID       0x90
-#define kFlash_VenAddr  0x00
-#define kFlash_DevAddr  0x01
-#define kFlash_VenID    0x01
-#define kFlash_DevID    0xA4    // 29F040
-//#define kFlash_DevID  0xAD    // 29F016
-
-
 // Macros
 
 #define LCDWriteData(x)        outl((x << 24), kLCD_DR)
@@ -89,9 +65,6 @@ struct lcd_display {
 #define WRITE_GAL(x,y) outl(y, 0x04000000 | (x))
 #define BusyCheck()    while ((LCDReadInst & 0x80) == 0x80)
 
-#define WRITE_FLASH(x,y) outb((char)y, kFlashBase | (x))
-#define READ_FLASH(x)  (inb(kFlashBase | (x)))
-
 
 
 /*
@@ -124,11 +97,6 @@ struct lcd_display {
 //  Button defs
 #define BUTTON_Read             50
 
-//  Flash command codes
-#define FLASH_Erase            60
-#define FLASH_Burn             61
-#define FLASH_Read             62
-
 
 // Ethernet LINK check hackaroo
 #define LINK_Check              90
index 4e4865e90e50b68a697764f9a07f0e87b2ce1d1e..492dbfb2efd678c0cc0798be8f70f054740b51b4 100644 (file)
@@ -63,8 +63,6 @@
 #include "3780i.h"
 
 static DEFINE_SPINLOCK(dsp_lock);
-static unsigned long flags;
-
 
 static void PaceMsaAccess(unsigned short usDspBaseIO)
 {
@@ -76,6 +74,7 @@ static void PaceMsaAccess(unsigned short usDspBaseIO)
 unsigned short dsp3780I_ReadMsaCfg(unsigned short usDspBaseIO,
                                    unsigned long ulMsaAddr)
 {
+       unsigned long flags;
        unsigned short val;
 
        PRINTK_3(TRACE_3780I,
@@ -96,6 +95,7 @@ unsigned short dsp3780I_ReadMsaCfg(unsigned short usDspBaseIO,
 void dsp3780I_WriteMsaCfg(unsigned short usDspBaseIO,
                           unsigned long ulMsaAddr, unsigned short usValue)
 {
+       unsigned long flags;
 
        PRINTK_4(TRACE_3780I,
                "3780i::dsp3780i_WriteMsaCfg entry usDspBaseIO %x ulMsaAddr %lx usValue %x\n",
@@ -175,6 +175,7 @@ int dsp3780I_EnableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings,
                        unsigned short *pIrqMap,
                        unsigned short *pDmaMap)
 {
+       unsigned long flags;
        unsigned short usDspBaseIO = pSettings->usDspBaseIO;
        int i;
        DSP_UART_CFG_1 rUartCfg1;
@@ -354,6 +355,7 @@ int dsp3780I_EnableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings,
 
 int dsp3780I_DisableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings)
 {
+       unsigned long flags;
        unsigned short usDspBaseIO = pSettings->usDspBaseIO;
        DSP_ISA_SLAVE_CONTROL rSlaveControl;
 
@@ -383,6 +385,7 @@ int dsp3780I_DisableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings)
 
 int dsp3780I_Reset(DSP_3780I_CONFIG_SETTINGS * pSettings)
 {
+       unsigned long flags;
        unsigned short usDspBaseIO = pSettings->usDspBaseIO;
        DSP_BOOT_DOMAIN rBootDomain;
        DSP_HBRIDGE_CONTROL rHBridgeControl;
@@ -427,6 +430,7 @@ int dsp3780I_Reset(DSP_3780I_CONFIG_SETTINGS * pSettings)
 
 int dsp3780I_Run(DSP_3780I_CONFIG_SETTINGS * pSettings)
 {
+       unsigned long flags;
        unsigned short usDspBaseIO = pSettings->usDspBaseIO;
        DSP_BOOT_DOMAIN rBootDomain;
        DSP_HBRIDGE_CONTROL rHBridgeControl;
@@ -473,6 +477,7 @@ int dsp3780I_Run(DSP_3780I_CONFIG_SETTINGS * pSettings)
 int dsp3780I_ReadDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
                         unsigned uCount, unsigned long ulDSPAddr)
 {
+       unsigned long flags;
        unsigned short __user *pusBuffer = pvBuffer;
        unsigned short val;
 
@@ -514,6 +519,7 @@ int dsp3780I_ReadAndClearDStore(unsigned short usDspBaseIO,
                                 void __user *pvBuffer, unsigned uCount,
                                 unsigned long ulDSPAddr)
 {
+       unsigned long flags;
        unsigned short __user *pusBuffer = pvBuffer;
        unsigned short val;
 
@@ -555,6 +561,7 @@ int dsp3780I_ReadAndClearDStore(unsigned short usDspBaseIO,
 int dsp3780I_WriteDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
                          unsigned uCount, unsigned long ulDSPAddr)
 {
+       unsigned long flags;
        unsigned short __user *pusBuffer = pvBuffer;
 
 
@@ -596,6 +603,7 @@ int dsp3780I_WriteDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
 int dsp3780I_ReadIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
                         unsigned uCount, unsigned long ulDSPAddr)
 {
+       unsigned long flags;
        unsigned short __user *pusBuffer = pvBuffer;
 
        PRINTK_5(TRACE_3780I,
@@ -643,6 +651,7 @@ int dsp3780I_ReadIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
 int dsp3780I_WriteIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
                          unsigned uCount, unsigned long ulDSPAddr)
 {
+       unsigned long flags;
        unsigned short __user *pusBuffer = pvBuffer;
 
        PRINTK_5(TRACE_3780I,
@@ -691,6 +700,7 @@ int dsp3780I_WriteIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
 int dsp3780I_GetIPCSource(unsigned short usDspBaseIO,
                           unsigned short *pusIPCSource)
 {
+       unsigned long flags;
        DSP_HBRIDGE_CONTROL rHBridgeControl;
        unsigned short temp;
 
index 0e82968c2f38ee74c30e6c0a779f365d2c5f5a52..f2e4ec4fd407968b7322dac8664b5fdcb6fff9e0 100644 (file)
@@ -273,6 +273,7 @@ static ssize_t cm4040_read(struct file *filp, char __user *buf,
        DEBUGP(6, dev, "BytesToRead=%lu\n", bytes_to_read);
 
        min_bytes_to_read = min(count, bytes_to_read + 5);
+       min_bytes_to_read = min_t(size_t, min_bytes_to_read, READ_WRITE_BUFFER_SIZE);
 
        DEBUGP(6, dev, "Min=%lu\n", min_bytes_to_read);
 
@@ -340,7 +341,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf,
                return 0;
        }
 
-       if (count < 5) {
+       if ((count < 5) || (count > READ_WRITE_BUFFER_SIZE)) {
                DEBUGP(2, dev, "<- cm4040_write buffersize=%Zd < 5\n", count);
                return -EIO;
        }
index 5289254e7ab3f1e0d0fdfbf48e411e07fdc9c31a..e453268566805238288ba64f96e1c5da0f8a1ba3 100644 (file)
@@ -1533,7 +1533,7 @@ void disassociate_ctty(int on_exit)
 
        spin_lock_irq(&current->sighand->siglock);
        tty_pgrp = current->signal->tty_old_pgrp;
-       current->signal->tty_old_pgrp = 0;
+       current->signal->tty_old_pgrp = NULL;
        spin_unlock_irq(&current->sighand->siglock);
        put_pid(tty_pgrp);
 
@@ -1901,6 +1901,20 @@ static int init_dev(struct tty_driver *driver, int idx,
        /* check whether we're reopening an existing tty */
        if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
                tty = devpts_get_tty(idx);
+               /*
+                * If we don't have a tty here on a slave open, it's because
+                * the master already started the close process and there's
+                * no relation between devpts file and tty anymore.
+                */
+               if (!tty && driver->subtype == PTY_TYPE_SLAVE) {
+                       retval = -EIO;
+                       goto end_init;
+               }
+               /*
+                * It's safe from now on because init_dev() is called with
+                * tty_mutex held and release_dev() won't change tty->count
+                * or tty->flags without having to grab tty_mutex
+                */
                if (tty && driver->subtype == PTY_TYPE_MASTER)
                        tty = tty->link;
        } else {
@@ -3713,15 +3727,14 @@ int tty_register_driver(struct tty_driver *driver)
 
        if (!driver->major) {
                error = alloc_chrdev_region(&dev, driver->minor_start, driver->num,
-                                               (char*)driver->name);
+                                               driver->name);
                if (!error) {
                        driver->major = MAJOR(dev);
                        driver->minor_start = MINOR(dev);
                }
        } else {
                dev = MKDEV(driver->major, driver->minor_start);
-               error = register_chrdev_region(dev, driver->num,
-                                               (char*)driver->name);
+               error = register_chrdev_region(dev, driver->num, driver->name);
        }
        if (error < 0) {
                kfree(p);
index ccaa6a39cb4b8195a9f30dafc38a41f6de821028..d42060ede93024481916f3497d479a45e5848184 100644 (file)
@@ -214,4 +214,7 @@ pm_good:
        return clocksource_register(&clocksource_acpi_pm);
 }
 
-module_init(init_acpi_pm_clocksource);
+/* We use fs_initcall because we want the PCI fixups to have run
+ * but we still need to load before device_initcall
+ */
+fs_initcall(init_acpi_pm_clocksource);
index 4f3925ceb36041a8cdbdaab80b0c330eebb28a61..1bde303b970ba2d008813d4dfd67d48ffeb5ceff 100644 (file)
@@ -116,4 +116,4 @@ static int __init init_cyclone_clocksource(void)
        return clocksource_register(&clocksource_cyclone);
 }
 
-module_init(init_cyclone_clocksource);
+arch_initcall(init_cyclone_clocksource);
index a44db75bc25bac35e97905c096fe50ffa2686c3e..a905f782033196259dcdb46b5931701d0a642bad 100644 (file)
@@ -128,7 +128,7 @@ EXPORT_SYMBOL_GPL(cn_netlink_send);
  */
 static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), void *data)
 {
-       struct cn_callback_entry *__cbq;
+       struct cn_callback_entry *__cbq, *__new_cbq;
        struct cn_dev *dev = &cdev;
        int err = -ENODEV;
 
@@ -148,27 +148,27 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v
                        } else {
                                struct cn_callback_data *d;
                                
-                               __cbq = kzalloc(sizeof(*__cbq), GFP_ATOMIC);
-                               if (__cbq) {
-                                       d = &__cbq->data;
+                               err = -ENOMEM;
+                               __new_cbq = kzalloc(sizeof(struct cn_callback_entry), GFP_ATOMIC);
+                               if (__new_cbq) {
+                                       d = &__new_cbq->data;
                                        d->callback_priv = msg;
                                        d->callback = __cbq->data.callback;
                                        d->ddata = data;
                                        d->destruct_data = destruct_data;
-                                       d->free = __cbq;
+                                       d->free = __new_cbq;
 
-                                       INIT_WORK(&__cbq->work,
+                                       INIT_WORK(&__new_cbq->work,
                                                        &cn_queue_wrapper);
-                                       
+
                                        if (queue_work(dev->cbdev->cn_queue,
-                                                   &__cbq->work))
+                                                   &__new_cbq->work))
                                                err = 0;
                                        else {
-                                               kfree(__cbq);
+                                               kfree(__new_cbq);
                                                err = -EINVAL;
                                        }
-                               } else
-                                       err = -ENOMEM;
+                               }
                        }
                        break;
                }
index d60bcb9d14ccd811c72fee221ebf894e8c695efc..8d053f500fc25907d9f1d6f1691297199ecaa62a 100644 (file)
@@ -432,9 +432,6 @@ static void do_dbs_timer(struct work_struct *work)
        /* We want all CPUs to do sampling nearly on same jiffy */
        int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
 
-       /* Permit rescheduling of this work item */
-       work_release(work);
-
        delay -= jiffies % delay;
 
        if (lock_policy_rwsem_write(cpu) < 0)
@@ -473,7 +470,7 @@ static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
        dbs_info->enable = 1;
        ondemand_powersave_bias_init();
        dbs_info->sample_type = DBS_NORMAL_SAMPLE;
-       INIT_DELAYED_WORK_NAR(&dbs_info->work, do_dbs_timer);
+       INIT_DELAYED_WORK(&dbs_info->work, do_dbs_timer);
        queue_delayed_work_on(dbs_info->cpu, kondemand_wq, &dbs_info->work,
                              delay);
 }
index 0eb62841e9b0bd6f207bdb0c159709318919bff4..6d3840e629de550c0b3de37a2090788cb6180351 100644 (file)
@@ -99,9 +99,8 @@ do_crypt(void *src, void *dst, int len, u32 flags)
 static unsigned int
 geode_aes_crypt(struct geode_aes_op *op)
 {
-
        u32 flags = 0;
-       int iflags;
+       unsigned long iflags;
 
        if (op->len == 0 || op->src == op->dst)
                return 0;
index 7452399501b42a0fe006eb5d438126e4ec966933..f4ee1afe488f0493748ba224ada537b04de44171 100644 (file)
@@ -667,7 +667,6 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
 
                if (item.format != HID_ITEM_FORMAT_SHORT) {
                        dbg("unexpected long global item");
-                       kfree(device->collection);
                        hid_free_device(device);
                        kfree(parser);
                        return NULL;
@@ -676,7 +675,6 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
                if (dispatch_type[item.type](parser, &item)) {
                        dbg("item %u %u %u %u parsing failed\n",
                                item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
-                       kfree(device->collection);
                        hid_free_device(device);
                        kfree(parser);
                        return NULL;
@@ -685,14 +683,12 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
                if (start == end) {
                        if (parser->collection_stack_ptr) {
                                dbg("unbalanced collection at end of report description");
-                               kfree(device->collection);
                                hid_free_device(device);
                                kfree(parser);
                                return NULL;
                        }
                        if (parser->local.delimiter_depth) {
                                dbg("unbalanced delimiter at end of report description");
-                               kfree(device->collection);
                                hid_free_device(device);
                                kfree(parser);
                                return NULL;
@@ -703,7 +699,6 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
        }
 
        dbg("item fetching failed at offset %d\n", (int)(end - start));
-       kfree(device->collection);
        hid_free_device(device);
        kfree(parser);
        return NULL;
@@ -880,7 +875,7 @@ static void hid_output_field(struct hid_field *field, __u8 *data)
 
        /* make sure the unused bits in the last byte are zeros */
        if (count > 0 && size > 0)
-               data[(count*size-1)/8] = 0;
+               data[(offset+count*size-1)/8] = 0;
 
        for (n = 0; n < count; n++) {
                if (field->logical_minimum < 0) /* signed values */
index 89241be4ec9b070a3679c3453c7a8c4a3dc1792d..83c4126b37c333f59b575a40dce9f6fd1d2b675b 100644 (file)
@@ -29,6 +29,7 @@
  */
 
 #include <linux/hid.h>
+#include <linux/hid-debug.h>
 
 struct hid_usage_entry {
        unsigned  page;
index 25d180a24fc42e1968de9b6b743c2ec76fd1c8c3..c8434023ba652ac325fb924b577fc051d331f86d 100644 (file)
@@ -2,7 +2,7 @@
  * $Id: hid-input.c,v 1.2 2002/04/23 00:59:25 rdamazio Exp $
  *
  *  Copyright (c) 2000-2001 Vojtech Pavlik
- *  Copyright (c) 2006 Jiri Kosina
+ *  Copyright (c) 2006-2007 Jiri Kosina
  *
  *  HID to Linux Input mapping
  */
@@ -71,7 +71,6 @@ static const struct {
 #define map_led(c)     do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; } while (0)
 
 #define map_abs_clear(c)       do { map_abs(c); clear_bit(c, bit); } while (0)
-#define map_rel_clear(c)       do { map_rel(c); clear_bit(c, bit); } while (0)
 #define map_key_clear(c)       do { map_key(c); clear_bit(c, bit); } while (0)
 
 #ifdef CONFIG_USB_HIDINPUT_POWERBOOK
@@ -296,7 +295,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                                        }
                        }
 
-                       map_key_clear(code);
+                       map_key(code);
                        break;
 
 
@@ -347,9 +346,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                                case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ:
                                case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL:
                                        if (field->flags & HID_MAIN_ITEM_RELATIVE)
-                                               map_rel_clear(usage->hid & 0xf);
+                                               map_rel(usage->hid & 0xf);
                                        else
-                                               map_abs_clear(usage->hid & 0xf);
+                                               map_abs(usage->hid & 0xf);
                                        break;
 
                                case HID_GD_HATSWITCH:
@@ -519,7 +518,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                                case 0x22f: map_key_clear(KEY_ZOOMRESET);       break;
                                case 0x233: map_key_clear(KEY_SCROLLUP);        break;
                                case 0x234: map_key_clear(KEY_SCROLLDOWN);      break;
-                               case 0x238: map_rel_clear(REL_HWHEEL);          break;
+                               case 0x238: map_rel(REL_HWHEEL);                break;
                                case 0x25f: map_key_clear(KEY_CANCEL);          break;
                                case 0x279: map_key_clear(KEY_REDO);            break;
 
@@ -532,6 +531,26 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                                case 0x302: map_key_clear(KEY_PROG2);           break;
                                case 0x303: map_key_clear(KEY_PROG3);           break;
 
+                               /* Reported on Logitech S510 wireless keyboard */
+                               case 0x101f: map_key_clear(KEY_ZOOMIN);         break;
+                               case 0x1020: map_key_clear(KEY_ZOOMOUT);        break;
+                               case 0x1021: map_key_clear(KEY_ZOOMRESET);      break;
+                               /* this one is marked as 'Rotate' */
+                               case 0x1028: map_key_clear(KEY_ANGLE);          break;
+                               case 0x1029: map_key_clear(KEY_SHUFFLE);        break;
+                               case 0x1041: map_key_clear(KEY_BATTERY);        break;
+                               case 0x1042: map_key_clear(KEY_WORDPROCESSOR);  break;
+                               case 0x1043: map_key_clear(KEY_SPREADSHEET);    break;
+                               case 0x1044: map_key_clear(KEY_PRESENTATION);   break;
+                               case 0x1045: map_key_clear(KEY_UNDO);           break;
+                               case 0x1046: map_key_clear(KEY_REDO);           break;
+                               case 0x1047: map_key_clear(KEY_PRINT);          break;
+                               case 0x1048: map_key_clear(KEY_SAVE);           break;
+                               case 0x1049: map_key_clear(KEY_PROG1);          break;
+                               case 0x104a: map_key_clear(KEY_PROG2);          break;
+                               case 0x104b: map_key_clear(KEY_PROG3);          break;
+                               case 0x104c: map_key_clear(KEY_PROG4);          break;
+
                                default:    goto ignore;
                        }
                        break;
@@ -647,6 +666,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
 
        set_bit(usage->type, input->evbit);
 
+       if (device->quirks & HID_QUIRK_DUPLICATE_USAGES &&
+                       (usage->type == EV_KEY ||
+                        usage->type == EV_REL ||
+                        usage->type == EV_ABS))
+               clear_bit(usage->code, bit);
+
        while (usage->code <= max && test_and_set_bit(usage->code, bit))
                usage->code = find_next_zero_bit(bit, max + 1, usage->code);
 
index 4d44a2db29ddca1bb0964100d995091b37f26b91..fb19dbb31e427fa29642aeacf592ad515b74f50a 100644 (file)
@@ -495,6 +495,16 @@ config I2C_VERSATILE
          This driver can also be built as a module.  If so, the module
          will be called i2c-versatile.
 
+config I2C_ACORN
+       bool "Acorn IOC/IOMD I2C bus support"
+       depends on I2C && ARCH_ACORN
+       default y
+       select I2C_ALGOBIT
+       help
+         Say yes if you want to support the I2C bus on Acorn platforms.
+
+         If you don't know, say Y.
+
 config I2C_VIA
        tristate "VIA 82C586B"
        depends on I2C && PCI && EXPERIMENTAL
index 03505aa44bbf0a8590dbb71f2e78584c3660a992..290b54018354088165b64d49f946e405509351b9 100644 (file)
@@ -42,6 +42,7 @@ 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_ACORN)                += i2c-acorn.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/drivers/i2c/busses/i2c-acorn.c b/drivers/i2c/busses/i2c-acorn.c
new file mode 100644 (file)
index 0000000..09bd7f4
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ *  linux/drivers/acorn/char/i2c.c
+ *
+ *  Copyright (C) 2000 Russell King
+ *
+ * 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.
+ *
+ *  ARM IOC/IOMD i2c driver.
+ *
+ *  On Acorn machines, the following i2c devices are on the bus:
+ *     - PCF8583 real time clock & static RAM
+ */
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/hardware/ioc.h>
+#include <asm/system.h>
+
+#define FORCE_ONES     0xdc
+#define SCL            0x02
+#define SDA            0x01
+
+/*
+ * We must preserve all non-i2c output bits in IOC_CONTROL.
+ * Note also that we need to preserve the value of SCL and
+ * SDA outputs as well (which may be different from the
+ * values read back from IOC_CONTROL).
+ */
+static u_int force_ones;
+
+static void ioc_setscl(void *data, int state)
+{
+       u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA);
+       u_int ones = force_ones;
+
+       if (state)
+               ones |= SCL;
+       else
+               ones &= ~SCL;
+
+       force_ones = ones;
+
+       ioc_writeb(ioc_control | ones, IOC_CONTROL);
+}
+
+static void ioc_setsda(void *data, int state)
+{
+       u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA);
+       u_int ones = force_ones;
+
+       if (state)
+               ones |= SDA;
+       else
+               ones &= ~SDA;
+
+       force_ones = ones;
+
+       ioc_writeb(ioc_control | ones, IOC_CONTROL);
+}
+
+static int ioc_getscl(void *data)
+{
+       return (ioc_readb(IOC_CONTROL) & SCL) != 0;
+}
+
+static int ioc_getsda(void *data)
+{
+       return (ioc_readb(IOC_CONTROL) & SDA) != 0;
+}
+
+static struct i2c_algo_bit_data ioc_data = {
+       .setsda         = ioc_setsda,
+       .setscl         = ioc_setscl,
+       .getsda         = ioc_getsda,
+       .getscl         = ioc_getscl,
+       .udelay         = 80,
+       .timeout        = 100
+};
+
+static struct i2c_adapter ioc_ops = {
+       .id                     = I2C_HW_B_IOC,
+       .algo_data              = &ioc_data,
+};
+
+static int __init i2c_ioc_init(void)
+{
+       force_ones = FORCE_ONES | SCL | SDA;
+
+       return i2c_bit_add_bus(&ioc_ops);
+}
+
+__initcall(i2c_ioc_init);
index 49234e32fd167f0de6591584048568d582349bc7..5d134bb75ba16f107c223871e7ef6ee53525ec85 100644 (file)
@@ -1023,7 +1023,7 @@ config BLK_DEV_4DRIVES
 config BLK_DEV_ALI14XX
        tristate "ALI M14xx support"
        help
-         This driver is enabled at runtime using the "ide0=ali14xx" kernel
+         This driver is enabled at runtime using the "ali14xx.probe" kernel
          boot parameter.  It enables support for the secondary IDE interface
          of the ALI M1439/1443/1445/1487/1489 chipsets, and permits faster
          I/O speeds to be set as well.  See the files
@@ -1033,7 +1033,7 @@ config BLK_DEV_ALI14XX
 config BLK_DEV_DTC2278
        tristate "DTC-2278 support"
        help
-         This driver is enabled at runtime using the "ide0=dtc2278" kernel
+         This driver is enabled at runtime using the "dtc2278.probe" kernel
          boot parameter. It enables support for the secondary IDE interface
          of the DTC-2278 card, and permits faster I/O speeds to be set as
          well. See the <file:Documentation/ide.txt> and
@@ -1042,7 +1042,7 @@ config BLK_DEV_DTC2278
 config BLK_DEV_HT6560B
        tristate "Holtek HT6560B support"
        help
-         This driver is enabled at runtime using the "ide0=ht6560b" kernel
+         This driver is enabled at runtime using the "ht6560b.probe" kernel
          boot parameter. It enables support for the secondary IDE interface
          of the Holtek card, and permits faster I/O speeds to be set as well.
          See the <file:Documentation/ide.txt> and
@@ -1051,7 +1051,7 @@ config BLK_DEV_HT6560B
 config BLK_DEV_QD65XX
        tristate "QDI QD65xx support"
        help
-         This driver is enabled at runtime using the "ide0=qd65xx" kernel
+         This driver is enabled at runtime using the "qd65xx.probe" kernel
          boot parameter.  It permits faster I/O speeds to be set.  See the
          <file:Documentation/ide.txt> and <file:drivers/ide/legacy/qd65xx.c> for
          more info.
@@ -1059,7 +1059,7 @@ config BLK_DEV_QD65XX
 config BLK_DEV_UMC8672
        tristate "UMC-8672 support"
        help
-         This driver is enabled at runtime using the "ide0=umc8672" kernel
+         This driver is enabled at runtime using the "umc8672.probe" kernel
          boot parameter. It enables support for the secondary IDE interface
          of the UMC-8672, and permits faster I/O speeds to be set as well.
          See the files <file:Documentation/ide.txt> and
index 6b2d152351b301f4243cb52843ed4b8e0fe7ffdb..556455fbfa2be045700a3c2e4145d560f8d6baf9 100644 (file)
@@ -17,8 +17,6 @@
  * device can't do DMA handshaking for some stupid reason. We don't need to do that.
  */
 
-#undef REALLY_SLOW_IO           /* most systems can safely undef this */
-
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/timer.h>
index e2cea1889c4d350f4153146b64433cabbc72b620..37aa6ddd97020f91bbf067a97fa0e168fe1e7083 100644 (file)
@@ -43,8 +43,6 @@
 
 #define IDEDISK_VERSION        "1.18"
 
-#undef REALLY_SLOW_IO          /* most systems can safely undef this */
-
 //#define DEBUG
 
 #include <linux/module.h>
index c67b3b1e6f4c64b255d043220a8cdc8b72aff80b..bd513f5a23236166541946391aab8239985201c9 100644 (file)
@@ -583,6 +583,8 @@ u8 eighty_ninty_three (ide_drive_t *drive)
        if(!(drive->id->hw_config & 0x4000))
                return 0;
 #endif /* CONFIG_IDEDMA_IVB */
+       if (!(drive->id->hw_config & 0x2000))
+               return 0;
        return 1;
 }
 
index 8afce4ceea310c6e47eea9ff1c715bdb39916591..68719314df3f099f0888e4de2fdf6b776173c577 100644 (file)
@@ -345,16 +345,16 @@ static int ide_scan_pio_blacklist (char *model)
 
 /**
  *     ide_get_best_pio_mode   -       get PIO mode from drive
- *     @driver: drive to consider
+ *     @drive: drive to consider
  *     @mode_wanted: preferred mode
- *     @max_mode: highest allowed
- *     @d: pio data
+ *     @max_mode: highest allowed mode
+ *     @d: PIO data
  *
  *     This routine returns the recommended PIO settings for a given drive,
  *     based on the drive->id information and the ide_pio_blacklist[].
- *     This is used by most chipset support modules when "auto-tuning".
  *
- *     Drive PIO mode auto selection
+ *     Drive PIO mode is auto-selected if 255 is passed as mode_wanted.
+ *     This is used by most chipset support modules when "auto-tuning".
  */
 
 u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode, ide_pio_data_t *d)
@@ -367,6 +367,7 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode, ide_p
 
        if (mode_wanted != 255) {
                pio_mode = mode_wanted;
+               use_iordy = (pio_mode > 2);
        } else if (!drive->id) {
                pio_mode = 0;
        } else if ((pio_mode = ide_scan_pio_blacklist(id->model)) != -1) {
@@ -396,19 +397,12 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode, ide_p
                        }
                }
 
-#if 0
-               if (drive->id->major_rev_num & 0x0004) printk("ATA-2 ");
-#endif
-
                /*
                 * Conservative "downgrade" for all pre-ATA2 drives
                 */
                if (pio_mode && pio_mode < 4) {
                        pio_mode--;
                        overridden = 1;
-#if 0
-                       use_iordy = (pio_mode > 2);
-#endif
                        if (cycle_time && cycle_time < ide_pio_timings[pio_mode].cycle_time)
                                cycle_time = 0; /* use standard timing */
                }
index 8afbd6cb94be9ac50db17f3c62f03c4804791a1e..8f15c23aa70d7eaa2e049ad7a0e2be95705886a0 100644 (file)
@@ -31,8 +31,6 @@
  *                     valid after probe time even with noprobe
  */
 
-#undef REALLY_SLOW_IO          /* most systems can safely undef this */
-
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/string.h>
index b3c0818c5c6c592eefa9289b0e2cbe1492bf73a3..dfbd7445852234dff93f9e30534cac343afb72db 100644 (file)
 #define        REVISION        "Revision: 7.00alpha2"
 #define        VERSION         "Id: ide.c 7.00a2 20020906"
 
-#undef REALLY_SLOW_IO          /* most systems can safely undef this */
-
 #define _IDE_C                 /* Tell ide.h it's really us */
 
 #include <linux/module.h>
@@ -1486,23 +1484,23 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m
 }
 
 #ifdef CONFIG_BLK_DEV_ALI14XX
-static int __initdata probe_ali14xx;
+extern int probe_ali14xx;
 extern int ali14xx_init(void);
 #endif
 #ifdef CONFIG_BLK_DEV_UMC8672
-static int __initdata probe_umc8672;
+extern int probe_umc8672;
 extern int umc8672_init(void);
 #endif
 #ifdef CONFIG_BLK_DEV_DTC2278
-static int __initdata probe_dtc2278;
+extern int probe_dtc2278;
 extern int dtc2278_init(void);
 #endif
 #ifdef CONFIG_BLK_DEV_HT6560B
-static int __initdata probe_ht6560b;
+extern int probe_ht6560b;
 extern int ht6560b_init(void);
 #endif
 #ifdef CONFIG_BLK_DEV_QD65XX
-static int __initdata probe_qd65xx;
+extern int probe_qd65xx;
 extern int qd65xx_init(void);
 #endif
 
@@ -1580,7 +1578,7 @@ static int __init ide_setup(char *s)
         */
        if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) {
                const char *hd_words[] = {
-                       "none", "noprobe", "nowerr", "cdrom", "serialize",
+                       "none", "noprobe", "nowerr", "cdrom", "minus5",
                        "autotune", "noautotune", "minus8", "swapdata", "bswap",
                        "noflush", "remap", "remap63", "scsi", NULL };
                unit = s[2] - 'a';
@@ -1608,9 +1606,6 @@ static int __init ide_setup(char *s)
                                drive->ready_stat = 0;
                                hwif->noprobe = 0;
                                goto done;
-                       case -5: /* "serialize" */
-                               printk(" -- USE \"ide%d=serialize\" INSTEAD", hw);
-                               goto do_serialize;
                        case -6: /* "autotune" */
                                drive->autotune = IDE_TUNE_AUTO;
                                goto obsolete_option;
@@ -1671,7 +1666,7 @@ static int __init ide_setup(char *s)
                 * (-8, -9, -10) are reserved to ease the hardcoding.
                 */
                static const char *ide_words[] = {
-                       "noprobe", "serialize", "autotune", "noautotune", 
+                       "noprobe", "serialize", "minus3", "minus4",
                        "reset", "dma", "ata66", "minus8", "minus9",
                        "minus10", "four", "qd65xx", "ht6560b", "cmd640_vlb",
                        "dtc2278", "umc8672", "ali14xx", NULL };
@@ -1742,12 +1737,17 @@ static int __init ide_setup(char *s)
                                hwif->chipset = mate->chipset = ide_4drives;
                                mate->irq = hwif->irq;
                                memcpy(mate->io_ports, hwif->io_ports, sizeof(hwif->io_ports));
-                               goto do_serialize;
+                               hwif->mate = mate;
+                               mate->mate = hwif;
+                               hwif->serialized = mate->serialized = 1;
+                               goto obsolete_option;
                        }
 #endif /* CONFIG_BLK_DEV_4DRIVES */
                        case -10: /* minus10 */
                        case -9: /* minus9 */
                        case -8: /* minus8 */
+                       case -4:
+                       case -3:
                                goto bad_option;
                        case -7: /* ata66 */
 #ifdef CONFIG_BLK_DEV_IDEPCI
@@ -1762,16 +1762,7 @@ static int __init ide_setup(char *s)
                        case -5: /* "reset" */
                                hwif->reset = 1;
                                goto obsolete_option;
-                       case -4: /* "noautotune" */
-                               hwif->drives[0].autotune = IDE_TUNE_NOAUTO;
-                               hwif->drives[1].autotune = IDE_TUNE_NOAUTO;
-                               goto obsolete_option;
-                       case -3: /* "autotune" */
-                               hwif->drives[0].autotune = IDE_TUNE_AUTO;
-                               hwif->drives[1].autotune = IDE_TUNE_AUTO;
-                               goto obsolete_option;
                        case -2: /* "serialize" */
-                       do_serialize:
                                hwif->mate = &ide_hwifs[hw^1];
                                hwif->mate->mate = hwif;
                                hwif->serialized = hwif->mate->serialized = 1;
@@ -1840,8 +1831,8 @@ static void __init probe_for_hwifs (void)
 #endif /* CONFIG_BLK_DEV_CMD640 */
 #ifdef CONFIG_BLK_DEV_IDE_PMAC
        {
-               extern void pmac_ide_probe(void);
-               pmac_ide_probe();
+               extern int pmac_ide_probe(void);
+               (void)pmac_ide_probe();
        }
 #endif /* CONFIG_BLK_DEV_IDE_PMAC */
 #ifdef CONFIG_BLK_DEV_GAYLE
index 9c544467cb74a50bf09aa24cd1a9e954d7e6e002..91961aa030474fa02057f8ed2e8dd270b69f87d3 100644 (file)
@@ -37,8 +37,6 @@
  * mode 4 for a while now with no trouble.)  -Derek
  */
 
-#undef REALLY_SLOW_IO           /* most systems can safely undef this */
-
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -230,9 +228,17 @@ static int __init ali14xx_probe(void)
        return 0;
 }
 
+int probe_ali14xx = 0;
+
+module_param_named(probe, probe_ali14xx, bool, 0);
+MODULE_PARM_DESC(probe, "probe for ALI M14xx chipsets");
+
 /* Can be called directly from ide.c. */
 int __init ali14xx_init(void)
 {
+       if (probe_ali14xx == 0)
+               goto out;
+
        /* auto-detect IDE controller port */
        if (findPort()) {
                if (ali14xx_probe())
@@ -240,6 +246,7 @@ int __init ali14xx_init(void)
                return 0;
        }
        printk(KERN_ERR "ali14xx: not found.\n");
+out:
        return -ENODEV;
 }
 
index 3b1d33baaa2f6c08758081c7ac1331ad5e3c8e74..0219ffa64db663fae60e8bc3e994e1d76bd048c7 100644 (file)
@@ -4,8 +4,6 @@
  *  Copyright (C) 1996  Linus Torvalds & author (see below)
  */
 
-#undef REALLY_SLOW_IO           /* most systems can safely undef this */
-
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -94,7 +92,7 @@ static void tune_dtc2278 (ide_drive_t *drive, u8 pio)
        HWIF(drive)->drives[!drive->select.b.unit].io_32bit = 1;
 }
 
-static int __init probe_dtc2278(void)
+static int __init dtc2278_probe(void)
 {
        unsigned long flags;
        ide_hwif_t *hwif, *mate;
@@ -145,10 +143,18 @@ static int __init probe_dtc2278(void)
        return 0;
 }
 
+int probe_dtc2278 = 0;
+
+module_param_named(probe, probe_dtc2278, bool, 0);
+MODULE_PARM_DESC(probe, "probe for DTC2278xx chipsets");
+
 /* Can be called directly from ide.c. */
 int __init dtc2278_init(void)
 {
-       if (probe_dtc2278()) {
+       if (probe_dtc2278 == 0)
+               return -ENODEV;
+
+       if (dtc2278_probe()) {
                printk(KERN_ERR "dtc2278: ide interfaces already in use!\n");
                return -EBUSY;
        }
index 19ccd006f205ae1a329c16ad64a76e29adae7ac1..a2832643c522f0cc6805ca497cde92e32fb5fbbc 100644 (file)
@@ -36,8 +36,6 @@
 
 #define HT6560B_VERSION "v0.07"
 
-#undef REALLY_SLOW_IO          /* most systems can safely undef this */
-
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -303,12 +301,20 @@ static void tune_ht6560b (ide_drive_t *drive, u8 pio)
 #endif
 }
 
+int probe_ht6560b = 0;
+
+module_param_named(probe, probe_ht6560b, bool, 0);
+MODULE_PARM_DESC(probe, "probe for HT6560B chipset");
+
 /* Can be called directly from ide.c. */
 int __init ht6560b_init(void)
 {
        ide_hwif_t *hwif, *mate;
        int t;
 
+       if (probe_ht6560b == 0)
+               return -ENODEV;
+
        hwif = &ide_hwifs[0];
        mate = &ide_hwifs[1];
 
index a5023cdbdc58ee1ec757f8ffc855ff791783fff6..b08c37c9f956abe9b4db335b479c92e548027374 100644 (file)
@@ -359,14 +359,17 @@ void ide_release(struct pcmcia_device *link)
 static struct pcmcia_device_id ide_ids[] = {
        PCMCIA_DEVICE_FUNC_ID(4),
        PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000),        /* Hitachi */
+       PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000),        /* I-O Data CFA */
+       PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001),        /* Mitsubishi CFA */
        PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
-       PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),
+       PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),        /* SanDisk CFA */
        PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000),        /* Toshiba */
        PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
        PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000),        /* Samsung */
        PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000),        /* Hitachi */
        PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
-       PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200),        /* Lexar */
+       PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0100),        /* Viking CFA */
+       PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200),        /* Lexar, Viking CFA */
        PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
        PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74),
        PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
index d3c3bc2640e766acf58d619a81b0284d3efe0a58..2fb8f50f1293e66df0008c9d0d44b4d6f39e43f4 100644 (file)
@@ -16,8 +16,8 @@
  * Please set local bus speed using kernel parameter idebus
  *     for example, "idebus=33" stands for 33Mhz VLbus
  * To activate controller support, use "ide0=qd65xx"
- * To enable tuning, use "ide0=autotune"
- * To enable second channel tuning (qd6580 only), use "ide1=autotune"
+ * To enable tuning, use "hda=autotune hdb=autotune"
+ * To enable 2nd channel tuning (qd6580 only), use "hdc=autotune hdd=autotune"
  */
 
 /*
@@ -25,8 +25,6 @@
  * Samuel Thibault <samuel.thibault@fnac.net>
  */
 
-#undef REALLY_SLOW_IO          /* most systems can safely undef this */
-
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -490,9 +488,17 @@ static int __init qd_probe(int base)
        return 1;
 }
 
+int probe_qd65xx = 0;
+
+module_param_named(probe, probe_qd65xx, bool, 0);
+MODULE_PARM_DESC(probe, "probe for QD65xx chipsets");
+
 /* Can be called directly from ide.c. */
 int __init qd65xx_init(void)
 {
+       if (probe_qd65xx == 0)
+               return -ENODEV;
+
        if (qd_probe(0x30))
                qd_probe(0xb0);
        if (ide_hwifs[0].chipset != ide_qd65xx &&
index 6e2c58c5f6a2f8ff5e6304f83fd1d3f009c53c2d..ca7974455578005242b4ec79bdcbffae174835c7 100644 (file)
@@ -165,12 +165,21 @@ static int __init umc8672_probe(void)
        return 0;
 }
 
+int probe_umc8672 = 0;
+
+module_param_named(probe, probe_umc8672, bool, 0);
+MODULE_PARM_DESC(probe, "probe for UMC8672 chipset");
+
 /* Can be called directly from ide.c. */
 int __init umc8672_init(void)
 {
-       if (umc8672_probe())
-               return -ENODEV;
-       return 0;
+       if (probe_umc8672 == 0)
+               goto out;
+
+       if (umc8672_probe() == 0)
+               return 0;;
+out:
+       return -ENODEV;;
 }
 
 #ifdef MODULE
index 0a59d5ef1599e16d323bfadb051c6ae9491c9e6f..b2dc028dc8ca17d424cc5677e070cdcf374f9e87 100644 (file)
@@ -29,8 +29,6 @@
  * Note: for more information, please refer "AMD Alchemy Au1200/Au1550 IDE
  *       Interface and Linux Device Driver" Application Note.
  */
-#undef REALLY_SLOW_IO           /* most systems can safely undef this */
-
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
index 4debd18d52f83da057dc1e73922d196a442ce2d5..83e0aa65a4316e8c6b74f4d35373dc8b0f0c3a7c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/pci/alim15x3.c            Version 0.17    2003/01/02
+ * linux/drivers/ide/pci/alim15x3.c            Version 0.21    2007/02/03
  *
  *  Copyright (C) 1998-2000 Michel Aubry, Maintainer
  *  Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer
@@ -9,6 +9,7 @@
  *  May be copied or modified under the terms of the GNU General Public License
  *  Copyright (C) 2002 Alan Cox <alan@redhat.com>
  *  ALi (now ULi M5228) support by Clear Zhang <Clear.Zhang@ali.com.tw>
+ *  Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com>
  *
  *  (U)DMA capable version of ali 1533/1543(C), 1535(D)
  *
@@ -280,15 +281,17 @@ static int ali_get_info (char *buffer, char **addr, off_t offset, int count)
 #endif  /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */
 
 /**
- *     ali15x3_tune_drive      -       set up a drive
+ *     ali15x3_tune_pio        -       set up chipset for PIO mode
  *     @drive: drive to tune
- *     @pio: unused
+ *     @pio: desired mode
  *
- *     Select the best PIO timing for the drive in question. Then
- *     program the controller for this drive set up
+ *     Select the best PIO mode for the drive in question.
+ *     Then program the controller for this mode.
+ *
+ *     Returns the PIO mode programmed.
  */
  
-static void ali15x3_tune_drive (ide_drive_t *drive, u8 pio)
+static u8 ali15x3_tune_pio (ide_drive_t *drive, u8 pio)
 {
        ide_pio_data_t d;
        ide_hwif_t *hwif = HWIF(drive);
@@ -356,6 +359,22 @@ static void ali15x3_tune_drive (ide_drive_t *drive, u8 pio)
         * { 20,   50,     30  }    PIO Mode 5 with IORDY (nonstandard)
         */
 
+       return pio;
+}
+
+/**
+ *     ali15x3_tune_drive      -       set up drive for PIO mode
+ *     @drive: drive to tune
+ *     @pio: desired mode
+ *
+ *     Program the controller with the best PIO timing for the given drive.
+ *     Then set up the drive itself.
+ */
+
+static void ali15x3_tune_drive (ide_drive_t *drive, u8 pio)
+{
+       pio = ali15x3_tune_pio(drive, pio);
+       (void) ide_config_drive_speed(drive, XFER_PIO_0 + pio);
 }
 
 /**
@@ -430,7 +449,7 @@ static u8 ali15x3_ratemask (ide_drive_t *drive)
 }
 
 /**
- *     ali15x3_tune_chipset    -       set up chiset for new speed
+ *     ali15x3_tune_chipset    -       set up chipset/drive for new speed
  *     @drive: drive to configure for
  *     @xferspeed: desired speed
  *
@@ -461,7 +480,7 @@ static int ali15x3_tune_chipset (ide_drive_t *drive, u8 xferspeed)
                pci_write_config_byte(dev, m5229_udma, tmpbyte);
 
                if (speed < XFER_SW_DMA_0)
-                       ali15x3_tune_drive(drive, speed);
+                       (void) ali15x3_tune_pio(drive, speed - XFER_PIO_0);
        } else {
                pci_read_config_byte(dev, m5229_udma, &tmpbyte);
                tmpbyte &= (0x0f << ((1-unit) << 2));
index 61b5f9c0b2f4da7620b8655b43afed4d580bc460..dc43f009acabb4190b1d8a91525f8f342f8aa745 100644 (file)
@@ -98,7 +98,6 @@
  *                      (patch courtesy of Zoltan Hidvegi)
  */
 
-#undef REALLY_SLOW_IO          /* most systems can safely undef this */
 #define CMD640_PREFETCH_MASKS 1
 
 //#define CMD640_DUMP_REGS
index 49df27513da7add4275f42bd71a33bdbdd3bc84f..b0d4825c56a9c45040dc062d05b185b2358869cd 100644 (file)
@@ -1,6 +1,6 @@
 /* $Id: cmd64x.c,v 1.21 2000/01/30 23:23:16
  *
- * linux/drivers/ide/pci/cmd64x.c              Version 1.30    Sept 10, 2002
+ * linux/drivers/ide/pci/cmd64x.c              Version 1.41    Feb 3, 2007
  *
  * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines.
  *           Note, this driver is not used at all on other systems because
@@ -12,6 +12,7 @@
  * Copyright (C) 1998          David S. Miller (davem@redhat.com)
  *
  * Copyright (C) 1999-2002     Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 2007          MontaVista Software, Inc. <source@mvista.com>
  */
 
 #include <linux/module.h>
@@ -262,43 +263,25 @@ static void program_drive_counts (ide_drive_t *drive, int setup_count, int activ
 }
 
 /*
- * Attempts to set the interface PIO mode.
- * The preferred method of selecting PIO modes (e.g. mode 4) is 
- * "echo 'piomode:4' > /proc/ide/hdx/settings".  Special cases are
- * 8: prefetch off, 9: prefetch on, 255: auto-select best mode.
- * Called with 255 at boot time.
+ * This routine selects drive's best PIO mode, calculates setup/active/recovery
+ * counts, and then writes them into the chipset registers.
  */
-
-static void cmd64x_tuneproc (ide_drive_t *drive, u8 mode_wanted)
+static u8 cmd64x_tune_pio (ide_drive_t *drive, u8 mode_wanted)
 {
        int setup_time, active_time, recovery_time;
        int clock_time, pio_mode, cycle_time;
        u8 recovery_count2, cycle_count;
        int setup_count, active_count, recovery_count;
        int bus_speed = system_bus_clock();
-       /*byte b;*/
        ide_pio_data_t  d;
 
-       switch (mode_wanted) {
-               case 8: /* set prefetch off */
-               case 9: /* set prefetch on */
-                       mode_wanted &= 1;
-                       /*set_prefetch_mode(index, mode_wanted);*/
-                       cmdprintk("%s: %sabled cmd640 prefetch\n",
-                               drive->name, mode_wanted ? "en" : "dis");
-                       return;
-       }
-
-       mode_wanted = ide_get_best_pio_mode (drive, mode_wanted, 5, &d);
-       pio_mode = d.pio_mode;
+       pio_mode = ide_get_best_pio_mode(drive, mode_wanted, 5, &d);
        cycle_time = d.cycle_time;
 
        /*
         * I copied all this complicated stuff from cmd640.c and made a few
         * minor changes.  For now I am just going to pray that it is correct.
         */
-       if (pio_mode > 5)
-               pio_mode = 5;
        setup_time  = ide_pio_timings[pio_mode].setup_time;
        active_time = ide_pio_timings[pio_mode].active_time;
        recovery_time = cycle_time - (setup_time + active_time);
@@ -320,22 +303,33 @@ static void cmd64x_tuneproc (ide_drive_t *drive, u8 mode_wanted)
        if (active_count > 16)
                active_count = 16; /* maximum allowed by cmd646 */
 
-       /*
-        * In a perfect world, we might set the drive pio mode here
-        * (using WIN_SETFEATURE) before continuing.
-        *
-        * But we do not, because:
-        *      1) this is the wrong place to do it
-        *              (proper is do_special() in ide.c)
-        *      2) in practice this is rarely, if ever, necessary
-        */
        program_drive_counts (drive, setup_count, active_count, recovery_count);
 
-       cmdprintk("%s: selected cmd646 PIO mode%d : %d (%dns)%s, "
+       cmdprintk("%s: PIO mode wanted %d, selected %d (%dns)%s, "
                "clocks=%d/%d/%d\n",
-               drive->name, pio_mode, mode_wanted, cycle_time,
+               drive->name, mode_wanted, pio_mode, cycle_time,
                d.overridden ? " (overriding vendor mode)" : "",
                setup_count, active_count, recovery_count);
+
+       return pio_mode;
+}
+
+/*
+ * Attempts to set drive's PIO mode.
+ * Special cases are 8: prefetch off, 9: prefetch on (both never worked),
+ * and 255: auto-select best mode (used at boot time).
+ */
+static void cmd64x_tune_drive (ide_drive_t *drive, u8 pio)
+{
+       /*
+        * Filter out the prefetch control values
+        * to prevent PIO5 from being programmed
+        */
+       if (pio == 8 || pio == 9)
+               return;
+
+       pio = cmd64x_tune_pio(drive, pio);
+       (void) ide_config_drive_speed(drive, XFER_PIO_0 + pio);
 }
 
 static u8 cmd64x_ratemask (ide_drive_t *drive)
@@ -387,22 +381,6 @@ static u8 cmd64x_ratemask (ide_drive_t *drive)
        return mode;
 }
 
-static void config_cmd64x_chipset_for_pio (ide_drive_t *drive, u8 set_speed)
-{
-       u8 speed        = 0x00;
-       u8 set_pio      = ide_get_best_pio_mode(drive, 4, 5, NULL);
-
-       cmd64x_tuneproc(drive, set_pio);
-       speed = XFER_PIO_0 + set_pio;
-       if (set_speed)
-               (void) ide_config_drive_speed(drive, speed);
-}
-
-static void config_chipset_for_pio (ide_drive_t *drive, u8 set_speed)
-{
-       config_cmd64x_chipset_for_pio(drive, set_speed);
-}
-
 static int cmd64x_tune_chipset (ide_drive_t *drive, u8 xferspeed)
 {
        ide_hwif_t *hwif        = HWIF(drive);
@@ -414,7 +392,7 @@ static int cmd64x_tune_chipset (ide_drive_t *drive, u8 xferspeed)
 
        u8 speed        = ide_rate_filter(cmd64x_ratemask(drive), xferspeed);
 
-       if (speed > XFER_PIO_4) {
+       if (speed >= XFER_SW_DMA_0) {
                (void) pci_read_config_byte(dev, pciD, &regD);
                (void) pci_read_config_byte(dev, pciU, &regU);
                regD &= ~(unit ? 0x40 : 0x20);
@@ -438,17 +416,20 @@ static int cmd64x_tune_chipset (ide_drive_t *drive, u8 xferspeed)
                case XFER_SW_DMA_2:     regD |= (unit ? 0x40 : 0x10); break;
                case XFER_SW_DMA_1:     regD |= (unit ? 0x80 : 0x20); break;
                case XFER_SW_DMA_0:     regD |= (unit ? 0xC0 : 0x30); break;
-               case XFER_PIO_4:        cmd64x_tuneproc(drive, 4); break;
-               case XFER_PIO_3:        cmd64x_tuneproc(drive, 3); break;
-               case XFER_PIO_2:        cmd64x_tuneproc(drive, 2); break;
-               case XFER_PIO_1:        cmd64x_tuneproc(drive, 1); break;
-               case XFER_PIO_0:        cmd64x_tuneproc(drive, 0); break;
+               case XFER_PIO_5:
+               case XFER_PIO_4:
+               case XFER_PIO_3:
+               case XFER_PIO_2:
+               case XFER_PIO_1:
+               case XFER_PIO_0:
+                       (void) cmd64x_tune_pio(drive, speed - XFER_PIO_0);
+                       break;
 
                default:
                        return 1;
        }
 
-       if (speed > XFER_PIO_4) {
+       if (speed >= XFER_SW_DMA_0) {
                (void) pci_write_config_byte(dev, pciU, regU);
                regD |= (unit ? 0x40 : 0x20);
                (void) pci_write_config_byte(dev, pciD, regD);
@@ -461,8 +442,6 @@ static int config_chipset_for_dma (ide_drive_t *drive)
 {
        u8 speed        = ide_dma_speed(drive, cmd64x_ratemask(drive));
 
-       config_chipset_for_pio(drive, !speed);
-
        if (!speed)
                return 0;
 
@@ -478,7 +457,7 @@ static int cmd64x_config_drive_for_dma (ide_drive_t *drive)
                return 0;
 
        if (ide_use_fast_pio(drive))
-               config_chipset_for_pio(drive, 1);
+               cmd64x_tune_drive(drive, 255);
 
        return -1;
 }
@@ -679,14 +658,13 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
        pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
        class_rev &= 0xff;
 
-       hwif->tuneproc  = &cmd64x_tuneproc;
+       hwif->tuneproc  = &cmd64x_tune_drive;
        hwif->speedproc = &cmd64x_tune_chipset;
 
-       if (!hwif->dma_base) {
-               hwif->drives[0].autotune = 1;
-               hwif->drives[1].autotune = 1;
+       hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
+
+       if (!hwif->dma_base)
                return;
-       }
 
        hwif->atapi_dma = 1;
 
index e2672fc65d305c8fa8e40c7d7f1d15c92b8dd00d..d4b753e70119725625997049347fef1c1a78361a 100644 (file)
@@ -122,7 +122,7 @@ static struct pci_driver driver = {
 static int
 delkin_cb_init (void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void
index b408c6c517eaa5683f4319e8a09d73b7c05a8473..f2c5a141ca10ca1927a03abea7b8e4e01ce0a1ba 100644 (file)
@@ -21,8 +21,6 @@
  * are deemed to be part of the source code.
  */
 
-#undef REALLY_SLOW_IO          /* most systems can safely undef this */
-
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
index 9ca60dd2185e636c70df8baa1464bae5965e3495..aede7eee9246fc087daa5c3c1541563a031a4e0f 100644 (file)
@@ -57,7 +57,7 @@
  * There is a 25/33MHz switch in configuration
  * register, but driver is written for use at any frequency which get
  * (use idebus=xx to select PCI bus speed).
- * Use ide0=autotune for automatical tune of the PIO modes.
+ * Use hda=autotune and hdb=autotune for automatical tune of the PIO modes.
  * If you get strange results, do not use this and set PIO manually
  * by hdparm.
  *
@@ -87,7 +87,6 @@
  * 0.5 doesn't work.
  */
 
-#undef REALLY_SLOW_IO  /* most systems can safely undef this */
 #define OPTI621_DEBUG          /* define for debug messages */
 
 #include <linux/types.h>
index 569822f4cf55d8ba28c79f9c385db511657b8d80..061d300ab8be7dfc3ddada57c904e40aedd54bbc 100644 (file)
@@ -1,10 +1,10 @@
 /*
- *  linux/drivers/ide/pci/piix.c       Version 0.46    December 3, 2006
+ *  linux/drivers/ide/pci/piix.c       Version 0.47    February 8, 2007
  *
  *  Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
  *  Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
  *  Copyright (C) 2003 Red Hat Inc <alan@redhat.com>
- *  Copyright (C) 2006 MontaVista Software, Inc. <source@mvista.com>
+ *  Copyright (C) 2006-2007 MontaVista Software, Inc. <source@mvista.com>
  *
  *  May be copied or modified under the terms of the GNU General Public License
  *
@@ -205,14 +205,13 @@ static u8 piix_dma_2_pio (u8 xfer_rate) {
 }
 
 /**
- *     piix_tune_drive         -       tune a drive attached to a PIIX
+ *     piix_tune_pio           -       tune PIIX for PIO mode
  *     @drive: drive to tune
  *     @pio: desired PIO mode
  *
- *     Set the interface PIO mode based upon  the settings done by AMI BIOS
- *     (might be useful if drive is not registered in CMOS for any reason).
+ *     Set the interface PIO mode based upon the settings done by AMI BIOS.
  */
-static void piix_tune_drive (ide_drive_t *drive, u8 pio)
+static void piix_tune_pio (ide_drive_t *drive, u8 pio)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        struct pci_dev *dev     = hwif->pci_dev;
@@ -233,8 +232,6 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio)
                                        { 2, 1 },
                                        { 2, 3 }, };
 
-       pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
-
        /*
         * Master vs slave is synchronized above us but the slave register is
         * shared by the two hwifs so the corner case of two slave timeouts in
@@ -253,19 +250,20 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio)
                master_data |=  0x4000;
                master_data &= ~0x0070;
                if (pio > 1) {
-                       /* enable PPE, IE and TIME */
-                       master_data = master_data | (control << 4);
+                       /* Set PPE, IE and TIME */
+                       master_data |= control << 4;
                }
                pci_read_config_byte(dev, slave_port, &slave_data);
-               slave_data = slave_data & (hwif->channel ? 0x0f : 0xf0);
-               slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1]) << (hwif->channel ? 4 : 0));
+               slave_data &= hwif->channel ? 0x0f : 0xf0;
+               slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) <<
+                              (hwif->channel ? 4 : 0);
        } else {
                master_data &= ~0x3307;
                if (pio > 1) {
                        /* enable PPE, IE and TIME */
-                       master_data = master_data | control;
+                       master_data |= control;
                }
-               master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8);
+               master_data |= (timings[pio][0] << 12) | (timings[pio][1] << 8);
        }
        pci_write_config_word(dev, master_port, master_data);
        if (is_slave)
@@ -273,6 +271,21 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio)
        spin_unlock_irqrestore(&tune_lock, flags);
 }
 
+/**
+ *     piix_tune_drive         -       tune a drive attached to PIIX
+ *     @drive: drive to tune
+ *     @pio: desired PIO mode
+ *
+ *     Set the drive's PIO mode (might be useful if drive is not registered
+ *     in CMOS for any reason).
+ */
+static void piix_tune_drive (ide_drive_t *drive, u8 pio)
+{
+       pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+       piix_tune_pio(drive, pio);
+       (void) ide_config_drive_speed(drive, XFER_PIO_0 + pio);
+}
+
 /**
  *     piix_tune_chipset       -       tune a PIIX interface
  *     @drive: IDE drive to tune
@@ -348,8 +361,8 @@ static int piix_tune_chipset (ide_drive_t *drive, u8 xferspeed)
                        pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
        }
 
-       piix_tune_drive(drive, piix_dma_2_pio(speed));
-       return (ide_config_drive_speed(drive, speed));
+       piix_tune_pio(drive, piix_dma_2_pio(speed));
+       return ide_config_drive_speed(drive, speed);
 }
 
 /**
@@ -392,9 +405,7 @@ static int piix_config_drive_xfer_rate (ide_drive_t *drive)
                return 0;
 
        if (ide_use_fast_pio(drive))
-               /* Find best PIO mode. */
-               piix_tune_chipset(drive, XFER_PIO_0 +
-                                 ide_get_best_pio_mode(drive, 255, 4, NULL));
+               piix_tune_drive(drive, 255);
 
        return -1;
 }
index c1855311052bb06a5d12934caa95324c3378131b..f8c954690142265fcb4202f06445e340a4e5b8a5 100644 (file)
@@ -15,8 +15,6 @@
  *  Dunno if this fixes both ports, or only the primary port (?).
  */
 
-#undef REALLY_SLOW_IO          /* most systems can safely undef this */
-
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
index 7b4c189a9d99c81384a8500ca7c339995b495f07..71eccdf5f817f10880e803c361a3e7983031e235 100644 (file)
  *     If you have strange problems with nVidia chipset systems please
  *     see the SI support documentation and update your system BIOS
  *     if neccessary
+ *
+ *  The Dell DRAC4 has some interesting features including effectively hot
+ *  unplugging/replugging the virtual CD interface when the DRAC is reset.
+ *  This often causes drivers/ide/siimage to panic but is ok with the rather
+ *  smarter code in libata.
  */
 
 #include <linux/types.h>
index ae7eb58d961c6f46a27c153aec56dee407befe84..852ccb36da1df943045b9b7775ec13ebfe235170 100644 (file)
@@ -1,8 +1,8 @@
 /*
- *  linux/drivers/ide/pci/slc90e66.c   Version 0.13    December 30, 2006
+ *  linux/drivers/ide/pci/slc90e66.c   Version 0.14    February 8, 2007
  *
  *  Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org>
- *  Copyright (C) 2006 MontaVista Software, Inc. <source@mvista.com>
+ *  Copyright (C) 2006-2007 MontaVista Software, Inc. <source@mvista.com>
  *
  * This is a look-alike variation of the ICH0 PIIX4 Ultra-66,
  * but this keeps the ISA-Bridge and slots alive.
@@ -57,11 +57,7 @@ static u8 slc90e66_dma_2_pio (u8 xfer_rate) {
        }
 }
 
-/*
- *  Based on settings done by AMI BIOS
- *  (might be useful if drive is not registered in CMOS for any reason).
- */
-static void slc90e66_tune_drive (ide_drive_t *drive, u8 pio)
+static void slc90e66_tune_pio (ide_drive_t *drive, u8 pio)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        struct pci_dev *dev     = hwif->pci_dev;
@@ -80,7 +76,6 @@ static void slc90e66_tune_drive (ide_drive_t *drive, u8 pio)
                                        { 2, 1 },
                                        { 2, 3 }, };
 
-       pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
        spin_lock_irqsave(&ide_lock, flags);
        pci_read_config_word(dev, master_port, &master_data);
 
@@ -94,19 +89,20 @@ static void slc90e66_tune_drive (ide_drive_t *drive, u8 pio)
                master_data |=  0x4000;
                master_data &= ~0x0070;
                if (pio > 1) {
-                       /* enable PPE, IE and TIME */
-                       master_data = master_data | (control << 4);
+                       /* Set PPE, IE and TIME */
+                       master_data |= control << 4;
                }
                pci_read_config_byte(dev, slave_port, &slave_data);
-               slave_data = slave_data & (hwif->channel ? 0x0f : 0xf0);
-               slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1]) << (hwif->channel ? 4 : 0));
+               slave_data &= hwif->channel ? 0x0f : 0xf0;
+               slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) <<
+                              (hwif->channel ? 4 : 0);
        } else {
                master_data &= ~0x3307;
                if (pio > 1) {
                        /* enable PPE, IE and TIME */
-                       master_data = master_data | control;
+                       master_data |= control;
                }
-               master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8);
+               master_data |= (timings[pio][0] << 12) | (timings[pio][1] << 8);
        }
        pci_write_config_word(dev, master_port, master_data);
        if (is_slave)
@@ -114,6 +110,13 @@ static void slc90e66_tune_drive (ide_drive_t *drive, u8 pio)
        spin_unlock_irqrestore(&ide_lock, flags);
 }
 
+static void slc90e66_tune_drive (ide_drive_t *drive, u8 pio)
+{
+       pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+       slc90e66_tune_pio(drive, pio);
+       (void) ide_config_drive_speed(drive, XFER_PIO_0 + pio);
+}
+
 static int slc90e66_tune_chipset (ide_drive_t *drive, u8 xferspeed)
 {
        ide_hwif_t *hwif        = HWIF(drive);
@@ -162,8 +165,8 @@ static int slc90e66_tune_chipset (ide_drive_t *drive, u8 xferspeed)
                        pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
        }
 
-       slc90e66_tune_drive(drive, slc90e66_dma_2_pio(speed));
-       return (ide_config_drive_speed(drive, speed));
+       slc90e66_tune_pio(drive, slc90e66_dma_2_pio(speed));
+       return ide_config_drive_speed(drive, speed);
 }
 
 static int slc90e66_config_drive_for_dma (ide_drive_t *drive)
@@ -185,8 +188,7 @@ static int slc90e66_config_drive_xfer_rate (ide_drive_t *drive)
                return 0;
 
        if (ide_use_fast_pio(drive))
-               (void)slc90e66_tune_chipset(drive, XFER_PIO_0 +
-                               ide_get_best_pio_mode(drive, 255, 4, NULL));
+               slc90e66_tune_drive(drive, 255);
 
        return -1;
 }
index 395d35253d5d0084bb9cd823eb2cb1658abb10b4..071a030ec26edd6cfc35ffb62a7bd2efc9700cec 100644 (file)
@@ -48,7 +48,7 @@
 #include <asm/mediabay.h>
 #endif
 
-#include "ide-timing.h"
+#include "../ide-timing.h"
 
 #undef IDE_PMAC_DEBUG
 
@@ -1551,19 +1551,34 @@ static struct pci_driver pmac_ide_pci_driver = {
 };
 MODULE_DEVICE_TABLE(pci, pmac_ide_pci_match);
 
-void __init
-pmac_ide_probe(void)
+int __init pmac_ide_probe(void)
 {
+       int error;
+
        if (!machine_is(powermac))
-               return;
+               return -ENODEV;
 
 #ifdef CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST
-       pci_register_driver(&pmac_ide_pci_driver);
-       macio_register_driver(&pmac_ide_macio_driver);
+       error = pci_register_driver(&pmac_ide_pci_driver);
+       if (error)
+               goto out;
+       error = macio_register_driver(&pmac_ide_macio_driver);
+       if (error) {
+               pci_unregister_driver(&pmac_ide_pci_driver);
+               goto out;
+       }
 #else
-       macio_register_driver(&pmac_ide_macio_driver);
-       pci_register_driver(&pmac_ide_pci_driver);
+       error = macio_register_driver(&pmac_ide_macio_driver);
+       if (error)
+               goto out;
+       error = pci_register_driver(&pmac_ide_pci_driver);
+       if (error) {
+               macio_unregister_driver(&pmac_ide_macio_driver);
+               goto out;
+       }
 #endif
+out:
+       return error;
 }
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
@@ -1983,7 +1998,7 @@ static void pmac_ide_dma_host_off(ide_drive_t *drive)
 {
 }
 
-static int pmac_ide_dma_host_on(ide_drive_t *drive)
+static void pmac_ide_dma_host_on(ide_drive_t *drive)
 {
 }
 
index de64b022478b9158edaf471dc31657ec2e56d022..f84bf791f72e901605594a79cb0f61491a8faac4 100644 (file)
@@ -509,6 +509,32 @@ static int scc_ide_dma_end(ide_drive_t * drive)
        return __ide_dma_end(drive);
 }
 
+/* returns 1 if dma irq issued, 0 otherwise */
+static int scc_dma_test_irq(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       u8 dma_stat             = hwif->INB(hwif->dma_status);
+
+       /* return 1 if INTR asserted */
+       if ((dma_stat & 4) == 4)
+               return 1;
+
+       /* Workaround for PTERADD: emulate DMA_INTR when
+        * - IDE_STATUS[ERR] = 1
+        * - INT_STATUS[INTRQ] = 1
+        * - DMA_STATUS[IORACTA] = 1
+        */
+       if (in_be32((void __iomem *)IDE_ALTSTATUS_REG) & ERR_STAT &&
+           in_be32((void __iomem *)(hwif->dma_base + 0x014)) & INTSTS_INTRQ &&
+               dma_stat & 1)
+               return 1;
+
+       if (!drive->waiting_for_dma)
+               printk(KERN_WARNING "%s: (%s) called while not waiting\n",
+                       drive->name, __FUNCTION__);
+       return 0;
+}
+
 /**
  *     setup_mmio_scc  -       map CTRL/BMID region
  *     @dev: PCI device we are configuring
@@ -712,6 +738,7 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
        hwif->speedproc = scc_tune_chipset;
        hwif->tuneproc = scc_tuneproc;
        hwif->ide_dma_check = scc_config_drive_for_dma;
+       hwif->ide_dma_test_irq = scc_dma_test_irq;
 
        hwif->drives[0].autotune = IDE_TUNE_AUTO;
        hwif->drives[1].autotune = IDE_TUNE_AUTO;
index d446998b12a4a1083c4d0b8a89ed5801f994d75e..842cd0b53e91a1b3b8d957ec78e803939b2b01b9 100644 (file)
@@ -88,7 +88,6 @@ struct cm_port {
 struct cm_device {
        struct list_head list;
        struct ib_device *device;
-       __be64 ca_guid;
        struct cm_port port[0];
 };
 
@@ -739,8 +738,8 @@ retest:
                ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
                spin_unlock_irqrestore(&cm_id_priv->lock, flags);
                ib_send_cm_rej(cm_id, IB_CM_REJ_TIMEOUT,
-                              &cm_id_priv->av.port->cm_dev->ca_guid,
-                              sizeof cm_id_priv->av.port->cm_dev->ca_guid,
+                              &cm_id_priv->id.device->node_guid,
+                              sizeof cm_id_priv->id.device->node_guid,
                               NULL, 0);
                break;
        case IB_CM_REQ_RCVD:
@@ -883,7 +882,7 @@ static void cm_format_req(struct cm_req_msg *req_msg,
 
        req_msg->local_comm_id = cm_id_priv->id.local_id;
        req_msg->service_id = param->service_id;
-       req_msg->local_ca_guid = cm_id_priv->av.port->cm_dev->ca_guid;
+       req_msg->local_ca_guid = cm_id_priv->id.device->node_guid;
        cm_req_set_local_qpn(req_msg, cpu_to_be32(param->qp_num));
        cm_req_set_resp_res(req_msg, param->responder_resources);
        cm_req_set_init_depth(req_msg, param->initiator_depth);
@@ -1442,7 +1441,7 @@ static void cm_format_rep(struct cm_rep_msg *rep_msg,
        cm_rep_set_flow_ctrl(rep_msg, param->flow_control);
        cm_rep_set_rnr_retry_count(rep_msg, param->rnr_retry_count);
        cm_rep_set_srq(rep_msg, param->srq);
-       rep_msg->local_ca_guid = cm_id_priv->av.port->cm_dev->ca_guid;
+       rep_msg->local_ca_guid = cm_id_priv->id.device->node_guid;
 
        if (param->private_data && param->private_data_len)
                memcpy(rep_msg->private_data, param->private_data,
@@ -3385,7 +3384,6 @@ static void cm_add_one(struct ib_device *device)
                return;
 
        cm_dev->device = device;
-       cm_dev->ca_guid = device->node_guid;
 
        set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask);
        for (i = 1; i <= device->phys_port_cnt; i++) {
index f8d69b3fa30796f8c4258a858a3664c0f5bff647..fde92ce45153efc7eeb6a2cfc3f46e71bb9df82b 100644 (file)
@@ -77,7 +77,6 @@ static int next_port;
 struct cma_device {
        struct list_head        list;
        struct ib_device        *device;
-       __be64                  node_guid;
        struct completion       comp;
        atomic_t                refcount;
        struct list_head        id_list;
@@ -1492,11 +1491,13 @@ static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms,
        ib_addr_get_dgid(addr, &path_rec.dgid);
        path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(addr));
        path_rec.numb_path = 1;
+       path_rec.reversible = 1;
 
        id_priv->query_id = ib_sa_path_rec_get(&sa_client, id_priv->id.device,
                                id_priv->id.port_num, &path_rec,
                                IB_SA_PATH_REC_DGID | IB_SA_PATH_REC_SGID |
-                               IB_SA_PATH_REC_PKEY | IB_SA_PATH_REC_NUMB_PATH,
+                               IB_SA_PATH_REC_PKEY | IB_SA_PATH_REC_NUMB_PATH |
+                               IB_SA_PATH_REC_REVERSIBLE,
                                timeout_ms, GFP_KERNEL,
                                cma_query_handler, work, &id_priv->query);
 
@@ -1820,7 +1821,7 @@ static int cma_alloc_port(struct idr *ps, struct rdma_id_private *id_priv,
        struct rdma_bind_list *bind_list;
        int port, ret;
 
-       bind_list = kmalloc(sizeof *bind_list, GFP_KERNEL);
+       bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL);
        if (!bind_list)
                return -ENOMEM;
 
@@ -2672,7 +2673,6 @@ static void cma_add_one(struct ib_device *device)
                return;
 
        cma_dev->device = device;
-       cma_dev->node_guid = device->node_guid;
 
        init_completion(&cma_dev->comp);
        atomic_set(&cma_dev->refcount, 1);
index b516b93b85505b5a243a88ad00a670defab4c452..c859134c1daa3a0d73306f517bebc1c3920a949d 100644 (file)
@@ -266,7 +266,7 @@ static int ucma_event_handler(struct rdma_cm_id *cm_id,
        mutex_lock(&ctx->file->mut);
        if (event->event == RDMA_CM_EVENT_CONNECT_REQUEST) {
                if (!ctx->backlog) {
-                       ret = -EDQUOT;
+                       ret = -ENOMEM;
                        kfree(uevent);
                        goto out;
                }
index df1efbc10882692b7de5a690d31cd8d79dec05a4..4fd75afa6a3a90689a12a27c2c8edce5f076fb7d 100644 (file)
@@ -622,8 +622,10 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
        obj->umem.virt_base = cmd.hca_va;
 
        pd = idr_read_pd(cmd.pd_handle, file->ucontext);
-       if (!pd)
+       if (!pd) {
+               ret = -EINVAL;
                goto err_release;
+       }
 
        mr = pd->device->reg_user_mr(pd, &obj->umem, cmd.access_flags, &udata);
        if (IS_ERR(mr)) {
index 8b5dd3649bbf37e8c0679393506a30a46d879e38..ccdf93d30b0166a09d4ae237553db33ffe4aebba 100644 (file)
@@ -167,7 +167,7 @@ int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc,
                ah_attr->grh.sgid_index = (u8) gid_index;
                flow_class = be32_to_cpu(grh->version_tclass_flow);
                ah_attr->grh.flow_label = flow_class & 0xFFFFF;
-               ah_attr->grh.hop_limit = grh->hop_limit;
+               ah_attr->grh.hop_limit = 0xFF;
                ah_attr->grh.traffic_class = (flow_class >> 20) & 0xFF;
        }
        return 0;
index 0e110f32f128526d3b2b8ce975a9be218fc3cf73..36b98989b15ecaf79274a547a0733a42859fb0d5 100644 (file)
@@ -8,5 +8,4 @@ iw_cxgb3-y :=  iwch_cm.o iwch_ev.o iwch_cq.o iwch_qp.o iwch_mem.o \
 
 ifdef CONFIG_INFINIBAND_CXGB3_DEBUG
 EXTRA_CFLAGS += -DDEBUG
-iw_cxgb3-y += cxio_dbg.o
 endif
index 114ac3b775dc2fb527222a0c575d782af5d7e736..818cf1aee8c7b1e58bdf1dc229e3b6797799bb0e 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/pci.h>
+#include <linux/dma-mapping.h>
 
 #include "cxio_resource.h"
 #include "cxio_hal.h"
@@ -45,7 +46,7 @@
 static LIST_HEAD(rdev_list);
 static cxio_hal_ev_callback_func_t cxio_ev_cb = NULL;
 
-static inline struct cxio_rdev *cxio_hal_find_rdev_by_name(char *dev_name)
+static struct cxio_rdev *cxio_hal_find_rdev_by_name(char *dev_name)
 {
        struct cxio_rdev *rdev;
 
@@ -55,8 +56,7 @@ static inline struct cxio_rdev *cxio_hal_find_rdev_by_name(char *dev_name)
        return NULL;
 }
 
-static inline struct cxio_rdev *cxio_hal_find_rdev_by_t3cdev(struct t3cdev
-                                                            *tdev)
+static struct cxio_rdev *cxio_hal_find_rdev_by_t3cdev(struct t3cdev *tdev)
 {
        struct cxio_rdev *rdev;
 
@@ -118,7 +118,7 @@ int cxio_hal_cq_op(struct cxio_rdev *rdev_p, struct t3_cq *cq,
        return 0;
 }
 
-static inline int cxio_hal_clear_cq_ctx(struct cxio_rdev *rdev_p, u32 cqid)
+static int cxio_hal_clear_cq_ctx(struct cxio_rdev *rdev_p, u32 cqid)
 {
        struct rdma_cq_setup setup;
        setup.id = cqid;
@@ -130,7 +130,7 @@ static inline int cxio_hal_clear_cq_ctx(struct cxio_rdev *rdev_p, u32 cqid)
        return (rdev_p->t3cdev_p->ctl(rdev_p->t3cdev_p, RDMA_CQ_SETUP, &setup));
 }
 
-int cxio_hal_clear_qp_ctx(struct cxio_rdev *rdev_p, u32 qpid)
+static int cxio_hal_clear_qp_ctx(struct cxio_rdev *rdev_p, u32 qpid)
 {
        u64 sge_cmd;
        struct t3_modify_qp_wr *wqe;
@@ -425,7 +425,7 @@ void cxio_flush_hw_cq(struct t3_cq *cq)
        }
 }
 
-static inline int cqe_completes_wr(struct t3_cqe *cqe, struct t3_wq *wq)
+static int cqe_completes_wr(struct t3_cqe *cqe, struct t3_wq *wq)
 {
        if (CQE_OPCODE(*cqe) == T3_TERMINATE)
                return 0;
@@ -760,17 +760,6 @@ ret:
        return err;
 }
 
-/* IN : stag key, pdid, pbl_size
- * Out: stag index, actaul pbl_size, and pbl_addr allocated.
- */
-int cxio_allocate_stag(struct cxio_rdev *rdev_p, u32 * stag, u32 pdid,
-                      enum tpt_mem_perm perm, u32 * pbl_size, u32 * pbl_addr)
-{
-       *stag = T3_STAG_UNSET;
-       return (__cxio_tpt_op(rdev_p, 0, stag, 0, pdid, TPT_NON_SHARED_MR,
-                             perm, 0, 0ULL, 0, 0, NULL, pbl_size, pbl_addr));
-}
-
 int cxio_register_phys_mem(struct cxio_rdev *rdev_p, u32 *stag, u32 pdid,
                           enum tpt_mem_perm perm, u32 zbva, u64 to, u32 len,
                           u8 page_size, __be64 *pbl, u32 *pbl_size,
@@ -1029,7 +1018,7 @@ void __exit cxio_hal_exit(void)
        cxio_hal_destroy_rhdl_resource();
 }
 
-static inline void flush_completed_wrs(struct t3_wq *wq, struct t3_cq *cq)
+static void flush_completed_wrs(struct t3_wq *wq, struct t3_cq *cq)
 {
        struct t3_swsq *sqp;
        __u32 ptr = wq->sq_rptr;
@@ -1058,9 +1047,8 @@ static inline void flush_completed_wrs(struct t3_wq *wq, struct t3_cq *cq)
                        break;
 }
 
-static inline void create_read_req_cqe(struct t3_wq *wq,
-                                      struct t3_cqe *hw_cqe,
-                                      struct t3_cqe *read_cqe)
+static void create_read_req_cqe(struct t3_wq *wq, struct t3_cqe *hw_cqe,
+                               struct t3_cqe *read_cqe)
 {
        read_cqe->u.scqe.wrid_hi = wq->oldest_read->sq_wptr;
        read_cqe->len = wq->oldest_read->read_len;
@@ -1073,7 +1061,7 @@ static inline void create_read_req_cqe(struct t3_wq *wq,
 /*
  * Return a ptr to the next read wr in the SWSQ or NULL.
  */
-static inline void advance_oldest_read(struct t3_wq *wq)
+static void advance_oldest_read(struct t3_wq *wq)
 {
 
        u32 rptr = wq->oldest_read - wq->sq + 1;
index 8ab04a7c6f6eec1558546a57c8e2397e920e643c..99543d634704d93c98b1f4bcfa615a5aee7bfc0d 100644 (file)
@@ -143,7 +143,6 @@ int cxio_rdev_open(struct cxio_rdev *rdev);
 void cxio_rdev_close(struct cxio_rdev *rdev);
 int cxio_hal_cq_op(struct cxio_rdev *rdev, struct t3_cq *cq,
                   enum t3_cq_opcode op, u32 credit);
-int cxio_hal_clear_qp_ctx(struct cxio_rdev *rdev, u32 qpid);
 int cxio_create_cq(struct cxio_rdev *rdev, struct t3_cq *cq);
 int cxio_destroy_cq(struct cxio_rdev *rdev, struct t3_cq *cq);
 int cxio_resize_cq(struct cxio_rdev *rdev, struct t3_cq *cq);
@@ -154,8 +153,6 @@ int cxio_create_qp(struct cxio_rdev *rdev, u32 kernel_domain, struct t3_wq *wq,
 int cxio_destroy_qp(struct cxio_rdev *rdev, struct t3_wq *wq,
                    struct cxio_ucontext *uctx);
 int cxio_peek_cq(struct t3_wq *wr, struct t3_cq *cq, int opcode);
-int cxio_allocate_stag(struct cxio_rdev *rdev, u32 * stag, u32 pdid,
-                      enum tpt_mem_perm perm, u32 * pbl_size, u32 * pbl_addr);
 int cxio_register_phys_mem(struct cxio_rdev *rdev, u32 * stag, u32 pdid,
                           enum tpt_mem_perm perm, u32 zbva, u64 to, u32 len,
                           u8 page_size, __be64 *pbl, u32 *pbl_size,
@@ -171,8 +168,6 @@ int cxio_deallocate_window(struct cxio_rdev *rdev, u32 stag);
 int cxio_rdma_init(struct cxio_rdev *rdev, struct t3_rdma_init_attr *attr);
 void cxio_register_ev_cb(cxio_hal_ev_callback_func_t ev_cb);
 void cxio_unregister_ev_cb(cxio_hal_ev_callback_func_t ev_cb);
-u32 cxio_hal_get_rhdl(void);
-void cxio_hal_put_rhdl(u32 rhdl);
 u32 cxio_hal_get_pdid(struct cxio_hal_resource *rscp);
 void cxio_hal_put_pdid(struct cxio_hal_resource *rscp, u32 pdid);
 int __init cxio_hal_init(void);
index 65bf577311aa628af1e980f073e4c4c9268e1383..d3095ae5bc2e1fb8cc66b61149c9fe479ee2beed 100644 (file)
@@ -179,7 +179,7 @@ tpt_err:
 /*
  * returns 0 if no resource available
  */
-static inline u32 cxio_hal_get_resource(struct kfifo *fifo)
+static u32 cxio_hal_get_resource(struct kfifo *fifo)
 {
        u32 entry;
        if (kfifo_get(fifo, (unsigned char *) &entry, sizeof(u32)))
@@ -188,21 +188,11 @@ static inline u32 cxio_hal_get_resource(struct kfifo *fifo)
                return 0;       /* fifo emptry */
 }
 
-static inline void cxio_hal_put_resource(struct kfifo *fifo, u32 entry)
+static void cxio_hal_put_resource(struct kfifo *fifo, u32 entry)
 {
        BUG_ON(kfifo_put(fifo, (unsigned char *) &entry, sizeof(u32)) == 0);
 }
 
-u32 cxio_hal_get_rhdl(void)
-{
-       return cxio_hal_get_resource(rhdl_fifo);
-}
-
-void cxio_hal_put_rhdl(u32 rhdl)
-{
-       cxio_hal_put_resource(rhdl_fifo, rhdl);
-}
-
 u32 cxio_hal_get_stag(struct cxio_hal_resource *rscp)
 {
        return cxio_hal_get_resource(rscp->tpt_fifo);
index e5442e34b788566f4adba514fa4bc332db8f8698..d0ed1d35ca3ebda4a171393fd1c6122aa916e9dd 100644 (file)
@@ -209,8 +209,7 @@ static enum iwch_ep_state state_read(struct iwch_ep_common *epc)
        return state;
 }
 
-static inline void __state_set(struct iwch_ep_common *epc,
-                              enum iwch_ep_state new)
+static void __state_set(struct iwch_ep_common *epc, enum iwch_ep_state new)
 {
        epc->state = new;
 }
@@ -306,8 +305,7 @@ static int status2errno(int status)
  */
 static struct sk_buff *get_skb(struct sk_buff *skb, int len, gfp_t gfp)
 {
-       if (skb) {
-               BUG_ON(skb_cloned(skb));
+       if (skb && !skb_is_nonlinear(skb) && !skb_cloned(skb)) {
                skb_trim(skb, 0);
                skb_get(skb);
        } else {
@@ -1416,6 +1414,7 @@ static int peer_close(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
                wake_up(&ep->com.waitq);
                break;
        case FPDU_MODE:
+               start_ep_timer(ep);
                __state_set(&ep->com, CLOSING);
                attrs.next_state = IWCH_QP_STATE_CLOSING;
                iwch_modify_qp(ep->com.qp->rhp, ep->com.qp,
@@ -1426,7 +1425,6 @@ static int peer_close(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
                disconnect = 0;
                break;
        case CLOSING:
-               start_ep_timer(ep);
                __state_set(&ep->com, MORIBUND);
                disconnect = 0;
                break;
@@ -1459,7 +1457,7 @@ static int peer_close(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
 /*
  * Returns whether an ABORT_REQ_RSS message is a negative advice.
  */
-static inline int is_neg_adv_abort(unsigned int status)
+static int is_neg_adv_abort(unsigned int status)
 {
        return status == CPL_ERR_RTX_NEG_ADVICE ||
               status == CPL_ERR_PERSIST_NEG_ADVICE;
@@ -1488,8 +1486,10 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
        case CONNECTING:
                break;
        case MPA_REQ_WAIT:
+               stop_ep_timer(ep);
                break;
        case MPA_REQ_SENT:
+               stop_ep_timer(ep);
                connect_reply_upcall(ep, -ECONNRESET);
                break;
        case MPA_REP_SENT:
@@ -1508,9 +1508,10 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
                get_ep(&ep->com);
                break;
        case MORIBUND:
+       case CLOSING:
                stop_ep_timer(ep);
+               /*FALLTHROUGH*/
        case FPDU_MODE:
-       case CLOSING:
                if (ep->com.cm_id && ep->com.qp) {
                        attrs.next_state = IWCH_QP_STATE_ERROR;
                        ret = iwch_modify_qp(ep->com.qp->rhp,
@@ -1571,7 +1572,6 @@ static int close_con_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
        spin_lock_irqsave(&ep->com.lock, flags);
        switch (ep->com.state) {
        case CLOSING:
-               start_ep_timer(ep);
                __state_set(&ep->com, MORIBUND);
                break;
        case MORIBUND:
@@ -1587,6 +1587,8 @@ static int close_con_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
                __state_set(&ep->com, DEAD);
                release = 1;
                break;
+       case ABORTING:
+               break;
        case DEAD:
        default:
                BUG_ON(1);
@@ -1635,6 +1637,7 @@ static int ec_status(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
 
                printk(KERN_ERR MOD "%s BAD CLOSE - Aborting tid %u\n",
                       __FUNCTION__, ep->hwtid);
+               stop_ep_timer(ep);
                attrs.next_state = IWCH_QP_STATE_ERROR;
                iwch_modify_qp(ep->com.qp->rhp,
                               ep->com.qp, IWCH_QP_ATTR_NEXT_STATE,
@@ -1659,6 +1662,7 @@ static void ep_timeout(unsigned long arg)
                break;
        case MPA_REQ_WAIT:
                break;
+       case CLOSING:
        case MORIBUND:
                if (ep->com.cm_id && ep->com.qp) {
                        attrs.next_state = IWCH_QP_STATE_ERROR;
@@ -1687,12 +1691,11 @@ int iwch_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
                return -ECONNRESET;
        }
        BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD);
-       state_set(&ep->com, CLOSING);
        if (mpa_rev == 0)
                abort_connection(ep, NULL, GFP_KERNEL);
        else {
                err = send_mpa_reject(ep, pdata, pdata_len);
-               err = send_halfclose(ep, GFP_KERNEL);
+               err = iwch_ep_disconnect(ep, 0, GFP_KERNEL);
        }
        return 0;
 }
@@ -1957,11 +1960,11 @@ int iwch_ep_disconnect(struct iwch_ep *ep, int abrupt, gfp_t gfp)
        case MPA_REQ_RCVD:
        case MPA_REP_SENT:
        case FPDU_MODE:
+               start_ep_timer(ep);
                ep->com.state = CLOSING;
                close = 1;
                break;
        case CLOSING:
-               start_ep_timer(ep);
                ep->com.state = MORIBUND;
                close = 1;
                break;
index 54362afbf72f6f410b5224e8c297afb92559a6e3..b40676662a8a88df1f46d21bac5c797475741cad 100644 (file)
@@ -47,12 +47,6 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp,
        struct iwch_qp_attributes attrs;
        struct iwch_qp *qhp;
 
-       printk(KERN_ERR "%s - AE qpid 0x%x opcode %d status 0x%x "
-              "type %d wrid.hi 0x%x wrid.lo 0x%x \n", __FUNCTION__,
-              CQE_QPID(rsp_msg->cqe), CQE_OPCODE(rsp_msg->cqe),
-              CQE_STATUS(rsp_msg->cqe), CQE_TYPE(rsp_msg->cqe),
-              CQE_WRID_HI(rsp_msg->cqe), CQE_WRID_LOW(rsp_msg->cqe));
-
        spin_lock(&rnicp->lock);
        qhp = get_qhp(rnicp, CQE_QPID(rsp_msg->cqe));
 
@@ -73,6 +67,12 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp,
                return;
        }
 
+       printk(KERN_ERR "%s - AE qpid 0x%x opcode %d status 0x%x "
+              "type %d wrid.hi 0x%x wrid.lo 0x%x \n", __FUNCTION__,
+              CQE_QPID(rsp_msg->cqe), CQE_OPCODE(rsp_msg->cqe),
+              CQE_STATUS(rsp_msg->cqe), CQE_TYPE(rsp_msg->cqe),
+              CQE_WRID_HI(rsp_msg->cqe), CQE_WRID_LOW(rsp_msg->cqe));
+
        atomic_inc(&qhp->refcnt);
        spin_unlock(&rnicp->lock);
 
index 2aef122f9955b63cce07d008aee911282cc14a40..f2774ae906bf66f9ac8d55a298b43e0bc7486ea1 100644 (file)
@@ -331,6 +331,7 @@ static int iwch_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
        int ret = 0;
        struct iwch_mm_entry *mm;
        struct iwch_ucontext *ucontext;
+       u64 addr;
 
        PDBG("%s pgoff 0x%lx key 0x%x len %d\n", __FUNCTION__, vma->vm_pgoff,
             key, len);
@@ -345,10 +346,11 @@ static int iwch_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
        mm = remove_mmap(ucontext, key, len);
        if (!mm)
                return -EINVAL;
+       addr = mm->addr;
        kfree(mm);
 
-       if ((mm->addr >= rdev_p->rnic_info.udbell_physbase) &&
-           (mm->addr < (rdev_p->rnic_info.udbell_physbase +
+       if ((addr >= rdev_p->rnic_info.udbell_physbase) &&
+           (addr < (rdev_p->rnic_info.udbell_physbase +
                       rdev_p->rnic_info.udbell_len))) {
 
                /*
@@ -362,7 +364,7 @@ static int iwch_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
                vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND;
                vma->vm_flags &= ~VM_MAYREAD;
                ret = io_remap_pfn_range(vma, vma->vm_start,
-                                        mm->addr >> PAGE_SHIFT,
+                                        addr >> PAGE_SHIFT,
                                         len, vma->vm_page_prot);
        } else {
 
@@ -370,7 +372,7 @@ static int iwch_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
                 * Map WQ or CQ contig dma memory...
                 */
                ret = remap_pfn_range(vma, vma->vm_start,
-                                     mm->addr >> PAGE_SHIFT,
+                                     addr >> PAGE_SHIFT,
                                      len, vma->vm_page_prot);
        }
 
@@ -463,9 +465,6 @@ static struct ib_mr *iwch_register_phys_mem(struct ib_pd *pd,
        php = to_iwch_pd(pd);
        rhp = php->rhp;
 
-       acc = iwch_convert_access(acc);
-
-
        mhp = kzalloc(sizeof(*mhp), GFP_KERNEL);
        if (!mhp)
                return ERR_PTR(-ENOMEM);
@@ -491,12 +490,7 @@ static struct ib_mr *iwch_register_phys_mem(struct ib_pd *pd,
        mhp->attr.pdid = php->pdid;
        mhp->attr.zbva = 0;
 
-       /* NOTE: TPT perms are backwards from BIND WR perms! */
-       mhp->attr.perms = (acc & 0x1) << 3;
-       mhp->attr.perms |= (acc & 0x2) << 1;
-       mhp->attr.perms |= (acc & 0x4) >> 1;
-       mhp->attr.perms |= (acc & 0x8) >> 3;
-
+       mhp->attr.perms = iwch_ib_to_tpt_access(acc);
        mhp->attr.va_fbo = *iova_start;
        mhp->attr.page_size = shift - 12;
 
@@ -525,7 +519,6 @@ static int iwch_reregister_phys_mem(struct ib_mr *mr,
        struct iwch_mr mh, *mhp;
        struct iwch_pd *php;
        struct iwch_dev *rhp;
-       int new_acc;
        __be64 *page_list = NULL;
        int shift = 0;
        u64 total_size;
@@ -546,14 +539,12 @@ static int iwch_reregister_phys_mem(struct ib_mr *mr,
        if (rhp != php->rhp)
                return -EINVAL;
 
-       new_acc = mhp->attr.perms;
-
        memcpy(&mh, mhp, sizeof *mhp);
 
        if (mr_rereg_mask & IB_MR_REREG_PD)
                php = to_iwch_pd(pd);
        if (mr_rereg_mask & IB_MR_REREG_ACCESS)
-               mh.attr.perms = iwch_convert_access(acc);
+               mh.attr.perms = iwch_ib_to_tpt_access(acc);
        if (mr_rereg_mask & IB_MR_REREG_TRANS)
                ret = build_phys_page_list(buffer_list, num_phys_buf,
                                           iova_start,
@@ -568,7 +559,7 @@ static int iwch_reregister_phys_mem(struct ib_mr *mr,
        if (mr_rereg_mask & IB_MR_REREG_PD)
                mhp->attr.pdid = php->pdid;
        if (mr_rereg_mask & IB_MR_REREG_ACCESS)
-               mhp->attr.perms = acc;
+               mhp->attr.perms = iwch_ib_to_tpt_access(acc);
        if (mr_rereg_mask & IB_MR_REREG_TRANS) {
                mhp->attr.zbva = 0;
                mhp->attr.va_fbo = *iova_start;
@@ -613,8 +604,6 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, struct ib_umem *region,
                goto err;
        }
 
-       acc = iwch_convert_access(acc);
-
        i = n = 0;
 
        list_for_each_entry(chunk, &region->chunk_list, list)
@@ -630,10 +619,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, struct ib_umem *region,
        mhp->rhp = rhp;
        mhp->attr.pdid = php->pdid;
        mhp->attr.zbva = 0;
-       mhp->attr.perms = (acc & 0x1) << 3;
-       mhp->attr.perms |= (acc & 0x2) << 1;
-       mhp->attr.perms |= (acc & 0x4) >> 1;
-       mhp->attr.perms |= (acc & 0x8) >> 3;
+       mhp->attr.perms = iwch_ib_to_tpt_access(acc);
        mhp->attr.va_fbo = region->virt_base;
        mhp->attr.page_size = shift - 12;
        mhp->attr.len = (u32) region->length;
@@ -736,10 +722,8 @@ static int iwch_destroy_qp(struct ib_qp *ib_qp)
        qhp = to_iwch_qp(ib_qp);
        rhp = qhp->rhp;
 
-       if (qhp->attr.state == IWCH_QP_STATE_RTS) {
-               attrs.next_state = IWCH_QP_STATE_ERROR;
-               iwch_modify_qp(rhp, qhp, IWCH_QP_ATTR_NEXT_STATE, &attrs, 0);
-       }
+       attrs.next_state = IWCH_QP_STATE_ERROR;
+       iwch_modify_qp(rhp, qhp, IWCH_QP_ATTR_NEXT_STATE, &attrs, 0);
        wait_event(qhp->wait, !qhp->ep);
 
        remove_handle(rhp, &rhp->qpidr, qhp->wq.qpid);
@@ -948,7 +932,7 @@ void iwch_qp_rem_ref(struct ib_qp *qp)
                wake_up(&(to_iwch_qp(qp)->wait));
 }
 
-struct ib_qp *iwch_get_qp(struct ib_device *dev, int qpn)
+static struct ib_qp *iwch_get_qp(struct ib_device *dev, int qpn)
 {
        PDBG("%s ib_dev %p qpn 0x%x\n", __FUNCTION__, dev, qpn);
        return (struct ib_qp *)get_qhp(to_iwch_dev(dev), qpn);
index 2af3e93b607f2a380f13b21148432e95bbd03557..93bcc56756bd42a14cce112f51b1a7ba2b3f8797 100644 (file)
@@ -178,7 +178,6 @@ static inline struct iwch_qp *to_iwch_qp(struct ib_qp *ibqp)
 
 void iwch_qp_add_ref(struct ib_qp *qp);
 void iwch_qp_rem_ref(struct ib_qp *qp);
-struct ib_qp *iwch_get_qp(struct ib_device *dev, int qpn);
 
 struct iwch_ucontext {
        struct ib_ucontext ibucontext;
@@ -287,27 +286,20 @@ static inline int iwch_convert_state(enum ib_qp_state ib_state)
        }
 }
 
-enum iwch_mem_perms {
-       IWCH_MEM_ACCESS_LOCAL_READ = 1 << 0,
-       IWCH_MEM_ACCESS_LOCAL_WRITE = 1 << 1,
-       IWCH_MEM_ACCESS_REMOTE_READ = 1 << 2,
-       IWCH_MEM_ACCESS_REMOTE_WRITE = 1 << 3,
-       IWCH_MEM_ACCESS_ATOMICS = 1 << 4,
-       IWCH_MEM_ACCESS_BINDING = 1 << 5,
-       IWCH_MEM_ACCESS_LOCAL =
-           (IWCH_MEM_ACCESS_LOCAL_READ | IWCH_MEM_ACCESS_LOCAL_WRITE),
-       IWCH_MEM_ACCESS_REMOTE =
-           (IWCH_MEM_ACCESS_REMOTE_WRITE | IWCH_MEM_ACCESS_REMOTE_READ)
-           /* cannot go beyond 1 << 31 */
-} __attribute__ ((packed));
-
-static inline u32 iwch_convert_access(int acc)
+static inline u32 iwch_ib_to_tpt_access(int acc)
 {
-       return (acc & IB_ACCESS_REMOTE_WRITE ? IWCH_MEM_ACCESS_REMOTE_WRITE : 0)
-           | (acc & IB_ACCESS_REMOTE_READ ? IWCH_MEM_ACCESS_REMOTE_READ : 0) |
-           (acc & IB_ACCESS_LOCAL_WRITE ? IWCH_MEM_ACCESS_LOCAL_WRITE : 0) |
-           (acc & IB_ACCESS_MW_BIND ? IWCH_MEM_ACCESS_BINDING : 0) |
-           IWCH_MEM_ACCESS_LOCAL_READ;
+       return (acc & IB_ACCESS_REMOTE_WRITE ? TPT_REMOTE_WRITE : 0) |
+              (acc & IB_ACCESS_REMOTE_READ ? TPT_REMOTE_READ : 0) |
+              (acc & IB_ACCESS_LOCAL_WRITE ? TPT_LOCAL_WRITE : 0) |
+              TPT_LOCAL_READ;
+}
+
+static inline u32 iwch_ib_to_mwbind_access(int acc)
+{
+       return (acc & IB_ACCESS_REMOTE_WRITE ? T3_MEM_ACCESS_REM_WRITE : 0) |
+              (acc & IB_ACCESS_REMOTE_READ ? T3_MEM_ACCESS_REM_READ : 0) |
+              (acc & IB_ACCESS_LOCAL_WRITE ? T3_MEM_ACCESS_LOCAL_WRITE : 0) |
+              T3_MEM_ACCESS_LOCAL_READ;
 }
 
 enum iwch_mmid_state {
index 4dda2f6da2dec84869e0838e5ced54e5f86d3ff2..0a472c9b44db1374f3b1111eb605c864b3935412 100644 (file)
@@ -36,8 +36,8 @@
 
 #define NO_SUPPORT -1
 
-static inline int iwch_build_rdma_send(union t3_wr *wqe, struct ib_send_wr *wr,
-                                      u8 * flit_cnt)
+static int iwch_build_rdma_send(union t3_wr *wqe, struct ib_send_wr *wr,
+                               u8 * flit_cnt)
 {
        int i;
        u32 plen;
@@ -96,8 +96,8 @@ static inline int iwch_build_rdma_send(union t3_wr *wqe, struct ib_send_wr *wr,
        return 0;
 }
 
-static inline int iwch_build_rdma_write(union t3_wr *wqe, struct ib_send_wr *wr,
-                                       u8 *flit_cnt)
+static int iwch_build_rdma_write(union t3_wr *wqe, struct ib_send_wr *wr,
+                                u8 *flit_cnt)
 {
        int i;
        u32 plen;
@@ -137,8 +137,8 @@ static inline int iwch_build_rdma_write(union t3_wr *wqe, struct ib_send_wr *wr,
        return 0;
 }
 
-static inline int iwch_build_rdma_read(union t3_wr *wqe, struct ib_send_wr *wr,
-                                      u8 *flit_cnt)
+static int iwch_build_rdma_read(union t3_wr *wqe, struct ib_send_wr *wr,
+                               u8 *flit_cnt)
 {
        if (wr->num_sge > 1)
                return -EINVAL;
@@ -158,9 +158,8 @@ static inline int iwch_build_rdma_read(union t3_wr *wqe, struct ib_send_wr *wr,
 /*
  * TBD: this is going to be moved to firmware. Missing pdid/qpid check for now.
  */
-static inline int iwch_sgl2pbl_map(struct iwch_dev *rhp,
-                                  struct ib_sge *sg_list, u32 num_sgle,
-                                  u32 * pbl_addr, u8 * page_size)
+static int iwch_sgl2pbl_map(struct iwch_dev *rhp, struct ib_sge *sg_list,
+                           u32 num_sgle, u32 * pbl_addr, u8 * page_size)
 {
        int i;
        struct iwch_mr *mhp;
@@ -206,9 +205,8 @@ static inline int iwch_sgl2pbl_map(struct iwch_dev *rhp,
        return 0;
 }
 
-static inline int iwch_build_rdma_recv(struct iwch_dev *rhp,
-                                                   union t3_wr *wqe,
-                                                   struct ib_recv_wr *wr)
+static int iwch_build_rdma_recv(struct iwch_dev *rhp, union t3_wr *wqe,
+                               struct ib_recv_wr *wr)
 {
        int i, err = 0;
        u32 pbl_addr[4];
@@ -441,7 +439,7 @@ int iwch_bind_mw(struct ib_qp *qp,
        wqe->bind.type = T3_VA_BASED_TO;
 
        /* TBD: check perms */
-       wqe->bind.perms = iwch_convert_access(mw_bind->mw_access_flags);
+       wqe->bind.perms = iwch_ib_to_mwbind_access(mw_bind->mw_access_flags);
        wqe->bind.mr_stag = cpu_to_be32(mw_bind->mr->lkey);
        wqe->bind.mw_stag = cpu_to_be32(mw->rkey);
        wqe->bind.mw_len = cpu_to_be32(mw_bind->length);
@@ -473,8 +471,7 @@ int iwch_bind_mw(struct ib_qp *qp,
        return err;
 }
 
-static inline void build_term_codes(int t3err, u8 *layer_type, u8 *ecode,
-                                   int tagged)
+static void build_term_codes(int t3err, u8 *layer_type, u8 *ecode, int tagged)
 {
        switch (t3err) {
        case TPT_ERR_STAG:
@@ -672,7 +669,7 @@ static void __flush_qp(struct iwch_qp *qhp, unsigned long *flag)
        spin_lock_irqsave(&qhp->lock, *flag);
 }
 
-static inline void flush_qp(struct iwch_qp *qhp, unsigned long *flag)
+static void flush_qp(struct iwch_qp *qhp, unsigned long *flag)
 {
        if (t3b_device(qhp->rhp))
                cxio_set_wq_in_error(&qhp->wq);
@@ -684,7 +681,7 @@ static inline void flush_qp(struct iwch_qp *qhp, unsigned long *flag)
 /*
  * Return non zero if at least one RECV was pre-posted.
  */
-static inline int rqes_posted(struct iwch_qp *qhp)
+static int rqes_posted(struct iwch_qp *qhp)
 {
        return fw_riwrh_opcode((struct fw_riwrh *)qhp->wq.queue) == T3_WR_RCV;
 }
index 40404c9e28179558d45feccc83880feb8b4132b5..82ded44c6cee4c40a9bd88460311d1900d60e43c 100644 (file)
@@ -52,6 +52,8 @@ struct ehca_mw;
 struct ehca_pd;
 struct ehca_av;
 
+#include <linux/wait.h>
+
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_user_verbs.h>
 
@@ -153,7 +155,9 @@ struct ehca_cq {
        spinlock_t cb_lock;
        struct hlist_head qp_hashtab[QP_HASHTAB_LEN];
        struct list_head entry;
-       u32 nr_callbacks;
+       u32 nr_callbacks; /* #events assigned to cpu by scaling code */
+       u32 nr_events;    /* #events seen */
+       wait_queue_head_t wait_completion;
        spinlock_t task_lock;
        u32 ownpid;
        /* mmap counter for resources mapped into user space */
index 6ebfa27e4e16edadbe3a44e803a20c264dbb916d..e2cdc1a16fe9214685df23aa2a56dc57ebb8e137 100644 (file)
@@ -146,6 +146,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe,
        spin_lock_init(&my_cq->spinlock);
        spin_lock_init(&my_cq->cb_lock);
        spin_lock_init(&my_cq->task_lock);
+       init_waitqueue_head(&my_cq->wait_completion);
        my_cq->ownpid = current->tgid;
 
        cq = &my_cq->ib_cq;
@@ -302,6 +303,16 @@ create_cq_exit1:
        return cq;
 }
 
+static int get_cq_nr_events(struct ehca_cq *my_cq)
+{
+       int ret;
+       unsigned long flags;
+       spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+       ret = my_cq->nr_events;
+       spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+       return ret;
+}
+
 int ehca_destroy_cq(struct ib_cq *cq)
 {
        u64 h_ret;
@@ -329,10 +340,11 @@ int ehca_destroy_cq(struct ib_cq *cq)
        }
 
        spin_lock_irqsave(&ehca_cq_idr_lock, flags);
-       while (my_cq->nr_callbacks) {
+       while (my_cq->nr_events) {
                spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
-               yield();
+               wait_event(my_cq->wait_completion, !get_cq_nr_events(my_cq));
                spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+               /* recheck nr_events to assure no cqe has just arrived */
        }
 
        idr_remove(&ehca_cq_idr, my_cq->token);
index 3ec53c687d0823c2eb0e7d34409f8684d7bdbe5e..20f36bf8b2b63c7138b72895692b846a6da7aa6d 100644 (file)
@@ -404,10 +404,11 @@ static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe)
        u32 token;
        unsigned long flags;
        struct ehca_cq *cq;
+
        eqe_value = eqe->entry;
        ehca_dbg(&shca->ib_device, "eqe_value=%lx", eqe_value);
        if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) {
-               ehca_dbg(&shca->ib_device, "... completion event");
+               ehca_dbg(&shca->ib_device, "Got completion event");
                token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
                spin_lock_irqsave(&ehca_cq_idr_lock, flags);
                cq = idr_find(&ehca_cq_idr, token);
@@ -419,16 +420,20 @@ static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe)
                        return;
                }
                reset_eq_pending(cq);
-               if (ehca_scaling_code) {
+               cq->nr_events++;
+               spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+               if (ehca_scaling_code)
                        queue_comp_task(cq);
-                       spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
-               } else {
-                       spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+               else {
                        comp_event_callback(cq);
+                       spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+                       cq->nr_events--;
+                       if (!cq->nr_events)
+                               wake_up(&cq->wait_completion);
+                       spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
                }
        } else {
-               ehca_dbg(&shca->ib_device,
-                        "Got non completion event");
+               ehca_dbg(&shca->ib_device, "Got non completion event");
                parse_identifier(shca, eqe_value);
        }
 }
@@ -478,6 +483,7 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
                                         "token=%x", token);
                                continue;
                        }
+                       eqe_cache[eqe_cnt].cq->nr_events++;
                        spin_unlock(&ehca_cq_idr_lock);
                } else
                        eqe_cache[eqe_cnt].cq = NULL;
@@ -504,12 +510,18 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
        /* call completion handler for cached eqes */
        for (i = 0; i < eqe_cnt; i++)
                if (eq->eqe_cache[i].cq) {
-                       if (ehca_scaling_code) {
-                               spin_lock(&ehca_cq_idr_lock);
+                       if (ehca_scaling_code)
                                queue_comp_task(eq->eqe_cache[i].cq);
-                               spin_unlock(&ehca_cq_idr_lock);
-                       } else
-                               comp_event_callback(eq->eqe_cache[i].cq);
+                       else {
+                               struct ehca_cq *cq = eq->eqe_cache[i].cq;
+                               comp_event_callback(cq);
+                               spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+                               cq->nr_events--;
+                               if (!cq->nr_events)
+                                       wake_up(&cq->wait_completion);
+                               spin_unlock_irqrestore(&ehca_cq_idr_lock,
+                                                      flags);
+                       }
                } else {
                        ehca_dbg(&shca->ib_device, "Got non completion event");
                        parse_identifier(shca, eq->eqe_cache[i].eqe->entry);
@@ -523,7 +535,6 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
                if (!eqe)
                        break;
                process_eqe(shca, eqe);
-               eqe_cnt++;
        } while (1);
 
 unlock_irq_spinlock:
@@ -567,8 +578,7 @@ static void __queue_comp_task(struct ehca_cq *__cq,
                list_add_tail(&__cq->entry, &cct->cq_list);
                cct->cq_jobs++;
                wake_up(&cct->wait_queue);
-       }
-       else
+       } else
                __cq->nr_callbacks++;
 
        spin_unlock(&__cq->task_lock);
@@ -577,18 +587,21 @@ static void __queue_comp_task(struct ehca_cq *__cq,
 
 static void queue_comp_task(struct ehca_cq *__cq)
 {
-       int cpu;
        int cpu_id;
        struct ehca_cpu_comp_task *cct;
+       int cq_jobs;
+       unsigned long flags;
 
-       cpu = get_cpu();
        cpu_id = find_next_online_cpu(pool);
        BUG_ON(!cpu_online(cpu_id));
 
        cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id);
        BUG_ON(!cct);
 
-       if (cct->cq_jobs > 0) {
+       spin_lock_irqsave(&cct->task_lock, flags);
+       cq_jobs = cct->cq_jobs;
+       spin_unlock_irqrestore(&cct->task_lock, flags);
+       if (cq_jobs > 0) {
                cpu_id = find_next_online_cpu(pool);
                cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id);
                BUG_ON(!cct);
@@ -608,11 +621,17 @@ static void run_comp_task(struct ehca_cpu_comp_task* cct)
                cq = list_entry(cct->cq_list.next, struct ehca_cq, entry);
                spin_unlock_irqrestore(&cct->task_lock, flags);
                comp_event_callback(cq);
-               spin_lock_irqsave(&cct->task_lock, flags);
 
+               spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+               cq->nr_events--;
+               if (!cq->nr_events)
+                       wake_up(&cq->wait_completion);
+               spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+
+               spin_lock_irqsave(&cct->task_lock, flags);
                spin_lock(&cq->task_lock);
                cq->nr_callbacks--;
-               if (cq->nr_callbacks == 0) {
+               if (!cq->nr_callbacks) {
                        list_del_init(cct->cq_list.next);
                        cct->cq_jobs--;
                }
index c1835121a82223612195fce09369ba0b58173e4a..059da9628bb56c3e103d81976dfeb0a3ce71079d 100644 (file)
@@ -52,7 +52,7 @@
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
 MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver");
-MODULE_VERSION("SVNEHCA_0021");
+MODULE_VERSION("SVNEHCA_0022");
 
 int ehca_open_aqp1     = 0;
 int ehca_debug_level   = 0;
@@ -810,7 +810,7 @@ int __init ehca_module_init(void)
        int ret;
 
        printk(KERN_INFO "eHCA Infiniband Device Driver "
-              "(Rel.: SVNEHCA_0021)\n");
+              "(Rel.: SVNEHCA_0022)\n");
        idr_init(&ehca_qp_idr);
        idr_init(&ehca_cq_idr);
        spin_lock_init(&ehca_qp_idr_lock);
index 6037dd3f87dfa16e8a165a9c41adc17538e69b51..8e4846b5c641ea3451452e636485883df9b7019e 100644 (file)
@@ -310,8 +310,9 @@ int mthca_write_mtt_size(struct mthca_dev *dev)
        return mthca_is_memfree(dev) ? (PAGE_SIZE / sizeof (u64)) : 0x7ffffff;
 }
 
-void mthca_tavor_write_mtt_seg(struct mthca_dev *dev, struct mthca_mtt *mtt,
-                             int start_index, u64 *buffer_list, int list_len)
+static void mthca_tavor_write_mtt_seg(struct mthca_dev *dev,
+                                     struct mthca_mtt *mtt, int start_index,
+                                     u64 *buffer_list, int list_len)
 {
        u64 __iomem *mtts;
        int i;
@@ -323,8 +324,9 @@ void mthca_tavor_write_mtt_seg(struct mthca_dev *dev, struct mthca_mtt *mtt,
                                  mtts + i);
 }
 
-void mthca_arbel_write_mtt_seg(struct mthca_dev *dev, struct mthca_mtt *mtt,
-                             int start_index, u64 *buffer_list, int list_len)
+static void mthca_arbel_write_mtt_seg(struct mthca_dev *dev,
+                                     struct mthca_mtt *mtt, int start_index,
+                                     u64 *buffer_list, int list_len)
 {
        __be64 *mtts;
        dma_addr_t dma_handle;
index 71dc84bd425498cd968a33cfa6e005804861474f..1c6b63aca26846c04537ba92eea18af88ec7f058 100644 (file)
@@ -1088,21 +1088,21 @@ static void mthca_unmap_memfree(struct mthca_dev *dev,
 static int mthca_alloc_memfree(struct mthca_dev *dev,
                               struct mthca_qp *qp)
 {
-       int ret = 0;
-
        if (mthca_is_memfree(dev)) {
                qp->rq.db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_RQ,
                                                 qp->qpn, &qp->rq.db);
                if (qp->rq.db_index < 0)
-                       return ret;
+                       return -ENOMEM;
 
                qp->sq.db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_SQ,
                                                 qp->qpn, &qp->sq.db);
-               if (qp->sq.db_index < 0)
+               if (qp->sq.db_index < 0) {
                        mthca_free_db(dev, MTHCA_DB_TYPE_RQ, qp->rq.db_index);
+                       return -ENOMEM;
+               }
        }
 
-       return ret;
+       return 0;
 }
 
 static void mthca_free_memfree(struct mthca_dev *dev,
index 2594db2030b3abef14ac28b9373c3b41999c7c54..fd558267d1cb4481eac786b4868863ad03334d2b 100644 (file)
@@ -219,7 +219,6 @@ struct ipoib_dev_priv {
 
        union ib_gid local_gid;
        u16          local_lid;
-       u8           local_rate;
 
        unsigned int admin_mtu;
        unsigned int mcast_mtu;
index 4d59682f7d4a39084e61361925c6b7dc0041047c..3484e8ba24a44672e109afda1c335856b525e0e5 100644 (file)
@@ -65,14 +65,14 @@ struct ipoib_cm_id {
 static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id,
                               struct ib_cm_event *event);
 
-static void ipoib_cm_dma_unmap_rx(struct ipoib_dev_priv *priv,
+static void ipoib_cm_dma_unmap_rx(struct ipoib_dev_priv *priv, int frags,
                                  u64 mapping[IPOIB_CM_RX_SG])
 {
        int i;
 
        ib_dma_unmap_single(priv->ca, mapping[0], IPOIB_CM_HEAD_SIZE, DMA_FROM_DEVICE);
 
-       for (i = 0; i < IPOIB_CM_RX_SG - 1; ++i)
+       for (i = 0; i < frags; ++i)
                ib_dma_unmap_single(priv->ca, mapping[i + 1], PAGE_SIZE, DMA_FROM_DEVICE);
 }
 
@@ -90,7 +90,8 @@ static int ipoib_cm_post_receive(struct net_device *dev, int id)
        ret = ib_post_srq_recv(priv->cm.srq, &priv->cm.rx_wr, &bad_wr);
        if (unlikely(ret)) {
                ipoib_warn(priv, "post srq failed for buf %d (%d)\n", id, ret);
-               ipoib_cm_dma_unmap_rx(priv, priv->cm.srq_ring[id].mapping);
+               ipoib_cm_dma_unmap_rx(priv, IPOIB_CM_RX_SG - 1,
+                                     priv->cm.srq_ring[id].mapping);
                dev_kfree_skb_any(priv->cm.srq_ring[id].skb);
                priv->cm.srq_ring[id].skb = NULL;
        }
@@ -98,8 +99,8 @@ static int ipoib_cm_post_receive(struct net_device *dev, int id)
        return ret;
 }
 
-static int ipoib_cm_alloc_rx_skb(struct net_device *dev, int id,
-                                u64 mapping[IPOIB_CM_RX_SG])
+static struct sk_buff *ipoib_cm_alloc_rx_skb(struct net_device *dev, int id, int frags,
+                                            u64 mapping[IPOIB_CM_RX_SG])
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct sk_buff *skb;
@@ -107,7 +108,7 @@ static int ipoib_cm_alloc_rx_skb(struct net_device *dev, int id,
 
        skb = dev_alloc_skb(IPOIB_CM_HEAD_SIZE + 12);
        if (unlikely(!skb))
-               return -ENOMEM;
+               return NULL;
 
        /*
         * IPoIB adds a 4 byte header. So we need 12 more bytes to align the
@@ -119,10 +120,10 @@ static int ipoib_cm_alloc_rx_skb(struct net_device *dev, int id,
                                       DMA_FROM_DEVICE);
        if (unlikely(ib_dma_mapping_error(priv->ca, mapping[0]))) {
                dev_kfree_skb_any(skb);
-               return -EIO;
+               return NULL;
        }
 
-       for (i = 0; i < IPOIB_CM_RX_SG - 1; i++) {
+       for (i = 0; i < frags; i++) {
                struct page *page = alloc_page(GFP_ATOMIC);
 
                if (!page)
@@ -136,7 +137,7 @@ static int ipoib_cm_alloc_rx_skb(struct net_device *dev, int id,
        }
 
        priv->cm.srq_ring[id].skb = skb;
-       return 0;
+       return skb;
 
 partial_error:
 
@@ -146,7 +147,7 @@ partial_error:
                ib_dma_unmap_single(priv->ca, mapping[i + 1], PAGE_SIZE, DMA_FROM_DEVICE);
 
        dev_kfree_skb_any(skb);
-       return -ENOMEM;
+       return NULL;
 }
 
 static struct ib_qp *ipoib_cm_create_rx_qp(struct net_device *dev,
@@ -309,7 +310,7 @@ static int ipoib_cm_rx_handler(struct ib_cm_id *cm_id,
 }
 /* Adjust length of skb with fragments to match received data */
 static void skb_put_frags(struct sk_buff *skb, unsigned int hdr_space,
-                         unsigned int length)
+                         unsigned int length, struct sk_buff *toskb)
 {
        int i, num_frags;
        unsigned int size;
@@ -326,7 +327,7 @@ static void skb_put_frags(struct sk_buff *skb, unsigned int hdr_space,
 
                if (length == 0) {
                        /* don't need this page */
-                       __free_page(frag->page);
+                       skb_fill_page_desc(toskb, i, frag->page, 0, PAGE_SIZE);
                        --skb_shinfo(skb)->nr_frags;
                } else {
                        size = min(length, (unsigned) PAGE_SIZE);
@@ -344,10 +345,11 @@ void ipoib_cm_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_CM_OP_SRQ;
-       struct sk_buff *skb;
+       struct sk_buff *skb, *newskb;
        struct ipoib_cm_rx *p;
        unsigned long flags;
        u64 mapping[IPOIB_CM_RX_SG];
+       int frags;
 
        ipoib_dbg_data(priv, "cm recv completion: id %d, op %d, status: %d\n",
                       wr_id, wc->opcode, wc->status);
@@ -383,7 +385,11 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
                }
        }
 
-       if (unlikely(ipoib_cm_alloc_rx_skb(dev, wr_id, mapping))) {
+       frags = PAGE_ALIGN(wc->byte_len - min(wc->byte_len,
+                                             (unsigned)IPOIB_CM_HEAD_SIZE)) / PAGE_SIZE;
+
+       newskb = ipoib_cm_alloc_rx_skb(dev, wr_id, frags, mapping);
+       if (unlikely(!newskb)) {
                /*
                 * If we can't allocate a new RX buffer, dump
                 * this packet and reuse the old buffer.
@@ -393,13 +399,13 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
                goto repost;
        }
 
-       ipoib_cm_dma_unmap_rx(priv, priv->cm.srq_ring[wr_id].mapping);
-       memcpy(priv->cm.srq_ring[wr_id].mapping, mapping, sizeof mapping);
+       ipoib_cm_dma_unmap_rx(priv, frags, priv->cm.srq_ring[wr_id].mapping);
+       memcpy(priv->cm.srq_ring[wr_id].mapping, mapping, (frags + 1) * sizeof *mapping);
 
        ipoib_dbg_data(priv, "received %d bytes, SLID 0x%04x\n",
                       wc->byte_len, wc->slid);
 
-       skb_put_frags(skb, IPOIB_CM_HEAD_SIZE, wc->byte_len);
+       skb_put_frags(skb, IPOIB_CM_HEAD_SIZE, wc->byte_len, newskb);
 
        skb->protocol = ((struct ipoib_header *) skb->data)->proto;
        skb->mac.raw = skb->data;
@@ -1193,7 +1199,8 @@ int ipoib_cm_dev_init(struct net_device *dev)
        priv->cm.rx_wr.num_sge = IPOIB_CM_RX_SG;
 
        for (i = 0; i < ipoib_recvq_size; ++i) {
-               if (ipoib_cm_alloc_rx_skb(dev, i, priv->cm.srq_ring[i].mapping)) {
+               if (!ipoib_cm_alloc_rx_skb(dev, i, IPOIB_CM_RX_SG - 1,
+                                          priv->cm.srq_ring[i].mapping)) {
                        ipoib_warn(priv, "failed to allocate receive buffer %d\n", i);
                        ipoib_cm_dev_cleanup(dev);
                        return -ENOMEM;
@@ -1228,7 +1235,8 @@ void ipoib_cm_dev_cleanup(struct net_device *dev)
                return;
        for (i = 0; i < ipoib_recvq_size; ++i)
                if (priv->cm.srq_ring[i].skb) {
-                       ipoib_cm_dma_unmap_rx(priv, priv->cm.srq_ring[i].mapping);
+                       ipoib_cm_dma_unmap_rx(priv, IPOIB_CM_RX_SG - 1,
+                                             priv->cm.srq_ring[i].mapping);
                        dev_kfree_skb_any(priv->cm.srq_ring[i].skb);
                        priv->cm.srq_ring[i].skb = NULL;
                }
index 18d27fd352ad9667972b71a6a2242a12ded97d39..f9dbc6f68145647078a74be3b49da198fe598781 100644 (file)
@@ -385,7 +385,7 @@ static void path_rec_completion(int status,
        struct sk_buff *skb;
        unsigned long flags;
 
-       if (pathrec)
+       if (!status)
                ipoib_dbg(priv, "PathRec LID 0x%04x for GID " IPOIB_GID_FMT "\n",
                          be16_to_cpu(pathrec->dlid), IPOIB_GID_ARG(pathrec->dgid));
        else
index b303ce6bc21ee6664d1471a3a99d2455e11aef2e..56c87a81bb675d82a5c40c0c7f05d68ba9b80aaf 100644 (file)
@@ -407,6 +407,10 @@ static int ipoib_mcast_join_complete(int status,
                        queue_delayed_work(ipoib_workqueue,
                                           &priv->mcast_task, 0);
                mutex_unlock(&mcast_mutex);
+
+               if (mcast == priv->broadcast)
+                       netif_carrier_on(dev);
+
                return 0;
        }
 
@@ -527,11 +531,9 @@ void ipoib_mcast_join_task(struct work_struct *work)
        {
                struct ib_port_attr attr;
 
-               if (!ib_query_port(priv->ca, priv->port, &attr)) {
-                       priv->local_lid  = attr.lid;
-                       priv->local_rate = attr.active_speed *
-                               ib_width_enum_to_int(attr.active_width);
-               } else
+               if (!ib_query_port(priv->ca, priv->port, &attr))
+                       priv->local_lid = attr.lid;
+               else
                        ipoib_warn(priv, "ib_query_port failed\n");
        }
 
@@ -596,7 +598,6 @@ void ipoib_mcast_join_task(struct work_struct *work)
        ipoib_dbg_mcast(priv, "successfully joined all multicast groups\n");
 
        clear_bit(IPOIB_MCAST_RUN, &priv->flags);
-       netif_carrier_on(dev);
 }
 
 int ipoib_mcast_start_thread(struct net_device *dev)
index 3cb551b8875625960654e587facebf02e3fcd838..7f3ec205e35f54980b2c00adc9aaac4538fd462c 100644 (file)
@@ -259,12 +259,13 @@ void ipoib_event(struct ib_event_handler *handler,
        struct ipoib_dev_priv *priv =
                container_of(handler, struct ipoib_dev_priv, event_handler);
 
-       if (record->event == IB_EVENT_PORT_ERR    ||
-           record->event == IB_EVENT_PKEY_CHANGE ||
-           record->event == IB_EVENT_PORT_ACTIVE ||
-           record->event == IB_EVENT_LID_CHANGE  ||
-           record->event == IB_EVENT_SM_CHANGE   ||
-           record->event == IB_EVENT_CLIENT_REREGISTER) {
+       if ((record->event == IB_EVENT_PORT_ERR    ||
+            record->event == IB_EVENT_PKEY_CHANGE ||
+            record->event == IB_EVENT_PORT_ACTIVE ||
+            record->event == IB_EVENT_LID_CHANGE  ||
+            record->event == IB_EVENT_SM_CHANGE   ||
+            record->event == IB_EVENT_CLIENT_REREGISTER) &&
+           record->element.port_num == priv->port) {
                ipoib_dbg(priv, "Port state change event\n");
                queue_work(ipoib_workqueue, &priv->flush_task);
        }
index 64509689fa6514827bccff60e62f24abe8df873f..f17e9c7d4b368f27fca7bb7536e271f430ca1c0e 100644 (file)
@@ -215,14 +215,16 @@ config KEYBOARD_AAED2000
          module will be called aaed2000_kbd.
 
 config KEYBOARD_GPIO
-       tristate "Buttons on CPU GPIOs (PXA)"
-       depends on (ARCH_SA1100 || ARCH_PXA || ARCH_S3C2410)
+       tristate "GPIO Buttons"
+       depends on GENERIC_GPIO
        help
          This driver implements support for buttons connected
-         directly to GPIO pins of SA1100, PXA or S3C24xx CPUs.
+         to GPIO pins of various CPUs (and some other chips).
 
          Say Y here if your device has buttons connected
-         directly to GPIO pins of the CPU.
+         directly to such GPIO pins.  Your board-specific
+         setup logic must also provide a platform device,
+         with configuration data saying which GPIOs are used.
 
          To compile this driver as a module, choose M here: the
          module will be called gpio-keys.
index fa03a00b4c6df8948e8d6eba0033cf58bf360ba8..ccf6df387b62d88e64790c3622202d0b296c21e3 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/input.h>
 #include <linux/irq.h>
+#include <linux/gpio_keys.h>
 
 #include <asm/gpio.h>
-#include <asm/arch/hardware.h>
-
-#include <asm/hardware/gpio_keys.h>
 
 static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
 {
index ec195a36e8f66ea9f170698d5b6dbb34f6140649..db9cca3b65e068f4e22002ebab7d448a510d8eb0 100644 (file)
@@ -553,7 +553,8 @@ static int __devinit i8042_check_aux(void)
  */
 
        param = 0x5a;
-       if (i8042_command(&param, I8042_CMD_AUX_LOOP) || param != 0x5a) {
+       retval = i8042_command(&param, I8042_CMD_AUX_LOOP);
+       if (retval || param != 0x5a) {
 
 /*
  * External connection test - filters out AT-soldered PS/2 i8042's
@@ -567,7 +568,12 @@ static int __devinit i8042_check_aux(void)
                    (param && param != 0xfa && param != 0xff))
                        return -1;
 
-               aux_loop_broken = 1;
+/*
+ * If AUX_LOOP completed without error but returned unexpected data
+ * mark it as broken
+ */
+               if (!retval)
+                       aux_loop_broken = 1;
        }
 
 /*
index 8b6c9a431ffa6d1ea0f6ccdec96000bab8d465c9..c921d6c522f50ef257d825894b0f059bc9f11044 100644 (file)
@@ -2,13 +2,25 @@
 # Config.in for the CAPI subsystem
 #
 config ISDN_DRV_AVMB1_VERBOSE_REASON
-       bool "Verbose reason code reporting (kernel size +=7K)"
+       bool "Verbose reason code reporting"
        depends on ISDN_CAPI
+       default y
        help
-         If you say Y here, the AVM B1 driver will give verbose reasons for
+         If you say Y here, the CAPI drivers will give verbose reasons for
          disconnecting. This will increase the size of the kernel by 7 KB. If
          unsure, say Y.
 
+config CAPI_TRACE
+       bool "CAPI trace support"
+       depends on ISDN_CAPI
+       default y
+       help
+         If you say Y here, the kernelcapi driver can make verbose traces
+         of CAPI messages. This feature can be enabled/disabled via IOCTL for
+         every controler (default disabled).
+         This will increase the size of the kernelcapi module by 20 KB.
+         If unsure, say Y.
+
 config ISDN_CAPI_MIDDLEWARE
        bool "CAPI2.0 Middleware support (EXPERIMENTAL)"
        depends on ISDN_CAPI && EXPERIMENTAL
index 2a49cea0a223e19e41cdeee3e4f900886521949f..23b6f7bc16b7e53ebac2a6d73e76608bcaa67ecf 100644 (file)
@@ -990,6 +990,7 @@ static void handle_plci(_cmsg * cmsg)
        capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
        capidrv_plci *plcip;
        isdn_ctrl cmd;
+       _cdebbuf *cdb;
 
        if (!card) {
                printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",
@@ -1122,8 +1123,15 @@ static void handle_plci(_cmsg * cmsg)
                                break;
                        }
                }
-               printk(KERN_ERR "capidrv-%d: %s\n",
-                               card->contrnr, capi_cmsg2str(cmsg));
+               cdb = capi_cmsg2str(cmsg);
+               if (cdb) {
+                       printk(KERN_WARNING "capidrv-%d: %s\n",
+                               card->contrnr, cdb->buf);
+                       cdebbuf_free(cdb);
+               } else
+                       printk(KERN_WARNING "capidrv-%d: CAPI_INFO_IND InfoNumber %x not handled\n",
+                               card->contrnr, cmsg->InfoNumber);
+
                break;
 
        case CAPI_CONNECT_ACTIVE_CONF:          /* plci */
@@ -1371,10 +1379,18 @@ static _cmsg s_cmsg;
 static void capidrv_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
 {
        capi_message2cmsg(&s_cmsg, skb->data);
-       if (debugmode > 3)
-               printk(KERN_DEBUG "capidrv_signal: applid=%d %s\n",
-                      ap->applid, capi_cmsg2str(&s_cmsg));
-       
+       if (debugmode > 3) {
+               _cdebbuf *cdb = capi_cmsg2str(&s_cmsg);
+
+               if (cdb) {
+                       printk(KERN_DEBUG "%s: applid=%d %s\n", __FUNCTION__,
+                               ap->applid, cdb->buf);
+                       cdebbuf_free(cdb);
+               } else
+                       printk(KERN_DEBUG "%s: applid=%d %s not traced\n",
+                               __FUNCTION__, ap->applid,
+                               capi_cmd2str(s_cmsg.Command, s_cmsg.Subcommand));
+       }
        if (s_cmsg.Command == CAPI_DATA_B3
            && s_cmsg.Subcommand == CAPI_IND) {
                handle_data(&s_cmsg, skb);
index c1b21552fc036ae88fba6f53b975a61d5b56dfdb..ad1e2702c2d1734b00d74678ab2295e350e10274 100644 (file)
@@ -648,6 +648,9 @@ char *capi_cmd2str(u8 cmd, u8 subcmd)
 
 
 /*-------------------------------------------------------*/
+
+#ifdef CONFIG_CAPI_TRACE
+
 /*-------------------------------------------------------*/
 
 static char *pnames[] =
@@ -703,44 +706,77 @@ static char *pnames[] =
 };
 
 
-static char buf[8192];
-static char *p = NULL;
 
 #include <stdarg.h>
 
 /*-------------------------------------------------------*/
-static void bufprint(char *fmt,...)
+static _cdebbuf *bufprint(_cdebbuf *cdb, char *fmt,...)
 {
        va_list f;
+       size_t n,r;
+
+       if (!cdb)
+               return NULL;
        va_start(f, fmt);
-       vsprintf(p, fmt, f);
+       r = cdb->size - cdb->pos;
+       n = vsnprintf(cdb->p, r, fmt, f);
        va_end(f);
-       p += strlen(p);
+       if (n >= r) {
+               /* truncated, need bigger buffer */
+               size_t ns = 2 * cdb->size;
+               u_char *nb;
+
+               while ((ns - cdb->pos) <= n)
+                       ns *= 2;
+               nb = kmalloc(ns, GFP_ATOMIC);
+               if (!nb) {
+                       cdebbuf_free(cdb);
+                       return NULL;
+               }
+               memcpy(nb, cdb->buf, cdb->pos);
+               kfree(cdb->buf);
+               nb[cdb->pos] = 0;
+               cdb->buf = nb;
+               cdb->p = cdb->buf + cdb->pos;
+               cdb->size = ns;
+               va_start(f, fmt);
+               r = cdb->size - cdb->pos;
+               n = vsnprintf(cdb->p, r, fmt, f);
+               va_end(f);
+       }
+       cdb->p += n;
+       cdb->pos += n;
+       return cdb;
 }
 
-static void printstructlen(u8 * m, unsigned len)
+static _cdebbuf *printstructlen(_cdebbuf *cdb, u8 * m, unsigned len)
 {
        unsigned hex = 0;
+
+       if (!cdb)
+               return NULL;
        for (; len; len--, m++)
                if (isalnum(*m) || *m == ' ') {
                        if (hex)
-                               bufprint(">");
-                       bufprint("%c", *m);
+                               cdb = bufprint(cdb, ">");
+                       cdb = bufprint(cdb, "%c", *m);
                        hex = 0;
                } else {
                        if (!hex)
-                               bufprint("<%02x", *m);
+                               cdb = bufprint(cdb, "<%02x", *m);
                        else
-                               bufprint(" %02x", *m);
+                               cdb = bufprint(cdb, " %02x", *m);
                        hex = 1;
                }
        if (hex)
-               bufprint(">");
+               cdb = bufprint(cdb, ">");
+       return cdb;
 }
 
-static void printstruct(u8 * m)
+static _cdebbuf *printstruct(_cdebbuf *cdb, u8 * m)
 {
        unsigned len;
+
        if (m[0] != 0xff) {
                len = m[0];
                m += 1;
@@ -748,42 +784,45 @@ static void printstruct(u8 * m)
                len = ((u16 *) (m + 1))[0];
                m += 3;
        }
-       printstructlen(m, len);
+       cdb = printstructlen(cdb, m, len);
+       return cdb;
 }
 
 /*-------------------------------------------------------*/
 #define NAME (pnames[cmsg->par[cmsg->p]])
 
-static void protocol_message_2_pars(_cmsg * cmsg, int level)
+static _cdebbuf *protocol_message_2_pars(_cdebbuf *cdb, _cmsg *cmsg, int level)
 {
        for (; TYP != _CEND; cmsg->p++) {
                int slen = 29 + 3 - level;
                int i;
 
-               bufprint("  ");
+               if (!cdb)
+                       return NULL;
+               cdb = bufprint(cdb, "  ");
                for (i = 0; i < level - 1; i++)
-                       bufprint(" ");
+                       cdb = bufprint(cdb, " ");
 
                switch (TYP) {
                case _CBYTE:
-                       bufprint("%-*s = 0x%x\n", slen, NAME, *(u8 *) (cmsg->m + cmsg->l));
+                       cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u8 *) (cmsg->m + cmsg->l));
                        cmsg->l++;
                        break;
                case _CWORD:
-                       bufprint("%-*s = 0x%x\n", slen, NAME, *(u16 *) (cmsg->m + cmsg->l));
+                       cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u16 *) (cmsg->m + cmsg->l));
                        cmsg->l += 2;
                        break;
                case _CDWORD:
-                       bufprint("%-*s = 0x%lx\n", slen, NAME, *(u32 *) (cmsg->m + cmsg->l));
+                       cdb = bufprint(cdb, "%-*s = 0x%lx\n", slen, NAME, *(u32 *) (cmsg->m + cmsg->l));
                        cmsg->l += 4;
                        break;
                case _CSTRUCT:
-                       bufprint("%-*s = ", slen, NAME);
+                       cdb = bufprint(cdb, "%-*s = ", slen, NAME);
                        if (cmsg->m[cmsg->l] == '\0')
-                               bufprint("default");
+                               cdb = bufprint(cdb, "default");
                        else
-                               printstruct(cmsg->m + cmsg->l);
-                       bufprint("\n");
+                               cdb = printstruct(cdb, cmsg->m + cmsg->l);
+                       cdb = bufprint(cdb, "\n");
                        if (cmsg->m[cmsg->l] != 0xff)
                                cmsg->l += 1 + cmsg->m[cmsg->l];
                        else
@@ -794,61 +833,184 @@ static void protocol_message_2_pars(_cmsg * cmsg, int level)
                case _CMSTRUCT:
 /*----- Metastruktur 0 -----*/
                        if (cmsg->m[cmsg->l] == '\0') {
-                               bufprint("%-*s = default\n", slen, NAME);
+                               cdb = bufprint(cdb, "%-*s = default\n", slen, NAME);
                                cmsg->l++;
                                jumpcstruct(cmsg);
                        } else {
                                char *name = NAME;
                                unsigned _l = cmsg->l;
-                               bufprint("%-*s\n", slen, name);
+                               cdb = bufprint(cdb, "%-*s\n", slen, name);
                                cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1;
                                cmsg->p++;
-                               protocol_message_2_pars(cmsg, level + 1);
+                               cdb = protocol_message_2_pars(cdb, cmsg, level + 1);
                        }
                        break;
                }
        }
+       return cdb;
 }
 /*-------------------------------------------------------*/
-char *capi_message2str(u8 * msg)
+
+static _cdebbuf *g_debbuf;
+static u_long g_debbuf_lock;
+static _cmsg *g_cmsg;
+
+_cdebbuf *cdebbuf_alloc(void)
 {
+       _cdebbuf *cdb;
+
+       if (likely(!test_and_set_bit(1, &g_debbuf_lock))) {
+               cdb = g_debbuf;
+               goto init;
+       } else
+               cdb = kmalloc(sizeof(_cdebbuf), GFP_ATOMIC);
+       if (!cdb)
+               return NULL;
+       cdb->buf = kmalloc(CDEBUG_SIZE, GFP_ATOMIC);
+       if (!cdb->buf) {
+               kfree(cdb);
+               return NULL;
+       }
+       cdb->size = CDEBUG_SIZE;
+init:
+       cdb->buf[0] = 0;
+       cdb->p = cdb->buf;
+       cdb->pos = 0;
+       return cdb;
+}
 
-       _cmsg cmsg;
-       p = buf;
-       p[0] = 0;
+void cdebbuf_free(_cdebbuf *cdb)
+{
+       if (likely(cdb == g_debbuf)) {
+               test_and_clear_bit(1, &g_debbuf_lock);
+               return;
+       }
+       if (likely(cdb))
+               kfree(cdb->buf);
+       kfree(cdb);
+}
 
-       cmsg.m = msg;
-       cmsg.l = 8;
-       cmsg.p = 0;
-       byteTRcpy(cmsg.m + 4, &cmsg.Command);
-       byteTRcpy(cmsg.m + 5, &cmsg.Subcommand);
-       cmsg.par = cpars[command_2_index(cmsg.Command, cmsg.Subcommand)];
 
-       bufprint("%-26s ID=%03d #0x%04x LEN=%04d\n",
-                mnames[command_2_index(cmsg.Command, cmsg.Subcommand)],
+_cdebbuf *capi_message2str(u8 * msg)
+{
+       _cdebbuf *cdb;
+       _cmsg   *cmsg;
+
+       cdb = cdebbuf_alloc();
+       if (unlikely(!cdb))
+               return NULL;
+       if (likely(cdb == g_debbuf))
+               cmsg = g_cmsg;
+       else
+               cmsg = kmalloc(sizeof(_cmsg), GFP_ATOMIC);
+       if (unlikely(!cmsg)) {
+               cdebbuf_free(cdb);
+               return NULL;
+       }
+       cmsg->m = msg;
+       cmsg->l = 8;
+       cmsg->p = 0;
+       byteTRcpy(cmsg->m + 4, &cmsg->Command);
+       byteTRcpy(cmsg->m + 5, &cmsg->Subcommand);
+       cmsg->par = cpars[command_2_index(cmsg->Command, cmsg->Subcommand)];
+
+       cdb = bufprint(cdb, "%-26s ID=%03d #0x%04x LEN=%04d\n",
+                mnames[command_2_index(cmsg->Command, cmsg->Subcommand)],
                 ((unsigned short *) msg)[1],
                 ((unsigned short *) msg)[3],
                 ((unsigned short *) msg)[0]);
 
-       protocol_message_2_pars(&cmsg, 1);
-       return buf;
+       cdb = protocol_message_2_pars(cdb, cmsg, 1);
+       if (unlikely(cmsg != g_cmsg))
+               kfree(cmsg);
+       return cdb;
 }
 
-char *capi_cmsg2str(_cmsg * cmsg)
+_cdebbuf *capi_cmsg2str(_cmsg * cmsg)
 {
-       p = buf;
-       p[0] = 0;
+       _cdebbuf *cdb;
+
+       cdb = cdebbuf_alloc();
+       if (!cdb)
+               return NULL;
        cmsg->l = 8;
        cmsg->p = 0;
-       bufprint("%s ID=%03d #0x%04x LEN=%04d\n",
+       cdb = bufprint(cdb, "%s ID=%03d #0x%04x LEN=%04d\n",
                 mnames[command_2_index(cmsg->Command, cmsg->Subcommand)],
                 ((u16 *) cmsg->m)[1],
                 ((u16 *) cmsg->m)[3],
                 ((u16 *) cmsg->m)[0]);
-       protocol_message_2_pars(cmsg, 1);
-       return buf;
+       cdb = protocol_message_2_pars(cdb, cmsg, 1);
+       return cdb;
 }
 
+int __init cdebug_init(void)
+{
+       g_cmsg= kmalloc(sizeof(_cmsg), GFP_KERNEL);
+       if (!g_cmsg)
+               return ENOMEM;
+       g_debbuf = kmalloc(sizeof(_cdebbuf), GFP_KERNEL);
+       if (!g_debbuf) {
+               kfree(g_cmsg);
+               return ENOMEM;
+       }
+       g_debbuf->buf = kmalloc(CDEBUG_GSIZE, GFP_KERNEL);
+       if (!g_debbuf->buf) {
+               kfree(g_cmsg);
+               kfree(g_debbuf);
+               return ENOMEM;;
+       }
+       g_debbuf->size = CDEBUG_GSIZE;
+       g_debbuf->buf[0] = 0;
+       g_debbuf->p = g_debbuf->buf;
+       g_debbuf->pos = 0;
+       return 0;
+}
+
+void __exit cdebug_exit(void)
+{
+       if (g_debbuf)
+               kfree(g_debbuf->buf);
+       kfree(g_debbuf);
+       kfree(g_cmsg);
+}
+
+#else /* !CONFIG_CAPI_TRACE */
+
+static _cdebbuf g_debbuf = {"CONFIG_CAPI_TRACE not enabled", NULL, 0, 0};
+
+_cdebbuf *capi_message2str(u8 * msg)
+{
+       return &g_debbuf;
+}
+
+_cdebbuf *capi_cmsg2str(_cmsg * cmsg)
+{
+       return &g_debbuf;
+}
+
+_cdebbuf *cdebbuf_alloc(void)
+{
+       return &g_debbuf;
+}
+
+void cdebbuf_free(_cdebbuf *cdb)
+{
+}
+
+int __init cdebug_init(void)
+{
+       return 0;
+}
+
+void __exit cdebug_exit(void)
+{
+}
+
+#endif
+
+EXPORT_SYMBOL(cdebbuf_alloc);
+EXPORT_SYMBOL(cdebbuf_free);
 EXPORT_SYMBOL(capi_cmsg2message);
 EXPORT_SYMBOL(capi_message2cmsg);
 EXPORT_SYMBOL(capi_cmsg_header);
index 783a25526315beacce63c85fa1536ddde2117c17..3ed34f7a1c4ff3ff79d209838c58eba860e5be60 100644 (file)
@@ -276,10 +276,17 @@ void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *s
        int showctl = 0;
        u8 cmd, subcmd;
        unsigned long flags;
+       _cdebbuf *cdb;
 
        if (card->cardstate != CARD_RUNNING) {
-               printk(KERN_INFO "kcapi: controller %d not active, got: %s",
-                      card->cnr, capi_message2str(skb->data));
+               cdb = capi_message2str(skb->data);
+               if (cdb) {
+                       printk(KERN_INFO "kcapi: controller [%03d] not active, got: %s",
+                               card->cnr, cdb->buf);
+                       cdebbuf_free(cdb);
+               } else
+                       printk(KERN_INFO "kcapi: controller [%03d] not active, cannot trace\n",
+                               card->cnr);
                goto error;
        }
 
@@ -295,15 +302,21 @@ void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *s
        showctl |= (card->traceflag & 1);
        if (showctl & 2) {
                if (showctl & 1) {
-                       printk(KERN_DEBUG "kcapi: got [0x%lx] id#%d %s len=%u\n",
-                              (unsigned long) card->cnr,
-                              CAPIMSG_APPID(skb->data),
+                       printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u\n",
+                              card->cnr, CAPIMSG_APPID(skb->data),
                               capi_cmd2str(cmd, subcmd),
                               CAPIMSG_LEN(skb->data));
                } else {
-                       printk(KERN_DEBUG "kcapi: got [0x%lx] %s\n",
-                                       (unsigned long) card->cnr,
-                                       capi_message2str(skb->data));
+                       cdb = capi_message2str(skb->data);
+                       if (cdb) {
+                               printk(KERN_DEBUG "kcapi: got [%03d] %s\n",
+                                       card->cnr, cdb->buf);
+                               cdebbuf_free(cdb);
+                       } else
+                               printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u, cannot trace\n",
+                                       card->cnr, CAPIMSG_APPID(skb->data),
+                                       capi_cmd2str(cmd, subcmd),
+                                       CAPIMSG_LEN(skb->data));
                }
 
        }
@@ -312,8 +325,15 @@ void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *s
        ap = get_capi_appl_by_nr(CAPIMSG_APPID(skb->data));
        if ((!ap) || (ap->release_in_progress)) {
                read_unlock_irqrestore(&application_lock, flags);
-               printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s)\n",
-                       CAPIMSG_APPID(skb->data), capi_message2str(skb->data));
+               cdb = capi_message2str(skb->data);
+               if (cdb) {
+                       printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s)\n",
+                       CAPIMSG_APPID(skb->data), cdb->buf);
+                       cdebbuf_free(cdb);
+               } else
+                       printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s) cannot trace\n",
+                               CAPIMSG_APPID(skb->data),
+                               capi_cmd2str(cmd, subcmd));
                goto error;
        }
        skb_queue_tail(&ap->recv_queue, skb);
@@ -332,7 +352,7 @@ void capi_ctr_ready(struct capi_ctr * card)
 {
        card->cardstate = CARD_RUNNING;
 
-        printk(KERN_NOTICE "kcapi: card %d \"%s\" ready.\n",
+        printk(KERN_NOTICE "kcapi: card [%03d] \"%s\" ready.\n",
               card->cnr, card->name);
 
        notify_push(KCI_CONTRUP, card->cnr, 0, 0);
@@ -364,7 +384,7 @@ void capi_ctr_reseted(struct capi_ctr * card)
                capi_ctr_put(card);
        }
 
-       printk(KERN_NOTICE "kcapi: card %d down.\n", card->cnr);
+       printk(KERN_NOTICE "kcapi: card [%03d] down.\n", card->cnr);
 
        notify_push(KCI_CONTRDOWN, card->cnr, 0, 0);
 }
@@ -374,7 +394,7 @@ EXPORT_SYMBOL(capi_ctr_reseted);
 void capi_ctr_suspend_output(struct capi_ctr *card)
 {
        if (!card->blocked) {
-               printk(KERN_DEBUG "kcapi: card %d suspend\n", card->cnr);
+               printk(KERN_DEBUG "kcapi: card [%03d] suspend\n", card->cnr);
                card->blocked = 1;
        }
 }
@@ -384,7 +404,7 @@ EXPORT_SYMBOL(capi_ctr_suspend_output);
 void capi_ctr_resume_output(struct capi_ctr *card)
 {
        if (card->blocked) {
-               printk(KERN_DEBUG "kcapi: card %d resume\n", card->cnr);
+               printk(KERN_DEBUG "kcapi: card [%03d] resume\n", card->cnr);
                card->blocked = 0;
        }
 }
@@ -432,7 +452,7 @@ attach_capi_ctr(struct capi_ctr *card)
        }
 
        ncards++;
-       printk(KERN_NOTICE "kcapi: Controller %d: %s attached\n",
+       printk(KERN_NOTICE "kcapi: Controller [%03d]: %s attached\n",
                        card->cnr, card->name);
        return 0;
 }
@@ -451,7 +471,7 @@ int detach_capi_ctr(struct capi_ctr *card)
           card->procent = NULL;
        }
        capi_cards[card->cnr - 1] = NULL;
-       printk(KERN_NOTICE "kcapi: Controller %d: %s unregistered\n",
+       printk(KERN_NOTICE "kcapi: Controller [%03d]: %s unregistered\n",
                        card->cnr, card->name);
 
        return 0;
@@ -623,17 +643,25 @@ u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb)
        showctl |= (card->traceflag & 1);
        if (showctl & 2) {
                if (showctl & 1) {
-                       printk(KERN_DEBUG "kcapi: put [%#x] id#%d %s len=%u\n",
+                       printk(KERN_DEBUG "kcapi: put [%03d] id#%d %s len=%u\n",
                               CAPIMSG_CONTROLLER(skb->data),
                               CAPIMSG_APPID(skb->data),
                               capi_cmd2str(cmd, subcmd),
                               CAPIMSG_LEN(skb->data));
                } else {
-                       printk(KERN_DEBUG "kcapi: put [%#x] %s\n",
-                              CAPIMSG_CONTROLLER(skb->data),
-                              capi_message2str(skb->data));
+                       _cdebbuf *cdb = capi_message2str(skb->data);
+                       if (cdb) {
+                               printk(KERN_DEBUG "kcapi: put [%03d] %s\n",
+                                       CAPIMSG_CONTROLLER(skb->data),
+                                       cdb->buf);
+                               cdebbuf_free(cdb);
+                       } else
+                               printk(KERN_DEBUG "kcapi: put [%03d] id#%d %s len=%u cannot trace\n",
+                                       CAPIMSG_CONTROLLER(skb->data),
+                                       CAPIMSG_APPID(skb->data),
+                                       capi_cmd2str(cmd, subcmd),
+                                       CAPIMSG_LEN(skb->data));
                }
-
        }
        return card->send_message(card, skb);
 }
@@ -894,7 +922,7 @@ int capi20_manufacturer(unsigned int cmd, void __user *data)
                        return -ESRCH;
 
                card->traceflag = fdef.flag;
-               printk(KERN_INFO "kcapi: contr %d set trace=%d\n",
+               printk(KERN_INFO "kcapi: contr [%03d] set trace=%d\n",
                        card->cnr, card->traceflag);
                return 0;
        }
@@ -967,7 +995,11 @@ static int __init kcapi_init(void)
 {
        char *p;
        char rev[32];
+       int ret;
 
+       ret = cdebug_init();
+       if (ret)
+               return ret;
         kcapi_proc_init();
 
        if ((p = strchr(revision, ':')) != 0 && p[1]) {
@@ -988,6 +1020,7 @@ static void __exit kcapi_exit(void)
 
        /* make sure all notifiers are finished */
        flush_scheduled_work();
+       cdebug_exit();
 }
 
 module_init(kcapi_init);
index 077e297d8c7239b9d6cbd5ee7307cd94f22ace16..e9d3189f56b70ed4e809e64f8bc397e461789b25 100644 (file)
@@ -1,8 +1,9 @@
-gigaset-y := common.o interface.o proc.o ev-layer.o i4l.o
-usb_gigaset-y := usb-gigaset.o asyncdata.o
+gigaset-y := common.o interface.o proc.o ev-layer.o i4l.o asyncdata.o
+usb_gigaset-y := usb-gigaset.o
+ser_gigaset-y := ser-gigaset.o
 bas_gigaset-y := bas-gigaset.o isocdata.o
-ser_gigaset-y := ser-gigaset.o asyncdata.o
 
-obj-$(CONFIG_GIGASET_M105) += usb_gigaset.o gigaset.o
-obj-$(CONFIG_GIGASET_BASE) += bas_gigaset.o gigaset.o
-obj-$(CONFIG_GIGASET_M101) += ser_gigaset.o gigaset.o
+obj-$(CONFIG_ISDN_DRV_GIGASET) += gigaset.o
+obj-$(CONFIG_GIGASET_M105) += usb_gigaset.o
+obj-$(CONFIG_GIGASET_BASE) += bas_gigaset.o
+obj-$(CONFIG_GIGASET_M101) += ser_gigaset.o
index ddf5e92be44429cc3b3c679844933b8e11d2a6a5..00a3be5b862bbf87416231c2f91c58851e593c87 100644 (file)
  * =====================================================================
  */
 
-/* not set by Kbuild when building both ser_gigaset and usb_gigaset */
-#ifndef KBUILD_MODNAME
-#define KBUILD_MODNAME "asy_gigaset"
-#endif
-
 #include "gigaset.h"
 #include <linux/crc-ccitt.h>
 #include <linux/bitrev.h>
@@ -444,6 +439,7 @@ nextbyte:
                atomic_set(&inbuf->head, head);
        }
 }
+EXPORT_SYMBOL_GPL(gigaset_m10x_input);
 
 
 /* == data output ========================================================== */
@@ -591,3 +587,4 @@ int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
 
        return len;     /* ok so far */
 }
+EXPORT_SYMBOL_GPL(gigaset_m10x_send_skb);
index 04574a9d4430b9deeb7458e0a037a1b76f1e6b23..0d122bf889db314195ce28314d5ceb717ced2db3 100644 (file)
@@ -14,6 +14,7 @@
 
 #include "vmx.h"
 #include <linux/kvm.h>
+#include <linux/kvm_para.h>
 
 #define CR0_PE_MASK (1ULL << 0)
 #define CR0_TS_MASK (1ULL << 3)
@@ -237,6 +238,9 @@ struct kvm_vcpu {
        unsigned long cr0;
        unsigned long cr2;
        unsigned long cr3;
+       gpa_t para_state_gpa;
+       struct page *para_state_page;
+       gpa_t hypercall_gpa;
        unsigned long cr4;
        unsigned long cr8;
        u64 pdptrs[4]; /* pae */
@@ -305,6 +309,7 @@ struct kvm {
        int busy;
        unsigned long rmap_overflow;
        struct list_head vm_list;
+       struct file *filp;
 };
 
 struct kvm_stat {
@@ -339,7 +344,7 @@ struct kvm_arch_ops {
        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_load)(struct kvm_vcpu *vcpu);
        void (*vcpu_put)(struct kvm_vcpu *vcpu);
        void (*vcpu_decache)(struct kvm_vcpu *vcpu);
 
@@ -382,6 +387,8 @@ struct kvm_arch_ops {
        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);
+       void (*patch_hypercall)(struct kvm_vcpu *vcpu,
+                               unsigned char *hypercall_addr);
 };
 
 extern struct kvm_stat kvm_stat;
@@ -476,6 +483,8 @@ void kvm_mmu_post_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes);
 int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva);
 void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu);
 
+int kvm_hypercall(struct kvm_vcpu *vcpu, struct kvm_run *run);
+
 static inline int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
                                     u32 error_code)
 {
@@ -523,7 +532,7 @@ 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;
+       return (struct kvm_mmu_page *)page_private(page);
 }
 
 static inline u16 read_fs(void)
index af866147ff25613ef1e1c4a7e0d0edccca0dc27a..a163bca38973024bc8b0a4627c0dbb2c8a0c007a 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/kvm.h>
 #include <linux/module.h>
 #include <linux/errno.h>
+#include <linux/magic.h>
 #include <asm/processor.h>
 #include <linux/percpu.h>
 #include <linux/gfp.h>
@@ -36,6 +37,9 @@
 #include <asm/desc.h>
 #include <linux/sysdev.h>
 #include <linux/cpu.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
 
 #include "x86_emulate.h"
 #include "segment_descriptor.h"
@@ -72,6 +76,8 @@ static struct kvm_stats_debugfs_item {
 
 static struct dentry *debugfs_dir;
 
+struct vfsmount *kvmfs_mnt;
+
 #define MAX_IO_MSRS 256
 
 #define CR0_RESEVED_BITS 0xffffffff1ffaffc0ULL
@@ -90,6 +96,58 @@ struct segment_descriptor_64 {
 
 #endif
 
+static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl,
+                          unsigned long arg);
+
+static struct inode *kvmfs_inode(struct file_operations *fops)
+{
+       int error = -ENOMEM;
+       struct inode *inode = new_inode(kvmfs_mnt->mnt_sb);
+
+       if (!inode)
+               goto eexit_1;
+
+       inode->i_fop = fops;
+
+       /*
+        * Mark the inode dirty from the very beginning,
+        * that way it will never be moved to the dirty
+        * list because mark_inode_dirty() will think
+        * that it already _is_ on the dirty list.
+        */
+       inode->i_state = I_DIRTY;
+       inode->i_mode = S_IRUSR | S_IWUSR;
+       inode->i_uid = current->fsuid;
+       inode->i_gid = current->fsgid;
+       inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+       return inode;
+
+eexit_1:
+       return ERR_PTR(error);
+}
+
+static struct file *kvmfs_file(struct inode *inode, void *private_data)
+{
+       struct file *file = get_empty_filp();
+
+       if (!file)
+               return ERR_PTR(-ENFILE);
+
+       file->f_path.mnt = mntget(kvmfs_mnt);
+       file->f_path.dentry = d_alloc_anon(inode);
+       if (!file->f_path.dentry)
+               return ERR_PTR(-ENOMEM);
+       file->f_mapping = inode->i_mapping;
+
+       file->f_pos = 0;
+       file->f_flags = O_RDWR;
+       file->f_op = inode->i_fop;
+       file->f_mode = FMODE_READ | FMODE_WRITE;
+       file->f_version = 0;
+       file->private_data = private_data;
+       return file;
+}
+
 unsigned long segment_base(u16 selector)
 {
        struct descriptor_table gdt;
@@ -126,10 +184,8 @@ static inline int valid_vcpu(int n)
        return likely(n >= 0 && n < KVM_MAX_VCPUS);
 }
 
-int kvm_read_guest(struct kvm_vcpu *vcpu,
-                            gva_t addr,
-                            unsigned long size,
-                            void *dest)
+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;
@@ -161,10 +217,8 @@ int kvm_read_guest(struct kvm_vcpu *vcpu,
 }
 EXPORT_SYMBOL_GPL(kvm_read_guest);
 
-int kvm_write_guest(struct kvm_vcpu *vcpu,
-                            gva_t addr,
-                            unsigned long size,
-                            void *data)
+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;
@@ -174,12 +228,15 @@ int kvm_write_guest(struct kvm_vcpu *vcpu,
                unsigned now;
                unsigned offset;
                hva_t guest_buf;
+               gfn_t gfn;
 
                paddr = gva_to_hpa(vcpu, addr);
 
                if (is_error_hpa(paddr))
                        break;
 
+               gfn = vcpu->mmu.gva_to_gpa(vcpu, addr) >> PAGE_SHIFT;
+               mark_page_dirty(vcpu->kvm, gfn);
                guest_buf = (hva_t)kmap_atomic(
                                pfn_to_page(paddr >> PAGE_SHIFT), KM_USER0);
                offset = addr & ~PAGE_MASK;
@@ -195,24 +252,30 @@ int kvm_write_guest(struct kvm_vcpu *vcpu,
 }
 EXPORT_SYMBOL_GPL(kvm_write_guest);
 
-static int vcpu_slot(struct kvm_vcpu *vcpu)
+/*
+ * Switches to specified vcpu, until a matching vcpu_put()
+ */
+static void vcpu_load(struct kvm_vcpu *vcpu)
 {
-       return vcpu - vcpu->kvm->vcpus;
+       mutex_lock(&vcpu->mutex);
+       kvm_arch_ops->vcpu_load(vcpu);
 }
 
 /*
- * Switches to specified vcpu, until a matching vcpu_put()
+ * Switches to specified vcpu, until a matching vcpu_put(). Will return NULL
+ * if the slot is not populated.
  */
-static struct kvm_vcpu *vcpu_load(struct kvm *kvm, int vcpu_slot)
+static struct kvm_vcpu *vcpu_load_slot(struct kvm *kvm, int slot)
 {
-       struct kvm_vcpu *vcpu = &kvm->vcpus[vcpu_slot];
+       struct kvm_vcpu *vcpu = &kvm->vcpus[slot];
 
        mutex_lock(&vcpu->mutex);
-       if (unlikely(!vcpu->vmcs)) {
+       if (!vcpu->vmcs) {
                mutex_unlock(&vcpu->mutex);
                return NULL;
        }
-       return kvm_arch_ops->vcpu_load(vcpu);
+       kvm_arch_ops->vcpu_load(vcpu);
+       return vcpu;
 }
 
 static void vcpu_put(struct kvm_vcpu *vcpu)
@@ -221,13 +284,13 @@ static void vcpu_put(struct kvm_vcpu *vcpu)
        mutex_unlock(&vcpu->mutex);
 }
 
-static int kvm_dev_open(struct inode *inode, struct file *filp)
+static struct kvm *kvm_create_vm(void)
 {
        struct kvm *kvm = kzalloc(sizeof(struct kvm), GFP_KERNEL);
        int i;
 
        if (!kvm)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        spin_lock_init(&kvm->lock);
        INIT_LIST_HEAD(&kvm->active_mmu_pages);
@@ -243,7 +306,11 @@ static int kvm_dev_open(struct inode *inode, struct file *filp)
                list_add(&kvm->vm_list, &vm_list);
                spin_unlock(&kvm_lock);
        }
-       filp->private_data = kvm;
+       return kvm;
+}
+
+static int kvm_dev_open(struct inode *inode, struct file *filp)
+{
        return 0;
 }
 
@@ -281,9 +348,10 @@ static void kvm_free_physmem(struct kvm *kvm)
 
 static void kvm_free_vcpu(struct kvm_vcpu *vcpu)
 {
-       if (!vcpu_load(vcpu->kvm, vcpu_slot(vcpu)))
+       if (!vcpu->vmcs)
                return;
 
+       vcpu_load(vcpu);
        kvm_mmu_destroy(vcpu);
        vcpu_put(vcpu);
        kvm_arch_ops->vcpu_free(vcpu);
@@ -299,14 +367,24 @@ static void kvm_free_vcpus(struct kvm *kvm)
 
 static int kvm_dev_release(struct inode *inode, struct file *filp)
 {
-       struct kvm *kvm = filp->private_data;
+       return 0;
+}
 
+static void kvm_destroy_vm(struct kvm *kvm)
+{
        spin_lock(&kvm_lock);
        list_del(&kvm->vm_list);
        spin_unlock(&kvm_lock);
        kvm_free_vcpus(kvm);
        kvm_free_physmem(kvm);
        kfree(kvm);
+}
+
+static int kvm_vm_release(struct inode *inode, struct file *filp)
+{
+       struct kvm *kvm = filp->private_data;
+
+       kvm_destroy_vm(kvm);
        return 0;
 }
 
@@ -457,7 +535,7 @@ EXPORT_SYMBOL_GPL(set_cr4);
 void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
 {
        if (is_long_mode(vcpu)) {
-               if ( cr3 & CR3_L_MODE_RESEVED_BITS) {
+               if (cr3 & CR3_L_MODE_RESEVED_BITS) {
                        printk(KERN_DEBUG "set_cr3: #GP, reserved bits\n");
                        inject_gp(vcpu);
                        return;
@@ -533,55 +611,11 @@ void fx_init(struct kvm_vcpu *vcpu)
 }
 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)
+static void do_remove_write_access(struct kvm_vcpu *vcpu, int slot)
 {
-       int r;
-       struct kvm_vcpu *vcpu;
-
-       r = -EINVAL;
-       if (!valid_vcpu(n))
-               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;
-
-       r = kvm_arch_ops->vcpu_create(vcpu);
-       if (r < 0)
-               goto out_free_vcpus;
-
-       r = kvm_mmu_create(vcpu);
-       if (r < 0)
-               goto out_free_vcpus;
-
-       kvm_arch_ops->vcpu_load(vcpu);
-       r = kvm_mmu_setup(vcpu);
-       if (r >= 0)
-               r = kvm_arch_ops->vcpu_setup(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;
+       spin_lock(&vcpu->kvm->lock);
+       kvm_mmu_slot_remove_write_access(vcpu, slot);
+       spin_unlock(&vcpu->kvm->lock);
 }
 
 /*
@@ -590,8 +624,8 @@ out:
  *
  * Discontiguous memory is allowed, mostly for framebuffers.
  */
-static int kvm_dev_ioctl_set_memory_region(struct kvm *kvm,
-                                          struct kvm_memory_region *mem)
+static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,
+                                         struct kvm_memory_region *mem)
 {
        int r;
        gfn_t base_gfn;
@@ -674,7 +708,7 @@ raced:
                                                     | __GFP_ZERO);
                        if (!new.phys_mem[i])
                                goto out_free;
-                       new.phys_mem[i]->private = 0;
+                       set_page_private(new.phys_mem[i],0);
                }
        }
 
@@ -711,9 +745,11 @@ raced:
        for (i = 0; i < KVM_MAX_VCPUS; ++i) {
                struct kvm_vcpu *vcpu;
 
-               vcpu = vcpu_load(kvm, i);
+               vcpu = vcpu_load_slot(kvm, i);
                if (!vcpu)
                        continue;
+               if (new.flags & KVM_MEM_LOG_DIRTY_PAGES)
+                       do_remove_write_access(vcpu, mem->slot);
                kvm_mmu_reset_context(vcpu);
                vcpu_put(vcpu);
        }
@@ -729,18 +765,11 @@ out:
        return r;
 }
 
-static void do_remove_write_access(struct kvm_vcpu *vcpu, int slot)
-{
-       spin_lock(&vcpu->kvm->lock);
-       kvm_mmu_slot_remove_write_access(vcpu, slot);
-       spin_unlock(&vcpu->kvm->lock);
-}
-
 /*
  * 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)
+static int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
+                                     struct kvm_dirty_log *log)
 {
        struct kvm_memory_slot *memslot;
        int r, i;
@@ -765,21 +794,21 @@ static int kvm_dev_ioctl_get_dirty_log(struct kvm *kvm,
        if (!memslot->dirty_bitmap)
                goto out;
 
-       n = ALIGN(memslot->npages, 8) / 8;
+       n = ALIGN(memslot->npages, BITS_PER_LONG) / 8;
 
-       for (i = 0; !any && i < n; ++i)
+       for (i = 0; !any && i < n/sizeof(long); ++i)
                any = memslot->dirty_bitmap[i];
 
        r = -EFAULT;
        if (copy_to_user(log->dirty_bitmap, memslot->dirty_bitmap, n))
                goto out;
 
-
        if (any) {
                cleared = 0;
                for (i = 0; i < KVM_MAX_VCPUS; ++i) {
-                       struct kvm_vcpu *vcpu = vcpu_load(kvm, i);
+                       struct kvm_vcpu *vcpu;
 
+                       vcpu = vcpu_load_slot(kvm, i);
                        if (!vcpu)
                                continue;
                        if (!cleared) {
@@ -903,8 +932,9 @@ static int emulator_read_emulated(unsigned long addr,
                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;
+                       return X86EMUL_PROPAGATE_FAULT;
                vcpu->mmio_needed = 1;
                vcpu->mmio_phys_addr = gpa;
                vcpu->mmio_size = bytes;
@@ -928,6 +958,7 @@ static int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
                return 0;
        page = gfn_to_page(m, gpa >> PAGE_SHIFT);
        kvm_mmu_pre_write(vcpu, gpa, bytes);
+       mark_page_dirty(vcpu->kvm, gpa >> PAGE_SHIFT);
        virt = kmap_atomic(page, KM_USER0);
        memcpy(virt + offset_in_page(gpa), &val, bytes);
        kunmap_atomic(virt, KM_USER0);
@@ -1142,6 +1173,42 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
 }
 EXPORT_SYMBOL_GPL(emulate_instruction);
 
+int kvm_hypercall(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       unsigned long nr, a0, a1, a2, a3, a4, a5, ret;
+
+       kvm_arch_ops->decache_regs(vcpu);
+       ret = -KVM_EINVAL;
+#ifdef CONFIG_X86_64
+       if (is_long_mode(vcpu)) {
+               nr = vcpu->regs[VCPU_REGS_RAX];
+               a0 = vcpu->regs[VCPU_REGS_RDI];
+               a1 = vcpu->regs[VCPU_REGS_RSI];
+               a2 = vcpu->regs[VCPU_REGS_RDX];
+               a3 = vcpu->regs[VCPU_REGS_RCX];
+               a4 = vcpu->regs[VCPU_REGS_R8];
+               a5 = vcpu->regs[VCPU_REGS_R9];
+       } else
+#endif
+       {
+               nr = vcpu->regs[VCPU_REGS_RBX] & -1u;
+               a0 = vcpu->regs[VCPU_REGS_RAX] & -1u;
+               a1 = vcpu->regs[VCPU_REGS_RCX] & -1u;
+               a2 = vcpu->regs[VCPU_REGS_RDX] & -1u;
+               a3 = vcpu->regs[VCPU_REGS_RSI] & -1u;
+               a4 = vcpu->regs[VCPU_REGS_RDI] & -1u;
+               a5 = vcpu->regs[VCPU_REGS_RBP] & -1u;
+       }
+       switch (nr) {
+       default:
+               ;
+       }
+       vcpu->regs[VCPU_REGS_RAX] = ret;
+       kvm_arch_ops->cache_regs(vcpu);
+       return 1;
+}
+EXPORT_SYMBOL_GPL(kvm_hypercall);
+
 static u64 mk_cr_64(u64 curr_cr, u32 new_val)
 {
        return (curr_cr & ~((1ULL << 32) - 1)) | new_val;
@@ -1208,6 +1275,75 @@ void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long val,
        }
 }
 
+/*
+ * Register the para guest with the host:
+ */
+static int vcpu_register_para(struct kvm_vcpu *vcpu, gpa_t para_state_gpa)
+{
+       struct kvm_vcpu_para_state *para_state;
+       hpa_t para_state_hpa, hypercall_hpa;
+       struct page *para_state_page;
+       unsigned char *hypercall;
+       gpa_t hypercall_gpa;
+
+       printk(KERN_DEBUG "kvm: guest trying to enter paravirtual mode\n");
+       printk(KERN_DEBUG ".... para_state_gpa: %08Lx\n", para_state_gpa);
+
+       /*
+        * Needs to be page aligned:
+        */
+       if (para_state_gpa != PAGE_ALIGN(para_state_gpa))
+               goto err_gp;
+
+       para_state_hpa = gpa_to_hpa(vcpu, para_state_gpa);
+       printk(KERN_DEBUG ".... para_state_hpa: %08Lx\n", para_state_hpa);
+       if (is_error_hpa(para_state_hpa))
+               goto err_gp;
+
+       mark_page_dirty(vcpu->kvm, para_state_gpa >> PAGE_SHIFT);
+       para_state_page = pfn_to_page(para_state_hpa >> PAGE_SHIFT);
+       para_state = kmap_atomic(para_state_page, KM_USER0);
+
+       printk(KERN_DEBUG "....  guest version: %d\n", para_state->guest_version);
+       printk(KERN_DEBUG "....           size: %d\n", para_state->size);
+
+       para_state->host_version = KVM_PARA_API_VERSION;
+       /*
+        * We cannot support guests that try to register themselves
+        * with a newer API version than the host supports:
+        */
+       if (para_state->guest_version > KVM_PARA_API_VERSION) {
+               para_state->ret = -KVM_EINVAL;
+               goto err_kunmap_skip;
+       }
+
+       hypercall_gpa = para_state->hypercall_gpa;
+       hypercall_hpa = gpa_to_hpa(vcpu, hypercall_gpa);
+       printk(KERN_DEBUG ".... hypercall_hpa: %08Lx\n", hypercall_hpa);
+       if (is_error_hpa(hypercall_hpa)) {
+               para_state->ret = -KVM_EINVAL;
+               goto err_kunmap_skip;
+       }
+
+       printk(KERN_DEBUG "kvm: para guest successfully registered.\n");
+       vcpu->para_state_page = para_state_page;
+       vcpu->para_state_gpa = para_state_gpa;
+       vcpu->hypercall_gpa = hypercall_gpa;
+
+       mark_page_dirty(vcpu->kvm, hypercall_gpa >> PAGE_SHIFT);
+       hypercall = kmap_atomic(pfn_to_page(hypercall_hpa >> PAGE_SHIFT),
+                               KM_USER1) + (hypercall_hpa & ~PAGE_MASK);
+       kvm_arch_ops->patch_hypercall(vcpu, hypercall);
+       kunmap_atomic(hypercall, KM_USER1);
+
+       para_state->ret = 0;
+err_kunmap_skip:
+       kunmap_atomic(para_state, KM_USER0);
+       return 0;
+err_gp:
+       return 1;
+}
+
 int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
 {
        u64 data;
@@ -1316,6 +1452,12 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
        case MSR_IA32_MISC_ENABLE:
                vcpu->ia32_misc_enable_msr = data;
                break;
+       /*
+        * This is the 'probe whether the host is KVM' logic:
+        */
+       case MSR_KVM_API_MAGIC:
+               return vcpu_register_para(vcpu, data);
+
        default:
                printk(KERN_ERR "kvm: unhandled wrmsr: 0x%x\n", msr);
                return 1;
@@ -1338,8 +1480,7 @@ 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));
+       vcpu_load(vcpu);
 }
 EXPORT_SYMBOL_GPL(kvm_resched);
 
@@ -1361,17 +1502,11 @@ void save_msrs(struct vmx_msr_entry *e, int n)
 }
 EXPORT_SYMBOL_GPL(save_msrs);
 
-static int kvm_dev_ioctl_run(struct kvm *kvm, struct kvm_run *kvm_run)
+static int kvm_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
-       struct kvm_vcpu *vcpu;
        int r;
 
-       if (!valid_vcpu(kvm_run->vcpu))
-               return -EINVAL;
-
-       vcpu = vcpu_load(kvm, kvm_run->vcpu);
-       if (!vcpu)
-               return -ENOENT;
+       vcpu_load(vcpu);
 
        /* re-sync apic's tpr */
        vcpu->cr8 = kvm_run->cr8;
@@ -1394,16 +1529,10 @@ static int kvm_dev_ioctl_run(struct kvm *kvm, struct kvm_run *kvm_run)
        return r;
 }
 
-static int kvm_dev_ioctl_get_regs(struct kvm *kvm, struct kvm_regs *regs)
+static int kvm_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu,
+                                  struct kvm_regs *regs)
 {
-       struct kvm_vcpu *vcpu;
-
-       if (!valid_vcpu(regs->vcpu))
-               return -EINVAL;
-
-       vcpu = vcpu_load(kvm, regs->vcpu);
-       if (!vcpu)
-               return -ENOENT;
+       vcpu_load(vcpu);
 
        kvm_arch_ops->cache_regs(vcpu);
 
@@ -1440,16 +1569,10 @@ static int kvm_dev_ioctl_get_regs(struct kvm *kvm, struct kvm_regs *regs)
        return 0;
 }
 
-static int kvm_dev_ioctl_set_regs(struct kvm *kvm, struct kvm_regs *regs)
+static int kvm_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu,
+                                  struct kvm_regs *regs)
 {
-       struct kvm_vcpu *vcpu;
-
-       if (!valid_vcpu(regs->vcpu))
-               return -EINVAL;
-
-       vcpu = vcpu_load(kvm, regs->vcpu);
-       if (!vcpu)
-               return -ENOENT;
+       vcpu_load(vcpu);
 
        vcpu->regs[VCPU_REGS_RAX] = regs->rax;
        vcpu->regs[VCPU_REGS_RBX] = regs->rbx;
@@ -1486,16 +1609,12 @@ static void get_segment(struct kvm_vcpu *vcpu,
        return kvm_arch_ops->get_segment(vcpu, var, seg);
 }
 
-static int kvm_dev_ioctl_get_sregs(struct kvm *kvm, struct kvm_sregs *sregs)
+static int kvm_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
+                                   struct kvm_sregs *sregs)
 {
-       struct kvm_vcpu *vcpu;
        struct descriptor_table dt;
 
-       if (!valid_vcpu(sregs->vcpu))
-               return -EINVAL;
-       vcpu = vcpu_load(kvm, sregs->vcpu);
-       if (!vcpu)
-               return -ENOENT;
+       vcpu_load(vcpu);
 
        get_segment(vcpu, &sregs->cs, VCPU_SREG_CS);
        get_segment(vcpu, &sregs->ds, VCPU_SREG_DS);
@@ -1537,18 +1656,14 @@ static void set_segment(struct kvm_vcpu *vcpu,
        return kvm_arch_ops->set_segment(vcpu, var, seg);
 }
 
-static int kvm_dev_ioctl_set_sregs(struct kvm *kvm, struct kvm_sregs *sregs)
+static int kvm_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
+                                   struct kvm_sregs *sregs)
 {
-       struct kvm_vcpu *vcpu;
        int mmu_reset_needed = 0;
        int i;
        struct descriptor_table dt;
 
-       if (!valid_vcpu(sregs->vcpu))
-               return -EINVAL;
-       vcpu = vcpu_load(kvm, sregs->vcpu);
-       if (!vcpu)
-               return -ENOENT;
+       vcpu_load(vcpu);
 
        set_segment(vcpu, &sregs->cs, VCPU_SREG_CS);
        set_segment(vcpu, &sregs->ds, VCPU_SREG_DS);
@@ -1654,20 +1769,14 @@ static int do_set_msr(struct kvm_vcpu *vcpu, unsigned index, u64 *data)
  *
  * @return number of msrs set successfully.
  */
-static int __msr_io(struct kvm *kvm, struct kvm_msrs *msrs,
+static int __msr_io(struct kvm_vcpu *vcpu, 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 (!valid_vcpu(msrs->vcpu))
-               return -EINVAL;
-
-       vcpu = vcpu_load(kvm, msrs->vcpu);
-       if (!vcpu)
-               return -ENOENT;
+       vcpu_load(vcpu);
 
        for (i = 0; i < msrs->nmsrs; ++i)
                if (do_msr(vcpu, entries[i].index, &entries[i].data))
@@ -1683,7 +1792,7 @@ static int __msr_io(struct kvm *kvm, struct kvm_msrs *msrs,
  *
  * @return number of msrs set successfully.
  */
-static int msr_io(struct kvm *kvm, struct kvm_msrs __user *user_msrs,
+static int msr_io(struct kvm_vcpu *vcpu, struct kvm_msrs __user *user_msrs,
                  int (*do_msr)(struct kvm_vcpu *vcpu,
                                unsigned index, u64 *data),
                  int writeback)
@@ -1711,7 +1820,7 @@ static int msr_io(struct kvm *kvm, struct kvm_msrs __user *user_msrs,
        if (copy_from_user(entries, user_msrs->entries, size))
                goto out_free;
 
-       r = n = __msr_io(kvm, &msrs, entries, do_msr);
+       r = n = __msr_io(vcpu, &msrs, entries, do_msr);
        if (r < 0)
                goto out_free;
 
@@ -1730,38 +1839,31 @@ out:
 /*
  * Translate a guest virtual address to a guest physical address.
  */
-static int kvm_dev_ioctl_translate(struct kvm *kvm, struct kvm_translation *tr)
+static int kvm_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
+                                   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);
+       vcpu_load(vcpu);
+       spin_lock(&vcpu->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);
+       spin_unlock(&vcpu->kvm->lock);
        vcpu_put(vcpu);
 
        return 0;
 }
 
-static int kvm_dev_ioctl_interrupt(struct kvm *kvm, struct kvm_interrupt *irq)
+static int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
+                                   struct kvm_interrupt *irq)
 {
-       struct kvm_vcpu *vcpu;
-
-       if (!valid_vcpu(irq->vcpu))
-               return -EINVAL;
        if (irq->irq < 0 || irq->irq >= 256)
                return -EINVAL;
-       vcpu = vcpu_load(kvm, irq->vcpu);
-       if (!vcpu)
-               return -ENOENT;
+       vcpu_load(vcpu);
 
        set_bit(irq->irq, vcpu->irq_pending);
        set_bit(irq->irq / BITS_PER_LONG, &vcpu->irq_summary);
@@ -1771,17 +1873,12 @@ static int kvm_dev_ioctl_interrupt(struct kvm *kvm, struct kvm_interrupt *irq)
        return 0;
 }
 
-static int kvm_dev_ioctl_debug_guest(struct kvm *kvm,
-                                    struct kvm_debug_guest *dbg)
+static int kvm_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu,
+                                     struct kvm_debug_guest *dbg)
 {
-       struct kvm_vcpu *vcpu;
        int r;
 
-       if (!valid_vcpu(dbg->vcpu))
-               return -EINVAL;
-       vcpu = vcpu_load(kvm, dbg->vcpu);
-       if (!vcpu)
-               return -ENOENT;
+       vcpu_load(vcpu);
 
        r = kvm_arch_ops->set_guest_debug(vcpu, dbg);
 
@@ -1790,30 +1887,129 @@ static int kvm_dev_ioctl_debug_guest(struct kvm *kvm,
        return r;
 }
 
-static long kvm_dev_ioctl(struct file *filp,
-                         unsigned int ioctl, unsigned long arg)
+static int kvm_vcpu_release(struct inode *inode, struct file *filp)
 {
-       struct kvm *kvm = filp->private_data;
+       struct kvm_vcpu *vcpu = filp->private_data;
+
+       fput(vcpu->kvm->filp);
+       return 0;
+}
+
+static struct file_operations kvm_vcpu_fops = {
+       .release        = kvm_vcpu_release,
+       .unlocked_ioctl = kvm_vcpu_ioctl,
+       .compat_ioctl   = kvm_vcpu_ioctl,
+};
+
+/*
+ * Allocates an inode for the vcpu.
+ */
+static int create_vcpu_fd(struct kvm_vcpu *vcpu)
+{
+       int fd, r;
+       struct inode *inode;
+       struct file *file;
+
+       atomic_inc(&vcpu->kvm->filp->f_count);
+       inode = kvmfs_inode(&kvm_vcpu_fops);
+       if (IS_ERR(inode)) {
+               r = PTR_ERR(inode);
+               goto out1;
+       }
+
+       file = kvmfs_file(inode, vcpu);
+       if (IS_ERR(file)) {
+               r = PTR_ERR(file);
+               goto out2;
+       }
+
+       r = get_unused_fd();
+       if (r < 0)
+               goto out3;
+       fd = r;
+       fd_install(fd, file);
+
+       return fd;
+
+out3:
+       fput(file);
+out2:
+       iput(inode);
+out1:
+       fput(vcpu->kvm->filp);
+       return r;
+}
+
+/*
+ * Creates some virtual cpus.  Good luck creating more than one.
+ */
+static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, int n)
+{
+       int r;
+       struct kvm_vcpu *vcpu;
+
+       r = -EINVAL;
+       if (!valid_vcpu(n))
+               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;
+
+       r = kvm_arch_ops->vcpu_create(vcpu);
+       if (r < 0)
+               goto out_free_vcpus;
+
+       r = kvm_mmu_create(vcpu);
+       if (r < 0)
+               goto out_free_vcpus;
+
+       kvm_arch_ops->vcpu_load(vcpu);
+       r = kvm_mmu_setup(vcpu);
+       if (r >= 0)
+               r = kvm_arch_ops->vcpu_setup(vcpu);
+       vcpu_put(vcpu);
+
+       if (r < 0)
+               goto out_free_vcpus;
+
+       r = create_vcpu_fd(vcpu);
+       if (r < 0)
+               goto out_free_vcpus;
+
+       return r;
+
+out_free_vcpus:
+       kvm_free_vcpu(vcpu);
+       mutex_unlock(&vcpu->mutex);
+out:
+       return r;
+}
+
+static long kvm_vcpu_ioctl(struct file *filp,
+                          unsigned int ioctl, unsigned long arg)
+{
+       struct kvm_vcpu *vcpu = filp->private_data;
        void __user *argp = (void __user *)arg;
        int r = -EINVAL;
 
        switch (ioctl) {
-       case KVM_GET_API_VERSION:
-               r = KVM_API_VERSION;
-               break;
-       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, argp, sizeof kvm_run))
                        goto out;
-               r = kvm_dev_ioctl_run(kvm, &kvm_run);
+               r = kvm_vcpu_ioctl_run(vcpu, &kvm_run);
                if (r < 0 &&  r != -EINTR)
                        goto out;
                if (copy_to_user(argp, &kvm_run, sizeof kvm_run)) {
@@ -1825,10 +2021,8 @@ static long kvm_dev_ioctl(struct file *filp,
        case KVM_GET_REGS: {
                struct kvm_regs kvm_regs;
 
-               r = -EFAULT;
-               if (copy_from_user(&kvm_regs, argp, sizeof kvm_regs))
-                       goto out;
-               r = kvm_dev_ioctl_get_regs(kvm, &kvm_regs);
+               memset(&kvm_regs, 0, sizeof kvm_regs);
+               r = kvm_vcpu_ioctl_get_regs(vcpu, &kvm_regs);
                if (r)
                        goto out;
                r = -EFAULT;
@@ -1843,7 +2037,7 @@ static long kvm_dev_ioctl(struct file *filp,
                r = -EFAULT;
                if (copy_from_user(&kvm_regs, argp, sizeof kvm_regs))
                        goto out;
-               r = kvm_dev_ioctl_set_regs(kvm, &kvm_regs);
+               r = kvm_vcpu_ioctl_set_regs(vcpu, &kvm_regs);
                if (r)
                        goto out;
                r = 0;
@@ -1852,10 +2046,8 @@ static long kvm_dev_ioctl(struct file *filp,
        case KVM_GET_SREGS: {
                struct kvm_sregs kvm_sregs;
 
-               r = -EFAULT;
-               if (copy_from_user(&kvm_sregs, argp, sizeof kvm_sregs))
-                       goto out;
-               r = kvm_dev_ioctl_get_sregs(kvm, &kvm_sregs);
+               memset(&kvm_sregs, 0, sizeof kvm_sregs);
+               r = kvm_vcpu_ioctl_get_sregs(vcpu, &kvm_sregs);
                if (r)
                        goto out;
                r = -EFAULT;
@@ -1870,7 +2062,7 @@ static long kvm_dev_ioctl(struct file *filp,
                r = -EFAULT;
                if (copy_from_user(&kvm_sregs, argp, sizeof kvm_sregs))
                        goto out;
-               r = kvm_dev_ioctl_set_sregs(kvm, &kvm_sregs);
+               r = kvm_vcpu_ioctl_set_sregs(vcpu, &kvm_sregs);
                if (r)
                        goto out;
                r = 0;
@@ -1882,7 +2074,7 @@ static long kvm_dev_ioctl(struct file *filp,
                r = -EFAULT;
                if (copy_from_user(&tr, argp, sizeof tr))
                        goto out;
-               r = kvm_dev_ioctl_translate(kvm, &tr);
+               r = kvm_vcpu_ioctl_translate(vcpu, &tr);
                if (r)
                        goto out;
                r = -EFAULT;
@@ -1897,7 +2089,7 @@ static long kvm_dev_ioctl(struct file *filp,
                r = -EFAULT;
                if (copy_from_user(&irq, argp, sizeof irq))
                        goto out;
-               r = kvm_dev_ioctl_interrupt(kvm, &irq);
+               r = kvm_vcpu_ioctl_interrupt(vcpu, &irq);
                if (r)
                        goto out;
                r = 0;
@@ -1909,19 +2101,45 @@ static long kvm_dev_ioctl(struct file *filp,
                r = -EFAULT;
                if (copy_from_user(&dbg, argp, sizeof dbg))
                        goto out;
-               r = kvm_dev_ioctl_debug_guest(kvm, &dbg);
+               r = kvm_vcpu_ioctl_debug_guest(vcpu, &dbg);
                if (r)
                        goto out;
                r = 0;
                break;
        }
+       case KVM_GET_MSRS:
+               r = msr_io(vcpu, argp, get_msr, 1);
+               break;
+       case KVM_SET_MSRS:
+               r = msr_io(vcpu, argp, do_set_msr, 0);
+               break;
+       default:
+               ;
+       }
+out:
+       return r;
+}
+
+static long kvm_vm_ioctl(struct file *filp,
+                          unsigned int ioctl, unsigned long arg)
+{
+       struct kvm *kvm = filp->private_data;
+       void __user *argp = (void __user *)arg;
+       int r = -EINVAL;
+
+       switch (ioctl) {
+       case KVM_CREATE_VCPU:
+               r = kvm_vm_ioctl_create_vcpu(kvm, arg);
+               if (r < 0)
+                       goto out;
+               break;
        case KVM_SET_MEMORY_REGION: {
                struct kvm_memory_region kvm_mem;
 
                r = -EFAULT;
                if (copy_from_user(&kvm_mem, argp, sizeof kvm_mem))
                        goto out;
-               r = kvm_dev_ioctl_set_memory_region(kvm, &kvm_mem);
+               r = kvm_vm_ioctl_set_memory_region(kvm, &kvm_mem);
                if (r)
                        goto out;
                break;
@@ -1932,16 +2150,112 @@ static long kvm_dev_ioctl(struct file *filp,
                r = -EFAULT;
                if (copy_from_user(&log, argp, sizeof log))
                        goto out;
-               r = kvm_dev_ioctl_get_dirty_log(kvm, &log);
+               r = kvm_vm_ioctl_get_dirty_log(kvm, &log);
                if (r)
                        goto out;
                break;
        }
-       case KVM_GET_MSRS:
-               r = msr_io(kvm, argp, get_msr, 1);
+       default:
+               ;
+       }
+out:
+       return r;
+}
+
+static struct page *kvm_vm_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_vm_vm_ops = {
+       .nopage = kvm_vm_nopage,
+};
+
+static int kvm_vm_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       vma->vm_ops = &kvm_vm_vm_ops;
+       return 0;
+}
+
+static struct file_operations kvm_vm_fops = {
+       .release        = kvm_vm_release,
+       .unlocked_ioctl = kvm_vm_ioctl,
+       .compat_ioctl   = kvm_vm_ioctl,
+       .mmap           = kvm_vm_mmap,
+};
+
+static int kvm_dev_ioctl_create_vm(void)
+{
+       int fd, r;
+       struct inode *inode;
+       struct file *file;
+       struct kvm *kvm;
+
+       inode = kvmfs_inode(&kvm_vm_fops);
+       if (IS_ERR(inode)) {
+               r = PTR_ERR(inode);
+               goto out1;
+       }
+
+       kvm = kvm_create_vm();
+       if (IS_ERR(kvm)) {
+               r = PTR_ERR(kvm);
+               goto out2;
+       }
+
+       file = kvmfs_file(inode, kvm);
+       if (IS_ERR(file)) {
+               r = PTR_ERR(file);
+               goto out3;
+       }
+       kvm->filp = file;
+
+       r = get_unused_fd();
+       if (r < 0)
+               goto out4;
+       fd = r;
+       fd_install(fd, file);
+
+       return fd;
+
+out4:
+       fput(file);
+out3:
+       kvm_destroy_vm(kvm);
+out2:
+       iput(inode);
+out1:
+       return r;
+}
+
+static long kvm_dev_ioctl(struct file *filp,
+                         unsigned int ioctl, unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       int r = -EINVAL;
+
+       switch (ioctl) {
+       case KVM_GET_API_VERSION:
+               r = KVM_API_VERSION;
                break;
-       case KVM_SET_MSRS:
-               r = msr_io(kvm, argp, do_set_msr, 0);
+       case KVM_CREATE_VM:
+               r = kvm_dev_ioctl_create_vm();
                break;
        case KVM_GET_MSR_INDEX_LIST: {
                struct kvm_msr_list __user *user_msr_list = argp;
@@ -1977,43 +2291,11 @@ 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 = {
@@ -2080,13 +2362,17 @@ static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val,
        int cpu = (long)v;
 
        switch (val) {
-       case CPU_DEAD:
+       case CPU_DOWN_PREPARE:
        case CPU_UP_CANCELED:
+               printk(KERN_INFO "kvm: disabling virtualization on CPU%d\n",
+                      cpu);
                decache_vcpus_on_cpu(cpu);
                smp_call_function_single(cpu, kvm_arch_ops->hardware_disable,
                                         NULL, 0, 1);
                break;
-       case CPU_UP_PREPARE:
+       case CPU_ONLINE:
+               printk(KERN_INFO "kvm: enabling virtualization on CPU%d\n",
+                      cpu);
                smp_call_function_single(cpu, kvm_arch_ops->hardware_enable,
                                         NULL, 0, 1);
                break;
@@ -2121,13 +2407,13 @@ static void kvm_exit_debug(void)
 static int kvm_suspend(struct sys_device *dev, pm_message_t state)
 {
        decache_vcpus_on_cpu(raw_smp_processor_id());
-       on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1);
+       on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1);
        return 0;
 }
 
 static int kvm_resume(struct sys_device *dev)
 {
-       on_each_cpu(kvm_arch_ops->hardware_enable, 0, 0, 1);
+       on_each_cpu(kvm_arch_ops->hardware_enable, NULL, 0, 1);
        return 0;
 }
 
@@ -2144,6 +2430,18 @@ static struct sys_device kvm_sysdev = {
 
 hpa_t bad_page_address;
 
+static int kvmfs_get_sb(struct file_system_type *fs_type, int flags,
+                       const char *dev_name, void *data, struct vfsmount *mnt)
+{
+       return get_sb_pseudo(fs_type, "kvm:", NULL, KVMFS_SUPER_MAGIC, mnt);
+}
+
+static struct file_system_type kvm_fs_type = {
+       .name           = "kvmfs",
+       .get_sb         = kvmfs_get_sb,
+       .kill_sb        = kill_anon_super,
+};
+
 int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module)
 {
        int r;
@@ -2220,8 +2518,16 @@ void kvm_exit_arch(void)
 static __init int kvm_init(void)
 {
        static struct page *bad_page;
-       int r = 0;
+       int r;
+
+       r = register_filesystem(&kvm_fs_type);
+       if (r)
+               goto out3;
 
+       kvmfs_mnt = kern_mount(&kvm_fs_type);
+       r = PTR_ERR(kvmfs_mnt);
+       if (IS_ERR(kvmfs_mnt))
+               goto out2;
        kvm_init_debug();
 
        kvm_init_msr_list();
@@ -2234,10 +2540,14 @@ static __init int kvm_init(void)
        bad_page_address = page_to_pfn(bad_page) << PAGE_SHIFT;
        memset(__va(bad_page_address), 0, PAGE_SIZE);
 
-       return r;
+       return 0;
 
 out:
        kvm_exit_debug();
+       mntput(kvmfs_mnt);
+out2:
+       unregister_filesystem(&kvm_fs_type);
+out3:
        return r;
 }
 
@@ -2245,6 +2555,8 @@ static __exit void kvm_exit(void)
 {
        kvm_exit_debug();
        __free_page(pfn_to_page(bad_page_address >> PAGE_SHIFT));
+       mntput(kvmfs_mnt);
+       unregister_filesystem(&kvm_fs_type);
 }
 
 module_init(kvm_init)
index 74cc862f4935ea9bf9a18aecf3daa9ad114cce38..624f1ca48657e9d0f4fafd3d1c45b63fbfd1ebe3 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __KVM_SVM_H
 #define __KVM_SVM_H
 
+#include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/list.h>
 #include <asm/msr.h>
@@ -18,7 +19,7 @@ static const u32 host_save_msrs[] = {
        MSR_IA32_LASTBRANCHTOIP, MSR_IA32_LASTINTFROMIP,MSR_IA32_LASTINTTOIP,*/
 };
 
-#define NR_HOST_SAVE_MSRS (sizeof(host_save_msrs) / sizeof(*host_save_msrs))
+#define NR_HOST_SAVE_MSRS ARRAY_SIZE(host_save_msrs)
 #define NUM_DB_REGS 4
 
 struct vcpu_svm {
index be793770f31b3045cef6beb7c70ec6d6864fa3f1..a1a93368f314d4e89226c3ab1b78dd9934135d42 100644 (file)
@@ -298,18 +298,18 @@ static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte)
        if (!is_rmap_pte(*spte))
                return;
        page = pfn_to_page((*spte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT);
-       if (!page->private) {
+       if (!page_private(page)) {
                rmap_printk("rmap_add: %p %llx 0->1\n", spte, *spte);
-               page->private = (unsigned long)spte;
-       } else if (!(page->private & 1)) {
+               set_page_private(page,(unsigned long)spte);
+       } else if (!(page_private(page) & 1)) {
                rmap_printk("rmap_add: %p %llx 1->many\n", spte, *spte);
                desc = mmu_alloc_rmap_desc(vcpu);
-               desc->shadow_ptes[0] = (u64 *)page->private;
+               desc->shadow_ptes[0] = (u64 *)page_private(page);
                desc->shadow_ptes[1] = spte;
-               page->private = (unsigned long)desc | 1;
+               set_page_private(page,(unsigned long)desc | 1);
        } else {
                rmap_printk("rmap_add: %p %llx many->many\n", spte, *spte);
-               desc = (struct kvm_rmap_desc *)(page->private & ~1ul);
+               desc = (struct kvm_rmap_desc *)(page_private(page) & ~1ul);
                while (desc->shadow_ptes[RMAP_EXT-1] && desc->more)
                        desc = desc->more;
                if (desc->shadow_ptes[RMAP_EXT-1]) {
@@ -337,12 +337,12 @@ static void rmap_desc_remove_entry(struct kvm_vcpu *vcpu,
        if (j != 0)
                return;
        if (!prev_desc && !desc->more)
-               page->private = (unsigned long)desc->shadow_ptes[0];
+               set_page_private(page,(unsigned long)desc->shadow_ptes[0]);
        else
                if (prev_desc)
                        prev_desc->more = desc->more;
                else
-                       page->private = (unsigned long)desc->more | 1;
+                       set_page_private(page,(unsigned long)desc->more | 1);
        mmu_free_rmap_desc(vcpu, desc);
 }
 
@@ -356,20 +356,20 @@ static void rmap_remove(struct kvm_vcpu *vcpu, u64 *spte)
        if (!is_rmap_pte(*spte))
                return;
        page = pfn_to_page((*spte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT);
-       if (!page->private) {
+       if (!page_private(page)) {
                printk(KERN_ERR "rmap_remove: %p %llx 0->BUG\n", spte, *spte);
                BUG();
-       } else if (!(page->private & 1)) {
+       } else if (!(page_private(page) & 1)) {
                rmap_printk("rmap_remove:  %p %llx 1->0\n", spte, *spte);
-               if ((u64 *)page->private != spte) {
+               if ((u64 *)page_private(page) != spte) {
                        printk(KERN_ERR "rmap_remove:  %p %llx 1->BUG\n",
                               spte, *spte);
                        BUG();
                }
-               page->private = 0;
+               set_page_private(page,0);
        } else {
                rmap_printk("rmap_remove:  %p %llx many->many\n", spte, *spte);
-               desc = (struct kvm_rmap_desc *)(page->private & ~1ul);
+               desc = (struct kvm_rmap_desc *)(page_private(page) & ~1ul);
                prev_desc = NULL;
                while (desc) {
                        for (i = 0; i < RMAP_EXT && desc->shadow_ptes[i]; ++i)
@@ -398,11 +398,11 @@ static void rmap_write_protect(struct kvm_vcpu *vcpu, u64 gfn)
        BUG_ON(!slot);
        page = gfn_to_page(slot, gfn);
 
-       while (page->private) {
-               if (!(page->private & 1))
-                       spte = (u64 *)page->private;
+       while (page_private(page)) {
+               if (!(page_private(page) & 1))
+                       spte = (u64 *)page_private(page);
                else {
-                       desc = (struct kvm_rmap_desc *)(page->private & ~1ul);
+                       desc = (struct kvm_rmap_desc *)(page_private(page) & ~1ul);
                        spte = desc->shadow_ptes[0];
                }
                BUG_ON(!spte);
@@ -1218,7 +1218,7 @@ static int alloc_mmu_pages(struct kvm_vcpu *vcpu)
                INIT_LIST_HEAD(&page_header->link);
                if ((page = alloc_page(GFP_KERNEL)) == NULL)
                        goto error_1;
-               page->private = (unsigned long)page_header;
+               set_page_private(page, (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);
index b6b90e9e13013eeab29adc4bc30c5cb1657f5732..f3bcee90465141b2ba767248e6c52d8b8af8f916 100644 (file)
@@ -128,8 +128,10 @@ static int FNAME(walk_addr)(struct guest_walker *walker,
                        goto access_error;
 #endif
 
-               if (!(*ptep & PT_ACCESSED_MASK))
-                       *ptep |= PT_ACCESSED_MASK;      /* avoid rmw */
+               if (!(*ptep & PT_ACCESSED_MASK)) {
+                       mark_page_dirty(vcpu->kvm, table_gfn);
+                       *ptep |= PT_ACCESSED_MASK;
+               }
 
                if (walker->level == PT_PAGE_TABLE_LEVEL) {
                        walker->gfn = (*ptep & PT_BASE_ADDR_MASK)
@@ -185,6 +187,12 @@ static void FNAME(release_walker)(struct guest_walker *walker)
                kunmap_atomic(walker->table, KM_USER0);
 }
 
+static void FNAME(mark_pagetable_dirty)(struct kvm *kvm,
+                                       struct guest_walker *walker)
+{
+       mark_page_dirty(kvm, walker->table_gfn[walker->level - 1]);
+}
+
 static void FNAME(set_pte)(struct kvm_vcpu *vcpu, u64 guest_pte,
                           u64 *shadow_pte, u64 access_bits, gfn_t gfn)
 {
@@ -348,12 +356,15 @@ static int FNAME(fix_write_pf)(struct kvm_vcpu *vcpu,
        } else if (kvm_mmu_lookup_page(vcpu, gfn)) {
                pgprintk("%s: found shadow page for %lx, marking ro\n",
                         __FUNCTION__, gfn);
+               mark_page_dirty(vcpu->kvm, gfn);
+               FNAME(mark_pagetable_dirty)(vcpu->kvm, walker);
                *guest_ent |= PT_DIRTY_MASK;
                *write_pt = 1;
                return 0;
        }
        mark_page_dirty(vcpu->kvm, gfn);
        *shadow_ent |= PT_WRITABLE_MASK;
+       FNAME(mark_pagetable_dirty)(vcpu->kvm, walker);
        *guest_ent |= PT_DIRTY_MASK;
        rmap_add(vcpu, shadow_ent);
 
@@ -430,9 +441,8 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
        /*
         * mmio: emulate if accessible, otherwise its a guest fault.
         */
-       if (is_io_pte(*shadow_pte)) {
+       if (is_io_pte(*shadow_pte))
                return 1;
-       }
 
        ++kvm_stat.pf_fixed;
        kvm_mmu_audit(vcpu, "post page fault (fixed)");
index 83da4ea150a335c3543315a7adef7855b1f047ce..3d8ea7ac2ecc308cded7d2b5f78473ff64f29a0f 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/kernel.h>
 #include <linux/vmalloc.h>
 #include <linux/highmem.h>
 #include <linux/profile.h>
@@ -75,7 +76,7 @@ struct svm_init_data {
 
 static u32 msrpm_ranges[] = {0, 0xc0000000, 0xc0010000};
 
-#define NUM_MSR_MAPS (sizeof(msrpm_ranges) / sizeof(*msrpm_ranges))
+#define NUM_MSR_MAPS ARRAY_SIZE(msrpm_ranges)
 #define MSRS_RANGE_SIZE 2048
 #define MSRS_IN_RANGE (MSRS_RANGE_SIZE * 8 / 2)
 
@@ -485,6 +486,7 @@ static void init_vmcb(struct vmcb *vmcb)
 
        control->intercept =    (1ULL << INTERCEPT_INTR) |
                                (1ULL << INTERCEPT_NMI) |
+                               (1ULL << INTERCEPT_SMI) |
                /*
                 * selective cr0 intercept bug?
                 *      0:   0f 22 d8                mov    %eax,%cr3
@@ -553,7 +555,7 @@ static void init_vmcb(struct vmcb *vmcb)
         * 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->cr0 = 0x00000010 | CR0_PG_MASK | CR0_WP_MASK;
        save->cr4 = CR4_PAE_MASK;
        /* rdx = ?? */
 }
@@ -598,10 +600,9 @@ static void svm_free_vcpu(struct kvm_vcpu *vcpu)
        kfree(vcpu->svm);
 }
 
-static struct kvm_vcpu *svm_vcpu_load(struct kvm_vcpu *vcpu)
+static void svm_vcpu_load(struct kvm_vcpu *vcpu)
 {
        get_cpu();
-       return vcpu;
 }
 
 static void svm_vcpu_put(struct kvm_vcpu *vcpu)
@@ -1042,22 +1043,22 @@ static int io_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 
                addr_mask = io_adress(vcpu, _in, &kvm_run->io.address);
                if (!addr_mask) {
-                       printk(KERN_DEBUG "%s: get io address failed\n", __FUNCTION__);
+                       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.count
+                               = vcpu->regs[VCPU_REGS_RCX] & addr_mask;
                        kvm_run->io.string_down = (vcpu->svm->vmcb->save.rflags
                                                   & X86_EFLAGS_DF) != 0;
                }
-       } else {
+       } 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;
@@ -1075,6 +1076,12 @@ static int halt_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        return 0;
 }
 
+static int vmmcall_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       vcpu->svm->vmcb->save.rip += 3;
+       return kvm_hypercall(vcpu, kvm_run);
+}
+
 static int invalid_op_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        inject_ud(vcpu);
@@ -1275,7 +1282,7 @@ static int (*svm_exit_handlers[])(struct kvm_vcpu *vcpu,
        [SVM_EXIT_TASK_SWITCH]                  = task_switch_interception,
        [SVM_EXIT_SHUTDOWN]                     = shutdown_interception,
        [SVM_EXIT_VMRUN]                        = invalid_op_interception,
-       [SVM_EXIT_VMMCALL]                      = invalid_op_interception,
+       [SVM_EXIT_VMMCALL]                      = vmmcall_interception,
        [SVM_EXIT_VMLOAD]                       = invalid_op_interception,
        [SVM_EXIT_VMSAVE]                       = invalid_op_interception,
        [SVM_EXIT_STGI]                         = invalid_op_interception,
@@ -1297,7 +1304,7 @@ static int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                       __FUNCTION__, vcpu->svm->vmcb->control.exit_int_info,
                       exit_code);
 
-       if (exit_code >= sizeof(svm_exit_handlers) / sizeof(*svm_exit_handlers)
+       if (exit_code >= ARRAY_SIZE(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",
@@ -1668,6 +1675,18 @@ static int is_disabled(void)
        return 0;
 }
 
+static void
+svm_patch_hypercall(struct kvm_vcpu *vcpu, unsigned char *hypercall)
+{
+       /*
+        * Patch in the VMMCALL instruction:
+        */
+       hypercall[0] = 0x0f;
+       hypercall[1] = 0x01;
+       hypercall[2] = 0xd9;
+       hypercall[3] = 0xc3;
+}
+
 static struct kvm_arch_ops svm_arch_ops = {
        .cpu_has_kvm_support = has_svm,
        .disabled_by_bios = is_disabled,
@@ -1716,6 +1735,7 @@ static struct kvm_arch_ops svm_arch_ops = {
        .run = svm_vcpu_run,
        .skip_emulated_instruction = skip_emulated_instruction,
        .vcpu_setup = svm_vcpu_setup,
+       .patch_hypercall = svm_patch_hypercall,
 };
 
 static int __init svm_init(void)
index fd4e91734388204a08e52d05fe0900920a48e866..c07178e61122c7ed9534f598100ef61a7c3b8008 100644 (file)
@@ -19,6 +19,7 @@
 #include "vmx.h"
 #include "kvm_vmx.h"
 #include <linux/module.h>
+#include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/profile.h>
@@ -27,7 +28,6 @@
 
 #include "segment_descriptor.h"
 
-
 MODULE_AUTHOR("Qumranet");
 MODULE_LICENSE("GPL");
 
@@ -76,7 +76,7 @@ static const u32 vmx_msr_index[] = {
 #endif
        MSR_EFER, MSR_K6_STAR,
 };
-#define NR_VMX_MSR (sizeof(vmx_msr_index) / sizeof(*vmx_msr_index))
+#define NR_VMX_MSR ARRAY_SIZE(vmx_msr_index)
 
 static inline int is_page_fault(u32 intr_info)
 {
@@ -204,7 +204,7 @@ static void vmcs_write64(unsigned long field, u64 value)
  * 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)
+static void vmx_vcpu_load(struct kvm_vcpu *vcpu)
 {
        u64 phys_addr = __pa(vcpu->vmcs);
        int cpu;
@@ -242,7 +242,6 @@ static struct kvm_vcpu *vmx_vcpu_load(struct kvm_vcpu *vcpu)
                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)
@@ -418,10 +417,9 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
        case MSR_IA32_SYSENTER_ESP:
                vmcs_write32(GUEST_SYSENTER_ESP, data);
                break;
-       case MSR_IA32_TIME_STAMP_COUNTER: {
+       case MSR_IA32_TIME_STAMP_COUNTER:
                guest_write_tsc(data);
                break;
-       }
        default:
                msr = find_msr_entry(vcpu, msr_index);
                if (msr) {
@@ -793,6 +791,9 @@ static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
  */
 static void vmx_set_cr0_no_modeswitch(struct kvm_vcpu *vcpu, unsigned long cr0)
 {
+       if (!vcpu->rmode.active && !(cr0 & CR0_PE_MASK))
+               enter_rmode(vcpu);
+
        vcpu->rmode.active = ((cr0 & CR0_PE_MASK) == 0);
        update_exception_bitmap(vcpu);
        vmcs_writel(CR0_READ_SHADOW, cr0);
@@ -1467,6 +1468,18 @@ static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        return 0;
 }
 
+static void
+vmx_patch_hypercall(struct kvm_vcpu *vcpu, unsigned char *hypercall)
+{
+       /*
+        * Patch in the VMCALL instruction:
+        */
+       hypercall[0] = 0x0f;
+       hypercall[1] = 0x01;
+       hypercall[2] = 0xc1;
+       hypercall[3] = 0xc3;
+}
+
 static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        u64 exit_qualification;
@@ -1643,6 +1656,12 @@ static int handle_halt(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        return 0;
 }
 
+static int handle_vmcall(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       vmcs_writel(GUEST_RIP, vmcs_readl(GUEST_RIP)+3);
+       return kvm_hypercall(vcpu, kvm_run);
+}
+
 /*
  * 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
@@ -1661,6 +1680,7 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu,
        [EXIT_REASON_MSR_WRITE]               = handle_wrmsr,
        [EXIT_REASON_PENDING_INTERRUPT]       = handle_interrupt_window,
        [EXIT_REASON_HLT]                     = handle_halt,
+       [EXIT_REASON_VMCALL]                  = handle_vmcall,
 };
 
 static const int kvm_vmx_max_exit_handlers =
@@ -2062,6 +2082,7 @@ static struct kvm_arch_ops vmx_arch_ops = {
        .run = vmx_vcpu_run,
        .skip_emulated_instruction = skip_emulated_instruction,
        .vcpu_setup = vmx_vcpu_setup,
+       .patch_hypercall = vmx_patch_hypercall,
 };
 
 static int __init vmx_init(void)
index 7399ba791116d882ecceae66fa7e9535cfea1404..80acd08f0e97bd3b9cf940e5a25ccb2d31fce312 100644 (file)
@@ -82,6 +82,18 @@ config LEDS_WRAP
        help
          This option enables support for the PCEngines WRAP programmable LEDs.
 
+config LEDS_H1940
+       tristate "LED Support for iPAQ H1940 device"
+       depends LEDS_CLASS && ARCH_H1940
+       help
+         This option enables support for the LEDs on the h1940.
+
+config LEDS_COBALT
+       tristate "LED Support for Cobalt Server front LED"
+       depends on LEDS_CLASS && MIPS_COBALT
+       help
+         This option enables support for the front LED on Cobalt Server
+
 comment "LED Triggers"
 
 config LEDS_TRIGGERS
index 500de3dc962adedcb2576e543754f6d54d439988..aa2c18efa5b2f150dffbfbf81a96669bb9d4fb45 100644 (file)
@@ -14,6 +14,8 @@ obj-$(CONFIG_LEDS_S3C24XX)            += leds-s3c24xx.o
 obj-$(CONFIG_LEDS_AMS_DELTA)           += leds-ams-delta.o
 obj-$(CONFIG_LEDS_NET48XX)             += leds-net48xx.o
 obj-$(CONFIG_LEDS_WRAP)                        += leds-wrap.o
+obj-$(CONFIG_LEDS_H1940)               += leds-h1940.o
+obj-$(CONFIG_LEDS_COBALT)              += leds-cobalt.o
 
 # LED Triggers
 obj-$(CONFIG_LEDS_TRIGGER_TIMER)       += ledtrig-timer.o
diff --git a/drivers/leds/leds-cobalt.c b/drivers/leds/leds-cobalt.c
new file mode 100644 (file)
index 0000000..d16439c
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2006 - Florian Fainelli <florian@openwrt.org>
+ *
+ * Control the Cobalt Qube/RaQ front LED
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/leds.h>
+#include <asm/mach-cobalt/cobalt.h>
+
+static void cobalt_led_set(struct led_classdev *led_cdev, enum led_brightness brightness)
+{
+       if (brightness)
+               COBALT_LED_PORT = COBALT_LED_BAR_LEFT | COBALT_LED_BAR_RIGHT;
+       else
+               COBALT_LED_PORT = 0;
+}
+
+static struct led_classdev cobalt_led = {
+       .name = "cobalt-front-led",
+       .brightness_set = cobalt_led_set,
+       .default_trigger = "ide-disk",
+};
+
+static int __init cobalt_led_init(void)
+{
+       return led_classdev_register(NULL, &cobalt_led);
+}
+
+static void __exit cobalt_led_exit(void)
+{
+       led_classdev_unregister(&cobalt_led);
+}
+
+module_init(cobalt_led_init);
+module_exit(cobalt_led_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Front LED support for Cobalt Server");
+MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
diff --git a/drivers/leds/leds-h1940.c b/drivers/leds/leds-h1940.c
new file mode 100644 (file)
index 0000000..1d49d2a
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * drivers/leds/h1940-leds.c
+ * Copyright (c) Arnaud Patard <arnaud.patard@rtp-net.org>
+ *
+ * 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.
+ *
+ * H1940 leds driver
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/leds.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/hardware.h>
+#include <asm/arch/h1940-latch.h>
+
+/*
+ * Green led.
+ */
+void h1940_greenled_set(struct led_classdev *led_dev, enum led_brightness value)
+{
+       switch (value) {
+               case LED_HALF:
+                       h1940_latch_control(0,H1940_LATCH_LED_FLASH);
+                       s3c2410_gpio_setpin(S3C2410_GPA7,1);
+                       break;
+               case LED_FULL:
+                       h1940_latch_control(0,H1940_LATCH_LED_GREEN);
+                       s3c2410_gpio_setpin(S3C2410_GPA7,1);
+                       break;
+               default:
+               case LED_OFF:
+                       h1940_latch_control(H1940_LATCH_LED_FLASH,0);
+                       h1940_latch_control(H1940_LATCH_LED_GREEN,0);
+                       s3c2410_gpio_setpin(S3C2410_GPA7,0);
+                       break;
+       }
+}
+
+static struct led_classdev h1940_greenled = {
+       .name                   = "h1940:green",
+       .brightness_set         = h1940_greenled_set,
+       .default_trigger        = "h1940-charger",
+};
+
+/*
+ * Red led.
+ */
+void h1940_redled_set(struct led_classdev *led_dev, enum led_brightness value)
+{
+       switch (value) {
+               case LED_HALF:
+                       h1940_latch_control(0,H1940_LATCH_LED_FLASH);
+                       s3c2410_gpio_setpin(S3C2410_GPA1,1);
+                       break;
+               case LED_FULL:
+                       h1940_latch_control(0,H1940_LATCH_LED_RED);
+                       s3c2410_gpio_setpin(S3C2410_GPA1,1);
+                       break;
+               default:
+               case LED_OFF:
+                       h1940_latch_control(H1940_LATCH_LED_FLASH,0);
+                       h1940_latch_control(H1940_LATCH_LED_RED,0);
+                       s3c2410_gpio_setpin(S3C2410_GPA1,0);
+                       break;
+       }
+}
+
+static struct led_classdev h1940_redled = {
+       .name                   = "h1940:red",
+       .brightness_set         = h1940_redled_set,
+       .default_trigger        = "h1940-charger",
+};
+
+/*
+ * Blue led.
+ * (it can only be blue flashing led)
+ */
+void h1940_blueled_set(struct led_classdev *led_dev, enum led_brightness value)
+{
+       if (value) {
+               /* flashing Blue */
+               h1940_latch_control(0,H1940_LATCH_LED_FLASH);
+               s3c2410_gpio_setpin(S3C2410_GPA3,1);
+       } else {
+               h1940_latch_control(H1940_LATCH_LED_FLASH,0);
+               s3c2410_gpio_setpin(S3C2410_GPA3,0);
+       }
+
+}
+
+static struct led_classdev h1940_blueled = {
+       .name                   = "h1940:blue",
+       .brightness_set         = h1940_blueled_set,
+       .default_trigger        = "h1940-bluetooth",
+};
+
+static int __init h1940leds_probe(struct platform_device *pdev)
+{
+       int ret;
+
+       ret = led_classdev_register(&pdev->dev, &h1940_greenled);
+       if (ret)
+               goto err_green;
+
+       ret = led_classdev_register(&pdev->dev, &h1940_redled);
+       if (ret)
+               goto err_red;
+
+       ret = led_classdev_register(&pdev->dev, &h1940_blueled);
+       if (ret)
+               goto err_blue;
+
+       return 0;
+
+err_blue:
+       led_classdev_unregister(&h1940_redled);
+err_red:
+       led_classdev_unregister(&h1940_greenled);
+err_green:
+       return ret;
+}
+
+static int h1940leds_remove(struct platform_device *pdev)
+{
+       led_classdev_unregister(&h1940_greenled);
+       led_classdev_unregister(&h1940_redled);
+       led_classdev_unregister(&h1940_blueled);
+       return 0;
+}
+
+
+static struct platform_driver h1940leds_driver = {
+       .driver         = {
+               .name   = "h1940-leds",
+       },
+       .probe          = h1940leds_probe,
+       .remove         = h1940leds_remove,
+};
+
+
+static int __init h1940leds_init(void)
+{
+       return platform_driver_register(&h1940leds_driver);
+}
+
+static void __exit h1940leds_exit(void)
+{
+       platform_driver_unregister(&h1940leds_driver);
+}
+
+module_init(h1940leds_init);
+module_exit(h1940leds_exit);
+
+MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
+MODULE_DESCRIPTION("LED driver for the iPAQ H1940");
+MODULE_LICENSE("GPL");
index 801a974342f919bc6d2e515f7e58919351cf6c77..7e27071746e4582c54ae6b622b2160f36782778e 100644 (file)
@@ -15,7 +15,7 @@
 
 #define MAX_PMU_LEVEL 0xFF
 
-static struct backlight_properties pmu_backlight_data;
+static struct backlight_ops pmu_backlight_data;
 static DEFINE_SPINLOCK(pmu_backlight_lock);
 static int sleeping;
 static u8 bl_curve[FB_BACKLIGHT_LEVELS];
@@ -72,7 +72,7 @@ static int pmu_backlight_update_status(struct backlight_device *bd)
 {
        struct adb_request req;
        unsigned long flags;
-       int level = bd->props->brightness;
+       int level = bd->props.brightness;
 
        spin_lock_irqsave(&pmu_backlight_lock, flags);
 
@@ -80,8 +80,8 @@ static int pmu_backlight_update_status(struct backlight_device *bd)
        if (sleeping)
                goto out;
 
-       if (bd->props->power != FB_BLANK_UNBLANK ||
-           bd->props->fb_blank != FB_BLANK_UNBLANK)
+       if (bd->props.power != FB_BLANK_UNBLANK ||
+           bd->props.fb_blank != FB_BLANK_UNBLANK)
                level = 0;
 
        if (level > 0) {
@@ -107,14 +107,13 @@ out:
 
 static int pmu_backlight_get_brightness(struct backlight_device *bd)
 {
-       return bd->props->brightness;
+       return bd->props.brightness;
 }
 
-static struct backlight_properties pmu_backlight_data = {
-       .owner          = THIS_MODULE,
+static struct backlight_ops pmu_backlight_data = {
        .get_brightness = pmu_backlight_get_brightness,
        .update_status  = pmu_backlight_update_status,
-       .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
+
 };
 
 #ifdef CONFIG_PM
@@ -152,9 +151,10 @@ void __init pmu_backlight_init()
                printk("pmubl: Backlight registration failed\n");
                goto error;
        }
+       bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
        pmu_backlight_init_curve(0x7F, 0x46, 0x0E);
 
-       level = pmu_backlight_data.max_brightness;
+       level = bd->props.max_brightness;
 
        if (autosave) {
                /* read autosaved value if available */
@@ -164,19 +164,12 @@ void __init pmu_backlight_init()
 
                level = pmu_backlight_curve_lookup(
                                (req.reply[0] >> 4) *
-                               pmu_backlight_data.max_brightness / 15);
+                               bd->props.max_brightness / 15);
        }
 
-       down(&bd->sem);
-       bd->props->brightness = level;
-       bd->props->power = FB_BLANK_UNBLANK;
-       bd->props->update_status(bd);
-       up(&bd->sem);
-
-       mutex_lock(&pmac_backlight_mutex);
-       if (!pmac_backlight)
-               pmac_backlight = bd;
-       mutex_unlock(&pmac_backlight_mutex);
+       bd->props.brightness = level;
+       bd->props.power = FB_BLANK_UNBLANK;
+       backlight_update_status(bd);
 
        printk("pmubl: Backlight initialized (%s)\n", name);
 
index 05febfd9f0712d0875b52dcb4f2c07cd15ff7c8f..6c06e825cff5af8f070ff9d370f987da7c64f34b 100644 (file)
@@ -1296,27 +1296,17 @@ static struct super_type super_types[] = {
                .sync_super     = super_1_sync,
        },
 };
-       
-static mdk_rdev_t * match_dev_unit(mddev_t *mddev, mdk_rdev_t *dev)
-{
-       struct list_head *tmp;
-       mdk_rdev_t *rdev;
-
-       ITERATE_RDEV(mddev,rdev,tmp)
-               if (rdev->bdev->bd_contains == dev->bdev->bd_contains)
-                       return rdev;
-
-       return NULL;
-}
 
 static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2)
 {
-       struct list_head *tmp;
-       mdk_rdev_t *rdev;
+       struct list_head *tmp, *tmp2;
+       mdk_rdev_t *rdev, *rdev2;
 
        ITERATE_RDEV(mddev1,rdev,tmp)
-               if (match_dev_unit(mddev2, rdev))
-                       return 1;
+               ITERATE_RDEV(mddev2, rdev2, tmp2)
+                       if (rdev->bdev->bd_contains ==
+                           rdev2->bdev->bd_contains)
+                               return 1;
 
        return 0;
 }
@@ -1325,8 +1315,7 @@ static LIST_HEAD(pending_raid_disks);
 
 static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
 {
-       mdk_rdev_t *same_pdev;
-       char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
+       char b[BDEVNAME_SIZE];
        struct kobject *ko;
        char *s;
 
@@ -1342,14 +1331,6 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
                else
                        mddev->size = rdev->size;
        }
-       same_pdev = match_dev_unit(mddev, rdev);
-       if (same_pdev)
-               printk(KERN_WARNING
-                       "%s: WARNING: %s appears to be on the same physical"
-                       " disk as %s. True\n     protection against single-disk"
-                       " failure might be compromised.\n",
-                       mdname(mddev), bdevname(rdev->bdev,b),
-                       bdevname(same_pdev->bdev,b2));
 
        /* Verify rdev->desc_nr is unique.
         * If it is -1, assign a free number, else
@@ -3109,6 +3090,36 @@ static int do_md_run(mddev_t * mddev)
                return -EINVAL;
        }
 
+       if (pers->sync_request) {
+               /* Warn if this is a potentially silly
+                * configuration.
+                */
+               char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
+               mdk_rdev_t *rdev2;
+               struct list_head *tmp2;
+               int warned = 0;
+               ITERATE_RDEV(mddev, rdev, tmp) {
+                       ITERATE_RDEV(mddev, rdev2, tmp2) {
+                               if (rdev < rdev2 &&
+                                   rdev->bdev->bd_contains ==
+                                   rdev2->bdev->bd_contains) {
+                                       printk(KERN_WARNING
+                                              "%s: WARNING: %s appears to be"
+                                              " on the same physical disk as"
+                                              " %s.\n",
+                                              mdname(mddev),
+                                              bdevname(rdev->bdev,b),
+                                              bdevname(rdev2->bdev,b2));
+                                       warned = 1;
+                               }
+                       }
+               }
+               if (warned)
+                       printk(KERN_WARNING
+                              "True protection against single-disk"
+                              " failure might be compromised.\n");
+       }
+
        mddev->recovery = 0;
        mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */
        mddev->barriers_work = 1;
@@ -3311,6 +3322,9 @@ static int do_md_stop(mddev_t * mddev, int mode)
                                set_disk_ro(disk, 0);
                        blk_queue_make_request(mddev->queue, md_fail_request);
                        mddev->pers->stop(mddev);
+                       mddev->queue->merge_bvec_fn = NULL;
+                       mddev->queue->unplug_fn = NULL;
+                       mddev->queue->issue_flush_fn = NULL;
                        if (mddev->pers->sync_request)
                                sysfs_remove_group(&mddev->kobj, &md_redundancy_group);
 
@@ -5343,6 +5357,44 @@ void md_do_sync(mddev_t *mddev)
 EXPORT_SYMBOL_GPL(md_do_sync);
 
 
+static int remove_and_add_spares(mddev_t *mddev)
+{
+       mdk_rdev_t *rdev;
+       struct list_head *rtmp;
+       int spares = 0;
+
+       ITERATE_RDEV(mddev,rdev,rtmp)
+               if (rdev->raid_disk >= 0 &&
+                   (test_bit(Faulty, &rdev->flags) ||
+                    ! test_bit(In_sync, &rdev->flags)) &&
+                   atomic_read(&rdev->nr_pending)==0) {
+                       if (mddev->pers->hot_remove_disk(
+                                   mddev, rdev->raid_disk)==0) {
+                               char nm[20];
+                               sprintf(nm,"rd%d", rdev->raid_disk);
+                               sysfs_remove_link(&mddev->kobj, nm);
+                               rdev->raid_disk = -1;
+                       }
+               }
+
+       if (mddev->degraded) {
+               ITERATE_RDEV(mddev,rdev,rtmp)
+                       if (rdev->raid_disk < 0
+                           && !test_bit(Faulty, &rdev->flags)) {
+                               rdev->recovery_offset = 0;
+                               if (mddev->pers->hot_add_disk(mddev,rdev)) {
+                                       char nm[20];
+                                       sprintf(nm, "rd%d", rdev->raid_disk);
+                                       sysfs_create_link(&mddev->kobj,
+                                                         &rdev->kobj, nm);
+                                       spares++;
+                                       md_new_event(mddev);
+                               } else
+                                       break;
+                       }
+       }
+       return spares;
+}
 /*
  * This routine is regularly called by all per-raid-array threads to
  * deal with generic issues like resync and super-block update.
@@ -5397,7 +5449,7 @@ void md_check_recovery(mddev_t *mddev)
                return;
 
        if (mddev_trylock(mddev)) {
-               int spares =0;
+               int spares = 0;
 
                spin_lock_irq(&mddev->write_lock);
                if (mddev->safemode && !atomic_read(&mddev->writes_pending) &&
@@ -5460,35 +5512,13 @@ void md_check_recovery(mddev_t *mddev)
                 * Spare are also removed and re-added, to allow
                 * the personality to fail the re-add.
                 */
-               ITERATE_RDEV(mddev,rdev,rtmp)
-                       if (rdev->raid_disk >= 0 &&
-                           (test_bit(Faulty, &rdev->flags) || ! test_bit(In_sync, &rdev->flags)) &&
-                           atomic_read(&rdev->nr_pending)==0) {
-                               if (mddev->pers->hot_remove_disk(mddev, rdev->raid_disk)==0) {
-                                       char nm[20];
-                                       sprintf(nm,"rd%d", rdev->raid_disk);
-                                       sysfs_remove_link(&mddev->kobj, nm);
-                                       rdev->raid_disk = -1;
-                               }
-                       }
-
-               if (mddev->degraded) {
-                       ITERATE_RDEV(mddev,rdev,rtmp)
-                               if (rdev->raid_disk < 0
-                                   && !test_bit(Faulty, &rdev->flags)) {
-                                       rdev->recovery_offset = 0;
-                                       if (mddev->pers->hot_add_disk(mddev,rdev)) {
-                                               char nm[20];
-                                               sprintf(nm, "rd%d", rdev->raid_disk);
-                                               sysfs_create_link(&mddev->kobj, &rdev->kobj, nm);
-                                               spares++;
-                                               md_new_event(mddev);
-                                       } else
-                                               break;
-                               }
-               }
 
-               if (spares) {
+               if (mddev->reshape_position != MaxSector) {
+                       if (mddev->pers->check_reshape(mddev) != 0)
+                               /* Cannot proceed */
+                               goto unlock;
+                       set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
+               } else if ((spares = remove_and_add_spares(mddev))) {
                        clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
                        clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
                } else if (mddev->recovery_cp < MaxSector) {
index a9401c017e3588f076411d83046c84b27495eab8..82249a69014f0295055d10d750d297ac8e4291c6 100644 (file)
@@ -429,7 +429,7 @@ static sector_t raid10_find_virt(conf_t *conf, sector_t sector, int dev)
                if (dev < 0)
                        dev += conf->raid_disks;
        } else {
-               while (sector > conf->stride) {
+               while (sector >= conf->stride) {
                        sector -= conf->stride;
                        if (dev < conf->near_copies)
                                dev += conf->raid_disks - conf->near_copies;
@@ -1801,6 +1801,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
                                                for (k=0; k<conf->copies; k++)
                                                        if (r10_bio->devs[k].devnum == i)
                                                                break;
+                                               BUG_ON(k == conf->copies);
                                                bio = r10_bio->devs[1].bio;
                                                bio->bi_next = biolist;
                                                biolist = bio;
@@ -2021,19 +2022,30 @@ static int run(mddev_t *mddev)
        if (!conf->tmppage)
                goto out_free_conf;
 
+       conf->mddev = mddev;
+       conf->raid_disks = mddev->raid_disks;
        conf->near_copies = nc;
        conf->far_copies = fc;
        conf->copies = nc*fc;
        conf->far_offset = fo;
        conf->chunk_mask = (sector_t)(mddev->chunk_size>>9)-1;
        conf->chunk_shift = ffz(~mddev->chunk_size) - 9;
+       size = mddev->size >> (conf->chunk_shift-1);
+       sector_div(size, fc);
+       size = size * conf->raid_disks;
+       sector_div(size, nc);
+       /* 'size' is now the number of chunks in the array */
+       /* calculate "used chunks per device" in 'stride' */
+       stride = size * conf->copies;
+       sector_div(stride, conf->raid_disks);
+       mddev->size = stride  << (conf->chunk_shift-1);
+
        if (fo)
-               conf->stride = 1 << conf->chunk_shift;
-       else {
-               stride = mddev->size >> (conf->chunk_shift-1);
+               stride = 1;
+       else
                sector_div(stride, fc);
-               conf->stride = stride << conf->chunk_shift;
-       }
+       conf->stride = stride << conf->chunk_shift;
+
        conf->r10bio_pool = mempool_create(NR_RAID10_BIOS, r10bio_pool_alloc,
                                                r10bio_pool_free, conf);
        if (!conf->r10bio_pool) {
@@ -2063,8 +2075,6 @@ static int run(mddev_t *mddev)
 
                disk->head_position = 0;
        }
-       conf->raid_disks = mddev->raid_disks;
-       conf->mddev = mddev;
        spin_lock_init(&conf->device_lock);
        INIT_LIST_HEAD(&conf->retry_list);
 
@@ -2106,16 +2116,8 @@ static int run(mddev_t *mddev)
        /*
         * Ok, everything is just fine now
         */
-       if (conf->far_offset) {
-               size = mddev->size >> (conf->chunk_shift-1);
-               size *= conf->raid_disks;
-               size <<= conf->chunk_shift;
-               sector_div(size, conf->far_copies);
-       } else
-               size = conf->stride * conf->raid_disks;
-       sector_div(size, conf->near_copies);
-       mddev->array_size = size/2;
-       mddev->resync_max_sectors = size;
+       mddev->array_size = size << (conf->chunk_shift-1);
+       mddev->resync_max_sectors = size << conf->chunk_shift;
 
        mddev->queue->unplug_fn = raid10_unplug;
        mddev->queue->issue_flush_fn = raid10_issue_flush;
index 11c3d7bfa797e8777c5b2bdf47d9ec6f68c7da74..54a1ad5eef42e5338c506894e71d03cc4ff36bcd 100644 (file)
@@ -1050,7 +1050,7 @@ static void compute_parity5(struct stripe_head *sh, int method)
 static void compute_parity6(struct stripe_head *sh, int method)
 {
        raid6_conf_t *conf = sh->raid_conf;
-       int i, pd_idx = sh->pd_idx, qd_idx, d0_idx, disks = conf->raid_disks, count;
+       int i, pd_idx = sh->pd_idx, qd_idx, d0_idx, disks = sh->disks, count;
        struct bio *chosen;
        /**** FIX THIS: This could be very bad if disks is close to 256 ****/
        void *ptrs[disks];
@@ -1131,8 +1131,7 @@ static void compute_parity6(struct stripe_head *sh, int method)
 /* Compute one missing block */
 static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero)
 {
-       raid6_conf_t *conf = sh->raid_conf;
-       int i, count, disks = conf->raid_disks;
+       int i, count, disks = sh->disks;
        void *ptr[MAX_XOR_BLOCKS], *p;
        int pd_idx = sh->pd_idx;
        int qd_idx = raid6_next_disk(pd_idx, disks);
@@ -1170,8 +1169,7 @@ static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero)
 /* Compute two missing blocks */
 static void compute_block_2(struct stripe_head *sh, int dd_idx1, int dd_idx2)
 {
-       raid6_conf_t *conf = sh->raid_conf;
-       int i, count, disks = conf->raid_disks;
+       int i, count, disks = sh->disks;
        int pd_idx = sh->pd_idx;
        int qd_idx = raid6_next_disk(pd_idx, disks);
        int d0_idx = raid6_next_disk(qd_idx, disks);
@@ -1887,11 +1885,11 @@ static void handle_stripe5(struct stripe_head *sh)
 static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
 {
        raid6_conf_t *conf = sh->raid_conf;
-       int disks = conf->raid_disks;
+       int disks = sh->disks;
        struct bio *return_bi= NULL;
        struct bio *bi;
        int i;
-       int syncing;
+       int syncing, expanding, expanded;
        int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0;
        int non_overwrite = 0;
        int failed_num[2] = {0, 0};
@@ -1909,6 +1907,8 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
        clear_bit(STRIPE_DELAYED, &sh->state);
 
        syncing = test_bit(STRIPE_SYNCING, &sh->state);
+       expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
+       expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
        /* Now to look around and see what can be done */
 
        rcu_read_lock();
@@ -2114,13 +2114,15 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
         * parity, or to satisfy requests
         * or to load a block that is being partially written.
         */
-       if (to_read || non_overwrite || (to_write && failed) || (syncing && (uptodate < disks))) {
+       if (to_read || non_overwrite || (to_write && failed) ||
+           (syncing && (uptodate < disks)) || expanding) {
                for (i=disks; i--;) {
                        dev = &sh->dev[i];
                        if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
                            (dev->toread ||
                             (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
                             syncing ||
+                            expanding ||
                             (failed >= 1 && (sh->dev[failed_num[0]].toread || to_write)) ||
                             (failed >= 2 && (sh->dev[failed_num[1]].toread || to_write))
                                    )
@@ -2355,6 +2357,79 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
                                }
                        }
                }
+
+       if (expanded && test_bit(STRIPE_EXPANDING, &sh->state)) {
+               /* Need to write out all blocks after computing P&Q */
+               sh->disks = conf->raid_disks;
+               sh->pd_idx = stripe_to_pdidx(sh->sector, conf,
+                                            conf->raid_disks);
+               compute_parity6(sh, RECONSTRUCT_WRITE);
+               for (i = conf->raid_disks ; i-- ;  ) {
+                       set_bit(R5_LOCKED, &sh->dev[i].flags);
+                       locked++;
+                       set_bit(R5_Wantwrite, &sh->dev[i].flags);
+               }
+               clear_bit(STRIPE_EXPANDING, &sh->state);
+       } else if (expanded) {
+               clear_bit(STRIPE_EXPAND_READY, &sh->state);
+               atomic_dec(&conf->reshape_stripes);
+               wake_up(&conf->wait_for_overlap);
+               md_done_sync(conf->mddev, STRIPE_SECTORS, 1);
+       }
+
+       if (expanding && locked == 0) {
+               /* We have read all the blocks in this stripe and now we need to
+                * copy some of them into a target stripe for expand.
+                */
+               clear_bit(STRIPE_EXPAND_SOURCE, &sh->state);
+               for (i = 0; i < sh->disks ; i++)
+                       if (i != pd_idx && i != qd_idx) {
+                               int dd_idx2, pd_idx2, j;
+                               struct stripe_head *sh2;
+
+                               sector_t bn = compute_blocknr(sh, i);
+                               sector_t s = raid5_compute_sector(
+                                       bn, conf->raid_disks,
+                                       conf->raid_disks - conf->max_degraded,
+                                       &dd_idx2, &pd_idx2, conf);
+                               sh2 = get_active_stripe(conf, s,
+                                                       conf->raid_disks,
+                                                      pd_idx2, 1);
+                               if (sh2 == NULL)
+                                       /* so for only the early blocks of
+                                        * this stripe have been requests.
+                                        * When later blocks get requests, we
+                                        * will try again
+                                        */
+                                       continue;
+                               if (!test_bit(STRIPE_EXPANDING, &sh2->state) ||
+                                   test_bit(R5_Expanded,
+                                            &sh2->dev[dd_idx2].flags)) {
+                                       /* must have already done this block */
+                                       release_stripe(sh2);
+                                       continue;
+                               }
+                               memcpy(page_address(sh2->dev[dd_idx2].page),
+                                      page_address(sh->dev[i].page),
+                                      STRIPE_SIZE);
+                               set_bit(R5_Expanded, &sh2->dev[dd_idx2].flags);
+                               set_bit(R5_UPTODATE, &sh2->dev[dd_idx2].flags);
+                               for (j = 0 ; j < conf->raid_disks ; j++)
+                                       if (j != sh2->pd_idx &&
+                                           j != raid6_next_disk(sh2->pd_idx,
+                                                          sh2->disks) &&
+                                           !test_bit(R5_Expanded,
+                                                     &sh2->dev[j].flags))
+                                               break;
+                               if (j == conf->raid_disks) {
+                                       set_bit(STRIPE_EXPAND_READY,
+                                               &sh2->state);
+                                       set_bit(STRIPE_HANDLE, &sh2->state);
+                               }
+                               release_stripe(sh2);
+                       }
+       }
+
        spin_unlock(&sh->lock);
 
        while ((bi=return_bi)) {
@@ -2395,7 +2470,7 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
                rcu_read_unlock();
 
                if (rdev) {
-                       if (syncing)
+                       if (syncing || expanding || expanded)
                                md_sync_acct(rdev->bdev, STRIPE_SECTORS);
 
                        bi->bi_bdev = rdev->bdev;
@@ -2915,8 +2990,9 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
        struct stripe_head *sh;
        int pd_idx;
        sector_t first_sector, last_sector;
-       int raid_disks;
-       int data_disks;
+       int raid_disks = conf->previous_raid_disks;
+       int data_disks = raid_disks - conf->max_degraded;
+       int new_data_disks = conf->raid_disks - conf->max_degraded;
        int i;
        int dd_idx;
        sector_t writepos, safepos, gap;
@@ -2925,7 +3001,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
            conf->expand_progress != 0) {
                /* restarting in the middle, skip the initial sectors */
                sector_nr = conf->expand_progress;
-               sector_div(sector_nr, conf->raid_disks-1);
+               sector_div(sector_nr, new_data_disks);
                *skipped = 1;
                return sector_nr;
        }
@@ -2939,14 +3015,14 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
         * to after where expand_lo old_maps to
         */
        writepos = conf->expand_progress +
-               conf->chunk_size/512*(conf->raid_disks-1);
-       sector_div(writepos, conf->raid_disks-1);
+               conf->chunk_size/512*(new_data_disks);
+       sector_div(writepos, new_data_disks);
        safepos = conf->expand_lo;
-       sector_div(safepos, conf->previous_raid_disks-1);
+       sector_div(safepos, data_disks);
        gap = conf->expand_progress - conf->expand_lo;
 
        if (writepos >= safepos ||
-           gap > (conf->raid_disks-1)*3000*2 /*3Meg*/) {
+           gap > (new_data_disks)*3000*2 /*3Meg*/) {
                /* Cannot proceed until we've updated the superblock... */
                wait_event(conf->wait_for_overlap,
                           atomic_read(&conf->reshape_stripes)==0);
@@ -2976,6 +3052,9 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
                        sector_t s;
                        if (j == sh->pd_idx)
                                continue;
+                       if (conf->level == 6 &&
+                           j == raid6_next_disk(sh->pd_idx, sh->disks))
+                               continue;
                        s = compute_blocknr(sh, j);
                        if (s < (mddev->array_size<<1)) {
                                skipped = 1;
@@ -2992,28 +3071,27 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
                release_stripe(sh);
        }
        spin_lock_irq(&conf->device_lock);
-       conf->expand_progress = (sector_nr + i)*(conf->raid_disks-1);
+       conf->expand_progress = (sector_nr + i) * new_data_disks;
        spin_unlock_irq(&conf->device_lock);
        /* Ok, those stripe are ready. We can start scheduling
         * reads on the source stripes.
         * The source stripes are determined by mapping the first and last
         * block on the destination stripes.
         */
-       raid_disks = conf->previous_raid_disks;
-       data_disks = raid_disks - 1;
        first_sector =
-               raid5_compute_sector(sector_nr*(conf->raid_disks-1),
+               raid5_compute_sector(sector_nr*(new_data_disks),
                                     raid_disks, data_disks,
                                     &dd_idx, &pd_idx, conf);
        last_sector =
                raid5_compute_sector((sector_nr+conf->chunk_size/512)
-                                    *(conf->raid_disks-1) -1,
+                                    *(new_data_disks) -1,
                                     raid_disks, data_disks,
                                     &dd_idx, &pd_idx, conf);
        if (last_sector >= (mddev->size<<1))
                last_sector = (mddev->size<<1)-1;
        while (first_sector <= last_sector) {
-               pd_idx = stripe_to_pdidx(first_sector, conf, conf->previous_raid_disks);
+               pd_idx = stripe_to_pdidx(first_sector, conf,
+                                        conf->previous_raid_disks);
                sh = get_active_stripe(conf, first_sector,
                                       conf->previous_raid_disks, pd_idx, 0);
                set_bit(STRIPE_EXPAND_SOURCE, &sh->state);
@@ -3348,35 +3426,44 @@ static int run(mddev_t *mddev)
                 */
                sector_t here_new, here_old;
                int old_disks;
+               int max_degraded = (mddev->level == 5 ? 1 : 2);
 
                if (mddev->new_level != mddev->level ||
                    mddev->new_layout != mddev->layout ||
                    mddev->new_chunk != mddev->chunk_size) {
-                       printk(KERN_ERR "raid5: %s: unsupported reshape required - aborting.\n",
+                       printk(KERN_ERR "raid5: %s: unsupported reshape "
+                              "required - aborting.\n",
                               mdname(mddev));
                        return -EINVAL;
                }
                if (mddev->delta_disks <= 0) {
-                       printk(KERN_ERR "raid5: %s: unsupported reshape (reduce disks) required - aborting.\n",
+                       printk(KERN_ERR "raid5: %s: unsupported reshape "
+                              "(reduce disks) required - aborting.\n",
                               mdname(mddev));
                        return -EINVAL;
                }
                old_disks = mddev->raid_disks - mddev->delta_disks;
                /* reshape_position must be on a new-stripe boundary, and one
-                * further up in new geometry must map after here in old geometry.
+                * further up in new geometry must map after here in old
+                * geometry.
                 */
                here_new = mddev->reshape_position;
-               if (sector_div(here_new, (mddev->chunk_size>>9)*(mddev->raid_disks-1))) {
-                       printk(KERN_ERR "raid5: reshape_position not on a stripe boundary\n");
+               if (sector_div(here_new, (mddev->chunk_size>>9)*
+                              (mddev->raid_disks - max_degraded))) {
+                       printk(KERN_ERR "raid5: reshape_position not "
+                              "on a stripe boundary\n");
                        return -EINVAL;
                }
                /* here_new is the stripe we will write to */
                here_old = mddev->reshape_position;
-               sector_div(here_old, (mddev->chunk_size>>9)*(old_disks-1));
-               /* here_old is the first stripe that we might need to read from */
+               sector_div(here_old, (mddev->chunk_size>>9)*
+                          (old_disks-max_degraded));
+               /* here_old is the first stripe that we might need to read
+                * from */
                if (here_new >= here_old) {
                        /* Reading from the same stripe as writing to - bad */
-                       printk(KERN_ERR "raid5: reshape_position too early for auto-recovery - aborting.\n");
+                       printk(KERN_ERR "raid5: reshape_position too early for "
+                              "auto-recovery - aborting.\n");
                        return -EINVAL;
                }
                printk(KERN_INFO "raid5: reshape will continue\n");
@@ -3814,6 +3901,8 @@ static int raid5_check_reshape(mddev_t *mddev)
        if (err)
                return err;
 
+       if (mddev->degraded > conf->max_degraded)
+               return -EINVAL;
        /* looks like we might be able to manage this */
        return 0;
 }
@@ -3827,8 +3916,7 @@ static int raid5_start_reshape(mddev_t *mddev)
        int added_devices = 0;
        unsigned long flags;
 
-       if (mddev->degraded ||
-           test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
+       if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
                return -EBUSY;
 
        ITERATE_RDEV(mddev, rdev, rtmp)
@@ -3836,7 +3924,7 @@ static int raid5_start_reshape(mddev_t *mddev)
                    !test_bit(Faulty, &rdev->flags))
                        spares++;
 
-       if (spares < mddev->delta_disks-1)
+       if (spares - mddev->degraded < mddev->delta_disks - conf->max_degraded)
                /* Not enough devices even to make a degraded array
                 * of that size
                 */
@@ -3899,7 +3987,8 @@ static void end_reshape(raid5_conf_t *conf)
        struct block_device *bdev;
 
        if (!test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) {
-               conf->mddev->array_size = conf->mddev->size * (conf->raid_disks-1);
+               conf->mddev->array_size = conf->mddev->size *
+                       (conf->raid_disks - conf->max_degraded);
                set_capacity(conf->mddev->gendisk, conf->mddev->array_size << 1);
                conf->mddev->changed = 1;
 
@@ -3972,6 +4061,10 @@ static struct mdk_personality raid6_personality =
        .spare_active   = raid5_spare_active,
        .sync_request   = sync_request,
        .resize         = raid5_resize,
+#ifdef CONFIG_MD_RAID5_RESHAPE
+       .check_reshape  = raid5_check_reshape,
+       .start_reshape  = raid5_start_reshape,
+#endif
        .quiesce        = raid5_quiesce,
 };
 static struct mdk_personality raid5_personality =
index 359157aaf9e0c2479dc58b12c99b7ebee2ece238..6181a5a3365a198d3aad83b52f6c7e09a4d5aad3 100644 (file)
@@ -30,14 +30,8 @@ const struct raid6_mmx_constants {
 
 static int raid6_have_mmx(void)
 {
-#ifdef __KERNEL__
        /* Not really "boot_cpu" but "all_cpus" */
        return boot_cpu_has(X86_FEATURE_MMX);
-#else
-       /* User space test code */
-       u32 features = cpuid_features();
-       return ( (features & (1<<23)) == (1<<23) );
-#endif
 }
 
 /*
@@ -48,13 +42,12 @@ static void raid6_mmx1_gen_syndrome(int disks, size_t bytes, void **ptrs)
        u8 **dptr = (u8 **)ptrs;
        u8 *p, *q;
        int d, z, z0;
-       raid6_mmx_save_t sa;
 
        z0 = disks - 3;         /* Highest data disk */
        p = dptr[z0+1];         /* XOR parity */
        q = dptr[z0+2];         /* RS syndrome */
 
-       raid6_before_mmx(&sa);
+       kernel_fpu_begin();
 
        asm volatile("movq %0,%%mm0" : : "m" (raid6_mmx_constants.x1d));
        asm volatile("pxor %mm5,%mm5"); /* Zero temp */
@@ -78,7 +71,7 @@ static void raid6_mmx1_gen_syndrome(int disks, size_t bytes, void **ptrs)
                asm volatile("pxor %mm4,%mm4");
        }
 
-       raid6_after_mmx(&sa);
+       kernel_fpu_end();
 }
 
 const struct raid6_calls raid6_mmxx1 = {
@@ -96,13 +89,12 @@ static void raid6_mmx2_gen_syndrome(int disks, size_t bytes, void **ptrs)
        u8 **dptr = (u8 **)ptrs;
        u8 *p, *q;
        int d, z, z0;
-       raid6_mmx_save_t sa;
 
        z0 = disks - 3;         /* Highest data disk */
        p = dptr[z0+1];         /* XOR parity */
        q = dptr[z0+2];         /* RS syndrome */
 
-       raid6_before_mmx(&sa);
+       kernel_fpu_begin();
 
        asm volatile("movq %0,%%mm0" : : "m" (raid6_mmx_constants.x1d));
        asm volatile("pxor %mm5,%mm5"); /* Zero temp */
@@ -137,7 +129,7 @@ static void raid6_mmx2_gen_syndrome(int disks, size_t bytes, void **ptrs)
                asm volatile("movq %%mm6,%0" : "=m" (q[d+8]));
        }
 
-       raid6_after_mmx(&sa);
+       kernel_fpu_end();
 }
 
 const struct raid6_calls raid6_mmxx2 = {
index f7e7859f71aa33acc7cd74a2b4fe91638ef438cd..f0a1ba8f40ba90c6b59fdc69073c4bb997b425b4 100644 (file)
@@ -33,16 +33,10 @@ extern const struct raid6_mmx_constants {
 
 static int raid6_have_sse1_or_mmxext(void)
 {
-#ifdef __KERNEL__
        /* Not really boot_cpu but "all_cpus" */
        return boot_cpu_has(X86_FEATURE_MMX) &&
                (boot_cpu_has(X86_FEATURE_XMM) ||
                 boot_cpu_has(X86_FEATURE_MMXEXT));
-#else
-       /* User space test code - this incorrectly breaks on some Athlons */
-       u32 features = cpuid_features();
-       return ( (features & (5<<23)) == (5<<23) );
-#endif
 }
 
 /*
@@ -53,14 +47,12 @@ static void raid6_sse11_gen_syndrome(int disks, size_t bytes, void **ptrs)
        u8 **dptr = (u8 **)ptrs;
        u8 *p, *q;
        int d, z, z0;
-       raid6_mmx_save_t sa;
 
        z0 = disks - 3;         /* Highest data disk */
        p = dptr[z0+1];         /* XOR parity */
        q = dptr[z0+2];         /* RS syndrome */
 
-       /* This is really MMX code, not SSE */
-       raid6_before_mmx(&sa);
+       kernel_fpu_begin();
 
        asm volatile("movq %0,%%mm0" : : "m" (raid6_mmx_constants.x1d));
        asm volatile("pxor %mm5,%mm5"); /* Zero temp */
@@ -94,8 +86,8 @@ static void raid6_sse11_gen_syndrome(int disks, size_t bytes, void **ptrs)
                asm volatile("movntq %%mm4,%0" : "=m" (q[d]));
        }
 
-       raid6_after_mmx(&sa);
        asm volatile("sfence" : : : "memory");
+       kernel_fpu_end();
 }
 
 const struct raid6_calls raid6_sse1x1 = {
@@ -113,13 +105,12 @@ static void raid6_sse12_gen_syndrome(int disks, size_t bytes, void **ptrs)
        u8 **dptr = (u8 **)ptrs;
        u8 *p, *q;
        int d, z, z0;
-       raid6_mmx_save_t sa;
 
        z0 = disks - 3;         /* Highest data disk */
        p = dptr[z0+1];         /* XOR parity */
        q = dptr[z0+2];         /* RS syndrome */
 
-       raid6_before_mmx(&sa);
+       kernel_fpu_begin();
 
        asm volatile("movq %0,%%mm0" : : "m" (raid6_mmx_constants.x1d));
        asm volatile("pxor %mm5,%mm5"); /* Zero temp */
@@ -157,8 +148,8 @@ static void raid6_sse12_gen_syndrome(int disks, size_t bytes, void **ptrs)
                asm volatile("movntq %%mm6,%0" : "=m" (q[d+8]));
        }
 
-       raid6_after_mmx(&sa);
        asm volatile("sfence" : :: "memory");
+       kernel_fpu_end();
 }
 
 const struct raid6_calls raid6_sse1x2 = {
index b3aa7fe0877e8d8a94a9923b0885e4aa9eeb9b11..0f019762a7c3cba42cba1ea68a99459465f17223 100644 (file)
@@ -30,17 +30,11 @@ static const struct raid6_sse_constants {
 
 static int raid6_have_sse2(void)
 {
-#ifdef __KERNEL__
        /* Not really boot_cpu but "all_cpus" */
        return boot_cpu_has(X86_FEATURE_MMX) &&
                boot_cpu_has(X86_FEATURE_FXSR) &&
                boot_cpu_has(X86_FEATURE_XMM) &&
                boot_cpu_has(X86_FEATURE_XMM2);
-#else
-       /* User space test code */
-       u32 features = cpuid_features();
-       return ( (features & (15<<23)) == (15<<23) );
-#endif
 }
 
 /*
@@ -51,13 +45,12 @@ static void raid6_sse21_gen_syndrome(int disks, size_t bytes, void **ptrs)
        u8 **dptr = (u8 **)ptrs;
        u8 *p, *q;
        int d, z, z0;
-       raid6_sse_save_t sa;
 
        z0 = disks - 3;         /* Highest data disk */
        p = dptr[z0+1];         /* XOR parity */
        q = dptr[z0+2];         /* RS syndrome */
 
-       raid6_before_sse2(&sa);
+       kernel_fpu_begin();
 
        asm volatile("movdqa %0,%%xmm0" : : "m" (raid6_sse_constants.x1d[0]));
        asm volatile("pxor %xmm5,%xmm5");       /* Zero temp */
@@ -93,8 +86,8 @@ static void raid6_sse21_gen_syndrome(int disks, size_t bytes, void **ptrs)
                asm volatile("pxor %xmm4,%xmm4");
        }
 
-       raid6_after_sse2(&sa);
        asm volatile("sfence" : : : "memory");
+       kernel_fpu_end();
 }
 
 const struct raid6_calls raid6_sse2x1 = {
@@ -112,13 +105,12 @@ static void raid6_sse22_gen_syndrome(int disks, size_t bytes, void **ptrs)
        u8 **dptr = (u8 **)ptrs;
        u8 *p, *q;
        int d, z, z0;
-       raid6_sse_save_t sa;
 
        z0 = disks - 3;         /* Highest data disk */
        p = dptr[z0+1];         /* XOR parity */
        q = dptr[z0+2];         /* RS syndrome */
 
-       raid6_before_sse2(&sa);
+       kernel_fpu_begin();
 
        asm volatile("movdqa %0,%%xmm0" : : "m" (raid6_sse_constants.x1d[0]));
        asm volatile("pxor %xmm5,%xmm5"); /* Zero temp */
@@ -156,8 +148,8 @@ static void raid6_sse22_gen_syndrome(int disks, size_t bytes, void **ptrs)
                asm volatile("movntdq %%xmm6,%0" : "=m" (q[d+16]));
        }
 
-       raid6_after_sse2(&sa);
        asm volatile("sfence" : : : "memory");
+       kernel_fpu_end();
 }
 
 const struct raid6_calls raid6_sse2x2 = {
@@ -179,13 +171,12 @@ static void raid6_sse24_gen_syndrome(int disks, size_t bytes, void **ptrs)
        u8 **dptr = (u8 **)ptrs;
        u8 *p, *q;
        int d, z, z0;
-       raid6_sse16_save_t sa;
 
        z0 = disks - 3;         /* Highest data disk */
        p = dptr[z0+1];         /* XOR parity */
        q = dptr[z0+2];         /* RS syndrome */
 
-       raid6_before_sse16(&sa);
+       kernel_fpu_begin();
 
        asm volatile("movdqa %0,%%xmm0" :: "m" (raid6_sse_constants.x1d[0]));
        asm volatile("pxor %xmm2,%xmm2");       /* P[0] */
@@ -256,8 +247,9 @@ static void raid6_sse24_gen_syndrome(int disks, size_t bytes, void **ptrs)
                asm volatile("movntdq %%xmm14,%0" : "=m" (q[d+48]));
                asm volatile("pxor %xmm14,%xmm14");
        }
+
        asm volatile("sfence" : : : "memory");
-       raid6_after_sse16(&sa);
+       kernel_fpu_end();
 }
 
 const struct raid6_calls raid6_sse2x4 = {
index 4cf20534fe442ea750b219f9f0de9c4520ff3f48..9111950414ff2d71c003591f2ad4c3503303de5c 100644 (file)
 
 #if defined(__i386__) || defined(__x86_64__)
 
-#ifdef __x86_64__
-
-typedef struct {
-       unsigned int fsave[27];
-       unsigned long cr0;
-} raid6_mmx_save_t __attribute__((aligned(16)));
-
-/* N.B.: For SSE we only save %xmm0-%xmm7 even for x86-64, since
-   the code doesn't know about the additional x86-64 registers */
-typedef struct {
-       unsigned int sarea[8*4+2];
-       unsigned long cr0;
-} raid6_sse_save_t __attribute__((aligned(16)));
-
-/* This is for x86-64-specific code which uses all 16 XMM registers */
-typedef struct {
-       unsigned int sarea[16*4+2];
-       unsigned long cr0;
-} raid6_sse16_save_t __attribute__((aligned(16)));
-
-/* On x86-64 the stack *SHOULD* be 16-byte aligned, but currently this
-   is buggy in the kernel and it's only 8-byte aligned in places, so
-   we need to do this anyway.  Sigh. */
-#define SAREA(x) ((unsigned int *)((((unsigned long)&(x)->sarea)+15) & ~15))
-
-#else /* __i386__ */
-
-typedef struct {
-       unsigned int fsave[27];
-       unsigned long cr0;
-} raid6_mmx_save_t;
-
-/* On i386, the stack is only 8-byte aligned, but SSE requires 16-byte
-   alignment.  The +3 is so we have the slack space to manually align
-   a properly-sized area correctly.  */
-typedef struct {
-       unsigned int sarea[8*4+3];
-       unsigned long cr0;
-} raid6_sse_save_t;
-
-/* Find the 16-byte aligned save area */
-#define SAREA(x) ((unsigned int *)((((unsigned long)&(x)->sarea)+15) & ~15))
-
-#endif
-
 #ifdef __KERNEL__ /* Real code */
 
-/* Note: %cr0 is 32 bits on i386 and 64 bits on x86-64 */
-
-static inline unsigned long raid6_get_fpu(void)
-{
-       unsigned long cr0;
-
-       preempt_disable();
-       asm volatile("mov %%cr0,%0 ; clts" : "=r" (cr0));
-       return cr0;
-}
-
-static inline void raid6_put_fpu(unsigned long cr0)
-{
-       asm volatile("mov %0,%%cr0" : : "r" (cr0));
-       preempt_enable();
-}
+#include <asm/i387.h>
 
 #else /* Dummy code for user space testing */
 
-static inline unsigned long raid6_get_fpu(void)
-{
-       return 0xf00ba6;
-}
-
-static inline void raid6_put_fpu(unsigned long cr0)
-{
-       (void)cr0;
-}
-
-#endif
-
-static inline void raid6_before_mmx(raid6_mmx_save_t *s)
-{
-       s->cr0 = raid6_get_fpu();
-       asm volatile("fsave %0 ; fwait" : "=m" (s->fsave[0]));
-}
-
-static inline void raid6_after_mmx(raid6_mmx_save_t *s)
-{
-       asm volatile("frstor %0" : : "m" (s->fsave[0]));
-       raid6_put_fpu(s->cr0);
-}
-
-static inline void raid6_before_sse(raid6_sse_save_t *s)
-{
-       unsigned int *rsa = SAREA(s);
-
-       s->cr0 = raid6_get_fpu();
-
-       asm volatile("movaps %%xmm0,%0" : "=m" (rsa[0]));
-       asm volatile("movaps %%xmm1,%0" : "=m" (rsa[4]));
-       asm volatile("movaps %%xmm2,%0" : "=m" (rsa[8]));
-       asm volatile("movaps %%xmm3,%0" : "=m" (rsa[12]));
-       asm volatile("movaps %%xmm4,%0" : "=m" (rsa[16]));
-       asm volatile("movaps %%xmm5,%0" : "=m" (rsa[20]));
-       asm volatile("movaps %%xmm6,%0" : "=m" (rsa[24]));
-       asm volatile("movaps %%xmm7,%0" : "=m" (rsa[28]));
-}
-
-static inline void raid6_after_sse(raid6_sse_save_t *s)
-{
-       unsigned int *rsa = SAREA(s);
-
-       asm volatile("movaps %0,%%xmm0" : : "m" (rsa[0]));
-       asm volatile("movaps %0,%%xmm1" : : "m" (rsa[4]));
-       asm volatile("movaps %0,%%xmm2" : : "m" (rsa[8]));
-       asm volatile("movaps %0,%%xmm3" : : "m" (rsa[12]));
-       asm volatile("movaps %0,%%xmm4" : : "m" (rsa[16]));
-       asm volatile("movaps %0,%%xmm5" : : "m" (rsa[20]));
-       asm volatile("movaps %0,%%xmm6" : : "m" (rsa[24]));
-       asm volatile("movaps %0,%%xmm7" : : "m" (rsa[28]));
-
-       raid6_put_fpu(s->cr0);
-}
-
-static inline void raid6_before_sse2(raid6_sse_save_t *s)
+static inline void kernel_fpu_begin(void)
 {
-       unsigned int *rsa = SAREA(s);
-
-       s->cr0 = raid6_get_fpu();
-
-       asm volatile("movdqa %%xmm0,%0" : "=m" (rsa[0]));
-       asm volatile("movdqa %%xmm1,%0" : "=m" (rsa[4]));
-       asm volatile("movdqa %%xmm2,%0" : "=m" (rsa[8]));
-       asm volatile("movdqa %%xmm3,%0" : "=m" (rsa[12]));
-       asm volatile("movdqa %%xmm4,%0" : "=m" (rsa[16]));
-       asm volatile("movdqa %%xmm5,%0" : "=m" (rsa[20]));
-       asm volatile("movdqa %%xmm6,%0" : "=m" (rsa[24]));
-       asm volatile("movdqa %%xmm7,%0" : "=m" (rsa[28]));
 }
 
-static inline void raid6_after_sse2(raid6_sse_save_t *s)
+static inline void kernel_fpu_end(void)
 {
-       unsigned int *rsa = SAREA(s);
-
-       asm volatile("movdqa %0,%%xmm0" : : "m" (rsa[0]));
-       asm volatile("movdqa %0,%%xmm1" : : "m" (rsa[4]));
-       asm volatile("movdqa %0,%%xmm2" : : "m" (rsa[8]));
-       asm volatile("movdqa %0,%%xmm3" : : "m" (rsa[12]));
-       asm volatile("movdqa %0,%%xmm4" : : "m" (rsa[16]));
-       asm volatile("movdqa %0,%%xmm5" : : "m" (rsa[20]));
-       asm volatile("movdqa %0,%%xmm6" : : "m" (rsa[24]));
-       asm volatile("movdqa %0,%%xmm7" : : "m" (rsa[28]));
-
-       raid6_put_fpu(s->cr0);
 }
 
-#ifdef __x86_64__
-
-static inline void raid6_before_sse16(raid6_sse16_save_t *s)
-{
-       unsigned int *rsa = SAREA(s);
-
-       s->cr0 = raid6_get_fpu();
+#define X86_FEATURE_MMX                (0*32+23) /* Multimedia Extensions */
+#define X86_FEATURE_FXSR       (0*32+24) /* FXSAVE and FXRSTOR instructions
+                                          * (fast save and restore) */
+#define X86_FEATURE_XMM                (0*32+25) /* Streaming SIMD Extensions */
+#define X86_FEATURE_XMM2       (0*32+26) /* Streaming SIMD Extensions-2 */
+#define X86_FEATURE_MMXEXT     (1*32+22) /* AMD MMX extensions */
 
-       asm volatile("movdqa %%xmm0,%0" : "=m" (rsa[0]));
-       asm volatile("movdqa %%xmm1,%0" : "=m" (rsa[4]));
-       asm volatile("movdqa %%xmm2,%0" : "=m" (rsa[8]));
-       asm volatile("movdqa %%xmm3,%0" : "=m" (rsa[12]));
-       asm volatile("movdqa %%xmm4,%0" : "=m" (rsa[16]));
-       asm volatile("movdqa %%xmm5,%0" : "=m" (rsa[20]));
-       asm volatile("movdqa %%xmm6,%0" : "=m" (rsa[24]));
-       asm volatile("movdqa %%xmm7,%0" : "=m" (rsa[28]));
-       asm volatile("movdqa %%xmm8,%0" : "=m" (rsa[32]));
-       asm volatile("movdqa %%xmm9,%0" : "=m" (rsa[36]));
-       asm volatile("movdqa %%xmm10,%0" : "=m" (rsa[40]));
-       asm volatile("movdqa %%xmm11,%0" : "=m" (rsa[44]));
-       asm volatile("movdqa %%xmm12,%0" : "=m" (rsa[48]));
-       asm volatile("movdqa %%xmm13,%0" : "=m" (rsa[52]));
-       asm volatile("movdqa %%xmm14,%0" : "=m" (rsa[56]));
-       asm volatile("movdqa %%xmm15,%0" : "=m" (rsa[60]));
-}
-
-static inline void raid6_after_sse16(raid6_sse16_save_t *s)
+/* Should work well enough on modern CPUs for testing */
+static inline int boot_cpu_has(int flag)
 {
-       unsigned int *rsa = SAREA(s);
+       u32 eax = (flag >> 5) ? 0x80000001 : 1;
+       u32 edx;
 
-       asm volatile("movdqa %0,%%xmm0" : : "m" (rsa[0]));
-       asm volatile("movdqa %0,%%xmm1" : : "m" (rsa[4]));
-       asm volatile("movdqa %0,%%xmm2" : : "m" (rsa[8]));
-       asm volatile("movdqa %0,%%xmm3" : : "m" (rsa[12]));
-       asm volatile("movdqa %0,%%xmm4" : : "m" (rsa[16]));
-       asm volatile("movdqa %0,%%xmm5" : : "m" (rsa[20]));
-       asm volatile("movdqa %0,%%xmm6" : : "m" (rsa[24]));
-       asm volatile("movdqa %0,%%xmm7" : : "m" (rsa[28]));
-       asm volatile("movdqa %0,%%xmm8" : : "m" (rsa[32]));
-       asm volatile("movdqa %0,%%xmm9" : : "m" (rsa[36]));
-       asm volatile("movdqa %0,%%xmm10" : : "m" (rsa[40]));
-       asm volatile("movdqa %0,%%xmm11" : : "m" (rsa[44]));
-       asm volatile("movdqa %0,%%xmm12" : : "m" (rsa[48]));
-       asm volatile("movdqa %0,%%xmm13" : : "m" (rsa[52]));
-       asm volatile("movdqa %0,%%xmm14" : : "m" (rsa[56]));
-       asm volatile("movdqa %0,%%xmm15" : : "m" (rsa[60]));
+       asm volatile("cpuid"
+                    : "+a" (eax), "=d" (edx)
+                    : : "ecx", "ebx");
 
-       raid6_put_fpu(s->cr0);
+       return (edx >> (flag & 31)) & 1;
 }
 
-#endif /* __x86_64__ */
-
-/* User space test hack */
-#ifndef __KERNEL__
-static inline int cpuid_features(void)
-{
-       u32 eax = 1;
-       u32 ebx, ecx, edx;
-
-       asm volatile("cpuid" :
-                    "+a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx));
-
-       return edx;
-}
 #endif /* ndef __KERNEL__ */
 
 #endif
index 87410dbd3df41829d36bd49e37af91272718eef5..91d25798ae4a625ceab60094f2a43340bc443f2f 100644 (file)
@@ -70,6 +70,7 @@ config VIDEO_TUNER
        depends on I2C
 
 config VIDEO_BUF
+       depends on PCI
        tristate
 
 config VIDEO_BUF_DVB
index f33e5d973413c2a1c064c66111c7f111383024dd..c120114c241b327458af773e270d66efa6a17286 100644 (file)
@@ -5,8 +5,4 @@ config VIDEO_SAA7146
 config VIDEO_SAA7146_VV
        tristate
        select VIDEO_BUF
-       select VIDEO_VIDEOBUF
        select VIDEO_SAA7146
-
-config VIDEO_VIDEOBUF
-       tristate
index 9a8dd8764c99df188e4bb7857282eea6b8a9746c..cbf7c05648896776e4a60b1bfd01c83956730051 100644 (file)
@@ -256,6 +256,112 @@ int ir_decode_biphase(u32 *samples, int count, int low, int high)
        return value;
 }
 
+/* RC5 decoding stuff, moved from bttv-input.c to share it with
+ * saa7134 */
+
+/* decode raw bit pattern to RC5 code */
+u32 ir_rc5_decode(unsigned int code)
+{
+       unsigned int org_code = code;
+       unsigned int pair;
+       unsigned int rc5 = 0;
+       int i;
+
+       for (i = 0; i < 14; ++i) {
+               pair = code & 0x3;
+               code >>= 2;
+
+               rc5 <<= 1;
+               switch (pair) {
+               case 0:
+               case 2:
+                       break;
+               case 1:
+                       rc5 |= 1;
+                       break;
+               case 3:
+                       dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code);
+                       return 0;
+               }
+       }
+       dprintk(1, "ir-common: code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
+               "instr=%x\n", rc5, org_code, RC5_START(rc5),
+               RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
+       return rc5;
+}
+
+void ir_rc5_timer_end(unsigned long data)
+{
+       struct card_ir *ir = (struct card_ir *)data;
+       struct timeval tv;
+       unsigned long current_jiffies, timeout;
+       u32 gap;
+       u32 rc5 = 0;
+
+       /* get time */
+       current_jiffies = jiffies;
+       do_gettimeofday(&tv);
+
+       /* avoid overflow with gap >1s */
+       if (tv.tv_sec - ir->base_time.tv_sec > 1) {
+               gap = 200000;
+       } else {
+               gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
+                   tv.tv_usec - ir->base_time.tv_usec;
+       }
+
+       /* Allow some timmer jitter (RC5 is ~24ms anyway so this is ok) */
+       if (gap < 28000) {
+               dprintk(1, "ir-common: spurious timer_end\n");
+               return;
+       }
+
+       ir->active = 0;
+       if (ir->last_bit < 20) {
+               /* ignore spurious codes (caused by light/other remotes) */
+               dprintk(1, "ir-common: short code: %x\n", ir->code);
+       } else {
+               ir->code = (ir->code << ir->shift_by) | 1;
+               rc5 = ir_rc5_decode(ir->code);
+
+               /* two start bits? */
+               if (RC5_START(rc5) != ir->start) {
+                       dprintk(1, "ir-common: rc5 start bits invalid: %u\n", RC5_START(rc5));
+
+                       /* right address? */
+               } else if (RC5_ADDR(rc5) == ir->addr) {
+                       u32 toggle = RC5_TOGGLE(rc5);
+                       u32 instr = RC5_INSTR(rc5);
+
+                       /* Good code, decide if repeat/repress */
+                       if (toggle != RC5_TOGGLE(ir->last_rc5) ||
+                           instr != RC5_INSTR(ir->last_rc5)) {
+                               dprintk(1, "ir-common: instruction %x, toggle %x\n", instr,
+                                       toggle);
+                               ir_input_nokey(ir->dev, &ir->ir);
+                               ir_input_keydown(ir->dev, &ir->ir, instr,
+                                                instr);
+                       }
+
+                       /* Set/reset key-up timer */
+                       timeout = current_jiffies + (500 + ir->rc5_key_timeout
+                                                    * HZ) / 1000;
+                       mod_timer(&ir->timer_keyup, timeout);
+
+                       /* Save code for repeat test */
+                       ir->last_rc5 = rc5;
+               }
+       }
+}
+
+void ir_rc5_timer_keyup(unsigned long data)
+{
+       struct card_ir *ir = (struct card_ir *)data;
+
+       dprintk(1, "ir-common: key released\n");
+       ir_input_nokey(ir->dev, &ir->ir);
+}
+
 EXPORT_SYMBOL_GPL(ir_input_init);
 EXPORT_SYMBOL_GPL(ir_input_nokey);
 EXPORT_SYMBOL_GPL(ir_input_keydown);
@@ -265,6 +371,10 @@ EXPORT_SYMBOL_GPL(ir_dump_samples);
 EXPORT_SYMBOL_GPL(ir_decode_biphase);
 EXPORT_SYMBOL_GPL(ir_decode_pulsedistance);
 
+EXPORT_SYMBOL_GPL(ir_rc5_decode);
+EXPORT_SYMBOL_GPL(ir_rc5_timer_end);
+EXPORT_SYMBOL_GPL(ir_rc5_timer_keyup);
+
 /*
  * Local variables:
  * c-basic-offset: 8
index 0e948a5c5a03481d56cefc9844db22a6590c4592..03b47a262f27f179bf8dea086894273601365854 100644 (file)
@@ -1606,3 +1606,174 @@ IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE] = {
 };
 
 EXPORT_SYMBOL_GPL(ir_codes_budget_ci_old);
+
+/*
+ * Marc Fargas <telenieko@telenieko.com>
+ * this is the remote control that comes with the asus p7131
+ * which has a label saying is "Model PC-39"
+ */
+IR_KEYTAB_TYPE ir_codes_asus_pc39[IR_KEYTAB_SIZE] = {
+       /* Keys 0 to 9 */
+       [ 0x15 ] = KEY_0,
+       [ 0x29 ] = KEY_1,
+       [ 0x2d ] = KEY_2,
+       [ 0x2b ] = KEY_3,
+       [ 0x09 ] = KEY_4,
+       [ 0x0d ] = KEY_5,
+       [ 0x0b ] = KEY_6,
+       [ 0x31 ] = KEY_7,
+       [ 0x35 ] = KEY_8,
+       [ 0x33 ] = KEY_9,
+
+       [ 0x3e ] = KEY_RADIO,           /* radio */
+       [ 0x03 ] = KEY_MENU,            /* dvd/menu */
+       [ 0x2a ] = KEY_VOLUMEUP,
+       [ 0x19 ] = KEY_VOLUMEDOWN,
+       [ 0x37 ] = KEY_UP,
+       [ 0x3b ] = KEY_DOWN,
+       [ 0x27 ] = KEY_LEFT,
+       [ 0x2f ] = KEY_RIGHT,
+       [ 0x25 ] = KEY_VIDEO,           /* video */
+       [ 0x39 ] = KEY_AUDIO,           /* music */
+
+       [ 0x21 ] = KEY_TV,              /* tv */
+       [ 0x1d ] = KEY_EXIT,            /* back */
+       [ 0x0a ] = KEY_CHANNELUP,       /* channel / program + */
+       [ 0x1b ] = KEY_CHANNELDOWN,     /* channel / program - */
+       [ 0x1a ] = KEY_ENTER,           /* enter */
+
+       [ 0x06 ] = KEY_PAUSE,           /* play/pause */
+       [ 0x1e ] = KEY_PREVIOUS,        /* rew */
+       [ 0x26 ] = KEY_NEXT,            /* forward */
+       [ 0x0e ] = KEY_REWIND,          /* backward << */
+       [ 0x3a ] = KEY_FASTFORWARD,     /* forward >> */
+       [ 0x36 ] = KEY_STOP,
+       [ 0x2e ] = KEY_RECORD,          /* recording */
+       [ 0x16 ] = KEY_POWER,           /* the button that reads "close" */
+
+       [ 0x11 ] = KEY_ZOOM,            /* full screen */
+       [ 0x13 ] = KEY_MACRO,           /* recall */
+       [ 0x23 ] = KEY_HOME,            /* home */
+       [ 0x05 ] = KEY_PVR,             /* picture */
+       [ 0x3d ] = KEY_MUTE,            /* mute */
+       [ 0x01 ] = KEY_DVD,             /* dvd */
+};
+
+EXPORT_SYMBOL_GPL(ir_codes_asus_pc39);
+
+
+/* Encore ENLTV-FM  - black plastic, white front cover with white glowing buttons
+    Juan Pablo Sormani <sorman@gmail.com> */
+IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE] = {
+
+       /* Power button does nothing, neither in Windows app,
+        although it sends data (used for BIOS wakeup?) */
+       [ 0x0d ] = KEY_MUTE,
+
+       [ 0x1e ] = KEY_TV,
+       [ 0x00 ] = KEY_VIDEO,
+       [ 0x01 ] = KEY_AUDIO,           /* music */
+       [ 0x02 ] = KEY_MHP,             /* picture */
+
+       [ 0x1f ] = KEY_1,
+       [ 0x03 ] = KEY_2,
+       [ 0x04 ] = KEY_3,
+       [ 0x05 ] = KEY_4,
+       [ 0x1c ] = KEY_5,
+       [ 0x06 ] = KEY_6,
+       [ 0x07 ] = KEY_7,
+       [ 0x08 ] = KEY_8,
+       [ 0x1d ] = KEY_9,
+       [ 0x0a ] = KEY_0,
+
+       [ 0x09 ] = KEY_LIST,        /* -/-- */
+       [ 0x0b ] = KEY_LAST,        /* recall */
+
+       [ 0x14 ] = KEY_HOME,            /* win start menu */
+       [ 0x15 ] = KEY_EXIT,            /* exit */
+       [ 0x16 ] = KEY_UP,
+       [ 0x12 ] = KEY_DOWN,
+       [ 0x0c ] = KEY_RIGHT,
+       [ 0x17 ] = KEY_LEFT,
+
+       [ 0x18 ] = KEY_ENTER,           /* OK */
+
+       [ 0x0e ] = KEY_ESC,
+       [ 0x13 ] = KEY_D,               /* desktop */
+       [ 0x11 ] = KEY_TAB,
+       [ 0x19 ] = KEY_SWITCHVIDEOMODE, /* switch */
+
+       [ 0x1a ] = KEY_MENU,
+       [ 0x1b ] = KEY_ZOOM,            /* fullscreen */
+       [ 0x44 ] = KEY_TIME,            /* time shift */
+       [ 0x40 ] = KEY_MODE,            /* source */
+
+       [ 0x5a ] = KEY_RECORD,
+       [ 0x42 ] = KEY_PLAY,            /* play/pause */
+       [ 0x45 ] = KEY_STOP,
+       [ 0x43 ] = KEY_CAMERA,          /* camera icon */
+
+       [ 0x48 ] = KEY_REWIND,
+       [ 0x4a ] = KEY_FASTFORWARD,
+       [ 0x49 ] = KEY_PREVIOUS,
+       [ 0x4b ] = KEY_NEXT,
+
+       [ 0x4c ] = KEY_FAVORITES,       /* tv wall */
+       [ 0x4d ] = KEY_SOUND,           /* DVD sound */
+       [ 0x4e ] = KEY_LANGUAGE,        /* DVD lang */
+       [ 0x4f ] = KEY_TEXT,            /* DVD text */
+
+       [ 0x50 ] = KEY_SLEEP,           /* shutdown */
+       [ 0x51 ] = KEY_MODE,            /* stereo > main */
+       [ 0x52 ] = KEY_SELECT,          /* stereo > sap */
+       [ 0x53 ] = KEY_PROG1,           /* teletext */
+
+
+       [ 0x59 ] = KEY_RED,             /* AP1 */
+       [ 0x41 ] = KEY_GREEN,           /* AP2 */
+       [ 0x47 ] = KEY_YELLOW,          /* AP3 */
+       [ 0x57 ] = KEY_BLUE,            /* AP4 */
+
+
+};
+
+EXPORT_SYMBOL_GPL(ir_codes_encore_enltv);
+
+/* for the Technotrend 1500 bundled remote: */
+IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE] = {
+       [ 0x01 ] = KEY_POWER,
+       [ 0x02 ] = KEY_SHUFFLE, /* ? double-arrow key */
+       [ 0x03 ] = KEY_1,
+       [ 0x04 ] = KEY_2,
+       [ 0x05 ] = KEY_3,
+       [ 0x06 ] = KEY_4,
+       [ 0x07 ] = KEY_5,
+       [ 0x08 ] = KEY_6,
+       [ 0x09 ] = KEY_7,
+       [ 0x0a ] = KEY_8,
+       [ 0x0b ] = KEY_9,
+       [ 0x0c ] = KEY_0,
+       [ 0x0d ] = KEY_UP,
+       [ 0x0e ] = KEY_LEFT,
+       [ 0x0f ] = KEY_OK,
+       [ 0x10 ] = KEY_RIGHT,
+       [ 0x11 ] = KEY_DOWN,
+       [ 0x12 ] = KEY_INFO,
+       [ 0x13 ] = KEY_EXIT,
+       [ 0x14 ] = KEY_RED,
+       [ 0x15 ] = KEY_GREEN,
+       [ 0x16 ] = KEY_YELLOW,
+       [ 0x17 ] = KEY_BLUE,
+       [ 0x18 ] = KEY_MUTE,
+       [ 0x19 ] = KEY_TEXT,
+       [ 0x1a ] = KEY_MODE,    /* ? TV/Radio */
+       [ 0x21 ] = KEY_OPTION,
+       [ 0x22 ] = KEY_EPG,
+       [ 0x23 ] = KEY_CHANNELUP,
+       [ 0x24 ] = KEY_CHANNELDOWN,
+       [ 0x25 ] = KEY_VOLUMEUP,
+       [ 0x26 ] = KEY_VOLUMEDOWN,
+       [ 0x27 ] = KEY_SETUP,
+};
+
+EXPORT_SYMBOL_GPL(ir_codes_tt_1500);
index b8dcfa16526665c03aa6342c47ae296acb9bfb92..c18a5da6493470ae3e3af67342e08650970441e4 100644 (file)
@@ -508,7 +508,7 @@ int saa7146_vv_release(struct saa7146_dev* dev)
 
        DEB_EE(("dev:%p\n",dev));
 
-       pci_free_consistent(dev->pci, SAA7146_RPS_MEM, vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle);
+       pci_free_consistent(dev->pci, SAA7146_CLIPPING_MEM, vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle);
        kfree(vv);
        dev->vv_data = NULL;
        dev->vv_callback = NULL;
index c2b35e3662422bc380a47d064dc3da4ce8c6d137..752cf79c532fca83ee93295e241838ac4b7d357a 100644 (file)
@@ -385,9 +385,9 @@ static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe,
        else buf[3] = 0x88;
 
        if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
+               fe->ops.i2c_gate_ctrl(fe, 0);
        deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n",fep->frequency, buf[0],buf[1],buf[2],buf[3]);
-       ret = fc->i2c_request(fc,FC_WRITE,FC_I2C_PORT_TUNER,0x61,buf[0],&buf[1],3);
+       ret = fc->i2c_request(fc, FC_WRITE, FC_I2C_PORT_TUNER, 0x61, buf[0], &buf[1], 3);
        deb_tuner("tuner write returned: %d\n",ret);
 
        return 0;
@@ -398,91 +398,71 @@ static u8 alps_tdee4_stv0297_inittab[] = {
        0x80, 0x00,
        0x81, 0x01,
        0x81, 0x00,
-       0x00, 0x09,
-       0x01, 0x69,
+       0x00, 0x48,
+       0x01, 0x58,
        0x03, 0x00,
        0x04, 0x00,
        0x07, 0x00,
        0x08, 0x00,
-       0x20, 0x00,
-       0x21, 0x40,
-       0x22, 0x00,
-       0x23, 0x00,
-       0x24, 0x40,
-       0x25, 0x88,
        0x30, 0xff,
-       0x31, 0x00,
+       0x31, 0x9d,
        0x32, 0xff,
        0x33, 0x00,
-       0x34, 0x50,
-       0x35, 0x7f,
-       0x36, 0x00,
-       0x37, 0x20,
-       0x38, 0x00,
-       0x40, 0x1c,
-       0x41, 0xff,
-       0x42, 0x29,
+       0x34, 0x29,
+       0x35, 0x55,
+       0x36, 0x80,
+       0x37, 0x6e,
+       0x38, 0x9c,
+       0x40, 0x1a,
+       0x41, 0xfe,
+       0x42, 0x33,
        0x43, 0x00,
        0x44, 0xff,
        0x45, 0x00,
        0x46, 0x00,
        0x49, 0x04,
-       0x4a, 0x00,
+       0x4a, 0x51,
        0x4b, 0xf8,
        0x52, 0x30,
-       0x55, 0xae,
-       0x56, 0x47,
-       0x57, 0xe1,
-       0x58, 0x3a,
-       0x5a, 0x1e,
-       0x5b, 0x34,
-       0x60, 0x00,
-       0x63, 0x00,
-       0x64, 0x00,
-       0x65, 0x00,
-       0x66, 0x00,
-       0x67, 0x00,
-       0x68, 0x00,
-       0x69, 0x00,
-       0x6a, 0x02,
-       0x6b, 0x00,
+       0x53, 0x06,
+       0x59, 0x06,
+       0x5a, 0x5e,
+       0x5b, 0x04,
+       0x61, 0x49,
+       0x62, 0x0a,
        0x70, 0xff,
-       0x71, 0x00,
+       0x71, 0x04,
        0x72, 0x00,
        0x73, 0x00,
        0x74, 0x0c,
-       0x80, 0x00,
+       0x80, 0x20,
        0x81, 0x00,
-       0x82, 0x00,
+       0x82, 0x30,
        0x83, 0x00,
        0x84, 0x04,
-       0x85, 0x80,
-       0x86, 0x24,
-       0x87, 0x78,
-       0x88, 0x10,
+       0x85, 0x22,
+       0x86, 0x08,
+       0x87, 0x1b,
+       0x88, 0x00,
        0x89, 0x00,
-       0x90, 0x01,
-       0x91, 0x01,
-       0xa0, 0x04,
+       0x90, 0x00,
+       0x91, 0x04,
+       0xa0, 0x86,
        0xa1, 0x00,
        0xa2, 0x00,
        0xb0, 0x91,
        0xb1, 0x0b,
-       0xc0, 0x53,
-       0xc1, 0x70,
+       0xc0, 0x5b,
+       0xc1, 0x10,
        0xc2, 0x12,
-       0xd0, 0x00,
+       0xd0, 0x02,
        0xd1, 0x00,
        0xd2, 0x00,
        0xd3, 0x00,
-       0xd4, 0x00,
+       0xd4, 0x02,
        0xd5, 0x00,
        0xde, 0x00,
-       0xdf, 0x00,
-       0x61, 0x49,
-       0x62, 0x0b,
-       0x53, 0x08,
-       0x59, 0x08,
+       0xdf, 0x01,
        0xff, 0xff,
 };
 
index 329a51c185626db52076c30a6e764c79ca79ee1e..83b090ef244555d782571eecc95a508675a8af59 100644 (file)
@@ -390,6 +390,7 @@ static struct cards card_list[] __devinitdata = {
        { 0xfc00270f, BTTV_BOARD_TWINHAN_DST,                   "ChainTech digitop DST-1000 DVB-S" },
        { 0x07711461, BTTV_BOARD_AVDVBT_771,                    "AVermedia AverTV DVB-T 771" },
        { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE,               "DViCO FusionHDTV DVB-T Lite" },
+       { 0xdb1118ac, BTTV_BOARD_DVICO_DVBT_LITE,               "Ultraview DVB-T Lite" },
        { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE,       "DViCO FusionHDTV 5 Lite" },
        { 0x20007063, BTTV_BOARD_PC_HDTV,                       "pcHDTV HD-2000 TV" },
        { 0x00261822, BTTV_BOARD_TWINHAN_DST,                   "DNTV Live! Mini" },
index 9f72b7000c080281e6149318a730b814348a9baf..0393a3d19920607e68189386def7e5f0ba707082 100644 (file)
@@ -1161,7 +1161,7 @@ static int dst_get_device_id(struct dst_state *state)
                }
        }
 
-       if (i >= sizeof (dst_tlist) / sizeof (dst_tlist [0])) {
+       if (i >= ARRAY_SIZE(dst_tlist)) {
                dprintk(verbose, DST_ERROR, 1, "Unable to recognize %s or %s", &state->rxbuffer[0], &state->rxbuffer[1]);
                dprintk(verbose, DST_ERROR, 1, "please email linux-dvb@linuxtv.org with this type in");
                use_dst_type = DST_TYPE_IS_SAT;
index 3e35931af35d13cd70d14f04eb5ec9fe26cd7db1..58f69f6ae3918601e56bc2b10694f7914d3935eb 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
@@ -213,7 +214,7 @@ static int cx24108_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend
                freq = 2150000; /* satellite IF is 950..2150MHz */
 
        /* decide which VCO to use for the input frequency */
-       for(i=1;(i<sizeof(osci)/sizeof(osci[0]))&&(osci[i]<freq);i++);
+       for(i = 1; (i < ARRAY_SIZE(osci)) && (osci[i] < freq); i++);
        printk("cx24108 debug: select vco #%d (f=%d)\n",i,freq);
        band=bandsel[i];
        /* the gain values must be set by SetSymbolrate */
index d64b96cb0c469ea9e325eca7e557e0f084ce7c39..a6cbbdd262d6212adc1b4879685e722287d0056d 100644 (file)
@@ -819,6 +819,11 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
                set_bit(rc_keys[i + 2], input_dev->keybit);
        input_dev->keycodesize = 0;
        input_dev->keycodemax = 0;
+       input_dev->id.bustype = BUS_USB;
+       input_dev->id.vendor = cinergyt2->udev->descriptor.idVendor;
+       input_dev->id.product = cinergyt2->udev->descriptor.idProduct;
+       input_dev->id.version = 1;
+       input_dev->cdev.dev = &cinergyt2->udev->dev;
 
        err = input_register_device(input_dev);
        if (err) {
index 7c42d53a1cc7df9ecc55ba8859f50d75ccc14a82..a21a894d3f98437f6958e30d504c0d606d181c74 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/list.h>
 #include <linux/freezer.h>
 #include <linux/jiffies.h>
+#include <linux/kthread.h>
 #include <asm/processor.h>
 
 #include "dvb_frontend.h"
@@ -100,7 +101,7 @@ struct dvb_frontend_private {
        struct semaphore sem;
        struct list_head list_head;
        wait_queue_head_t wait_queue;
-       pid_t thread_pid;
+       struct task_struct *thread;
        unsigned long release_jiffies;
        unsigned int exit;
        unsigned int wakeup;
@@ -508,19 +509,11 @@ static int dvb_frontend_thread(void *data)
        struct dvb_frontend *fe = data;
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
        unsigned long timeout;
-       char name [15];
        fe_status_t s;
        struct dvb_frontend_parameters *params;
 
        dprintk("%s\n", __FUNCTION__);
 
-       snprintf (name, sizeof(name), "kdvb-fe-%i", fe->dvb->num);
-
-       lock_kernel();
-       daemonize(name);
-       sigfillset(&current->blocked);
-       unlock_kernel();
-
        fepriv->check_wrapped = 0;
        fepriv->quality = 0;
        fepriv->delay = 3*HZ;
@@ -532,16 +525,18 @@ static int dvb_frontend_thread(void *data)
 
        while (1) {
                up(&fepriv->sem);           /* is locked when we enter the thread... */
-
+restart:
                timeout = wait_event_interruptible_timeout(fepriv->wait_queue,
-                                                          dvb_frontend_should_wakeup(fe),
-                                                          fepriv->delay);
-               if (0 != dvb_frontend_is_exiting(fe)) {
+                       dvb_frontend_should_wakeup(fe) || kthread_should_stop(),
+                       fepriv->delay);
+
+               if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) {
                        /* got signal or quitting */
                        break;
                }
 
-               try_to_freeze();
+               if (try_to_freeze())
+                       goto restart;
 
                if (down_interruptible(&fepriv->sem))
                        break;
@@ -591,7 +586,7 @@ static int dvb_frontend_thread(void *data)
                        fe->ops.sleep(fe);
        }
 
-       fepriv->thread_pid = 0;
+       fepriv->thread = NULL;
        mb();
 
        dvb_frontend_wakeup(fe);
@@ -600,7 +595,6 @@ static int dvb_frontend_thread(void *data)
 
 static void dvb_frontend_stop(struct dvb_frontend *fe)
 {
-       unsigned long ret;
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
 
        dprintk ("%s\n", __FUNCTION__);
@@ -608,33 +602,17 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
        fepriv->exit = 1;
        mb();
 
-       if (!fepriv->thread_pid)
+       if (!fepriv->thread)
                return;
 
-       /* check if the thread is really alive */
-       if (kill_proc(fepriv->thread_pid, 0, 1) == -ESRCH) {
-               printk("dvb_frontend_stop: thread PID %d already died\n",
-                               fepriv->thread_pid);
-               /* make sure the mutex was not held by the thread */
-               init_MUTEX (&fepriv->sem);
-               return;
-       }
-
-       /* wake up the frontend thread, so it notices that fe->exit == 1 */
-       dvb_frontend_wakeup(fe);
-
-       /* wait until the frontend thread has exited */
-       ret = wait_event_interruptible(fepriv->wait_queue,0 == fepriv->thread_pid);
-       if (-ERESTARTSYS != ret) {
-               fepriv->state = FESTATE_IDLE;
-               return;
-       }
+       kthread_stop(fepriv->thread);
+       init_MUTEX (&fepriv->sem);
        fepriv->state = FESTATE_IDLE;
 
        /* paranoia check in case a signal arrived */
-       if (fepriv->thread_pid)
-               printk("dvb_frontend_stop: warning: thread PID %d won't exit\n",
-                               fepriv->thread_pid);
+       if (fepriv->thread)
+               printk("dvb_frontend_stop: warning: thread %p won't exit\n",
+                               fepriv->thread);
 }
 
 s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime)
@@ -684,10 +662,11 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
 {
        int ret;
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
+       struct task_struct *fe_thread;
 
        dprintk ("%s\n", __FUNCTION__);
 
-       if (fepriv->thread_pid) {
+       if (fepriv->thread) {
                if (!fepriv->exit)
                        return 0;
                else
@@ -701,18 +680,18 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
 
        fepriv->state = FESTATE_IDLE;
        fepriv->exit = 0;
-       fepriv->thread_pid = 0;
+       fepriv->thread = NULL;
        mb();
 
-       ret = kernel_thread (dvb_frontend_thread, fe, 0);
-
-       if (ret < 0) {
-               printk("dvb_frontend_start: failed to start kernel_thread (%d)\n", ret);
+       fe_thread = kthread_run(dvb_frontend_thread, fe,
+               "kdvb-fe-%i", fe->dvb->num);
+       if (IS_ERR(fe_thread)) {
+               ret = PTR_ERR(fe_thread);
+               printk("dvb_frontend_start: failed to start kthread (%d)\n", ret);
                up(&fepriv->sem);
                return ret;
        }
-       fepriv->thread_pid = ret;
-
+       fepriv->thread = fe_thread;
        return 0;
 }
 
index 826b47f155a02cfae38471272360024da72d37f7..490337b5ee3e2ec9c8007c536d8eec1b1fa783d9 100644 (file)
@@ -199,12 +199,14 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
                        const struct dvb_device *template, void *priv, int type)
 {
        struct dvb_device *dvbdev;
+       struct file_operations *dvbdevfops;
+
        int id;
 
        if (mutex_lock_interruptible(&dvbdev_register_lock))
                return -ERESTARTSYS;
 
-       if ((id = dvbdev_get_free_id (adap, type)) < 0) {
+       if ((id = dvbdev_get_free_id (adap, type)) < 0){
                mutex_unlock(&dvbdev_register_lock);
                *pdvbdev = NULL;
                printk ("%s: could get find free device id...\n", __FUNCTION__);
@@ -213,7 +215,15 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
 
        *pdvbdev = dvbdev = kmalloc(sizeof(struct dvb_device), GFP_KERNEL);
 
-       if (!dvbdev) {
+       if (!dvbdev){
+               mutex_unlock(&dvbdev_register_lock);
+               return -ENOMEM;
+       }
+
+       dvbdevfops = kzalloc(sizeof(struct file_operations), GFP_KERNEL);
+
+       if (!dvbdevfops){
+               kfree (dvbdev);
                mutex_unlock(&dvbdev_register_lock);
                return -ENOMEM;
        }
@@ -223,7 +233,9 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
        dvbdev->id = id;
        dvbdev->adapter = adap;
        dvbdev->priv = priv;
+       dvbdev->fops = dvbdevfops;
 
+       memcpy(dvbdev->fops, template->fops, sizeof(struct file_operations));
        dvbdev->fops->owner = adap->module;
 
        list_add_tail (&dvbdev->list_head, &adap->device_list);
@@ -251,6 +263,7 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
                                        dvbdev->type, dvbdev->id)));
 
        list_del (&dvbdev->list_head);
+       kfree (dvbdev->fops);
        kfree (dvbdev);
 }
 EXPORT_SYMBOL(dvb_unregister_device);
index ad52143602cd4ce2f8924b251ea34b2babec512a..80f67a51b90819cfcb50f0a24df931b73e91398d 100644 (file)
@@ -109,6 +109,34 @@ config DVB_USB_CXUSB
          Medion MD95700 hybrid USB2.0 device.
          DViCO FusionHDTV (Bluebird) USB2.0 devices
 
+config DVB_USB_M920X
+       tristate "Uli m920x DVB-T USB2.0 support"
+       depends on DVB_USB
+       select DVB_MT352 if !DVB_FE_CUSTOMISE
+       select DVB_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+       help
+         Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver.
+         Currently, only devices with a product id of
+         "DTV USB MINI" (in cold state) are supported.
+         Firmware required.
+
+config DVB_USB_GL861
+       tristate "Genesys Logic GL861 USB2.0 support"
+       depends on DVB_USB
+       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
+       select DVB_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+       help
+         Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0
+         receiver with USB ID 0db0:5581.
+
+config DVB_USB_AU6610
+       tristate "Alcor Micro AU6610 USB2.0 support"
+       depends on DVB_USB
+       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
+       select DVB_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+       help
+         Say Y here to support the Sigmatek DVB-110 DVB-T USB2.0 receiver.
+
 config DVB_USB_DIGITV
        tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support"
        depends on DVB_USB
index 154d593bbb02788a5c9a9589dab63fc54bfa7546..40f28f559b54742d20e4bbbb9003a468b2fe7c9d 100644 (file)
@@ -30,6 +30,15 @@ obj-$(CONFIG_DVB_USB_NOVA_T_USB2) += dvb-usb-dibusb-common.o dvb-usb-nova-t-usb2
 dvb-usb-umt-010-objs = umt-010.o
 obj-$(CONFIG_DVB_USB_UMT_010) += dvb-usb-dibusb-common.o dvb-usb-umt-010.o
 
+dvb-usb-m920x-objs = m920x.o
+obj-$(CONFIG_DVB_USB_M920X) += dvb-usb-m920x.o
+
+dvb-usb-gl861-objs = gl861.o
+obj-$(CONFIG_DVB_USB_GL861) += dvb-usb-gl861.o
+
+dvb-usb-au6610-objs = au6610.o
+obj-$(CONFIG_DVB_USB_AU6610) += dvb-usb-au6610.o
+
 dvb-usb-digitv-objs = digitv.o
 obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o
 
diff --git a/drivers/media/dvb/dvb-usb/au6610.c b/drivers/media/dvb/dvb-usb/au6610.c
new file mode 100644 (file)
index 0000000..0dc66a8
--- /dev/null
@@ -0,0 +1,255 @@
+/* DVB USB compliant linux driver for Sigmatek DVB-110 DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2006 Antti Palosaari <crope@iki.fi>
+ *
+ *     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
+ */
+
+#include "au6610.h"
+
+#include "zl10353.h"
+#include "qt1010.h"
+
+/* debug */
+static int dvb_usb_au6610_debug;
+module_param_named(debug, dvb_usb_au6610_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+
+static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
+                         u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
+{
+       int ret;
+       u16 index;
+       u8 usb_buf[6]; /* enough for all known requests,
+                         read returns 5 and write 6 bytes */
+       switch (wlen) {
+       case 1:
+               index = wbuf[0] << 8;
+               break;
+       case 2:
+               index = wbuf[0] << 8;
+               index += wbuf[1];
+               break;
+       default:
+               warn("wlen = %x, aborting.", wlen);
+               return -EINVAL;
+       }
+
+       ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), operation,
+                             USB_TYPE_VENDOR|USB_DIR_IN, addr, index, usb_buf,
+                             sizeof(usb_buf), AU6610_USB_TIMEOUT);
+
+       if (ret < 0)
+               return ret;
+
+       switch (operation) {
+       case AU6610_REQ_I2C_READ:
+       case AU6610_REQ_USB_READ:
+               /* requested value is always 5th byte in buffer */
+               rbuf[0] = usb_buf[4];
+       }
+
+       return ret;
+}
+
+static int au6610_i2c_msg(struct dvb_usb_device *d, u8 addr,
+                         u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
+{
+       u8 request;
+       u8 wo = (rbuf == NULL || rlen == 0); /* write-only */
+
+       if (wo) {
+               request = AU6610_REQ_I2C_WRITE;
+       } else { /* rw */
+               request = AU6610_REQ_I2C_READ;
+       }
+
+       return au6610_usb_msg(d, request, addr, wbuf, wlen, rbuf, rlen);
+}
+
+
+/* I2C */
+static int au6610_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+                          int num)
+{
+       struct dvb_usb_device *d = i2c_get_adapdata(adap);
+       int i;
+
+       if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+               return -EAGAIN;
+
+       if (num > 2)
+               return -EINVAL;
+
+       for (i = 0; i < num; i++) {
+               /* write/read request */
+               if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
+                       if (au6610_i2c_msg(d, msg[i].addr, msg[i].buf,
+                                          msg[i].len, msg[i+1].buf,
+                                          msg[i+1].len) < 0)
+                               break;
+                       i++;
+               } else if (au6610_i2c_msg(d, msg[i].addr, msg[i].buf,
+                                              msg[i].len, NULL, 0) < 0)
+                               break;
+       }
+
+       mutex_unlock(&d->i2c_mutex);
+       return i;
+}
+
+
+static u32 au6610_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm au6610_i2c_algo = {
+       .master_xfer   = au6610_i2c_xfer,
+       .functionality = au6610_i2c_func,
+};
+
+/* Callbacks for DVB USB */
+static int au6610_identify_state(struct usb_device *udev,
+                                struct dvb_usb_device_properties *props,
+                                struct dvb_usb_device_description **desc,
+                                int *cold)
+{
+       *cold = 0;
+       return 0;
+}
+
+static struct zl10353_config au6610_zl10353_config = {
+       .demod_address = 0x1e,
+       .no_tuner = 1,
+       .parallel_ts = 1,
+};
+
+static int au6610_zl10353_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       if ((adap->fe = dvb_attach(zl10353_attach, &au6610_zl10353_config,
+                                  &adap->dev->i2c_adap)) != NULL) {
+               return 0;
+       }
+
+       return -EIO;
+}
+
+static struct qt1010_config au6610_qt1010_config = {
+       .i2c_address = 0xc4
+};
+
+static int au6610_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
+{
+       return dvb_attach(qt1010_attach,
+                         adap->fe, &adap->dev->i2c_adap,
+                         &au6610_qt1010_config) == NULL ? -ENODEV : 0;
+}
+
+/* DVB USB Driver stuff */
+static struct dvb_usb_device_properties au6610_properties;
+
+static int au6610_probe(struct usb_interface *intf,
+                       const struct usb_device_id *id)
+{
+       struct dvb_usb_device *d;
+       struct usb_host_interface *alt;
+       int ret;
+
+       if (intf->num_altsetting < AU6610_ALTSETTING_COUNT)
+               return -ENODEV;
+
+       if ((ret = dvb_usb_device_init(intf, &au6610_properties, THIS_MODULE, &d)) == 0) {
+               alt = usb_altnum_to_altsetting(intf, AU6610_ALTSETTING);
+
+               if (alt == NULL) {
+                       deb_rc("no alt found!\n");
+                       return -ENODEV;
+               }
+               ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber,
+                                       alt->desc.bAlternateSetting);
+       }
+
+       return ret;
+}
+
+
+static struct usb_device_id au6610_table [] = {
+       { USB_DEVICE(USB_VID_ALCOR_MICRO, USB_PID_SIGMATEK_DVB_110) },
+       { }             /* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, au6610_table);
+
+static struct dvb_usb_device_properties au6610_properties = {
+       .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+       .usb_ctrl = DEVICE_SPECIFIC,
+       .size_of_priv     = 0,
+       .identify_state   = au6610_identify_state,
+       .num_adapters = 1,
+       .adapter = {
+               {
+                       .frontend_attach  = au6610_zl10353_frontend_attach,
+                       .tuner_attach     = au6610_qt1010_tuner_attach,
+
+                       .stream = {
+                               .type = USB_ISOC,
+                               .count = 5,
+                               .endpoint = 0x82,
+                               .u = {
+                                       .isoc = {
+                                               .framesperurb = 40,
+                                               .framesize = 942,   /* maximum packet size */
+                                               .interval = 1.25,   /* 125 us */
+                                       }
+                               }
+                       },
+               }
+       },
+       .i2c_algo = &au6610_i2c_algo,
+       .num_device_descs = 1,
+       .devices = {
+               {
+                       "Sigmatek DVB-110 DVB-T USB2.0",
+                       { &au6610_table[0], NULL },
+                       { NULL },
+               },
+       }
+};
+
+static struct usb_driver au6610_driver = {
+       .name       = "dvb_usb_au6610",
+       .probe      = au6610_probe,
+       .disconnect = dvb_usb_device_exit,
+       .id_table   = au6610_table,
+};
+
+/* module stuff */
+static int __init au6610_module_init(void)
+{
+       int ret;
+
+       if ((ret = usb_register(&au6610_driver))) {
+               err("usb_register failed. Error number %d", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static void __exit au6610_module_exit(void)
+{
+       /* deregister this driver from the USB subsystem */
+       usb_deregister(&au6610_driver);
+}
+
+module_init (au6610_module_init);
+module_exit (au6610_module_exit);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Driver Sigmatek DVB-110 DVB-T USB2.0 / AU6610");
+MODULE_VERSION("0.1");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/au6610.h b/drivers/media/dvb/dvb-usb/au6610.h
new file mode 100644 (file)
index 0000000..4161b05
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef _DVB_USB_AU6610_H_
+#define _DVB_USB_AU6610_H_
+
+#define DVB_USB_LOG_PREFIX "au6610"
+#include "dvb-usb.h"
+
+#define deb_rc(args...)   dprintk(dvb_usb_au6610_debug,0x01,args)
+
+#define AU6610_REQ_I2C_WRITE   0x14
+#define AU6610_REQ_I2C_READ    0x13
+#define AU6610_REQ_USB_WRITE   0x16
+#define AU6610_REQ_USB_READ    0x15
+
+#define AU6610_USB_TIMEOUT 1000
+
+#define AU6610_ALTSETTING_COUNT 6
+#define AU6610_ALTSETTING       5
+
+#endif
index 15d12fce34df871e8ffaed1b4c39b7566fa97d82..127a94b9a1b537c9b0a810eaf0ad92d19f8d71db 100644 (file)
@@ -469,9 +469,9 @@ static int bluebird_patch_dvico_firmware_download(struct usb_device *udev,
            fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) {
 
                fw->data[BLUEBIRD_01_ID_OFFSET + 2] =
-                       udev->descriptor.idProduct + 1;
+                       le16_to_cpu(udev->descriptor.idProduct) + 1;
                fw->data[BLUEBIRD_01_ID_OFFSET + 3] =
-                       udev->descriptor.idProduct >> 8;
+                       le16_to_cpu(udev->descriptor.idProduct) >> 8;
 
                return usb_cypress_load_firmware(udev, fw, CYPRESS_FX2);
        }
index 4a198d4755b0699f818d08c83ba73e9093b41037..b5acb11c0bc95bf0bcacedc1c4db84366553e8b1 100644 (file)
@@ -119,6 +119,8 @@ static int digitv_nxt6000_tuner_set_params(struct dvb_frontend *fe, struct dvb_f
        struct dvb_usb_adapter *adap = fe->dvb->priv;
        u8 b[5];
        dvb_usb_tuner_calc_regs(fe,fep,b, 5);
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        return digitv_ctrl_msg(adap->dev, USB_WRITE_TUNER, 0, &b[1], 4, NULL, 0);
 }
 
index 299382dcb81d35bbdf0245fd546379a04a73a095..148386aba2752f987ae4b2d8cbaadc4d3371cb8d 100644 (file)
@@ -11,6 +11,7 @@
 
 /* Vendor IDs */
 #define USB_VID_ADSTECH                                0x06e1
+#define USB_VID_ALCOR_MICRO            0x058f
 #define USB_VID_ANCHOR                         0x0547
 #define USB_VID_AVERMEDIA                      0x07ca
 #define USB_VID_COMPRO                         0x185b
@@ -29,6 +30,7 @@
 #define USB_VID_LEADTEK                                0x0413
 #define USB_VID_LITEON                         0x04ca
 #define USB_VID_MEDION                         0x1660
+#define USB_VID_MSI                            0x0db0
 #define USB_VID_PINNACLE                       0x2304
 #define USB_VID_VISIONPLUS                     0x13d3
 #define USB_VID_TWINHAN                                0x1822
 #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_MSI_MEGASKY580                         0x5580
+#define USB_PID_MSI_MEGASKY580_55801                   0x5581
 #define USB_PID_KYE_DVB_T_COLD                         0x701e
 #define USB_PID_KYE_DVB_T_WARM                         0x701f
 #define USB_PID_PCTV_200E                              0x020e
 #define USB_PID_WINFAST_DTV_DONGLE_STK7700P            0x6f00
 #define USB_PID_GENPIX_8PSK_COLD                       0x0200
 #define USB_PID_GENPIX_8PSK_WARM                       0x0201
+#define USB_PID_SIGMATEK_DVB_110                       0x6610
 
 
 #endif
index 19ff5978bc914f675fc1108bfe01f0d11abaa1dc..9511a31c8f506bc90296133a8974564191c4ccbb 100644 (file)
@@ -151,7 +151,7 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
 int dvb_usb_remote_exit(struct dvb_usb_device *d)
 {
        if (d->state & DVB_USB_STATE_REMOTE) {
-               cancel_delayed_work(&d->rc_query_work);
+               cancel_rearming_delayed_work(&d->rc_query_work);
                flush_scheduled_work();
                input_unregister_device(d->rc_input_dev);
        }
diff --git a/drivers/media/dvb/dvb-usb/gl861.c b/drivers/media/dvb/dvb-usb/gl861.c
new file mode 100644 (file)
index 0000000..c9f38a5
--- /dev/null
@@ -0,0 +1,231 @@
+/* DVB USB compliant linux driver for GL861 USB2.0 devices.
+ *
+ *     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
+ */
+#include "gl861.h"
+
+#include "zl10353.h"
+#include "qt1010.h"
+
+/* debug */
+int dvb_usb_gl861_debug;
+module_param_named(debug,dvb_usb_gl861_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+
+static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
+                        u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
+{
+       u16 index;
+       u16 value = addr << 8;
+       int wo = (rbuf == NULL || rlen == 0); /* write-only */
+       u8 req, type;
+
+       if (wo) {
+               req = GL861_REQ_I2C_WRITE;
+               type = GL861_WRITE;
+       } else { /* rw */
+               req = GL861_REQ_I2C_READ;
+               type = GL861_READ;
+       }
+
+       switch (wlen) {
+       case 1:
+               index = wbuf[0];
+               break;
+       case 2:
+               index = wbuf[0];
+               value = value + wbuf[1];
+               break;
+       default:
+               warn("wlen = %x, aborting.", wlen);
+               return -EINVAL;
+       }
+
+       return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), req, type,
+                              value, index, rbuf, rlen, 2000);
+}
+
+/* I2C */
+static int gl861_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+                         int num)
+{
+       struct dvb_usb_device *d = i2c_get_adapdata(adap);
+       int i;
+
+       if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+               return -EAGAIN;
+
+       if (num > 2)
+               return -EINVAL;
+
+       for (i = 0; i < num; i++) {
+               /* write/read request */
+               if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
+                       if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf,
+                                         msg[i].len, msg[i+1].buf, msg[i+1].len) < 0)
+                               break;
+                       i++;
+               } else
+                       if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf,
+                                         msg[i].len, NULL, 0) < 0)
+                               break;
+       }
+
+       mutex_unlock(&d->i2c_mutex);
+       return i;
+}
+
+static u32 gl861_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm gl861_i2c_algo = {
+       .master_xfer   = gl861_i2c_xfer,
+       .functionality = gl861_i2c_func,
+};
+
+/* Callbacks for DVB USB */
+static int gl861_identify_state(struct usb_device *udev,
+                               struct dvb_usb_device_properties *props,
+                               struct dvb_usb_device_description **desc,
+                               int *cold)
+{
+       *cold = 0;
+
+       return 0;
+}
+
+static struct zl10353_config gl861_zl10353_config = {
+       .demod_address = 0x1e,
+       .no_tuner = 1,
+       .parallel_ts = 1,
+};
+
+static int gl861_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       if ((adap->fe = dvb_attach(zl10353_attach, &gl861_zl10353_config,
+                                  &adap->dev->i2c_adap)) != NULL) {
+               return 0;
+       }
+
+       return -EIO;
+}
+
+static struct qt1010_config gl861_qt1010_config = {
+       .i2c_address = 0xc4
+};
+
+static int gl861_tuner_attach(struct dvb_usb_adapter *adap)
+{
+       return dvb_attach(qt1010_attach,
+                         adap->fe, &adap->dev->i2c_adap,
+                         &gl861_qt1010_config) == NULL ? -ENODEV : 0;
+}
+
+/* DVB USB Driver stuff */
+static struct dvb_usb_device_properties gl861_properties;
+
+static int gl861_probe(struct usb_interface *intf,
+                      const struct usb_device_id *id)
+{
+       struct dvb_usb_device *d;
+       struct usb_host_interface *alt;
+       int ret;
+
+       if (intf->num_altsetting < 2)
+               return -ENODEV;
+
+       if ((ret = dvb_usb_device_init(intf, &gl861_properties, THIS_MODULE, &d)) == 0) {
+               alt = usb_altnum_to_altsetting(intf, 0);
+
+               if (alt == NULL) {
+                       deb_rc("not alt found!\n");
+                       return -ENODEV;
+               }
+
+               ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber,
+                                       alt->desc.bAlternateSetting);
+       }
+
+       return ret;
+}
+
+static struct usb_device_id gl861_table [] = {
+               { USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580_55801) },
+               { }             /* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, gl861_table);
+
+static struct dvb_usb_device_properties gl861_properties = {
+       .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+       .usb_ctrl = DEVICE_SPECIFIC,
+
+       .size_of_priv     = 0,
+
+       .identify_state   = gl861_identify_state,
+       .num_adapters = 1,
+       .adapter = {{
+
+               .frontend_attach  = gl861_frontend_attach,
+               .tuner_attach     = gl861_tuner_attach,
+
+               .stream = {
+                       .type = USB_BULK,
+                       .count = 7,
+                       .endpoint = 0x81,
+                       .u = {
+                               .bulk = {
+                                       .buffersize = 512,
+                               }
+                       }
+               },
+       }},
+       .i2c_algo         = &gl861_i2c_algo,
+
+       .num_device_descs = 1,
+       .devices = {
+               {   "MSI Mega Sky 55801 DVB-T USB2.0",
+                       { &gl861_table[0], NULL },
+                       { NULL },
+               },
+       }
+};
+
+static struct usb_driver gl861_driver = {
+       .name           = "dvb_usb_gl861",
+       .probe          = gl861_probe,
+       .disconnect     = dvb_usb_device_exit,
+       .id_table       = gl861_table,
+};
+
+/* module stuff */
+static int __init gl861_module_init(void)
+{
+       int ret;
+
+       if ((ret = usb_register(&gl861_driver))) {
+               err("usb_register failed. Error number %d", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static void __exit gl861_module_exit(void)
+{
+       /* deregister this driver from the USB subsystem */
+       usb_deregister(&gl861_driver);
+}
+
+module_init (gl861_module_init);
+module_exit (gl861_module_exit);
+
+MODULE_AUTHOR("Carl Lundqvist <comabug@gmail.com>");
+MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / GL861");
+MODULE_VERSION("0.1");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/gl861.h b/drivers/media/dvb/dvb-usb/gl861.h
new file mode 100644 (file)
index 0000000..72a51af
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef _DVB_USB_GL861_H_
+#define _DVB_USB_GL861_H_
+
+#define DVB_USB_LOG_PREFIX "gl861"
+#include "dvb-usb.h"
+
+#define deb_rc(args...)   dprintk(dvb_usb_gl861_debug,0x01,args)
+
+#define GL861_WRITE            0x40
+#define GL861_READ             0xc0
+
+#define GL861_REQ_I2C_WRITE    0x01
+#define GL861_REQ_I2C_READ     0x02
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c
new file mode 100644 (file)
index 0000000..d48b24d
--- /dev/null
@@ -0,0 +1,541 @@
+/* DVB USB compliant linux driver for MSI Mega Sky 580 DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2006 Aapo Tahkola (aet@rasterburn.org)
+ *
+ *     This program is free software; you can redistribute it and/or modify it
+ *     under the terms of the GNU General Public License as published by the Free
+ *     Software Foundation, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+
+#include "m920x.h"
+
+#include "mt352.h"
+#include "mt352_priv.h"
+#include "qt1010.h"
+
+/* debug */
+static int dvb_usb_m920x_debug;
+module_param_named(debug,dvb_usb_m920x_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+
+static struct dvb_usb_rc_key megasky_rc_keys [] = {
+       { 0x0, 0x12, KEY_POWER },
+       { 0x0, 0x1e, KEY_CYCLEWINDOWS }, /* min/max */
+       { 0x0, 0x02, KEY_CHANNELUP },
+       { 0x0, 0x05, KEY_CHANNELDOWN },
+       { 0x0, 0x03, KEY_VOLUMEUP },
+       { 0x0, 0x06, KEY_VOLUMEDOWN },
+       { 0x0, 0x04, KEY_MUTE },
+       { 0x0, 0x07, KEY_OK }, /* TS */
+       { 0x0, 0x08, KEY_STOP },
+       { 0x0, 0x09, KEY_MENU }, /* swap */
+       { 0x0, 0x0a, KEY_REWIND },
+       { 0x0, 0x1b, KEY_PAUSE },
+       { 0x0, 0x1f, KEY_FASTFORWARD },
+       { 0x0, 0x0c, KEY_RECORD },
+       { 0x0, 0x0d, KEY_CAMERA }, /* screenshot */
+       { 0x0, 0x0e, KEY_COFFEE }, /* "MTS" */
+};
+
+static inline int m9206_read(struct usb_device *udev, u8 request, u16 value,\
+                            u16 index, void *data, int size)
+{
+       int ret;
+
+       ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+                             request, USB_TYPE_VENDOR | USB_DIR_IN,
+                             value, index, data, size, 2000);
+       if (ret < 0)
+               return ret;
+
+       if (ret != size)
+               return -EIO;
+
+       return 0;
+}
+
+static inline int m9206_write(struct usb_device *udev, u8 request,
+                             u16 value, u16 index)
+{
+       int ret;
+
+       ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                             request, USB_TYPE_VENDOR | USB_DIR_OUT,
+                             value, index, NULL, 0, 2000);
+       return ret;
+}
+
+static int m9206_rc_init(struct usb_device *udev)
+{
+       int ret = 0;
+
+       /* Remote controller init. */
+       if ((ret = m9206_write(udev, M9206_CORE, 0xa8, M9206_RC_INIT2)) != 0)
+               return ret;
+
+       if ((ret = m9206_write(udev, M9206_CORE, 0x51, M9206_RC_INIT1)) != 0)
+               return ret;
+
+       return ret;
+}
+
+static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+       struct m9206_state *m = d->priv;
+       int i, ret = 0;
+       u8 rc_state[2];
+
+
+       if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0)
+               goto unlock;
+
+       if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0)
+               goto unlock;
+
+       for (i = 0; i < ARRAY_SIZE(megasky_rc_keys); i++)
+               if (megasky_rc_keys[i].data == rc_state[1]) {
+                       *event = megasky_rc_keys[i].event;
+
+                       switch(rc_state[0]) {
+                       case 0x80:
+                               *state = REMOTE_NO_KEY_PRESSED;
+                               goto unlock;
+
+                       case 0x93:
+                       case 0x92:
+                               m->rep_count = 0;
+                               *state = REMOTE_KEY_PRESSED;
+                               goto unlock;
+
+                       case 0x91:
+                               /* For comfort. */
+                               if (++m->rep_count > 2)
+                                       *state = REMOTE_KEY_REPEAT;
+                               goto unlock;
+
+                       default:
+                               deb_rc("Unexpected rc response %x\n", rc_state[0]);
+                               *state = REMOTE_NO_KEY_PRESSED;
+                               goto unlock;
+                       }
+               }
+
+       if (rc_state[1] != 0)
+               deb_rc("Unknown rc key %x\n", rc_state[1]);
+
+       *state = REMOTE_NO_KEY_PRESSED;
+
+       unlock:
+
+       return ret;
+}
+
+/* I2C */
+static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+                         int num)
+{
+       struct dvb_usb_device *d = i2c_get_adapdata(adap);
+       struct m9206_state *m = d->priv;
+       int i;
+       int ret = 0;
+
+       if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+               return -EAGAIN;
+
+       if (num > 2)
+               return -EINVAL;
+
+       for (i = 0; i < num; i++) {
+               if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].addr, 0x80)) != 0)
+                       goto unlock;
+
+               if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[0], 0x0)) != 0)
+                       goto unlock;
+
+               if (i + 1 < num && msg[i + 1].flags & I2C_M_RD) {
+                       int i2c_i;
+
+                       for (i2c_i = 0; i2c_i < M9206_I2C_MAX; i2c_i++)
+                               if (msg[i].addr == m->i2c_r[i2c_i].addr)
+                                       break;
+
+                       if (i2c_i >= M9206_I2C_MAX) {
+                               deb_rc("No magic for i2c addr!\n");
+                               ret = -EINVAL;
+                               goto unlock;
+                       }
+
+                       if ((ret = m9206_write(d->udev, M9206_I2C, m->i2c_r[i2c_i].magic, 0x80)) != 0)
+                               goto unlock;
+
+                       if ((ret = m9206_read(d->udev, M9206_I2C, 0x0, 0x60, msg[i + 1].buf, msg[i + 1].len)) != 0)
+                               goto unlock;
+
+                       i++;
+               } else {
+                       if (msg[i].len != 2)
+                               return -EINVAL;
+
+                       if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[1], 0x40)) != 0)
+                               goto unlock;
+               }
+       }
+       ret = i;
+       unlock:
+       mutex_unlock(&d->i2c_mutex);
+
+       return ret;
+}
+
+static u32 m9206_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm m9206_i2c_algo = {
+       .master_xfer   = m9206_i2c_xfer,
+       .functionality = m9206_i2c_func,
+};
+
+
+static int m9206_set_filter(struct dvb_usb_adapter *adap, int type, int idx,
+                           int pid)
+{
+       int ret = 0;
+
+       if (pid >= 0x8000)
+               return -EINVAL;
+
+       pid |= 0x8000;
+
+       if ((ret = m9206_write(adap->dev->udev, M9206_FILTER, pid, (type << 8) | (idx * 4) )) != 0)
+               return ret;
+
+       if ((ret = m9206_write(adap->dev->udev, M9206_FILTER, 0, (type << 8) | (idx * 4) )) != 0)
+               return ret;
+
+       return ret;
+}
+
+static int m9206_update_filters(struct dvb_usb_adapter *adap)
+{
+       struct m9206_state *m = adap->dev->priv;
+       int enabled = m->filtering_enabled;
+       int i, ret = 0, filter = 0;
+
+       for (i = 0; i < M9206_MAX_FILTERS; i++)
+               if (m->filters[i] == 8192)
+                       enabled = 0;
+
+       /* Disable all filters */
+       if ((ret = m9206_set_filter(adap, 0x81, 1, enabled)) != 0)
+               return ret;
+
+       for (i = 0; i < M9206_MAX_FILTERS; i++)
+               if ((ret = m9206_set_filter(adap, 0x81, i + 2, 0)) != 0)
+                       return ret;
+
+       if ((ret = m9206_set_filter(adap, 0x82, 0, 0x0)) != 0)
+               return ret;
+
+       /* Set */
+       if (enabled) {
+               for (i = 0; i < M9206_MAX_FILTERS; i++) {
+                       if (m->filters[i] == 0)
+                               continue;
+
+                       if ((ret = m9206_set_filter(adap, 0x81, filter + 2, m->filters[i])) != 0)
+                               return ret;
+
+                       filter++;
+               }
+       }
+
+       if ((ret = m9206_set_filter(adap, 0x82, 0, 0x02f5)) != 0)
+               return ret;
+
+       return ret;
+}
+
+static int m9206_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+       struct m9206_state *m = adap->dev->priv;
+
+       m->filtering_enabled = onoff ? 1 : 0;
+
+       return m9206_update_filters(adap);
+}
+
+static int m9206_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
+                           int onoff)
+{
+       struct m9206_state *m = adap->dev->priv;
+
+       m->filters[index] = onoff ? pid : 0;
+
+       return m9206_update_filters(adap);
+}
+
+static int m9206_firmware_download(struct usb_device *udev,
+                                  const struct firmware *fw)
+{
+       u16 value, index, size;
+       u8 read[4], *buff;
+       int i, pass, ret = 0;
+
+       buff = kmalloc(65536, GFP_KERNEL);
+
+       if ((ret = m9206_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0)
+               goto done;
+       deb_rc("%x %x %x %x\n", read[0], read[1], read[2], read[3]);
+
+       if ((ret = m9206_read(udev, M9206_FW, 0x0, 0x0, read, 1)) != 0)
+               goto done;
+       deb_rc("%x\n", read[0]);
+
+       for (pass = 0; pass < 2; pass++) {
+               for (i = 0; i + (sizeof(u16) * 3) < fw->size;) {
+                       value = le16_to_cpu(*(u16 *)(fw->data + i));
+                       i += sizeof(u16);
+
+                       index = le16_to_cpu(*(u16 *)(fw->data + i));
+                       i += sizeof(u16);
+
+                       size = le16_to_cpu(*(u16 *)(fw->data + i));
+                       i += sizeof(u16);
+
+                       if (pass == 1) {
+                               /* Will stall if using fw->data ... */
+                               memcpy(buff, fw->data + i, size);
+
+                               ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0),
+                                           M9206_FW,
+                                           USB_TYPE_VENDOR | USB_DIR_OUT,
+                                           value, index, buff, size, 20);
+                               if (ret != size) {
+                                       deb_rc("error while uploading fw!\n");
+                                       ret = -EIO;
+                                       goto done;
+                               }
+                               msleep(3);
+                       }
+                       i += size;
+               }
+               if (i != fw->size) {
+                       ret = -EINVAL;
+                       goto done;
+               }
+       }
+
+       msleep(36);
+
+       /* m9206 will disconnect itself from the bus after this. */
+       (void) m9206_write(udev, M9206_CORE, 0x01, M9206_FW_GO);
+       deb_rc("firmware uploaded!\n");
+
+       done:
+       kfree(buff);
+
+       return ret;
+}
+
+/* Callbacks for DVB USB */
+static int megasky_identify_state(struct usb_device *udev,
+                                 struct dvb_usb_device_properties *props,
+                                 struct dvb_usb_device_description **desc,
+                                 int *cold)
+{
+       struct usb_host_interface *alt;
+
+       alt = usb_altnum_to_altsetting(usb_ifnum_to_if(udev, 0), 1);
+       *cold = (alt == NULL) ? 1 : 0;
+
+       return 0;
+}
+
+static int megasky_mt352_demod_init(struct dvb_frontend *fe)
+{
+       u8 config[] = { CONFIG, 0x3d };
+       u8 clock[] = { CLOCK_CTL, 0x30 };
+       u8 reset[] = { RESET, 0x80 };
+       u8 adc_ctl[] = { ADC_CTL_1, 0x40 };
+       u8 agc[] = { AGC_TARGET, 0x1c, 0x20 };
+       u8 sec_agc[] = { 0x69, 0x00, 0xff, 0xff, 0x40, 0xff, 0x00, 0x40, 0x40 };
+       u8 unk1[] = { 0x93, 0x1a };
+       u8 unk2[] = { 0xb5, 0x7a };
+
+       mt352_write(fe, config, ARRAY_SIZE(config));
+       mt352_write(fe, clock, ARRAY_SIZE(clock));
+       mt352_write(fe, reset, ARRAY_SIZE(reset));
+       mt352_write(fe, adc_ctl, ARRAY_SIZE(adc_ctl));
+       mt352_write(fe, agc, ARRAY_SIZE(agc));
+       mt352_write(fe, sec_agc, ARRAY_SIZE(sec_agc));
+       mt352_write(fe, unk1, ARRAY_SIZE(unk1));
+       mt352_write(fe, unk2, ARRAY_SIZE(unk2));
+
+       deb_rc("Demod init!\n");
+
+       return 0;
+}
+
+static struct mt352_config megasky_mt352_config = {
+       .demod_address = 0x1e,
+       .no_tuner = 1,
+       .demod_init = megasky_mt352_demod_init,
+};
+
+static int megasky_mt352_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       struct m9206_state *m = adap->dev->priv;
+
+       deb_rc("megasky_frontend_attach!\n");
+
+       m->i2c_r[M9206_I2C_DEMOD].addr = megasky_mt352_config.demod_address;
+       m->i2c_r[M9206_I2C_DEMOD].magic = 0x1f;
+
+       if ((adap->fe = dvb_attach(mt352_attach, &megasky_mt352_config, &adap->dev->i2c_adap)) == NULL)
+               return -EIO;
+
+       return 0;
+}
+
+static struct qt1010_config megasky_qt1010_config = {
+       .i2c_address = 0xc4
+};
+
+static int megasky_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
+{
+       struct m9206_state *m = adap->dev->priv;
+
+       m->i2c_r[M9206_I2C_TUNER].addr = megasky_qt1010_config.i2c_address;
+       m->i2c_r[M9206_I2C_TUNER].magic = 0xc5;
+
+       if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap,
+                      &megasky_qt1010_config) == NULL)
+               return -ENODEV;
+
+       return 0;
+}
+
+/* DVB USB Driver stuff */
+static struct dvb_usb_device_properties megasky_properties;
+
+static int m920x_probe(struct usb_interface *intf,
+                      const struct usb_device_id *id)
+{
+       struct dvb_usb_device *d;
+       struct usb_host_interface *alt;
+       int ret;
+
+       if ((ret = dvb_usb_device_init(intf, &megasky_properties, THIS_MODULE, &d)) == 0) {
+               deb_rc("probed!\n");
+
+               alt = usb_altnum_to_altsetting(intf, 1);
+               if (alt == NULL) {
+                       deb_rc("not alt found!\n");
+                       return -ENODEV;
+               }
+
+               ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber,
+                                       alt->desc.bAlternateSetting);
+               if (ret < 0)
+                       return ret;
+
+               deb_rc("Changed to alternate setting!\n");
+
+               if ((ret = m9206_rc_init(d->udev)) != 0)
+                       return ret;
+       }
+       return ret;
+}
+
+static struct usb_device_id m920x_table [] = {
+               { USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580) },
+               { }             /* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, m920x_table);
+
+static struct dvb_usb_device_properties megasky_properties = {
+       .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+       .usb_ctrl = DEVICE_SPECIFIC,
+       .firmware = "dvb-usb-megasky-02.fw",
+       .download_firmware = m9206_firmware_download,
+
+       .rc_interval      = 100,
+       .rc_key_map       = megasky_rc_keys,
+       .rc_key_map_size  = ARRAY_SIZE(megasky_rc_keys),
+       .rc_query         = m9206_rc_query,
+
+       .size_of_priv     = sizeof(struct m9206_state),
+
+       .identify_state   = megasky_identify_state,
+       .num_adapters = 1,
+       .adapter = {{
+               .caps = DVB_USB_ADAP_HAS_PID_FILTER |
+                       DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+
+               .pid_filter_count = 8,
+               .pid_filter       = m9206_pid_filter,
+               .pid_filter_ctrl  = m9206_pid_filter_ctrl,
+
+               .frontend_attach  = megasky_mt352_frontend_attach,
+               .tuner_attach     = megasky_qt1010_tuner_attach,
+
+               .stream = {
+                       .type = USB_BULK,
+                       .count = 8,
+                       .endpoint = 0x81,
+                       .u = {
+                               .bulk = {
+                                       .buffersize = 512,
+                               }
+                       }
+               },
+       }},
+       .i2c_algo         = &m9206_i2c_algo,
+
+       .num_device_descs = 1,
+       .devices = {
+               {   "MSI Mega Sky 580 DVB-T USB2.0",
+                       { &m920x_table[0], NULL },
+                       { NULL },
+               },
+       }
+};
+
+static struct usb_driver m920x_driver = {
+       .name           = "dvb_usb_m920x",
+       .probe          = m920x_probe,
+       .disconnect     = dvb_usb_device_exit,
+       .id_table       = m920x_table,
+};
+
+/* module stuff */
+static int __init m920x_module_init(void)
+{
+       int ret;
+
+       if ((ret = usb_register(&m920x_driver))) {
+               err("usb_register failed. Error number %d", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static void __exit m920x_module_exit(void)
+{
+       /* deregister this driver from the USB subsystem */
+       usb_deregister(&m920x_driver);
+}
+
+module_init (m920x_module_init);
+module_exit (m920x_module_exit);
+
+MODULE_AUTHOR("Aapo Tahkola <aet@rasterburn.org>");
+MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / Uli m920x");
+MODULE_VERSION("0.1");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/m920x.h b/drivers/media/dvb/dvb-usb/m920x.h
new file mode 100644 (file)
index 0000000..c354196
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef _DVB_USB_M920X_H_
+#define _DVB_USB_M920X_H_
+
+#define DVB_USB_LOG_PREFIX "m920x"
+#include "dvb-usb.h"
+
+#define deb_rc(args...)   dprintk(dvb_usb_m920x_debug,0x01,args)
+
+#define M9206_CORE     0x22
+#define M9206_RC_STATE 0xff51
+#define M9206_RC_KEY   0xff52
+#define M9206_RC_INIT1 0xff54
+#define M9206_RC_INIT2 0xff55
+#define M9206_FW_GO    0xff69
+
+#define M9206_I2C      0x23
+#define M9206_FILTER   0x25
+#define M9206_FW       0x30
+
+#define M9206_MAX_FILTERS 8
+
+#define M9206_I2C_TUNER        0
+#define M9206_I2C_DEMOD        1
+#define M9206_I2C_MAX  2
+
+struct m9206_state {
+       u16 filters[M9206_MAX_FILTERS];
+       int filtering_enabled;
+       int rep_count;
+       struct {
+               unsigned char addr;
+               unsigned char magic;
+       }i2c_r[M9206_I2C_MAX];
+};
+#endif
index af314bb1dcac47b35a4435949bff85a4ede0afb8..22c2cf2cea9885a4a967ae4c290a9c2c76a69601 100644 (file)
@@ -290,6 +290,13 @@ config DVB_TDA826X
        help
          A DVB-S silicon tuner module. Say Y when you want to support this tuner.
 
+config DVB_TUNER_QT1010
+       tristate "Quantek QT1010 silicon tuner"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A driver for the silicon tuner QT1010 from Quantek.
+
 config DVB_TUNER_MT2060
        tristate "Microtune MT2060 silicon IF tuner"
        depends on I2C
index 3fa6e5d32a9cfa870610db0819943a9936014cdd..a646d9969b717d5ff4b52ed0162652536602b942 100644 (file)
@@ -38,5 +38,6 @@ obj-$(CONFIG_DVB_ISL6421) += isl6421.o
 obj-$(CONFIG_DVB_TDA10086) += tda10086.o
 obj-$(CONFIG_DVB_TDA826X) += tda826x.o
 obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o
+obj-$(CONFIG_DVB_TUNER_QT1010) += qt1010.o
 obj-$(CONFIG_DVB_TUA6100) += tua6100.o
 obj-$(CONFIG_DVB_TUNER_LGH06XF) += lgh06xf.o
index ae96395217a2e475c2c79a9b2b21ca62b2ac18bf..10fc0c8316dd2dab1d1bb48171a367c8f25a0fc9 100644 (file)
@@ -254,7 +254,7 @@ static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate)
        if (srate<500000)
                srate=500000;
 
-       for(i=0;(i<sizeof(bands)/sizeof(bands[0]))&&(srate>bands[i]);i++)
+       for(i = 0; (i < ARRAY_SIZE(bands)) && (srate>bands[i]); i++)
                ;
        /* first, check which sample rate is appropriate: 45, 60 80 or 90 MHz,
           and set the PLL accordingly (R07[1:0] Fclk, R06[7:4] PLLmult,
@@ -361,7 +361,7 @@ static int cx24110_initfe(struct dvb_frontend* fe)
 
        dprintk("%s: init chip\n", __FUNCTION__);
 
-       for(i=0;i<sizeof(cx24110_regdata)/sizeof(cx24110_regdata[0]);i++) {
+       for(i = 0; i < ARRAY_SIZE(cx24110_regdata); i++) {
                cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data);
        };
 
index a356d28fc3bb25af35b9b32e6ae2d0c138a1bf14..732e94aaa364779f53920780f7b04a5dc7e0e5fa 100644 (file)
@@ -507,7 +507,7 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa
        int i = 0;
        int pump = 2;
        int band = 0;
-       int num_bands = sizeof(cx24123_bandselect_vals) / sizeof(cx24123_bandselect_vals[0]);
+       int num_bands = ARRAY_SIZE(cx24123_bandselect_vals);
 
        /* Defaults for low freq, low rate */
        state->VCAarg = cx24123_AGC_vals[0].VCAprogdata;
@@ -516,7 +516,7 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa
        vco_div = cx24123_bandselect_vals[0].VCOdivider;
 
        /* For the given symbol rate, determine the VCA, VGA and FILTUNE programming bits */
-       for (i = 0; i < sizeof(cx24123_AGC_vals) / sizeof(cx24123_AGC_vals[0]); i++)
+       for (i = 0; i < ARRAY_SIZE(cx24123_AGC_vals); i++)
        {
                if ((cx24123_AGC_vals[i].symbolrate_low <= p->u.qpsk.symbol_rate) &&
                    (cx24123_AGC_vals[i].symbolrate_high >= p->u.qpsk.symbol_rate) ) {
@@ -658,7 +658,7 @@ static int cx24123_initfe(struct dvb_frontend* fe)
        dprintk("%s:  init frontend\n",__FUNCTION__);
 
        /* Configure the demod to a good set of defaults */
-       for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++)
+       for (i = 0; i < ARRAY_SIZE(cx24123_regdata); i++)
                cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data);
 
        /* Set the LNB polarity */
index 23aa75a27c1f7fda92a52099b6427891878a4677..054d7e6d9662d5715e59b1d7e30ce1f0bbab4701 100644 (file)
@@ -475,7 +475,7 @@ static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dibx
        tmp = ((chan->nfft & 0x1) << 7) | (chan->guard << 5) | (chan->nqam << 3) | chan->vit_alpha;
        dib3000mc_write_word(state, 0, tmp);
 
-       dib3000mc_write_word(state, 5, seq);
+       dib3000mc_write_word(state, 5, (1 << 8) | ((seq & 0xf) << 4));
 
        tmp = (chan->vit_hrch << 4) | (chan->vit_select_hp);
        if (!chan->vit_hrch || (chan->vit_hrch && chan->vit_select_hp))
diff --git a/drivers/media/dvb/frontends/qt1010.c b/drivers/media/dvb/frontends/qt1010.c
new file mode 100644 (file)
index 0000000..825aa14
--- /dev/null
@@ -0,0 +1,485 @@
+/*
+ *  Driver for Quantek QT1010 silicon tuner
+ *
+ *  Copyright (C) 2006 Antti Palosaari <crope@iki.fi>
+ *                     Aapo Tahkola <aet@rasterburn.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "qt1010.h"
+#include "qt1010_priv.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+#define dprintk(args...) \
+       do { \
+               if (debug) printk(KERN_DEBUG "QT1010: " args); \
+       } while (0)
+
+/* read single register */
+static int qt1010_readreg(struct qt1010_priv *priv, u8 reg, u8 *val)
+{
+       struct i2c_msg msg[2] = {
+               { .addr = priv->cfg->i2c_address,
+                 .flags = 0, .buf = &reg, .len = 1 },
+               { .addr = priv->cfg->i2c_address,
+                 .flags = I2C_M_RD, .buf = val, .len = 1 },
+       };
+
+       if (i2c_transfer(priv->i2c, msg, 2) != 2) {
+               printk(KERN_WARNING "qt1010 I2C read failed\n");
+               return -EREMOTEIO;
+       }
+       return 0;
+}
+
+/* write single register */
+static int qt1010_writereg(struct qt1010_priv *priv, u8 reg, u8 val)
+{
+       u8 buf[2] = { reg, val };
+       struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
+                              .flags = 0, .buf = buf, .len = 2 };
+
+       if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+               printk(KERN_WARNING "qt1010 I2C write failed\n");
+               return -EREMOTEIO;
+       }
+       return 0;
+}
+
+/* dump all registers */
+static void qt1010_dump_regs(struct qt1010_priv *priv)
+{
+       char buf[52], buf2[4];
+       u8 reg, val;
+
+       for (reg = 0; ; reg++) {
+               if (reg % 16 == 0) {
+                       if (reg)
+                               printk("%s\n", buf);
+                       sprintf(buf, "%02x: ", reg);
+               }
+               if (qt1010_readreg(priv, reg, &val) == 0)
+                       sprintf(buf2, "%02x ", val);
+               else
+                       strcpy(buf2, "-- ");
+               strcat(buf, buf2);
+               if (reg == 0x2f)
+                       break;
+       }
+       printk("%s\n", buf);
+}
+
+static int qt1010_set_params(struct dvb_frontend *fe,
+                            struct dvb_frontend_parameters *params)
+{
+       struct qt1010_priv *priv;
+       int err;
+       u32 freq, div, mod1, mod2;
+       u8 i, tmpval, reg05;
+       qt1010_i2c_oper_t rd[48] = {
+               { QT1010_WR, 0x01, 0x80 },
+               { QT1010_WR, 0x02, 0x3f },
+               { QT1010_WR, 0x05, 0xff }, /* 02 c write */
+               { QT1010_WR, 0x06, 0x44 },
+               { QT1010_WR, 0x07, 0xff }, /* 04 c write */
+               { QT1010_WR, 0x08, 0x08 },
+               { QT1010_WR, 0x09, 0xff }, /* 06 c write */
+               { QT1010_WR, 0x0a, 0xff }, /* 07 c write */
+               { QT1010_WR, 0x0b, 0xff }, /* 08 c write */
+               { QT1010_WR, 0x0c, 0xe1 },
+               { QT1010_WR, 0x1a, 0xff }, /* 10 c write */
+               { QT1010_WR, 0x1b, 0x00 },
+               { QT1010_WR, 0x1c, 0x89 },
+               { QT1010_WR, 0x11, 0xff }, /* 13 c write */
+               { QT1010_WR, 0x12, 0xff }, /* 14 c write */
+               { QT1010_WR, 0x22, 0xff }, /* 15 c write */
+               { QT1010_WR, 0x1e, 0x00 },
+               { QT1010_WR, 0x1e, 0xd0 },
+               { QT1010_RD, 0x22, 0xff }, /* 16 c read */
+               { QT1010_WR, 0x1e, 0x00 },
+               { QT1010_RD, 0x05, 0xff }, /* 20 c read */
+               { QT1010_RD, 0x22, 0xff }, /* 21 c read */
+               { QT1010_WR, 0x23, 0xd0 },
+               { QT1010_WR, 0x1e, 0x00 },
+               { QT1010_WR, 0x1e, 0xe0 },
+               { QT1010_RD, 0x23, 0xff }, /* 25 c read */
+               { QT1010_RD, 0x23, 0xff }, /* 26 c read */
+               { QT1010_WR, 0x1e, 0x00 },
+               { QT1010_WR, 0x24, 0xd0 },
+               { QT1010_WR, 0x1e, 0x00 },
+               { QT1010_WR, 0x1e, 0xf0 },
+               { QT1010_RD, 0x24, 0xff }, /* 31 c read */
+               { QT1010_WR, 0x1e, 0x00 },
+               { QT1010_WR, 0x14, 0x7f },
+               { QT1010_WR, 0x15, 0x7f },
+               { QT1010_WR, 0x05, 0xff }, /* 35 c write */
+               { QT1010_WR, 0x06, 0x00 },
+               { QT1010_WR, 0x15, 0x1f },
+               { QT1010_WR, 0x16, 0xff },
+               { QT1010_WR, 0x18, 0xff },
+               { QT1010_WR, 0x1f, 0xff }, /* 40 c write */
+               { QT1010_WR, 0x20, 0xff }, /* 41 c write */
+               { QT1010_WR, 0x21, 0x53 },
+               { QT1010_WR, 0x25, 0xff }, /* 43 c write */
+               { QT1010_WR, 0x26, 0x15 },
+               { QT1010_WR, 0x00, 0xff }, /* 45 c write */
+               { QT1010_WR, 0x02, 0x00 },
+               { QT1010_WR, 0x01, 0x00 }
+       };
+
+#define FREQ1 32000000 /* 32 MHz */
+#define FREQ2  4000000 /* 4 MHz Quartz oscillator in the stick? */
+
+       priv = fe->tuner_priv;
+       freq = params->frequency;
+       div = (freq + QT1010_OFFSET) / QT1010_STEP;
+       freq = (div * QT1010_STEP) - QT1010_OFFSET;
+       mod1 = (freq + QT1010_OFFSET) % FREQ1;
+       mod2 = (freq + QT1010_OFFSET) % FREQ2;
+       priv->bandwidth =
+               (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
+       priv->frequency = freq;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
+
+       /* reg 05 base value */
+       if      (freq < 290000000) reg05 = 0x14; /* 290 MHz */
+       else if (freq < 610000000) reg05 = 0x34; /* 610 MHz */
+       else if (freq < 802000000) reg05 = 0x54; /* 802 MHz */
+       else                       reg05 = 0x74;
+
+       /* 0x5 */
+       rd[2].val = reg05;
+
+       /* 07 - set frequency: 32 MHz scale */
+       rd[4].val = (freq + QT1010_OFFSET) / FREQ1;
+
+       /* 09 - changes every 8/24 MHz */
+       if (mod1 < 8000000) rd[6].val = 0x1d;
+       else                rd[6].val = 0x1c;
+
+       /* 0a - set frequency: 4 MHz scale (max 28 MHz) */
+       if      (mod1 < 1*FREQ2) rd[7].val = 0x09; /*  +0 MHz */
+       else if (mod1 < 2*FREQ2) rd[7].val = 0x08; /*  +4 MHz */
+       else if (mod1 < 3*FREQ2) rd[7].val = 0x0f; /*  +8 MHz */
+       else if (mod1 < 4*FREQ2) rd[7].val = 0x0e; /* +12 MHz */
+       else if (mod1 < 5*FREQ2) rd[7].val = 0x0d; /* +16 MHz */
+       else if (mod1 < 6*FREQ2) rd[7].val = 0x0c; /* +20 MHz */
+       else if (mod1 < 7*FREQ2) rd[7].val = 0x0b; /* +24 MHz */
+       else                     rd[7].val = 0x0a; /* +28 MHz */
+
+       /* 0b - changes every 2/2 MHz */
+       if (mod2 < 2000000) rd[8].val = 0x45;
+       else                rd[8].val = 0x44;
+
+       /* 1a - set frequency: 125 kHz scale (max 3875 kHz)*/
+       tmpval = 0x78; /* byte, overflows intentionally */
+       rd[10].val = tmpval-((mod2/QT1010_STEP)*0x08);
+
+       /* 11 */
+       rd[13].val = 0xfd; /* TODO: correct value calculation */
+
+       /* 12 */
+       rd[14].val = 0x91; /* TODO: correct value calculation */
+
+       /* 22 */
+       if      (freq < 450000000) rd[15].val = 0xd0; /* 450 MHz */
+       else if (freq < 482000000) rd[15].val = 0xd1; /* 482 MHz */
+       else if (freq < 514000000) rd[15].val = 0xd4; /* 514 MHz */
+       else if (freq < 546000000) rd[15].val = 0xd7; /* 546 MHz */
+       else if (freq < 610000000) rd[15].val = 0xda; /* 610 MHz */
+       else                       rd[15].val = 0xd0;
+
+       /* 05 */
+       rd[35].val = (reg05 & 0xf0);
+
+       /* 1f */
+       if      (mod1 <  8000000) tmpval = 0x00;
+       else if (mod1 < 12000000) tmpval = 0x01;
+       else if (mod1 < 16000000) tmpval = 0x02;
+       else if (mod1 < 24000000) tmpval = 0x03;
+       else if (mod1 < 28000000) tmpval = 0x04;
+       else                      tmpval = 0x05;
+       rd[40].val = (priv->reg1f_init_val + 0x0e + tmpval);
+
+       /* 20 */
+       if      (mod1 <  8000000) tmpval = 0x00;
+       else if (mod1 < 12000000) tmpval = 0x01;
+       else if (mod1 < 20000000) tmpval = 0x02;
+       else if (mod1 < 24000000) tmpval = 0x03;
+       else if (mod1 < 28000000) tmpval = 0x04;
+       else                      tmpval = 0x05;
+       rd[41].val = (priv->reg20_init_val + 0x0d + tmpval);
+
+       /* 25 */
+       rd[43].val = priv->reg25_init_val;
+
+       /* 00 */
+       rd[45].val = 0x92; /* TODO: correct value calculation */
+
+       dprintk("freq:%u 05:%02x 07:%02x 09:%02x 0a:%02x 0b:%02x " \
+               "1a:%02x 11:%02x 12:%02x 22:%02x 05:%02x 1f:%02x " \
+               "20:%02x 25:%02x 00:%02x", \
+               freq, rd[2].val, rd[4].val, rd[6].val, rd[7].val, rd[8].val, \
+               rd[10].val, rd[13].val, rd[14].val, rd[15].val, rd[35].val, \
+               rd[40].val, rd[41].val, rd[43].val, rd[45].val);
+
+       for (i = 0; i < ARRAY_SIZE(rd); i++) {
+               if (rd[i].oper == QT1010_WR) {
+                       err = qt1010_writereg(priv, rd[i].reg, rd[i].val);
+               } else { /* read is required to proper locking */
+                       err = qt1010_readreg(priv, rd[i].reg, &tmpval);
+               }
+               if (err) return err;
+       }
+
+       if (debug)
+               qt1010_dump_regs(priv);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
+
+       return 0;
+}
+
+static int qt1010_init_meas1(struct qt1010_priv *priv,
+                            u8 oper, u8 reg, u8 reg_init_val, u8 *retval)
+{
+       u8 i, val1, val2;
+       int err;
+
+       qt1010_i2c_oper_t i2c_data[] = {
+               { QT1010_WR, reg, reg_init_val },
+               { QT1010_WR, 0x1e, 0x00 },
+               { QT1010_WR, 0x1e, oper },
+               { QT1010_RD, reg, 0xff }
+       };
+
+       for (i = 0; i < ARRAY_SIZE(i2c_data); i++) {
+               if (i2c_data[i].oper == QT1010_WR) {
+                       err = qt1010_writereg(priv, i2c_data[i].reg,
+                                             i2c_data[i].val);
+               } else {
+                       err = qt1010_readreg(priv, i2c_data[i].reg, &val2);
+               }
+               if (err) return err;
+       }
+
+       do {
+               val1 = val2;
+               err = qt1010_readreg(priv, reg, &val2);
+               if (err) return err;
+               dprintk("compare reg:%02x %02x %02x", reg, val1, val2);
+       } while (val1 != val2);
+       *retval = val1;
+
+       return qt1010_writereg(priv, 0x1e, 0x00);
+}
+
+static u8 qt1010_init_meas2(struct qt1010_priv *priv,
+                           u8 reg_init_val, u8 *retval)
+{
+       u8 i, val;
+       int err;
+       qt1010_i2c_oper_t i2c_data[] = {
+               { QT1010_WR, 0x07, reg_init_val },
+               { QT1010_WR, 0x22, 0xd0 },
+               { QT1010_WR, 0x1e, 0x00 },
+               { QT1010_WR, 0x1e, 0xd0 },
+               { QT1010_RD, 0x22, 0xff },
+               { QT1010_WR, 0x1e, 0x00 },
+               { QT1010_WR, 0x22, 0xff }
+       };
+       for (i = 0; i < ARRAY_SIZE(i2c_data); i++) {
+               if (i2c_data[i].oper == QT1010_WR) {
+                       err = qt1010_writereg(priv, i2c_data[i].reg,
+                                             i2c_data[i].val);
+               } else {
+                       err = qt1010_readreg(priv, i2c_data[i].reg, &val);
+               }
+               if (err) return err;
+       }
+       *retval = val;
+       return 0;
+}
+
+static int qt1010_init(struct dvb_frontend *fe)
+{
+       struct qt1010_priv *priv = fe->tuner_priv;
+       struct dvb_frontend_parameters params;
+       int err = 0;
+       u8 i, tmpval, *valptr = NULL;
+
+       qt1010_i2c_oper_t i2c_data[] = {
+               { QT1010_WR, 0x01, 0x80 },
+               { QT1010_WR, 0x0d, 0x84 },
+               { QT1010_WR, 0x0e, 0xb7 },
+               { QT1010_WR, 0x2a, 0x23 },
+               { QT1010_WR, 0x2c, 0xdc },
+               { QT1010_M1, 0x25, 0x40 }, /* get reg 25 init value */
+               { QT1010_M1, 0x81, 0xff }, /* get reg 25 init value */
+               { QT1010_WR, 0x2b, 0x70 },
+               { QT1010_WR, 0x2a, 0x23 },
+               { QT1010_M1, 0x26, 0x08 },
+               { QT1010_M1, 0x82, 0xff },
+               { QT1010_WR, 0x05, 0x14 },
+               { QT1010_WR, 0x06, 0x44 },
+               { QT1010_WR, 0x07, 0x28 },
+               { QT1010_WR, 0x08, 0x0b },
+               { QT1010_WR, 0x11, 0xfd },
+               { QT1010_M1, 0x22, 0x0d },
+               { QT1010_M1, 0xd0, 0xff },
+               { QT1010_WR, 0x06, 0x40 },
+               { QT1010_WR, 0x16, 0xf0 },
+               { QT1010_WR, 0x02, 0x38 },
+               { QT1010_WR, 0x03, 0x18 },
+               { QT1010_WR, 0x20, 0xe0 },
+               { QT1010_M1, 0x1f, 0x20 }, /* get reg 1f init value */
+               { QT1010_M1, 0x84, 0xff }, /* get reg 1f init value */
+               { QT1010_RD, 0x20, 0x20 }, /* get reg 20 init value */
+               { QT1010_WR, 0x03, 0x19 },
+               { QT1010_WR, 0x02, 0x3f },
+               { QT1010_WR, 0x21, 0x53 },
+               { QT1010_RD, 0x21, 0xff },
+               { QT1010_WR, 0x11, 0xfd },
+               { QT1010_WR, 0x05, 0x34 },
+               { QT1010_WR, 0x06, 0x44 },
+               { QT1010_WR, 0x08, 0x08 }
+       };
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
+
+       for (i = 0; i < ARRAY_SIZE(i2c_data); i++) {
+               switch (i2c_data[i].oper) {
+               case QT1010_WR:
+                       err = qt1010_writereg(priv, i2c_data[i].reg,
+                                             i2c_data[i].val);
+                       break;
+               case QT1010_RD:
+                       if (i2c_data[i].val == 0x20)
+                               valptr = &priv->reg20_init_val;
+                       else
+                               valptr = &tmpval;
+                       err = qt1010_readreg(priv, i2c_data[i].reg, valptr);
+                       break;
+               case QT1010_M1:
+                       if (i2c_data[i].val == 0x25)
+                               valptr = &priv->reg25_init_val;
+                       else if (i2c_data[i].val == 0x1f)
+                               valptr = &priv->reg1f_init_val;
+                       else
+                               valptr = &tmpval;
+                       err = qt1010_init_meas1(priv, i2c_data[i+1].reg,
+                                               i2c_data[i].reg,
+                                               i2c_data[i].val, valptr);
+                       i++;
+                       break;
+               }
+               if (err) return err;
+       }
+
+       for (i = 0x31; i < 0x3a; i++) /* 0x31 - 0x39 */
+               if ((err = qt1010_init_meas2(priv, i, &tmpval)))
+                       return err;
+
+       params.frequency = 545000000; /* Sigmatek DVB-110 545000000 */
+                                     /* MSI Megasky 580 GL861 533000000 */
+       return qt1010_set_params(fe, &params);
+}
+
+static int qt1010_release(struct dvb_frontend *fe)
+{
+       kfree(fe->tuner_priv);
+       fe->tuner_priv = NULL;
+       return 0;
+}
+
+static int qt1010_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+       struct qt1010_priv *priv = fe->tuner_priv;
+       *frequency = priv->frequency;
+       return 0;
+}
+
+static int qt1010_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+       struct qt1010_priv *priv = fe->tuner_priv;
+       *bandwidth = priv->bandwidth;
+       return 0;
+}
+
+static const struct dvb_tuner_ops qt1010_tuner_ops = {
+       .info = {
+               .name           = "Quantek QT1010",
+               .frequency_min  = QT1010_MIN_FREQ,
+               .frequency_max  = QT1010_MAX_FREQ,
+               .frequency_step = QT1010_STEP,
+       },
+
+       .release       = qt1010_release,
+       .init          = qt1010_init,
+       /* TODO: implement sleep */
+
+       .set_params    = qt1010_set_params,
+       .get_frequency = qt1010_get_frequency,
+       .get_bandwidth = qt1010_get_bandwidth
+};
+
+struct dvb_frontend * qt1010_attach(struct dvb_frontend *fe,
+                                   struct i2c_adapter *i2c,
+                                   struct qt1010_config *cfg)
+{
+       struct qt1010_priv *priv = NULL;
+       u8 id;
+
+       priv = kzalloc(sizeof(struct qt1010_priv), GFP_KERNEL);
+       if (priv == NULL)
+               return NULL;
+
+       priv->cfg = cfg;
+       priv->i2c = i2c;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
+
+
+       /* Try to detect tuner chip. Probably this is not correct register. */
+       if (qt1010_readreg(priv, 0x29, &id) != 0 || (id != 0x39)) {
+               kfree(priv);
+               return NULL;
+       }
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
+
+       printk(KERN_INFO "Quantek QT1010 successfully identified.\n");
+       memcpy(&fe->ops.tuner_ops, &qt1010_tuner_ops,
+              sizeof(struct dvb_tuner_ops));
+
+       fe->tuner_priv = priv;
+       return fe;
+}
+EXPORT_SYMBOL(qt1010_attach);
+
+MODULE_DESCRIPTION("Quantek QT1010 silicon tuner driver");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_AUTHOR("Aapo Tahkola <aet@rasterburn.org>");
+MODULE_VERSION("0.1");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/qt1010.h b/drivers/media/dvb/frontends/qt1010.h
new file mode 100644 (file)
index 0000000..3ab4aa0
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *  Driver for Quantek QT1010 silicon tuner
+ *
+ *  Copyright (C) 2006 Antti Palosaari <crope@iki.fi>
+ *                     Aapo Tahkola <aet@rasterburn.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef QT1010_H
+#define QT1010_H
+
+#include "dvb_frontend.h"
+
+struct qt1010_config {
+       u8 i2c_address;
+};
+
+/**
+ * Attach a qt1010 tuner to the supplied frontend structure.
+ *
+ * @param fe   frontend to attach to
+ * @param i2c  i2c adapter to use
+ * @param cfg  tuner hw based configuration
+ * @return fe  pointer on success, NULL on failure
+ */
+#if defined(CONFIG_DVB_TUNER_QT1010) || (defined(CONFIG_DVB_TUNER_QT1010_MODULE) && defined(MODULE))
+extern struct dvb_frontend *qt1010_attach(struct dvb_frontend *fe,
+                                         struct i2c_adapter *i2c,
+                                         struct qt1010_config *cfg);
+#else
+static inline struct dvb_frontend *qt1010_attach(struct dvb_frontend *fe,
+                                                struct i2c_adapter *i2c,
+                                                struct qt1010_config *cfg)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_TUNER_QT1010
+
+#endif
diff --git a/drivers/media/dvb/frontends/qt1010_priv.h b/drivers/media/dvb/frontends/qt1010_priv.h
new file mode 100644 (file)
index 0000000..090cf47
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ *  Driver for Quantek QT1010 silicon tuner
+ *
+ *  Copyright (C) 2006 Antti Palosaari <crope@iki.fi>
+ *                     Aapo Tahkola <aet@rasterburn.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef QT1010_PRIV_H
+#define QT1010_PRIV_H
+
+/*
+reg def meaning
+=== === =======
+00  00  ?
+01  a0  ? operation start/stop; start=80, stop=00
+02  00  ?
+03  19  ?
+04  00  ?
+05  00  ? maybe band selection
+06  00  ?
+07  2b  set frequency: 32 MHz scale, n*32 MHz
+08  0b  ?
+09  10  ? changes every 8/24 MHz; values 1d/1c
+0a  08  set frequency: 4 MHz scale, n*4 MHz
+0b  41  ? changes every 2/2 MHz; values 45/45
+0c  e1  ?
+0d  94  ?
+0e  b6  ?
+0f  2c  ?
+10  10  ?
+11  f1  ? maybe device specified adjustment
+12  11  ? maybe device specified adjustment
+13  3f  ?
+14  1f  ?
+15  3f  ?
+16  ff  ?
+17  ff  ?
+18  f7  ?
+19  80  ?
+1a  d0  set frequency: 125 kHz scale, n*125 kHz
+1b  00  ?
+1c  89  ?
+1d  00  ?
+1e  00  ? looks like operation register; write cmd here, read result from 1f-26
+1f  20  ? chip initialization
+20  e0  ? chip initialization
+21  20  ?
+22  d0  ?
+23  d0  ?
+24  d0  ?
+25  40  ? chip initialization
+26  08  ?
+27  29  ?
+28  55  ?
+29  39  ?
+2a  13  ?
+2b  01  ?
+2c  ea  ?
+2d  00  ?
+2e  00  ? not used?
+2f  00  ? not used?
+*/
+
+#define QT1010_STEP         125000 /*  125 kHz used by Windows drivers,
+                                     hw could be more precise but we don't
+                                     know how to use */
+#define QT1010_MIN_FREQ   48000000 /*   48 MHz */
+#define QT1010_MAX_FREQ  860000000 /*  860 MHz */
+#define QT1010_OFFSET   1246000000 /* 1246 MHz */
+
+#define QT1010_WR 0
+#define QT1010_RD 1
+#define QT1010_M1 3
+
+typedef struct {
+       u8 oper, reg, val;
+} qt1010_i2c_oper_t;
+
+struct qt1010_priv {
+       struct qt1010_config *cfg;
+       struct i2c_adapter   *i2c;
+
+       u8 reg1f_init_val;
+       u8 reg20_init_val;
+       u8 reg25_init_val;
+
+       u32 frequency;
+       u32 bandwidth;
+};
+
+#endif
index 1ca64249010ce54d4a3fa58946695396d22ccf74..9a343972ff50589c5a5fed69f78bd03a0ad8a270 100644 (file)
@@ -35,6 +35,7 @@ struct stv0297_state {
        const struct stv0297_config *config;
        struct dvb_frontend frontend;
 
+       unsigned long last_ber;
        unsigned long base_freq;
 };
 
@@ -310,6 +311,8 @@ static int stv0297_init(struct dvb_frontend *fe)
                stv0297_writereg(state, state->config->inittab[i], state->config->inittab[i+1]);
        msleep(200);
 
+       state->last_ber = 0;
+
        return 0;
 }
 
@@ -340,11 +343,13 @@ static int stv0297_read_ber(struct dvb_frontend *fe, u32 * ber)
        struct stv0297_state *state = fe->demodulator_priv;
        u8 BER[3];
 
-       stv0297_writereg(state, 0xA0, 0x80);    // Start Counting bit errors for 4096 Bytes
-       mdelay(25);             // Hopefully got 4096 Bytes
        stv0297_readregs(state, 0xA0, BER, 3);
-       mdelay(25);
-       *ber = (BER[2] << 8 | BER[1]) / (8 * 4096);
+       if (!(BER[0] & 0x80)) {
+               state->last_ber = BER[2] << 8 | BER[1];
+               stv0297_writereg_mask(state, 0xA0, 0x80, 0x80);
+       }
+
+       *ber = state->last_ber;
 
        return 0;
 }
@@ -376,9 +381,14 @@ static int stv0297_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks)
 {
        struct stv0297_state *state = fe->demodulator_priv;
 
+       stv0297_writereg_mask(state, 0xDF, 0x03, 0x03); /* freeze the counters */
+
        *ucblocks = (stv0297_readreg(state, 0xD5) << 8)
                | stv0297_readreg(state, 0xD4);
 
+       stv0297_writereg_mask(state, 0xDF, 0x03, 0x02); /* clear the counters */
+       stv0297_writereg_mask(state, 0xDF, 0x03, 0x01); /* re-enable the counters */
+
        return 0;
 }
 
@@ -648,6 +658,7 @@ struct dvb_frontend *stv0297_attach(const struct stv0297_config *config,
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
+       state->last_ber = 0;
        state->base_freq = 0;
 
        /* check if the demod is there */
index 93483769eca842bfabfcbd83c029fd7b1c3f4599..18768d2f6d40116ea827ad6bd1344a0dea5928a9 100644 (file)
@@ -92,7 +92,7 @@ static int stv0299_writeregI (struct stv0299_state* state, u8 reg, u8 data)
        return (ret != 1) ? -EREMOTEIO : 0;
 }
 
-int stv0299_write(struct dvb_frontend* fe, u8 *buf, int len)
+static int stv0299_write(struct dvb_frontend* fe, u8 *buf, int len)
 {
        struct stv0299_state* state = fe->demodulator_priv;
 
index dca89171be1fe232239cd5a143b8b4c855054fa6..5b9c5bb29b23392bde89d510aeac3759e338ed20 100644 (file)
@@ -201,7 +201,7 @@ static int tda10021_set_symbolrate (struct tda10021_state* state, u32 symbolrate
        return 0;
 }
 
-int tda10021_write(struct dvb_frontend* fe, u8 *buf, int len)
+static int tda10021_write(struct dvb_frontend* fe, u8 *buf, int len)
 {
        struct tda10021_state* state = fe->demodulator_priv;
 
index 00e4bcd9f1a4304e5ec99dbaeab0899af9b8de6e..f4a9cf9d26d07d11d44ceee4cdb378ebfe909a21 100644 (file)
@@ -579,7 +579,7 @@ static int tda1004x_decode_fec(int tdafec)
        return -1;
 }
 
-int tda1004x_write(struct dvb_frontend* fe, u8 *buf, int len)
+static int tda1004x_write(struct dvb_frontend* fe, u8 *buf, int len)
 {
        struct tda1004x_state* state = fe->demodulator_priv;
 
index 0e9b59af271edcb96a3ffdd89f5efe92897d8b62..245f9b7dddfa58cb6d4476bbb904755bd9216ca4 100644 (file)
@@ -38,6 +38,12 @@ struct zl10353_state {
        struct zl10353_config config;
 };
 
+static int debug;
+#define dprintk(args...) \
+       do { \
+               if (debug) printk(KERN_DEBUG "zl10353: " args); \
+       } while (0)
+
 static int debug_regs = 0;
 
 static int zl10353_single_write(struct dvb_frontend *fe, u8 reg, u8 val)
@@ -54,7 +60,7 @@ static int zl10353_single_write(struct dvb_frontend *fe, u8 reg, u8 val)
        return 0;
 }
 
-int zl10353_write(struct dvb_frontend *fe, u8 *ibuf, int ilen)
+static int zl10353_write(struct dvb_frontend *fe, u8 *ibuf, int ilen)
 {
        int err, i;
        for (i = 0; i < ilen - 1; i++)
@@ -113,6 +119,36 @@ static void zl10353_dump_regs(struct dvb_frontend *fe)
        printk(KERN_DEBUG "%s\n", buf);
 }
 
+static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
+                                     enum fe_bandwidth bandwidth,
+                                     u16 *nominal_rate)
+{
+       u32 adc_clock = 22528; /* 20.480 MHz on the board(!?) */
+       u8 bw;
+       struct zl10353_state *state = fe->demodulator_priv;
+
+       if (state->config.adc_clock)
+               adc_clock = state->config.adc_clock;
+
+       switch (bandwidth) {
+       case BANDWIDTH_6_MHZ:
+               bw = 6;
+               break;
+       case BANDWIDTH_7_MHZ:
+               bw = 7;
+               break;
+       case BANDWIDTH_8_MHZ:
+       default:
+               bw = 8;
+               break;
+       }
+
+       *nominal_rate = (64 * bw * (1<<16) / (7 * 8) * 4000 / adc_clock + 2) / 4;
+
+       dprintk("%s: bw %d, adc_clock %d => 0x%x\n",
+               __FUNCTION__, bw, adc_clock, *nominal_rate);
+}
+
 static int zl10353_sleep(struct dvb_frontend *fe)
 {
        static u8 zl10353_softdown[] = { 0x50, 0x0C, 0x44 };
@@ -125,7 +161,7 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
                                  struct dvb_frontend_parameters *param)
 {
        struct zl10353_state *state = fe->demodulator_priv;
-
+       u16 nominal_rate;
        u8 pllbuf[6] = { 0x67 };
 
        /* These settings set "auto-everything" and start the FSM. */
@@ -138,18 +174,23 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
        zl10353_single_write(fe, 0x56, 0x28);
        zl10353_single_write(fe, 0x89, 0x20);
        zl10353_single_write(fe, 0x5E, 0x00);
-       zl10353_single_write(fe, 0x65, 0x5A);
-       zl10353_single_write(fe, 0x66, 0xE9);
+
+       zl10353_calc_nominal_rate(fe, param->u.ofdm.bandwidth, &nominal_rate);
+       zl10353_single_write(fe, TRL_NOMINAL_RATE_1, msb(nominal_rate));
+       zl10353_single_write(fe, TRL_NOMINAL_RATE_0, lsb(nominal_rate));
+
        zl10353_single_write(fe, 0x6C, 0xCD);
        zl10353_single_write(fe, 0x6D, 0x7E);
-       zl10353_single_write(fe, 0x62, 0x0A);
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
 
        // if there is no attached secondary tuner, we call set_params to program
        // a potential tuner attached somewhere else
        if (state->config.no_tuner) {
                if (fe->ops.tuner_ops.set_params) {
                        fe->ops.tuner_ops.set_params(fe, param);
-                       if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+                       if (fe->ops.i2c_gate_ctrl)
+                               fe->ops.i2c_gate_ctrl(fe, 0);
                }
        }
 
@@ -213,6 +254,29 @@ static int zl10353_read_status(struct dvb_frontend *fe, fe_status_t *status)
        return 0;
 }
 
+static int zl10353_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+       struct zl10353_state *state = fe->demodulator_priv;
+
+       *ber = zl10353_read_register(state, RS_ERR_CNT_2) << 16 |
+              zl10353_read_register(state, RS_ERR_CNT_1) << 8 |
+              zl10353_read_register(state, RS_ERR_CNT_0);
+
+       return 0;
+}
+
+static int zl10353_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+       struct zl10353_state *state = fe->demodulator_priv;
+
+       u16 signal = zl10353_read_register(state, AGC_GAIN_1) << 10 |
+                    zl10353_read_register(state, AGC_GAIN_0) << 2 | 3;
+
+       *strength = ~signal;
+
+       return 0;
+}
+
 static int zl10353_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
        struct zl10353_state *state = fe->demodulator_priv;
@@ -227,6 +291,16 @@ static int zl10353_read_snr(struct dvb_frontend *fe, u16 *snr)
        return 0;
 }
 
+static int zl10353_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+       struct zl10353_state *state = fe->demodulator_priv;
+
+       *ucblocks = zl10353_read_register(state, RS_UBC_1) << 8 |
+                   zl10353_read_register(state, RS_UBC_0);
+
+       return 0;
+}
+
 static int zl10353_get_tune_settings(struct dvb_frontend *fe,
                                     struct dvb_frontend_tune_settings
                                         *fe_tune_settings)
@@ -261,6 +335,16 @@ static int zl10353_init(struct dvb_frontend *fe)
        return 0;
 }
 
+static int zl10353_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+       u8 val = 0x0a;
+
+       if (enable)
+               val |= 0x10;
+
+       return zl10353_single_write(fe, 0x62, val);
+}
+
 static void zl10353_release(struct dvb_frontend *fe)
 {
        struct zl10353_state *state = fe->demodulator_priv;
@@ -319,15 +403,22 @@ static struct dvb_frontend_ops zl10353_ops = {
 
        .init = zl10353_init,
        .sleep = zl10353_sleep,
+       .i2c_gate_ctrl = zl10353_i2c_gate_ctrl,
        .write = zl10353_write,
 
        .set_frontend = zl10353_set_parameters,
        .get_tune_settings = zl10353_get_tune_settings,
 
        .read_status = zl10353_read_status,
+       .read_ber = zl10353_read_ber,
+       .read_signal_strength = zl10353_read_signal_strength,
        .read_snr = zl10353_read_snr,
+       .read_ucblocks = zl10353_read_ucblocks,
 };
 
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
 module_param(debug_regs, int, 0644);
 MODULE_PARM_DESC(debug_regs, "Turn on/off frontend register dumps (default:off).");
 
index 0bc0109737f1b54380a2bca47dbd2b9137c4e0be..cb274dc12b82596ead31dfd1f5bf5667197992d5 100644 (file)
@@ -29,6 +29,9 @@ struct zl10353_config
        /* demodulator's I2C address */
        u8 demod_address;
 
+       /* frequencies in kHz */
+       int adc_clock;  // default: 22528
+
        /* set if no pll is connected to the secondary i2c bus */
        int no_tuner;
 
index b72224bd7ddebb512539c7daa43a6cc53922ac5b..4962434b35e751e94df246ea55548358e0d5b563 100644 (file)
 
 #define ID_ZL10353     0x14
 
+#define msb(x) (((x) >> 8) & 0xff)
+#define lsb(x) ((x) & 0xff)
+
 enum zl10353_reg_addr {
-       INTERRUPT_0     = 0x00,
-       INTERRUPT_1     = 0x01,
-       INTERRUPT_2     = 0x02,
-       INTERRUPT_3     = 0x03,
-       INTERRUPT_4     = 0x04,
-       INTERRUPT_5     = 0x05,
-       STATUS_6        = 0x06,
-       STATUS_7        = 0x07,
-       STATUS_8        = 0x08,
-       STATUS_9        = 0x09,
-       SNR             = 0x10,
-       CHIP_ID         = 0x7F,
+       INTERRUPT_0        = 0x00,
+       INTERRUPT_1        = 0x01,
+       INTERRUPT_2        = 0x02,
+       INTERRUPT_3        = 0x03,
+       INTERRUPT_4        = 0x04,
+       INTERRUPT_5        = 0x05,
+       STATUS_6           = 0x06,
+       STATUS_7           = 0x07,
+       STATUS_8           = 0x08,
+       STATUS_9           = 0x09,
+       AGC_GAIN_1         = 0x0A,
+       AGC_GAIN_0         = 0x0B,
+       SNR                = 0x10,
+       RS_ERR_CNT_2       = 0x11,
+       RS_ERR_CNT_1       = 0x12,
+       RS_ERR_CNT_0       = 0x13,
+       RS_UBC_1           = 0x14,
+       RS_UBC_0           = 0x15,
+       TRL_NOMINAL_RATE_1 = 0x65,
+       TRL_NOMINAL_RATE_0 = 0x66,
+       CHIP_ID            = 0x7F,
 };
 
 #endif                          /* _ZL10353_PRIV_ */
index 366c1371ee97dcf3e5eb41e8241fcc495a1aa5cc..29ed532ba966932e9d1c687e13057cfef63c393c 100644 (file)
@@ -51,6 +51,7 @@
 #include <linux/firmware.h>
 #include <linux/crc32.h>
 #include <linux/i2c.h>
+#include <linux/kthread.h>
 
 #include <asm/system.h>
 
@@ -223,11 +224,10 @@ static void recover_arm(struct av7110 *av7110)
 
 static void av7110_arm_sync(struct av7110 *av7110)
 {
-       av7110->arm_rmmod = 1;
-       wake_up_interruptible(&av7110->arm_wait);
+       if (av7110->arm_thread)
+               kthread_stop(av7110->arm_thread);
 
-       while (av7110->arm_thread)
-               msleep(1);
+       av7110->arm_thread = NULL;
 }
 
 static int arm_thread(void *data)
@@ -238,17 +238,11 @@ static int arm_thread(void *data)
 
        dprintk(4, "%p\n",av7110);
 
-       lock_kernel();
-       daemonize("arm_mon");
-       sigfillset(&current->blocked);
-       unlock_kernel();
-
-       av7110->arm_thread = current;
-
        for (;;) {
                timeout = wait_event_interruptible_timeout(av7110->arm_wait,
-                                                          av7110->arm_rmmod, 5 * HZ);
-               if (-ERESTARTSYS == timeout || av7110->arm_rmmod) {
+                       kthread_should_stop(), 5 * HZ);
+
+               if (-ERESTARTSYS == timeout || kthread_should_stop()) {
                        /* got signal or told to quit*/
                        break;
                }
@@ -276,7 +270,6 @@ static int arm_thread(void *data)
                av7110->arm_errors = 0;
        }
 
-       av7110->arm_thread = NULL;
        return 0;
 }
 
@@ -695,8 +688,8 @@ static void gpioirq(unsigned long data)
 static int dvb_osd_ioctl(struct inode *inode, struct file *file,
                         unsigned int cmd, void *parg)
 {
-       struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-       struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct av7110 *av7110 = dvbdev->priv;
 
        dprintk(4, "%p\n", av7110);
 
@@ -786,7 +779,7 @@ int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
 static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
 {
        struct dvb_demux_feed *dvbdmxfeed = dvbdmxfilter->feed;
-       struct av7110 *av7110 = (struct av7110 *) dvbdmxfeed->demux->priv;
+       struct av7110 *av7110 = dvbdmxfeed->demux->priv;
        u16 buf[20];
        int ret, i;
        u16 handle;
@@ -835,7 +828,7 @@ static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
 
 static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
 {
-       struct av7110 *av7110 = (struct av7110 *) dvbdmxfilter->feed->demux->priv;
+       struct av7110 *av7110 = dvbdmxfilter->feed->demux->priv;
        u16 buf[3];
        u16 answ[2];
        int ret;
@@ -871,7 +864,7 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
 static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
 {
        struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-       struct av7110 *av7110 = (struct av7110 *) dvbdmx->priv;
+       struct av7110 *av7110 = dvbdmx->priv;
        u16 *pid = dvbdmx->pids, npids[5];
        int i;
        int ret = 0;
@@ -914,7 +907,7 @@ static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
 static int dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed)
 {
        struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-       struct av7110 *av7110 = (struct av7110 *) dvbdmx->priv;
+       struct av7110 *av7110 = dvbdmx->priv;
        u16 *pid = dvbdmx->pids, npids[5];
        int i;
 
@@ -1103,9 +1096,9 @@ static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
 
        /* pointer casting paranoia... */
        BUG_ON(!demux);
-       dvbdemux = (struct dvb_demux *) demux->priv;
+       dvbdemux = demux->priv;
        BUG_ON(!dvbdemux);
-       av7110 = (struct av7110 *) dvbdemux->priv;
+       av7110 = dvbdemux->priv;
 
        dprintk(4, "%p\n", av7110);
 
@@ -1137,7 +1130,7 @@ static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
 
 static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
 {
-       struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
+       struct av7110* av7110 = fe->dvb->priv;
 
        switch (tone) {
        case SEC_TONE_ON:
@@ -1197,7 +1190,7 @@ static int start_ts_capture(struct av7110 *budget)
 static int budget_start_feed(struct dvb_demux_feed *feed)
 {
        struct dvb_demux *demux = feed->demux;
-       struct av7110 *budget = (struct av7110 *) demux->priv;
+       struct av7110 *budget = demux->priv;
        int status;
 
        dprintk(2, "av7110: %p\n", budget);
@@ -1212,7 +1205,7 @@ static int budget_start_feed(struct dvb_demux_feed *feed)
 static int budget_stop_feed(struct dvb_demux_feed *feed)
 {
        struct dvb_demux *demux = feed->demux;
-       struct av7110 *budget = (struct av7110 *) demux->priv;
+       struct av7110 *budget = demux->priv;
        int status;
 
        dprintk(2, "budget: %p\n", budget);
@@ -1551,7 +1544,7 @@ static int get_firmware(struct av7110* av7110)
 
 static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
-       struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
+       struct av7110* av7110 = fe->dvb->priv;
        u8 pwr = 0;
        u8 buf[4];
        struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
@@ -1702,7 +1695,7 @@ static int alps_tdlb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_front
 static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
 {
 #if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE)
-       struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
+       struct av7110* av7110 = fe->dvb->priv;
 
        return request_firmware(fw, name, &av7110->dev->pci->dev);
 #else
@@ -1867,7 +1860,7 @@ static struct stv0297_config nexusca_stv0297_config = {
 
 static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
-       struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
+       struct av7110* av7110 = fe->dvb->priv;
        u32 div;
        u8 cfg, cpump, band_select;
        u8 data[4];
@@ -2338,6 +2331,7 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
        const int length = TS_WIDTH * TS_HEIGHT;
        struct pci_dev *pdev = dev->pci;
        struct av7110 *av7110;
+       struct task_struct *thread;
        int ret, count = 0;
 
        dprintk(4, "dev: %p\n", dev);
@@ -2622,9 +2616,12 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
                printk ("dvb-ttpci: Warning, firmware version 0x%04x is too old. "
                        "System might be unstable!\n", FW_VERSION(av7110->arm_app));
 
-       ret = kernel_thread(arm_thread, (void *) av7110, 0);
-       if (ret < 0)
+       thread = kthread_run(arm_thread, (void *) av7110, "arm_mon");
+       if (IS_ERR(thread)) {
+               ret = PTR_ERR(thread);
                goto err_stop_arm_9;
+       }
+       av7110->arm_thread = thread;
 
        /* set initial volume in mixer struct */
        av7110->mixer.volume_left  = volume;
index 9c79696da08a60d622aaf347cc5a67609fe74388..b98bd453cade62f7755d7d443ce7641d8bdb007c 100644 (file)
@@ -35,7 +35,6 @@
 
 #define ANALOG_TUNER_VES1820 1
 #define ANALOG_TUNER_STV0297 2
-#define ANALOG_TUNER_VBI     0x100
 
 extern int av7110_debug;
 
@@ -205,7 +204,6 @@ struct av7110 {
        struct task_struct *arm_thread;
        wait_queue_head_t   arm_wait;
        u16                 arm_loops;
-       int                 arm_rmmod;
 
        void               *debi_virt;
        dma_addr_t          debi_bus;
index 795e6e95915c6d5e5a9d25d2033d30f8f6f1903a..e719af807685f50324a46d260ed12284c5531d7f 100644 (file)
@@ -880,8 +880,8 @@ static int dvb_video_get_event (struct av7110 *av7110, struct video_event *event
 
 static unsigned int dvb_video_poll(struct file *file, poll_table *wait)
 {
-       struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-       struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct av7110 *av7110 = dvbdev->priv;
        unsigned int mask = 0;
 
        dprintk(2, "av7110:%p, \n", av7110);
@@ -908,8 +908,8 @@ static unsigned int dvb_video_poll(struct file *file, poll_table *wait)
 static ssize_t dvb_video_write(struct file *file, const char __user *buf,
                               size_t count, loff_t *ppos)
 {
-       struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-       struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct av7110 *av7110 = dvbdev->priv;
 
        dprintk(2, "av7110:%p, \n", av7110);
 
@@ -924,8 +924,8 @@ static ssize_t dvb_video_write(struct file *file, const char __user *buf,
 
 static unsigned int dvb_audio_poll(struct file *file, poll_table *wait)
 {
-       struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-       struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct av7110 *av7110 = dvbdev->priv;
        unsigned int mask = 0;
 
        dprintk(2, "av7110:%p, \n", av7110);
@@ -944,8 +944,8 @@ static unsigned int dvb_audio_poll(struct file *file, poll_table *wait)
 static ssize_t dvb_audio_write(struct file *file, const char __user *buf,
                               size_t count, loff_t *ppos)
 {
-       struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-       struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct av7110 *av7110 = dvbdev->priv;
 
        dprintk(2, "av7110:%p, \n", av7110);
 
@@ -989,8 +989,8 @@ static int play_iframe(struct av7110 *av7110, u8 __user *buf, unsigned int len,
 static int dvb_video_ioctl(struct inode *inode, struct file *file,
                           unsigned int cmd, void *parg)
 {
-       struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-       struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct av7110 *av7110 = dvbdev->priv;
        unsigned long arg = (unsigned long) parg;
        int ret = 0;
 
@@ -1203,8 +1203,8 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file,
 static int dvb_audio_ioctl(struct inode *inode, struct file *file,
                           unsigned int cmd, void *parg)
 {
-       struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-       struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct av7110 *av7110 = dvbdev->priv;
        unsigned long arg = (unsigned long) parg;
        int ret = 0;
 
@@ -1349,8 +1349,8 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
 
 static int dvb_video_open(struct inode *inode, struct file *file)
 {
-       struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-       struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct av7110 *av7110 = dvbdev->priv;
        int err;
 
        dprintk(2, "av7110:%p, \n", av7110);
@@ -1374,8 +1374,8 @@ static int dvb_video_open(struct inode *inode, struct file *file)
 
 static int dvb_video_release(struct inode *inode, struct file *file)
 {
-       struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-       struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct av7110 *av7110 = dvbdev->priv;
 
        dprintk(2, "av7110:%p, \n", av7110);
 
@@ -1388,9 +1388,9 @@ static int dvb_video_release(struct inode *inode, struct file *file)
 
 static int dvb_audio_open(struct inode *inode, struct file *file)
 {
-       struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-       struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
-       int err=dvb_generic_open(inode, file);
+       struct dvb_device *dvbdev = file->private_data;
+       struct av7110 *av7110 = dvbdev->priv;
+       int err = dvb_generic_open(inode, file);
 
        dprintk(2, "av7110:%p, \n", av7110);
 
@@ -1403,8 +1403,8 @@ static int dvb_audio_open(struct inode *inode, struct file *file)
 
 static int dvb_audio_release(struct inode *inode, struct file *file)
 {
-       struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-       struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct av7110 *av7110 = dvbdev->priv;
 
        dprintk(2, "av7110:%p, \n", av7110);
 
index 4251a97d420e81ee128edf9ec0bab913ddd300f4..e9b4e88e793231f6c49765e0103c4935d02a4d73 100644 (file)
@@ -214,8 +214,8 @@ static ssize_t ci_ll_read(struct dvb_ringbuffer *cibuf, struct file *file,
 
 static int dvb_ca_open(struct inode *inode, struct file *file)
 {
-       struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-       struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct av7110 *av7110 = dvbdev->priv;
        int err = dvb_generic_open(inode, file);
 
        dprintk(8, "av7110:%p\n",av7110);
@@ -228,8 +228,8 @@ static int dvb_ca_open(struct inode *inode, struct file *file)
 
 static unsigned int dvb_ca_poll (struct file *file, poll_table *wait)
 {
-       struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-       struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct av7110 *av7110 = dvbdev->priv;
        struct dvb_ringbuffer *rbuf = &av7110->ci_rbuffer;
        struct dvb_ringbuffer *wbuf = &av7110->ci_wbuffer;
        unsigned int mask = 0;
@@ -251,8 +251,8 @@ static unsigned int dvb_ca_poll (struct file *file, poll_table *wait)
 static int dvb_ca_ioctl(struct inode *inode, struct file *file,
                 unsigned int cmd, void *parg)
 {
-       struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-       struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct av7110 *av7110 = dvbdev->priv;
        unsigned long arg = (unsigned long) parg;
 
        dprintk(8, "av7110:%p\n",av7110);
@@ -329,8 +329,8 @@ static int dvb_ca_ioctl(struct inode *inode, struct file *file,
 static ssize_t dvb_ca_write(struct file *file, const char __user *buf,
                            size_t count, loff_t *ppos)
 {
-       struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-       struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct av7110 *av7110 = dvbdev->priv;
 
        dprintk(8, "av7110:%p\n",av7110);
        return ci_ll_write(&av7110->ci_wbuffer, file, buf, count, ppos);
@@ -339,15 +339,13 @@ static ssize_t dvb_ca_write(struct file *file, const char __user *buf,
 static ssize_t dvb_ca_read(struct file *file, char __user *buf,
                           size_t count, loff_t *ppos)
 {
-       struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-       struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct av7110 *av7110 = dvbdev->priv;
 
        dprintk(8, "av7110:%p\n",av7110);
        return ci_ll_read(&av7110->ci_rbuffer, file, buf, count, ppos);
 }
 
-
-
 static struct file_operations dvb_ca_fops = {
        .owner          = THIS_MODULE,
        .read           = dvb_ca_read,
index e4544ea2b89b60e0a95b63160ce261a628bb40dc..f59465bb0af3cb62c2628253d186294b676bb645 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/moduleparam.h>
 #include <linux/input.h>
 #include <linux/proc_fs.h>
+#include <linux/kernel.h>
 #include <asm/bitops.h>
 
 #include "av7110.h"
@@ -16,6 +17,7 @@
 static int av_cnt;
 static struct av7110 *av_list[4];
 static struct input_dev *input_dev;
+static char input_phys[32];
 
 static u8 delay_timer_finished;
 
@@ -217,7 +219,7 @@ 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])
+       if (av_cnt >= ARRAY_SIZE(av_list))
                return -ENOSPC;
 
        av7110_setup_irc_config(av7110, 0x0001);
@@ -231,8 +233,22 @@ int __devinit av7110_ir_init(struct av7110 *av7110)
                if (!input_dev)
                        return -ENOMEM;
 
+               snprintf(input_phys, sizeof(input_phys),
+                       "pci-%s/ir0", pci_name(av7110->dev->pci));
+
                input_dev->name = "DVB on-card IR receiver";
 
+               input_dev->phys = input_phys;
+               input_dev->id.bustype = BUS_PCI;
+               input_dev->id.version = 1;
+               if (av7110->dev->pci->subsystem_vendor) {
+                       input_dev->id.vendor = av7110->dev->pci->subsystem_vendor;
+                       input_dev->id.product = av7110->dev->pci->subsystem_device;
+               } else {
+                       input_dev->id.vendor = av7110->dev->pci->vendor;
+                       input_dev->id.product = av7110->dev->pci->device;
+               }
+               input_dev->cdev.dev = &av7110->dev->pci->dev;
                set_bit(EV_KEY, input_dev->evbit);
                set_bit(EV_REP, input_dev->evbit);
                input_register_keys();
index dbfd5e7b4be0c3ef40b79ec3a4b48a6c6a2855af..cde5d3ae7ec783b32f73e9ee517013daa1be59c7 100644 (file)
@@ -140,17 +140,6 @@ static int ves1820_writereg(struct saa7146_dev *dev, u8 addr, u8 reg, u8 data)
        return 0;
 }
 
-static int stv0297_writereg(struct saa7146_dev *dev, u8 addr, u8 reg, u8 data)
-{
-       u8 buf [] = { reg, data };
-       struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 2 };
-
-       if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1))
-               return -1;
-       return 0;
-}
-
-
 static int tuner_write(struct saa7146_dev *dev, u8 addr, u8 data [4])
 {
        struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 };
@@ -193,6 +182,7 @@ static int ves1820_set_tv_freq(struct saa7146_dev *dev, u32 freq)
 
 static int stv0297_set_tv_freq(struct saa7146_dev *dev, u32 freq)
 {
+       struct av7110 *av7110 = (struct av7110*)dev->ext_priv;
        u32 div;
        u8 data[4];
 
@@ -213,8 +203,8 @@ static int stv0297_set_tv_freq(struct saa7146_dev *dev, u32 freq)
        else
                return -EINVAL;
 
-       stv0297_writereg(dev, 0x1C, 0x87, 0x78);
-       stv0297_writereg(dev, 0x1C, 0x86, 0xc8);
+       if (av7110->fe->ops.i2c_gate_ctrl)
+               av7110->fe->ops.i2c_gate_ctrl(av7110->fe, 1);
        return tuner_write(dev, 0x63, data);
 }
 
@@ -817,20 +807,20 @@ int av7110_init_v4l(struct av7110 *av7110)
                saa7146_vv_release(dev);
                return -ENODEV;
        }
-       if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) {
+       if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI))
                ERR(("cannot register vbi v4l2 device. skipping.\n"));
-       } else {
-               if (av7110->analog_tuner_flags)
-                       av7110->analog_tuner_flags |= ANALOG_TUNER_VBI;
-       }
        return 0;
 }
 
 int av7110_exit_v4l(struct av7110 *av7110)
 {
+       struct saa7146_dev* dev = av7110->dev;
+
        saa7146_unregister_device(&av7110->v4l_dev, av7110->dev);
-       if (av7110->analog_tuner_flags & ANALOG_TUNER_VBI)
-               saa7146_unregister_device(&av7110->vbi_dev, av7110->dev);
+       saa7146_unregister_device(&av7110->vbi_dev, av7110->dev);
+
+       saa7146_vv_release(dev);
+
        return 0;
 }
 
index 89ab4b59155cde27035bcb4ce4d8f3a887c8eac7..3035b224c7a32efafa249a1c27ed46e8e605c818 100644 (file)
@@ -1089,6 +1089,8 @@ static int budget_av_detach(struct saa7146_dev *dev)
                msleep(200);
 
                saa7146_unregister_device(&budget_av->vd, dev);
+
+               saa7146_vv_release(dev);
        }
 
        if (budget_av->budget.ci_present)
@@ -1145,6 +1147,7 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
                if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) {
                        /* fixme: proper cleanup here */
                        ERR(("cannot register capture v4l2 device.\n"));
+                       saa7146_vv_release(dev);
                        return err;
                }
 
index f2066b47baee6ce9d61358b7aea5e35a6f4891c9..464feaf1a9ad2401afbeeb686b0996b36765aa5d 100644 (file)
@@ -29,8 +29,6 @@
  * the project's page is at http://www.linuxtv.org/dvb/
  */
 
-#include "budget.h"
-
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
@@ -39,6 +37,8 @@
 #include <linux/spinlock.h>
 #include <media/ir-common.h>
 
+#include "budget.h"
+
 #include "dvb_ca_en50221.h"
 #include "stv0299.h"
 #include "stv0297.h"
@@ -130,6 +130,7 @@ static void msp430_ir_interrupt(unsigned long data)
        int toggle;
        static int prev_toggle = -1;
        static u32 ir_key;
+       static int state = 0;
        u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
 
        /*
@@ -138,21 +139,34 @@ static void msp430_ir_interrupt(unsigned long data)
         * 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
+        * Each signal from the remote control can generate one or more command
+        * bytes and one or more device bytes. For the repeated bytes, the
+        * highest bit (X) is set. The first command byte is always generated
+        * before the first device byte. Other than that, no specific order
+        * seems to apply.
+        *
+        * Only when we have a command and device byte, a keypress is
+        * generated.
         */
 
+       if (ir_debug)
+               printk("budget_ci: received byte 0x%02x\n", command);
+
+       /* Is this a repeated byte? */
+       if (command & 0x80)
+               return;
+
        /* Is this a RC5 command byte? */
        if (command & 0x40) {
-               if (ir_debug)
-                       printk("budget_ci: received command byte 0x%02x\n", command);
+               state = 1;
                ir_key = command & 0x3f;
                return;
        }
 
        /* It's a RC5 device byte */
-       if (ir_debug)
-               printk("budget_ci: received device byte 0x%02x\n", command);
+       if (!state)
+               return;
+       state = 0;
        device = command & 0x1f;
        toggle = command & 0x20;
 
@@ -223,7 +237,6 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
        switch (budget_ci->budget.dev->pci->subsystem_device) {
        case 0x100c:
        case 0x100f:
-       case 0x1010:
        case 0x1011:
        case 0x1012:
        case 0x1017:
@@ -236,6 +249,16 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
                else
                        budget_ci->ir.rc5_device = rc5_device;
                break;
+       case 0x1010:
+               /* for the Technotrend 1500 bundled remote */
+               ir_input_init(input_dev, &budget_ci->ir.state,
+                             IR_TYPE_RC5, ir_codes_tt_1500);
+
+               if (rc5_device < 0)
+                       budget_ci->ir.rc5_device = IR_DEVICE_ANY;
+               else
+                       budget_ci->ir.rc5_device = rc5_device;
+               break;
        default:
                /* unknown remote */
                ir_input_init(input_dev, &budget_ci->ir.state,
@@ -869,6 +892,17 @@ static struct tda1004x_config philips_tdm1316l_config = {
        .request_firmware = philips_tdm1316l_request_firmware,
 };
 
+static struct tda1004x_config philips_tdm1316l_config_invert = {
+
+       .demod_address = 0x8,
+       .invert = 1,
+       .invert_oclk = 0,
+       .xtal_freq = TDA10046_XTAL_4M,
+       .agc_config = TDA10046_AGC_DEFAULT,
+       .if_freq = TDA10046_FREQ_3617,
+       .request_firmware = philips_tdm1316l_request_firmware,
+};
+
 static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
        struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
@@ -1092,9 +1126,8 @@ static void frontend_init(struct budget_ci *budget_ci)
 
        case 0x1012:            // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt))
                budget_ci->tuner_pll_address = 0x60;
-               philips_tdm1316l_config.invert = 1;
                budget_ci->budget.dvb_frontend =
-                       dvb_attach(tda10046_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
+                       dvb_attach(tda10046_attach, &philips_tdm1316l_config_invert, &budget_ci->budget.i2c_adap);
                if (budget_ci->budget.dvb_frontend) {
                        budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
                        budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
index bd6e7baae2ec9d6bd5d53f0b5b04d414b51a432a..78c98b0899759d48f33174e152e3a0ae3fbb29ef 100644 (file)
@@ -20,8 +20,6 @@
  *
  */
 
-#include <linux/mutex.h>
-
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -35,6 +33,8 @@
 #include <linux/init.h>
 #include <linux/input.h>
 
+#include <linux/mutex.h>
+
 #include "dmxdev.h"
 #include "dvb_demux.h"
 #include "dvb_filter.h"
index 19d45cc940b55dc33a4e680628a2a75e09ba85a2..9f1addae6928e0c6eb4dfe5190f870efd9ab51fd 100644 (file)
@@ -180,136 +180,163 @@ static int az_setfreq(struct az_device *dev, unsigned long frequency)
        return 0;
 }
 
-static int az_do_ioctl(struct inode *inode, struct file *file,
-                      unsigned int cmd, void *arg)
+static int vidioc_querycap (struct file *file, void  *priv,
+                                       struct v4l2_capability *v)
+{
+       strlcpy(v->driver, "radio-aztech", sizeof (v->driver));
+       strlcpy(v->card, "Aztech Radio", sizeof (v->card));
+       sprintf(v->bus_info,"ISA");
+       v->version = RADIO_VERSION;
+       v->capabilities = V4L2_CAP_TUNER;
+       return 0;
+}
+
+static int vidioc_g_tuner (struct file *file, void *priv,
+                               struct v4l2_tuner *v)
 {
        struct video_device *dev = video_devdata(file);
        struct az_device *az = dev->priv;
 
-       switch(cmd)
-       {
-               case VIDIOC_QUERYCAP:
-               {
-                       struct v4l2_capability *v = arg;
-                       memset(v,0,sizeof(*v));
-                       strlcpy(v->driver, "radio-aztech", sizeof (v->driver));
-                       strlcpy(v->card, "Aztech Radio", sizeof (v->card));
-                       sprintf(v->bus_info,"ISA");
-                       v->version = RADIO_VERSION;
-                       v->capabilities = V4L2_CAP_TUNER;
+       if (v->index > 0)
+               return -EINVAL;
 
-                       return 0;
-               }
-               case VIDIOC_G_TUNER:
-               {
-                       struct v4l2_tuner *v = arg;
-
-                       if (v->index > 0)
-                               return -EINVAL;
-
-                       memset(v,0,sizeof(*v));
-                       strcpy(v->name, "FM");
-                       v->type = V4L2_TUNER_RADIO;
-
-                       v->rangelow=(87*16000);
-                       v->rangehigh=(108*16000);
-                       v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
-                       v->capability=V4L2_TUNER_CAP_LOW;
-                       if(az_getstereo(az))
-                               v->audmode = V4L2_TUNER_MODE_STEREO;
-                       else
-                               v->audmode = V4L2_TUNER_MODE_MONO;
-                       v->signal=0xFFFF*az_getsigstr(az);
+       strcpy(v->name, "FM");
+       v->type = V4L2_TUNER_RADIO;
 
-                       return 0;
-               }
-               case VIDIOC_S_TUNER:
-               {
-                       struct v4l2_tuner *v = arg;
+       v->rangelow=(87*16000);
+       v->rangehigh=(108*16000);
+       v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
+       v->capability=V4L2_TUNER_CAP_LOW;
+       if(az_getstereo(az))
+               v->audmode = V4L2_TUNER_MODE_STEREO;
+       else
+               v->audmode = V4L2_TUNER_MODE_MONO;
+       v->signal=0xFFFF*az_getsigstr(az);
 
-                       if (v->index > 0)
-                               return -EINVAL;
+       return 0;
+}
 
-                       return 0;
-               }
-               case VIDIOC_S_FREQUENCY:
-               {
-                       struct v4l2_frequency *f = arg;
 
-                       az->curfreq = f->frequency;
-                       az_setfreq(az, az->curfreq);
-                       return 0;
-               }
-               case VIDIOC_G_FREQUENCY:
-               {
-                       struct v4l2_frequency *f = arg;
+static int vidioc_s_tuner (struct file *file, void *priv,
+                               struct v4l2_tuner *v)
+{
+       if (v->index > 0)
+               return -EINVAL;
 
-                       f->type = V4L2_TUNER_RADIO;
-                       f->frequency = az->curfreq;
+       return 0;
+}
 
-                       return 0;
-               }
+static int vidioc_g_audio (struct file *file, void *priv,
+                          struct v4l2_audio *a)
+{
+       if (a->index > 1)
+               return -EINVAL;
 
-               case VIDIOC_QUERYCTRL:
-               {
-                       struct v4l2_queryctrl *qc = arg;
-                       int i;
-
-                       for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
-                               if (qc->id && qc->id == radio_qctrl[i].id) {
-                                       memcpy(qc, &(radio_qctrl[i]),
-                                                               sizeof(*qc));
-                                       return (0);
-                               }
-                       }
-                       return -EINVAL;
-               }
-               case VIDIOC_G_CTRL:
-               {
-                       struct v4l2_control *ctrl= arg;
-
-                       switch (ctrl->id) {
-                               case V4L2_CID_AUDIO_MUTE:
-                                       if (az->curvol==0)
-                                               ctrl->value=1;
-                                       else
-                                               ctrl->value=0;
-                                       return (0);
-                               case V4L2_CID_AUDIO_VOLUME:
-                                       ctrl->value=az->curvol * 6554;
-                                       return (0);
-                       }
-                       return -EINVAL;
-               }
-               case VIDIOC_S_CTRL:
-               {
-                       struct v4l2_control *ctrl= arg;
-
-                       switch (ctrl->id) {
-                               case V4L2_CID_AUDIO_MUTE:
-                                       if (ctrl->value) {
-                                               az_setvol(az,0);
-                                       } else {
-                                               az_setvol(az,az->curvol);
-                                       }
-                                       return (0);
-                               case V4L2_CID_AUDIO_VOLUME:
-                                       az_setvol(az,ctrl->value);
-                                       return (0);
-                       }
-                       return -EINVAL;
+       strcpy(a->name, "Radio");
+       a->capability = V4L2_AUDCAP_STEREO;
+       return 0;
+}
+
+static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+       *i = 0;
+       return 0;
+}
+
+static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
+{
+       if (i != 0)
+               return -EINVAL;
+       return 0;
+}
+
+
+static int vidioc_s_audio (struct file *file, void *priv,
+                          struct v4l2_audio *a)
+{
+       if (a->index != 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int vidioc_s_frequency (struct file *file, void *priv,
+                               struct v4l2_frequency *f)
+{
+       struct video_device *dev = video_devdata(file);
+       struct az_device *az = dev->priv;
+
+       az->curfreq = f->frequency;
+       az_setfreq(az, az->curfreq);
+       return 0;
+}
+
+static int vidioc_g_frequency (struct file *file, void *priv,
+                               struct v4l2_frequency *f)
+{
+       struct video_device *dev = video_devdata(file);
+       struct az_device *az = dev->priv;
+
+       f->type = V4L2_TUNER_RADIO;
+       f->frequency = az->curfreq;
+
+       return 0;
+}
+
+static int vidioc_queryctrl (struct file *file, void *priv,
+                           struct v4l2_queryctrl *qc)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+               if (qc->id && qc->id == radio_qctrl[i].id) {
+                       memcpy(qc, &(radio_qctrl[i]),
+                                               sizeof(*qc));
+                       return (0);
                }
+       }
+       return -EINVAL;
+}
+
+static int vidioc_g_ctrl (struct file *file, void *priv,
+                           struct v4l2_control *ctrl)
+{
+       struct video_device *dev = video_devdata(file);
+       struct az_device *az = dev->priv;
 
-               default:
-                       return v4l_compat_translate_ioctl(inode,file,cmd,arg,
-                                                         az_do_ioctl);
+       switch (ctrl->id) {
+               case V4L2_CID_AUDIO_MUTE:
+                       if (az->curvol==0)
+                               ctrl->value=1;
+                       else
+                               ctrl->value=0;
+                       return (0);
+               case V4L2_CID_AUDIO_VOLUME:
+                       ctrl->value=az->curvol * 6554;
+                       return (0);
        }
+       return -EINVAL;
 }
 
-static int az_ioctl(struct inode *inode, struct file *file,
-                   unsigned int cmd, unsigned long arg)
+static int vidioc_s_ctrl (struct file *file, void *priv,
+                           struct v4l2_control *ctrl)
 {
-       return video_usercopy(inode, file, cmd, arg, az_do_ioctl);
+       struct video_device *dev = video_devdata(file);
+       struct az_device *az = dev->priv;
+
+       switch (ctrl->id) {
+               case V4L2_CID_AUDIO_MUTE:
+                       if (ctrl->value) {
+                               az_setvol(az,0);
+                       } else {
+                               az_setvol(az,az->curvol);
+                       }
+                       return (0);
+               case V4L2_CID_AUDIO_VOLUME:
+                       az_setvol(az,ctrl->value);
+                       return (0);
+       }
+       return -EINVAL;
 }
 
 static struct az_device aztech_unit;
@@ -318,20 +345,35 @@ static const struct file_operations aztech_fops = {
        .owner          = THIS_MODULE,
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
-       .ioctl          = az_ioctl,
+       .ioctl          = video_ioctl2,
        .compat_ioctl   = v4l_compat_ioctl32,
        .llseek         = no_llseek,
 };
 
 static struct video_device aztech_radio=
 {
-       .owner          = THIS_MODULE,
-       .name           = "Aztech radio",
-       .type           = VID_TYPE_TUNER,
-       .hardware       = 0,
-       .fops           = &aztech_fops,
+       .owner              = THIS_MODULE,
+       .name               = "Aztech radio",
+       .type               = VID_TYPE_TUNER,
+       .hardware           = 0,
+       .fops               = &aztech_fops,
+       .vidioc_querycap    = vidioc_querycap,
+       .vidioc_g_tuner     = vidioc_g_tuner,
+       .vidioc_s_tuner     = vidioc_s_tuner,
+       .vidioc_g_audio     = vidioc_g_audio,
+       .vidioc_s_audio     = vidioc_s_audio,
+       .vidioc_g_input     = vidioc_g_input,
+       .vidioc_s_input     = vidioc_s_input,
+       .vidioc_g_frequency = vidioc_g_frequency,
+       .vidioc_s_frequency = vidioc_s_frequency,
+       .vidioc_queryctrl   = vidioc_queryctrl,
+       .vidioc_g_ctrl      = vidioc_g_ctrl,
+       .vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
+module_param_named(debug,aztech_radio.debug, int, 0644);
+MODULE_PARM_DESC(debug,"activates debug info");
+
 static int __init aztech_init(void)
 {
        if(io==-1)
index 05e5aa77025f992ecba9af5ac5a2a5697677ca16..74976cba869f521ae0d558b136f1979a991d46c0 100644 (file)
@@ -89,14 +89,6 @@ static struct v4l2_queryctrl radio_qctrl[] = {
 #define GEMTEK_PCI_RANGE_HIGH (108*16000)
 #endif
 
-#ifndef TRUE
-#define TRUE (1)
-#endif
-
-#ifndef FALSE
-#define FALSE (0)
-#endif
-
 struct gemtek_pci_card {
        struct video_device *videodev;
 
@@ -146,12 +138,12 @@ static void __gemtek_pci_cmd( u16 value, u32 port, u8 *last_byte, int keep )
 
 static inline void gemtek_pci_nil( u32 port, u8 *last_byte )
 {
-       __gemtek_pci_cmd( 0x00, port, last_byte, FALSE );
+       __gemtek_pci_cmd( 0x00, port, last_byte, false );
 }
 
 static inline void gemtek_pci_cmd( u16 cmd, u32 port, u8 *last_byte )
 {
-       __gemtek_pci_cmd( cmd, port, last_byte, TRUE );
+       __gemtek_pci_cmd( cmd, port, last_byte, true );
 }
 
 static void gemtek_pci_setfrequency( struct gemtek_pci_card *card, unsigned long frequency )
@@ -184,14 +176,14 @@ static void gemtek_pci_setfrequency( struct gemtek_pci_card *card, unsigned long
 static inline void gemtek_pci_mute( struct gemtek_pci_card *card )
 {
        outb( 0x1f, card->iobase );
-       card->mute = TRUE;
+       card->mute = true;
 }
 
 static inline void gemtek_pci_unmute( struct gemtek_pci_card *card )
 {
        if ( card->mute ) {
                gemtek_pci_setfrequency( card, card->current_frequency );
-               card->mute = FALSE;
+               card->mute = false;
        }
 }
 
@@ -259,7 +251,7 @@ static int gemtek_pci_do_ioctl(struct inode *inode, struct file *file,
 
                        gemtek_pci_setfrequency( card, f->frequency );
                        card->current_frequency = f->frequency;
-                       card->mute = FALSE;
+                       card->mute = false;
                        return 0;
                }
                case VIDIOC_QUERYCTRL:
index 6beeb74004b1349a90f17f97e3f784b77dfc2663..8e184cfc1c94aa897665f73e6a21fec40c26d973 100644 (file)
@@ -27,7 +27,9 @@
  * BUGS:
  *   - card unmutes if you change frequency
  *
- * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
+ * (c) 2006, 2007 by Mauro Carvalho Chehab <mchehab@infradead.org>:
+ *     - Conversion to V4L2 API
+ *      - Uses video_ioctl2 for parsing and to add debug support
  */
 
 
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 
-#define DRIVER_VERSION "0.76"
+#define DRIVER_VERSION "0.77"
 
 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
-#define RADIO_VERSION KERNEL_VERSION(0,7,6)
+#define RADIO_VERSION KERNEL_VERSION(0,7,7)
+
+static struct video_device maxiradio_radio;
+
+#define dprintk(num, fmt, arg...)                                          \
+       do {                                                               \
+               if (maxiradio_radio.debug >= num)                          \
+                       printk(KERN_DEBUG "%s: " fmt,                      \
+                               maxiradio_radio.name, ## arg); } while (0)
 
 static struct v4l2_queryctrl radio_qctrl[] = {
        {
@@ -81,30 +91,21 @@ module_param(radio_nr, int, 0);
 #define FREQ_IF         171200 /* 10.7*16000   */
 #define FREQ_STEP       200    /* 12.5*16      */
 
-#define FREQ2BITS(x)   ((( (unsigned int)(x)+FREQ_IF+(FREQ_STEP<<1))\
-                       /(FREQ_STEP<<2))<<2) /* (x==fmhz*16*1000) -> bits */
+/* (x==fmhz*16*1000) -> bits */
+#define FREQ2BITS(x)   ((( (unsigned int)(x)+FREQ_IF+(FREQ_STEP<<1)) \
+                       /(FREQ_STEP<<2))<<2)
 
 #define BITS2FREQ(x)   ((x) * FREQ_STEP - FREQ_IF)
 
 
-static int radio_ioctl(struct inode *inode, struct file *file,
-                      unsigned int cmd, unsigned long arg);
-
 static const struct file_operations maxiradio_fops = {
        .owner          = THIS_MODULE,
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
-       .ioctl          = radio_ioctl,
+       .ioctl          = video_ioctl2,
        .compat_ioctl   = v4l_compat_ioctl32,
        .llseek         = no_llseek,
 };
-static struct video_device maxiradio_radio =
-{
-       .owner          = THIS_MODULE,
-       .name           = "Maxi Radio FM2000 radio",
-       .type           = VID_TYPE_TUNER,
-       .fops           = &maxiradio_fops,
-};
 
 static struct radio_device
 {
@@ -116,12 +117,14 @@ static struct radio_device
        unsigned long freq;
 
        struct mutex lock;
-} radio_unit = {0, 0, 0, 0, };
-
+} radio_unit = {
+       .muted =1,
+       .freq = FREQ_LO,
+};
 
 static void outbit(unsigned long bit, __u16 io)
 {
-       if(bit != 0)
+       if (bit != 0)
                {
                        outb(  power|wren|data     ,io); udelay(4);
                        outb(  power|wren|data|clk ,io); udelay(4);
@@ -137,14 +140,20 @@ static void outbit(unsigned long bit, __u16 io)
 
 static void turn_power(__u16 io, int p)
 {
-       if(p != 0) outb(power, io); else outb(0,io);
+       if (p != 0) {
+               dprintk(1, "Radio powered on\n");
+               outb(power, io);
+       } else {
+               dprintk(1, "Radio powered off\n");
+               outb(0,io);
+       }
 }
 
-
-static void set_freq(__u16 io, __u32 data)
+static void set_freq(__u16 io, __u32 freq)
 {
        unsigned long int si;
        int bl;
+       int data = FREQ2BITS(freq);
 
        /* TEA5757 shift register bits (see pdf) */
 
@@ -163,161 +172,225 @@ static void set_freq(__u16 io, __u32 data)
        outbit(0,io); // 16  search level
 
        si = 0x8000;
-       for(bl = 1; bl <= 16 ; bl++) { outbit(data & si,io); si >>=1; }
+       for (bl = 1; bl <= 16 ; bl++) {
+               outbit(data & si,io);
+               si >>=1;
+       }
 
-       outb(power,io);
+       dprintk(1, "Radio freq set to %d.%02d MHz\n",
+                               freq / 16000,
+                               freq % 16000 * 100 / 16000);
+
+       turn_power(io, 1);
 }
 
 static int get_stereo(__u16 io)
 {
-       outb(power,io); udelay(4);
+       outb(power,io);
+       udelay(4);
+
        return !(inb(io) & mo_st);
 }
 
 static int get_tune(__u16 io)
 {
-       outb(power+clk,io); udelay(4);
+       outb(power+clk,io);
+       udelay(4);
+
        return !(inb(io) & mo_st);
 }
 
 
-static inline int radio_function(struct inode *inode, struct file *file,
-                                unsigned int cmd, void *arg)
+static int vidioc_querycap (struct file *file, void  *priv,
+                           struct v4l2_capability *v)
+{
+       strlcpy(v->driver, "radio-maxiradio", sizeof (v->driver));
+       strlcpy(v->card, "Maxi Radio FM2000 radio", sizeof (v->card));
+       sprintf(v->bus_info,"ISA");
+       v->version = RADIO_VERSION;
+       v->capabilities = V4L2_CAP_TUNER;
+
+       return 0;
+}
+
+static int vidioc_g_tuner (struct file *file, void *priv,
+                          struct v4l2_tuner *v)
 {
        struct video_device *dev = video_devdata(file);
        struct radio_device *card=dev->priv;
 
-       switch(cmd) {
-               case VIDIOC_QUERYCAP:
-               {
-                       struct v4l2_capability *v = arg;
-                       memset(v,0,sizeof(*v));
-                       strlcpy(v->driver, "radio-maxiradio", sizeof (v->driver));
-                       strlcpy(v->card, "Maxi Radio FM2000 radio", sizeof (v->card));
-                       sprintf(v->bus_info,"ISA");
-                       v->version = RADIO_VERSION;
-                       v->capabilities = V4L2_CAP_TUNER;
+       if (v->index > 0)
+               return -EINVAL;
 
-                       return 0;
-               }
-               case VIDIOC_G_TUNER:
-               {
-                       struct v4l2_tuner *v = arg;
+       memset(v,0,sizeof(*v));
+       strcpy(v->name, "FM");
+       v->type = V4L2_TUNER_RADIO;
 
-                       if (v->index > 0)
-                               return -EINVAL;
+       v->rangelow=FREQ_LO;
+       v->rangehigh=FREQ_HI;
+       v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
+       v->capability=V4L2_TUNER_CAP_LOW;
+       if(get_stereo(card->io))
+               v->audmode = V4L2_TUNER_MODE_STEREO;
+       else
+               v->audmode = V4L2_TUNER_MODE_MONO;
+       v->signal=0xffff*get_tune(card->io);
 
-                       memset(v,0,sizeof(*v));
-                       strcpy(v->name, "FM");
-                       v->type = V4L2_TUNER_RADIO;
+       return 0;
+}
 
-                       v->rangelow=FREQ_LO;
-                       v->rangehigh=FREQ_HI;
-                       v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
-                       v->capability=V4L2_TUNER_CAP_LOW;
-                       if(get_stereo(card->io))
-                               v->audmode = V4L2_TUNER_MODE_STEREO;
-                       else
-                               v->audmode = V4L2_TUNER_MODE_MONO;
-                       v->signal=0xffff*get_tune(card->io);
+static int vidioc_s_tuner (struct file *file, void *priv,
+                          struct v4l2_tuner *v)
+{
+       if (v->index > 0)
+               return -EINVAL;
 
-                       return 0;
-               }
-               case VIDIOC_S_TUNER:
-               {
-                       struct v4l2_tuner *v = arg;
+       return 0;
+}
 
-                       if (v->index > 0)
-                               return -EINVAL;
+static int vidioc_g_audio (struct file *file, void *priv,
+                          struct v4l2_audio *a)
+{
+       if (a->index > 1)
+               return -EINVAL;
 
-                       return 0;
-               }
-               case VIDIOC_S_FREQUENCY:
-               {
-                       struct v4l2_frequency *f = arg;
+       strcpy(a->name, "FM");
+       a->capability = V4L2_AUDCAP_STEREO;
+       return 0;
+}
 
-                       if (f->frequency < FREQ_LO || f->frequency > FREQ_HI)
-                               return -EINVAL;
+static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+       *i = 0;
 
-                       card->freq = f->frequency;
-                       set_freq(card->io, FREQ2BITS(card->freq));
-                       msleep(125);
-                       return 0;
-               }
-               case VIDIOC_G_FREQUENCY:
-               {
-                       struct v4l2_frequency *f = arg;
+       return 0;
+}
 
-                       f->type = V4L2_TUNER_RADIO;
-                       f->frequency = card->freq;
+static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
+{
+       if (i != 0)
+               return -EINVAL;
 
-                       return 0;
-               }
-               case VIDIOC_QUERYCTRL:
-               {
-                       struct v4l2_queryctrl *qc = arg;
-                       int i;
-
-                       for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
-                               if (qc->id && qc->id == radio_qctrl[i].id) {
-                                       memcpy(qc, &(radio_qctrl[i]),
-                                                               sizeof(*qc));
-                                       return (0);
-                               }
-                       }
-                       return -EINVAL;
-               }
-               case VIDIOC_G_CTRL:
-               {
-                       struct v4l2_control *ctrl= arg;
-
-                       switch (ctrl->id) {
-                               case V4L2_CID_AUDIO_MUTE:
-                                       ctrl->value=card->muted;
-                                       return (0);
-                       }
-                       return -EINVAL;
-               }
-               case VIDIOC_S_CTRL:
-               {
-                       struct v4l2_control *ctrl= arg;
-
-                       switch (ctrl->id) {
-                               case V4L2_CID_AUDIO_MUTE:
-                                       card->muted = ctrl->value;
-                                       if(card->muted)
-                                               turn_power(card->io, 0);
-                                       else
-                                               set_freq(card->io, FREQ2BITS(card->freq));
-                                       return 0;
-                       }
-                       return -EINVAL;
-               }
+       return 0;
+}
+
+
+static int vidioc_s_audio (struct file *file, void *priv,
+                          struct v4l2_audio *a)
+{
+       if (a->index != 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int vidioc_s_frequency (struct file *file, void *priv,
+                              struct v4l2_frequency *f)
+{
+       struct video_device *dev = video_devdata(file);
+       struct radio_device *card=dev->priv;
 
-               default:
-                       return v4l_compat_translate_ioctl(inode,file,cmd,arg,
-                                                         radio_function);
+       if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) {
+               dprintk(1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n",
+                                       f->frequency / 16000,
+                                       f->frequency % 16000 * 100 / 16000,
+                                       FREQ_LO / 16000, FREQ_HI / 16000);
 
+               return -EINVAL;
        }
+
+       card->freq = f->frequency;
+       set_freq(card->io, card->freq);
+       msleep(125);
+
+       return 0;
 }
 
-static int radio_ioctl(struct inode *inode, struct file *file,
-                      unsigned int cmd, unsigned long arg)
+static int vidioc_g_frequency (struct file *file, void *priv,
+                              struct v4l2_frequency *f)
 {
        struct video_device *dev = video_devdata(file);
        struct radio_device *card=dev->priv;
-       int ret;
 
-       mutex_lock(&card->lock);
-       ret = video_usercopy(inode, file, cmd, arg, radio_function);
-       mutex_unlock(&card->lock);
-       return ret;
+       f->type = V4L2_TUNER_RADIO;
+       f->frequency = card->freq;
+
+       dprintk(4, "radio freq is %d.%02d MHz",
+                               f->frequency / 16000,
+                               f->frequency % 16000 * 100 / 16000);
+
+       return 0;
 }
 
-MODULE_AUTHOR("Dimitromanolakis Apostolos, apdim@grecian.net");
-MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000 radio.");
-MODULE_LICENSE("GPL");
+static int vidioc_queryctrl (struct file *file, void *priv,
+                            struct v4l2_queryctrl *qc)
+{
+       int i;
 
+       for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+               if (qc->id && qc->id == radio_qctrl[i].id) {
+                       memcpy(qc, &(radio_qctrl[i]), sizeof(*qc));
+                       return (0);
+               }
+       }
+
+       return -EINVAL;
+}
+
+static int vidioc_g_ctrl (struct file *file, void *priv,
+                           struct v4l2_control *ctrl)
+{
+       struct video_device *dev = video_devdata(file);
+       struct radio_device *card=dev->priv;
+
+       switch (ctrl->id) {
+               case V4L2_CID_AUDIO_MUTE:
+                       ctrl->value=card->muted;
+                       return (0);
+       }
+
+       return -EINVAL;
+}
+
+static int vidioc_s_ctrl (struct file *file, void *priv,
+                         struct v4l2_control *ctrl)
+{
+       struct video_device *dev = video_devdata(file);
+       struct radio_device *card=dev->priv;
+
+       switch (ctrl->id) {
+               case V4L2_CID_AUDIO_MUTE:
+                       card->muted = ctrl->value;
+                       if(card->muted)
+                               turn_power(card->io, 0);
+                       else
+                               set_freq(card->io, card->freq);
+                       return 0;
+       }
+
+       return -EINVAL;
+}
+
+static struct video_device maxiradio_radio =
+{
+       .owner              = THIS_MODULE,
+       .name               = "Maxi Radio FM2000 radio",
+       .type               = VID_TYPE_TUNER,
+       .fops               = &maxiradio_fops,
+
+       .vidioc_querycap    = vidioc_querycap,
+       .vidioc_g_tuner     = vidioc_g_tuner,
+       .vidioc_s_tuner     = vidioc_s_tuner,
+       .vidioc_g_audio     = vidioc_g_audio,
+       .vidioc_s_audio     = vidioc_s_audio,
+       .vidioc_g_input     = vidioc_g_input,
+       .vidioc_s_input     = vidioc_s_input,
+       .vidioc_g_frequency = vidioc_g_frequency,
+       .vidioc_s_frequency = vidioc_s_frequency,
+       .vidioc_queryctrl   = vidioc_queryctrl,
+       .vidioc_g_ctrl      = vidioc_g_ctrl,
+       .vidioc_s_ctrl      = vidioc_s_ctrl,
+};
 
 static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
@@ -334,7 +407,7 @@ static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_d
        mutex_init(&radio_unit.lock);
        maxiradio_radio.priv = &radio_unit;
 
-       if(video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr)==-1) {
+       if (video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr)==-1) {
                printk("radio-maxiradio: can't register device!");
                goto err_out_free_region;
        }
@@ -389,3 +462,10 @@ static void __exit maxiradio_radio_exit(void)
 
 module_init(maxiradio_radio_init);
 module_exit(maxiradio_radio_exit);
+
+MODULE_AUTHOR("Dimitromanolakis Apostolos, apdim@grecian.net");
+MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000 radio.");
+MODULE_LICENSE("GPL");
+
+module_param_named(debug,maxiradio_radio.debug, int, 0644);
+MODULE_PARM_DESC(debug,"activates debug info");
index 57357db31b8a7b58a841252fe7912b57e199a9b8..7a6105153f23231ef971e46bd603c1d1b5b1f76a 100644 (file)
@@ -342,7 +342,7 @@ endmenu # encoder / decoder chips
 
 config VIDEO_VIVI
        tristate "Virtual Video Driver"
-       depends on VIDEO_V4L2 && !SPARC32 && !SPARC64
+       depends on VIDEO_V4L2 && !SPARC32 && !SPARC64 && PCI
        select VIDEO_BUF
        default n
        ---help---
index 9b1f3f06bb7ce267d5dc868be48b4e2dd6965cc4..44ccaed40b49f798d61f7debb51b509d5f91730c 100644 (file)
@@ -113,4 +113,3 @@ obj-$(CONFIG_USB_QUICKCAM_MESSENGER)        += usbvideo/
 obj-$(CONFIG_VIDEO_VIVI) += vivi.o
 
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-extra-cflags-$(CONFIG_VIDEO_V4L1_COMPAT) += -DCONFIG_VIDEO_V4L1_COMPAT
index 21ebe8f13815ef69f284a82b65b19cb8b3c886d6..6addc42df045f77b8760aa185541a4b0c41f07f9 100644 (file)
@@ -307,6 +307,7 @@ static struct CARD {
        { 0x07711461, BTTV_BOARD_AVDVBT_771,    "AVermedia AverTV DVB-T 771" },
        { 0x07611461, BTTV_BOARD_AVDVBT_761,    "AverMedia AverTV DVB-T 761" },
        { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE,    "DViCO FusionHDTV DVB-T Lite" },
+       { 0xdb1118ac, BTTV_BOARD_DVICO_DVBT_LITE,    "Ultraview DVB-T Lite" },
        { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE,    "DViCO FusionHDTV 5 Lite" },
        { 0x00261822, BTTV_BOARD_TWINHAN_DST,   "DNTV Live! Mini "},
 
@@ -578,14 +579,9 @@ struct tvcard bttv_tvcards[] = {
                .svhs           = 2,
                .gpiomask       = 0x01fe00,
                .muxsel         = { 2, 3, 1, 1 },
-       #if 0
-               /* old */
-               .gpiomux        = { 0x01c000, 0, 0x018000, 0x014000, 0x002000 },
-       #else
                /* 2003-10-20 by "Anton A. Arapov" <arapov@mail.ru> */
                .gpiomux        = { 0x001e00, 0, 0x018000, 0x014000 },
                .gpiomute       = 0x002000,
-       #endif
                .needs_tvaudio  = 1,
                .pll            = PLL_28,
                .tuner_type     = -1,
@@ -894,15 +890,10 @@ struct tvcard bttv_tvcards[] = {
                .tuner          = 0,
                .svhs           = 2,
                .muxsel         = { 2, 3, 1, 1, 0 }, /* TV, CVid, SVid, CVid over SVid connector */
-       #if 0
-               .gpiomask       = 0xc33000,
-               .gpiomux        = { 0x422000,0x1000,0x0000,0x620000,0x800000 },
-       #else
                /* Alexander Varakin <avarakin@hotmail.com> [stereo version] */
                .gpiomask       = 0xb33000,
                .gpiomux        = { 0x122000,0x1000,0x0000,0x620000 },
                .gpiomute       = 0x800000,
-       #endif
                /* Audio Routing for "WinFast 2000 XP" (no tv stereo !)
                        gpio23 -- hef4052:nEnable (0x800000)
                        gpio12 -- hef4052:A1
@@ -1937,11 +1928,6 @@ struct tvcard bttv_tvcards[] = {
                .video_inputs   = 4,
                .audio_inputs   = 1,
                .tuner          = -1,
-       #if 0 /* TODO ... */
-               .svhs           = OSPREY540_SVID_ANALOG,
-               .muxsel         = {       [OSPREY540_COMP_ANALOG] = 2,
-                                       [OSPREY540_SVID_ANALOG] = 3, },
-       #endif
                .pll            = PLL_28,
                .tuner_type     = -1,
                .tuner_addr     = ADDR_UNSET,
@@ -1949,10 +1935,6 @@ struct tvcard bttv_tvcards[] = {
                .no_msp34xx     = 1,
                .no_tda9875     = 1,
                .no_tda7432     = 1,
-       #if 0 /* TODO ... */
-               .muxsel_hook    = osprey_540_muxsel,
-               .picture_hook   = osprey_540_set_picture,
-       #endif
        },
 
                /* ---- card 0x5C ---------------------------------- */
@@ -2627,9 +2609,6 @@ struct tvcard bttv_tvcards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .has_radio      = 0,
-       #if 0
-               .has_remote     = 1,
-       #endif
        },
        [BTTV_BOARD_SUPER_TV] = {
                /* Rick C <cryptdragoon@gmail.com> */
index 41fd09d7d11e4dbbb3b714ac9a54b8e667cf615f..5720b77ac9a78deed24e01a422b8b649cfa26187 100644 (file)
@@ -9,6 +9,10 @@
     some v4l2 code lines are taken from Justin's bttv2 driver which is
     (c) 2000 Justin Schoeman <justin@suntiger.ee.up.ac.za>
 
+    Cropping and overscan support
+    Copyright (C) 2005, 2006 Michael H. Schimek <mschimek@gmx.at>
+    Sponsored by OPQ Systems AB
+
     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
@@ -64,6 +68,7 @@ static unsigned int radio[BTTV_MAX];
 static unsigned int irq_debug;
 static unsigned int gbuffers = 8;
 static unsigned int gbufsize = 0x208000;
+static unsigned int reset_crop = 1;
 
 static int video_nr = -1;
 static int radio_nr = -1;
@@ -103,6 +108,7 @@ module_param(radio_nr,          int, 0444);
 module_param(vbi_nr,            int, 0444);
 module_param(gbuffers,          int, 0444);
 module_param(gbufsize,          int, 0444);
+module_param(reset_crop,        int, 0444);
 
 module_param(v4l2,              int, 0644);
 module_param(bigendian,         int, 0644);
@@ -129,6 +135,8 @@ MODULE_PARM_DESC(bttv_debug,"debug messages, default is 0 (no)");
 MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)");
 MODULE_PARM_DESC(gbuffers,"number of capture buffers. range 2-32, default 8");
 MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000");
+MODULE_PARM_DESC(reset_crop,"reset cropping parameters at open(), default "
+                "is 1 (yes) for compatibility with older applications");
 MODULE_PARM_DESC(automute,"mute audio on bad/missing video signal, default is 1 (yes)");
 MODULE_PARM_DESC(chroma_agc,"enables the AGC of chroma signal, default is 0 (no)");
 MODULE_PARM_DESC(adc_crush,"enables the luminance ADC crush, default is 1 (yes)");
@@ -192,6 +200,33 @@ static u8 SRAM_Table[][60] =
        }
 };
 
+/* minhdelayx1 first video pixel we can capture on a line and
+   hdelayx1    start of active video, both relative to rising edge of
+               /HRESET pulse (0H) in 1 / fCLKx1.
+   swidth      width of active video and
+   totalwidth  total line width, both in 1 / fCLKx1.
+   sqwidth     total line width in square pixels.
+   vdelay      start of active video in 2 * field lines relative to
+               trailing edge of /VRESET pulse (VDELAY register).
+   sheight     height of active video in 2 * field lines.
+   videostart0 ITU-R frame line number of the line corresponding
+               to vdelay in the first field. */
+#define CROPCAP(minhdelayx1, hdelayx1, swidth, totalwidth, sqwidth,     \
+               vdelay, sheight, videostart0)                            \
+       .cropcap.bounds.left = minhdelayx1,                              \
+       /* * 2 because vertically we count field lines times two, */     \
+       /* e.g. 23 * 2 to 23 * 2 + 576 in PAL-BGHI defrect. */           \
+       .cropcap.bounds.top = (videostart0) * 2 - (vdelay) + MIN_VDELAY, \
+       /* 4 is a safety margin at the end of the line. */               \
+       .cropcap.bounds.width = (totalwidth) - (minhdelayx1) - 4,        \
+       .cropcap.bounds.height = (sheight) + (vdelay) - MIN_VDELAY,      \
+       .cropcap.defrect.left = hdelayx1,                                \
+       .cropcap.defrect.top = (videostart0) * 2,                        \
+       .cropcap.defrect.width = swidth,                                 \
+       .cropcap.defrect.height = sheight,                               \
+       .cropcap.pixelaspect.numerator = totalwidth,                     \
+       .cropcap.pixelaspect.denominator = sqwidth,
+
 const struct bttv_tvnorm bttv_tvnorms[] = {
        /* PAL-BDGHI */
        /* max. active video is actually 922, but 924 is divisible by 4 and 3! */
@@ -210,11 +245,26 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                .hdelayx1       = 186,
                .hactivex1      = 924,
                .vdelay         = 0x20,
-               .vbipack        = 255,
+               .vbipack        = 255, /* min (2048 / 4, 0x1ff) & 0xff */
                .sram           = 0,
                /* ITU-R frame line number of the first VBI line
-                  we can capture, of the first and second field. */
-               .vbistart       = { 7,320 },
+                  we can capture, of the first and second field.
+                  The last line is determined by cropcap.bounds. */
+               .vbistart       = { 7, 320 },
+               CROPCAP(/* minhdelayx1 */ 68,
+                       /* hdelayx1 */ 186,
+                       /* Should be (768 * 1135 + 944 / 2) / 944.
+                          cropcap.defrect is used for image width
+                          checks, so we keep the old value 924. */
+                       /* swidth */ 924,
+                       /* totalwidth */ 1135,
+                       /* sqwidth */ 944,
+                       /* vdelay */ 0x20,
+                       /* sheight */ 576,
+                       /* videostart0 */ 23)
+               /* bt878 (and bt848?) can capture another
+                  line below active video. */
+               .cropcap.bounds.height = (576 + 2) + 0x20 - 2,
        },{
                .v4l2_id        = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
                .name           = "NTSC",
@@ -229,9 +279,18 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                .hdelayx1       = 128,
                .hactivex1      = 910,
                .vdelay         = 0x1a,
-               .vbipack        = 144,
+               .vbipack        = 144, /* min (1600 / 4, 0x1ff) & 0xff */
                .sram           = 1,
                .vbistart       = { 10, 273 },
+               CROPCAP(/* minhdelayx1 */ 68,
+                       /* hdelayx1 */ 128,
+                       /* Should be (640 * 910 + 780 / 2) / 780? */
+                       /* swidth */ 768,
+                       /* totalwidth */ 910,
+                       /* sqwidth */ 780,
+                       /* vdelay */ 0x1a,
+                       /* sheight */ 480,
+                       /* videostart0 */ 23)
        },{
                .v4l2_id        = V4L2_STD_SECAM,
                .name           = "SECAM",
@@ -249,6 +308,14 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                .vbipack        = 255,
                .sram           = 0, /* like PAL, correct? */
                .vbistart       = { 7, 320 },
+               CROPCAP(/* minhdelayx1 */ 68,
+                       /* hdelayx1 */ 186,
+                       /* swidth */ 924,
+                       /* totalwidth */ 1135,
+                       /* sqwidth */ 944,
+                       /* vdelay */ 0x20,
+                       /* sheight */ 576,
+                       /* videostart0 */ 23)
        },{
                .v4l2_id        = V4L2_STD_PAL_Nc,
                .name           = "PAL-Nc",
@@ -266,6 +333,14 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                .vbipack        = 144,
                .sram           = -1,
                .vbistart       = { 7, 320 },
+               CROPCAP(/* minhdelayx1 */ 68,
+                       /* hdelayx1 */ 130,
+                       /* swidth */ (640 * 910 + 780 / 2) / 780,
+                       /* totalwidth */ 910,
+                       /* sqwidth */ 780,
+                       /* vdelay */ 0x1a,
+                       /* sheight */ 576,
+                       /* videostart0 */ 23)
        },{
                .v4l2_id        = V4L2_STD_PAL_M,
                .name           = "PAL-M",
@@ -283,6 +358,14 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                .vbipack        = 144,
                .sram           = -1,
                .vbistart       = { 10, 273 },
+               CROPCAP(/* minhdelayx1 */ 68,
+                       /* hdelayx1 */ 135,
+                       /* swidth */ (640 * 910 + 780 / 2) / 780,
+                       /* totalwidth */ 910,
+                       /* sqwidth */ 780,
+                       /* vdelay */ 0x1a,
+                       /* sheight */ 480,
+                       /* videostart0 */ 23)
        },{
                .v4l2_id        = V4L2_STD_PAL_N,
                .name           = "PAL-N",
@@ -299,7 +382,15 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                .vdelay         = 0x20,
                .vbipack        = 144,
                .sram           = -1,
-               .vbistart       = { 7, 320},
+               .vbistart       = { 7, 320 },
+               CROPCAP(/* minhdelayx1 */ 68,
+                       /* hdelayx1 */ 186,
+                       /* swidth */ (768 * 1135 + 944 / 2) / 944,
+                       /* totalwidth */ 1135,
+                       /* sqwidth */ 944,
+                       /* vdelay */ 0x20,
+                       /* sheight */ 576,
+                       /* videostart0 */ 23)
        },{
                .v4l2_id        = V4L2_STD_NTSC_M_JP,
                .name           = "NTSC-JP",
@@ -316,7 +407,15 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                .vdelay         = 0x16,
                .vbipack        = 144,
                .sram           = -1,
-               .vbistart       = {10, 273},
+               .vbistart       = { 10, 273 },
+               CROPCAP(/* minhdelayx1 */ 68,
+                       /* hdelayx1 */ 135,
+                       /* swidth */ (640 * 910 + 780 / 2) / 780,
+                       /* totalwidth */ 910,
+                       /* sqwidth */ 780,
+                       /* vdelay */ 0x16,
+                       /* sheight */ 480,
+                       /* videostart0 */ 23)
        },{
                /* that one hopefully works with the strange timing
                 * which video recorders produce when playing a NTSC
@@ -338,6 +437,14 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                .vtotal         = 524,
                .sram           = -1,
                .vbistart       = { 10, 273 },
+               CROPCAP(/* minhdelayx1 */ 68,
+                       /* hdelayx1 */ 186,
+                       /* swidth */ 924,
+                       /* totalwidth */ 1135,
+                       /* sqwidth */ 944,
+                       /* vdelay */ 0x1a,
+                       /* sheight */ 480,
+                       /* videostart0 */ 23)
        }
 };
 static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
@@ -678,25 +785,89 @@ static const int BTTV_CTLS = ARRAY_SIZE(bttv_ctls);
 /* ----------------------------------------------------------------------- */
 /* resource management                                                     */
 
+/*
+   RESOURCE_    allocated by                freed by
+
+   VIDEO_READ   bttv_read 1)                bttv_read 2)
+
+   VIDEO_STREAM VIDIOC_STREAMON             VIDIOC_STREAMOFF
+                VIDIOC_QBUF 1)              bttv_release
+                VIDIOCMCAPTURE 1)
+
+   OVERLAY      VIDIOCCAPTURE on            VIDIOCCAPTURE off
+                VIDIOC_OVERLAY on           VIDIOC_OVERLAY off
+                3)                          bttv_release
+
+   VBI          VIDIOC_STREAMON             VIDIOC_STREAMOFF
+                VIDIOC_QBUF 1)              bttv_release
+                bttv_read, bttv_poll 1) 4)
+
+   1) The resource must be allocated when we enter buffer prepare functions
+      and remain allocated while buffers are in the DMA queue.
+   2) This is a single frame read.
+   3) VIDIOC_S_FBUF and VIDIOC_S_FMT (OVERLAY) still work when
+      RESOURCE_OVERLAY is allocated.
+   4) This is a continuous read, implies VIDIOC_STREAMON.
+
+   Note this driver permits video input and standard changes regardless if
+   resources are allocated.
+*/
+
+#define VBI_RESOURCES (RESOURCE_VBI)
+#define VIDEO_RESOURCES (RESOURCE_VIDEO_READ | \
+                        RESOURCE_VIDEO_STREAM | \
+                        RESOURCE_OVERLAY)
+
 static
 int check_alloc_btres(struct bttv *btv, struct bttv_fh *fh, int bit)
 {
+       int xbits; /* mutual exclusive resources */
+
        if (fh->resources & bit)
                /* have it already allocated */
                return 1;
 
+       xbits = bit;
+       if (bit & (RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM))
+               xbits |= RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM;
+
        /* is it free? */
-       mutex_lock(&btv->reslock);
-       if (btv->resources & bit) {
+       mutex_lock(&btv->lock);
+       if (btv->resources & xbits) {
                /* no, someone else uses it */
-               mutex_unlock(&btv->reslock);
-               return 0;
+               goto fail;
+       }
+
+       if ((bit & VIDEO_RESOURCES)
+           && 0 == (btv->resources & VIDEO_RESOURCES)) {
+               /* Do crop - use current, don't - use default parameters. */
+               __s32 top = btv->crop[!!fh->do_crop].rect.top;
+
+               if (btv->vbi_end > top)
+                       goto fail;
+
+               /* We cannot capture the same line as video and VBI data.
+                  Claim scan lines crop[].rect.top to bottom. */
+               btv->crop_start = top;
+       } else if (bit & VBI_RESOURCES) {
+               __s32 end = fh->vbi_fmt.end;
+
+               if (end > btv->crop_start)
+                       goto fail;
+
+               /* Claim scan lines above fh->vbi_fmt.end. */
+               btv->vbi_end = end;
        }
+
        /* it's free, grab it */
        fh->resources  |= bit;
        btv->resources |= bit;
-       mutex_unlock(&btv->reslock);
+       mutex_unlock(&btv->lock);
        return 1;
+
+ fail:
+       mutex_unlock(&btv->lock);
+       return 0;
 }
 
 static
@@ -711,6 +882,35 @@ int locked_btres(struct bttv *btv, int bit)
        return (btv->resources & bit);
 }
 
+/* Call with btv->lock down. */
+static void
+disclaim_vbi_lines(struct bttv *btv)
+{
+       btv->vbi_end = 0;
+}
+
+/* Call with btv->lock down. */
+static void
+disclaim_video_lines(struct bttv *btv)
+{
+       const struct bttv_tvnorm *tvnorm;
+       u8 crop;
+
+       tvnorm = &bttv_tvnorms[btv->tvnorm];
+       btv->crop_start = tvnorm->cropcap.bounds.top
+               + tvnorm->cropcap.bounds.height;
+
+       /* VBI capturing ends at VDELAY, start of video capturing, no
+          matter how many lines the VBI RISC program expects. When video
+          capturing is off, it shall no longer "preempt" VBI capturing,
+          so we set VDELAY to maximum. */
+       crop = btread(BT848_E_CROP) | 0xc0;
+       btwrite(crop, BT848_E_CROP);
+       btwrite(0xfe, BT848_E_VDELAY_LO);
+       btwrite(crop, BT848_O_CROP);
+       btwrite(0xfe, BT848_O_VDELAY_LO);
+}
+
 static
 void free_btres(struct bttv *btv, struct bttv_fh *fh, int bits)
 {
@@ -718,10 +918,19 @@ void free_btres(struct bttv *btv, struct bttv_fh *fh, int bits)
                /* trying to free ressources not allocated by us ... */
                printk("bttv: BUG! (btres)\n");
        }
-       mutex_lock(&btv->reslock);
+       mutex_lock(&btv->lock);
        fh->resources  &= ~bits;
        btv->resources &= ~bits;
-       mutex_unlock(&btv->reslock);
+
+       bits = btv->resources;
+
+       if (0 == (bits & VIDEO_RESOURCES))
+               disclaim_video_lines(btv);
+
+       if (0 == (bits & VBI_RESOURCES))
+               disclaim_vbi_lines(btv);
+
+       mutex_unlock(&btv->lock);
 }
 
 /* ----------------------------------------------------------------------- */
@@ -1030,6 +1239,36 @@ i2c_vidiocschan(struct bttv *btv)
                bttv_tda9880_setnorm(btv,btv->tvnorm);
 }
 
+static void
+bttv_crop_calc_limits(struct bttv_crop *c)
+{
+       /* Scale factor min. 1:1, max. 16:1. Min. image size
+          48 x 32. Scaled width must be a multiple of 4. */
+
+       if (1) {
+               /* For bug compatibility with VIDIOCGCAP and image
+                  size checks in earlier driver versions. */
+               c->min_scaled_width = 48;
+               c->min_scaled_height = 32;
+       } else {
+               c->min_scaled_width =
+                       (max(48, c->rect.width >> 4) + 3) & ~3;
+               c->min_scaled_height =
+                       max(32, c->rect.height >> 4);
+       }
+
+       c->max_scaled_width  = c->rect.width & ~3;
+       c->max_scaled_height = c->rect.height;
+}
+
+static void
+bttv_crop_reset(struct bttv_crop *c, int norm)
+{
+       c->rect = bttv_tvnorms[norm].cropcap.defrect;
+       bttv_crop_calc_limits(c);
+}
+
+/* Call with btv->lock down. */
 static int
 set_tvnorm(struct bttv *btv, unsigned int norm)
 {
@@ -1038,9 +1277,24 @@ set_tvnorm(struct bttv *btv, unsigned int norm)
        if (norm < 0 || norm >= BTTV_TVNORMS)
                return -EINVAL;
 
-       btv->tvnorm = norm;
        tvnorm = &bttv_tvnorms[norm];
 
+       if (btv->tvnorm < 0 ||
+           btv->tvnorm >= BTTV_TVNORMS ||
+           0 != memcmp(&bttv_tvnorms[btv->tvnorm].cropcap,
+                       &tvnorm->cropcap,
+                       sizeof (tvnorm->cropcap))) {
+               bttv_crop_reset(&btv->crop[0], norm);
+               btv->crop[1] = btv->crop[0]; /* current = default */
+
+               if (0 == (btv->resources & VIDEO_RESOURCES)) {
+                       btv->crop_start = tvnorm->cropcap.bounds.top
+                               + tvnorm->cropcap.bounds.height;
+               }
+       }
+
+       btv->tvnorm = norm;
+
        btwrite(tvnorm->adelay, BT848_ADELAY);
        btwrite(tvnorm->bdelay, BT848_BDELAY);
        btaor(tvnorm->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH),
@@ -1057,6 +1311,7 @@ set_tvnorm(struct bttv *btv, unsigned int norm)
        return 0;
 }
 
+/* Call with btv->lock down. */
 static void
 set_input(struct bttv *btv, unsigned int input)
 {
@@ -1459,13 +1714,13 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
        btv->loop_irq |= 1;
        bttv_set_dma(btv, 0x03);
        spin_unlock_irqrestore(&btv->s_lock,flags);
-       if (NULL == new)
-               free_btres(btv,fh,RESOURCE_OVERLAY);
        if (NULL != old) {
                dprintk("switch_overlay: old=%p state is %d\n",old,old->vb.state);
                bttv_dma_free(&fh->cap,btv, old);
                kfree(old);
        }
+       if (NULL == new)
+               free_btres(btv,fh,RESOURCE_OVERLAY);
        dprintk("switch_overlay: done\n");
        return retval;
 }
@@ -1479,7 +1734,10 @@ static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,
                               unsigned int width, unsigned int height,
                               enum v4l2_field field)
 {
+       struct bttv_fh *fh = q->priv_data;
        int redo_dma_risc = 0;
+       struct bttv_crop c;
+       int norm;
        int rc;
 
        /* check settings */
@@ -1491,12 +1749,52 @@ static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,
                if (width*height > buf->vb.bsize)
                        return -EINVAL;
                buf->vb.size = buf->vb.bsize;
+
+               /* Make sure tvnorm and vbi_end remain consistent
+                  until we're done. */
+               mutex_lock(&btv->lock);
+
+               norm = btv->tvnorm;
+
+               /* In this mode capturing always starts at defrect.top
+                  (default VDELAY), ignoring cropping parameters. */
+               if (btv->vbi_end > bttv_tvnorms[norm].cropcap.defrect.top) {
+                       mutex_unlock(&btv->lock);
+                       return -EINVAL;
+               }
+
+               mutex_unlock(&btv->lock);
+
+               c.rect = bttv_tvnorms[norm].cropcap.defrect;
        } else {
-               if (width  < 48 ||
-                   height < 32 ||
-                   width  > bttv_tvnorms[btv->tvnorm].swidth ||
-                   height > bttv_tvnorms[btv->tvnorm].sheight)
+               mutex_lock(&btv->lock);
+
+               norm = btv->tvnorm;
+               c = btv->crop[!!fh->do_crop];
+
+               mutex_unlock(&btv->lock);
+
+               if (width < c.min_scaled_width ||
+                   width > c.max_scaled_width ||
+                   height < c.min_scaled_height)
                        return -EINVAL;
+
+               switch (field) {
+               case V4L2_FIELD_TOP:
+               case V4L2_FIELD_BOTTOM:
+               case V4L2_FIELD_ALTERNATE:
+                       /* btv->crop counts frame lines. Max. scale
+                          factor is 16:1 for frames, 8:1 for fields. */
+                       if (height * 2 > c.max_scaled_height)
+                               return -EINVAL;
+                       break;
+
+               default:
+                       if (height > c.max_scaled_height)
+                               return -EINVAL;
+                       break;
+               }
+
                buf->vb.size = (width * height * fmt->depth) >> 3;
                if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
                        return -EINVAL;
@@ -1505,12 +1803,17 @@ static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,
        /* alloc + fill struct bttv_buffer (if changed) */
        if (buf->vb.width != width || buf->vb.height != height ||
            buf->vb.field != field ||
-           buf->tvnorm != btv->tvnorm || buf->fmt != fmt) {
+           buf->tvnorm != norm || buf->fmt != fmt ||
+           buf->crop.top != c.rect.top ||
+           buf->crop.left != c.rect.left ||
+           buf->crop.width != c.rect.width ||
+           buf->crop.height != c.rect.height) {
                buf->vb.width  = width;
                buf->vb.height = height;
                buf->vb.field  = field;
-               buf->tvnorm    = btv->tvnorm;
+               buf->tvnorm    = norm;
                buf->fmt       = fmt;
+               buf->crop      = c.rect;
                redo_dma_risc = 1;
        }
 
@@ -1577,7 +1880,7 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
        struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
        struct bttv_fh *fh = q->priv_data;
 
-       bttv_dma_free(&fh->cap,fh->btv,buf);
+       bttv_dma_free(q,fh->btv,buf);
 }
 
 static struct videobuf_queue_ops bttv_video_qops = {
@@ -1939,11 +2242,179 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
        return 0;
 }
 
-static int verify_window(const struct bttv_tvnorm *tvn,
-                        struct v4l2_window *win, int fixup)
+/* Given cropping boundaries b and the scaled width and height of a
+   single field or frame, which must not exceed hardware limits, this
+   function adjusts the cropping parameters c. */
+static void
+bttv_crop_adjust       (struct bttv_crop *             c,
+                        const struct v4l2_rect *       b,
+                        __s32                          width,
+                        __s32                          height,
+                        enum v4l2_field                field)
+{
+       __s32 frame_height = height << !V4L2_FIELD_HAS_BOTH(field);
+       __s32 max_left;
+       __s32 max_top;
+
+       if (width < c->min_scaled_width) {
+               /* Max. hor. scale factor 16:1. */
+               c->rect.width = width * 16;
+       } else if (width > c->max_scaled_width) {
+               /* Min. hor. scale factor 1:1. */
+               c->rect.width = width;
+
+               max_left = b->left + b->width - width;
+               max_left = min(max_left, (__s32) MAX_HDELAY);
+               if (c->rect.left > max_left)
+                       c->rect.left = max_left;
+       }
+
+       if (height < c->min_scaled_height) {
+               /* Max. vert. scale factor 16:1, single fields 8:1. */
+               c->rect.height = height * 16;
+       } else if (frame_height > c->max_scaled_height) {
+               /* Min. vert. scale factor 1:1.
+                  Top and height count field lines times two. */
+               c->rect.height = (frame_height + 1) & ~1;
+
+               max_top = b->top + b->height - c->rect.height;
+               if (c->rect.top > max_top)
+                       c->rect.top = max_top;
+       }
+
+       bttv_crop_calc_limits(c);
+}
+
+/* Returns an error if scaling to a frame or single field with the given
+   width and height is not possible with the current cropping parameters
+   and width aligned according to width_mask. If adjust_size is TRUE the
+   function may adjust the width and/or height instead, rounding width
+   to (width + width_bias) & width_mask. If adjust_crop is TRUE it may
+   also adjust the current cropping parameters to get closer to the
+   desired image size. */
+static int
+limit_scaled_size       (struct bttv_fh *               fh,
+                        __s32 *                        width,
+                        __s32 *                        height,
+                        enum v4l2_field                field,
+                        unsigned int                   width_mask,
+                        unsigned int                   width_bias,
+                        int                            adjust_size,
+                        int                            adjust_crop)
+{
+       struct bttv *btv = fh->btv;
+       const struct v4l2_rect *b;
+       struct bttv_crop *c;
+       __s32 min_width;
+       __s32 min_height;
+       __s32 max_width;
+       __s32 max_height;
+       int rc;
+
+       BUG_ON((int) width_mask >= 0 ||
+              width_bias >= (unsigned int) -width_mask);
+
+       /* Make sure tvnorm, vbi_end and the current cropping parameters
+          remain consistent until we're done. */
+       mutex_lock(&btv->lock);
+
+       b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
+
+       /* Do crop - use current, don't - use default parameters. */
+       c = &btv->crop[!!fh->do_crop];
+
+       if (fh->do_crop
+           && adjust_size
+           && adjust_crop
+           && !locked_btres(btv, VIDEO_RESOURCES)) {
+               min_width = 48;
+               min_height = 32;
+
+               /* We cannot scale up. When the scaled image is larger
+                  than crop.rect we adjust the crop.rect as required
+                  by the V4L2 spec, hence cropcap.bounds are our limit. */
+               max_width = min(b->width, (__s32) MAX_HACTIVE);
+               max_height = b->height;
+
+               /* We cannot capture the same line as video and VBI data.
+                  Note btv->vbi_end is really a minimum, see
+                  bttv_vbi_try_fmt(). */
+               if (btv->vbi_end > b->top) {
+                       max_height -= btv->vbi_end - b->top;
+                       rc = -EBUSY;
+                       if (min_height > max_height)
+                               goto fail;
+               }
+       } else {
+               rc = -EBUSY;
+               if (btv->vbi_end > c->rect.top)
+                       goto fail;
+
+               min_width  = c->min_scaled_width;
+               min_height = c->min_scaled_height;
+               max_width  = c->max_scaled_width;
+               max_height = c->max_scaled_height;
+
+               adjust_crop = 0;
+       }
+
+       min_width = (min_width - width_mask - 1) & width_mask;
+       max_width = max_width & width_mask;
+
+       /* Max. scale factor is 16:1 for frames, 8:1 for fields. */
+       min_height = min_height;
+       /* Min. scale factor is 1:1. */
+       max_height >>= !V4L2_FIELD_HAS_BOTH(field);
+
+       if (adjust_size) {
+               *width = clamp(*width, min_width, max_width);
+               *height = clamp(*height, min_height, max_height);
+
+               /* Round after clamping to avoid overflow. */
+               *width = (*width + width_bias) & width_mask;
+
+               if (adjust_crop) {
+                       bttv_crop_adjust(c, b, *width, *height, field);
+
+                       if (btv->vbi_end > c->rect.top) {
+                               /* Move the crop window out of the way. */
+                               c->rect.top = btv->vbi_end;
+                       }
+               }
+       } else {
+               rc = -EINVAL;
+               if (*width  < min_width ||
+                   *height < min_height ||
+                   *width  > max_width ||
+                   *height > max_height ||
+                   0 != (*width & ~width_mask))
+                       goto fail;
+       }
+
+       rc = 0; /* success */
+
+ fail:
+       mutex_unlock(&btv->lock);
+
+       return rc;
+}
+
+/* Returns an error if the given overlay window dimensions are not
+   possible with the current cropping parameters. If adjust_size is
+   TRUE the function may adjust the window width and/or height
+   instead, however it always rounds the horizontal position and
+   width as btcx_align() does. If adjust_crop is TRUE the function
+   may also adjust the current cropping parameters to get closer
+   to the desired window size. */
+static int
+verify_window          (struct bttv_fh *               fh,
+                        struct v4l2_window *           win,
+                        int                            adjust_size,
+                        int                            adjust_crop)
 {
        enum v4l2_field field;
-       int maxw, maxh;
+       unsigned int width_mask;
+       int rc;
 
        if (win->w.width  < 48 || win->w.height < 32)
                return -EINVAL;
@@ -1951,32 +2422,52 @@ static int verify_window(const struct bttv_tvnorm *tvn,
                return -EINVAL;
 
        field = win->field;
-       maxw  = tvn->swidth;
-       maxh  = tvn->sheight;
 
        if (V4L2_FIELD_ANY == field) {
-               field = (win->w.height > maxh/2)
+               __s32 height2;
+
+               height2 = fh->btv->crop[!!fh->do_crop].rect.height >> 1;
+               field = (win->w.height > height2)
                        ? V4L2_FIELD_INTERLACED
                        : V4L2_FIELD_TOP;
        }
        switch (field) {
        case V4L2_FIELD_TOP:
        case V4L2_FIELD_BOTTOM:
-               maxh = maxh / 2;
-               break;
        case V4L2_FIELD_INTERLACED:
                break;
        default:
                return -EINVAL;
        }
 
-       if (!fixup && (win->w.width > maxw || win->w.height > maxh))
+       /* 4-byte alignment. */
+       if (NULL == fh->ovfmt)
                return -EINVAL;
+       width_mask = ~0;
+       switch (fh->ovfmt->depth) {
+       case 8:
+       case 24:
+               width_mask = ~3;
+               break;
+       case 16:
+               width_mask = ~1;
+               break;
+       case 32:
+               break;
+       default:
+               BUG();
+       }
+
+       win->w.width -= win->w.left & ~width_mask;
+       win->w.left = (win->w.left - width_mask - 1) & width_mask;
+
+       rc = limit_scaled_size(fh, &win->w.width, &win->w.height,
+                              field, width_mask,
+                              /* width_bias: round down */ 0,
+                              adjust_size, adjust_crop);
+       if (0 != rc)
+               return rc;
 
-       if (win->w.width > maxw)
-               win->w.width = maxw;
-       if (win->w.height > maxh)
-               win->w.height = maxh;
        win->field = field;
        return 0;
 }
@@ -1991,7 +2482,9 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv,
                return -EINVAL;
        if (!(fh->ovfmt->flags & FORMAT_FLAGS_PACKED))
                return -EINVAL;
-       retval = verify_window(&bttv_tvnorms[btv->tvnorm],win,fixup);
+       retval = verify_window(fh, win,
+                              /* adjust_size */ fixup,
+                              /* adjust_crop */ fixup);
        if (0 != retval)
                return retval;
 
@@ -2048,6 +2541,7 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv,
                struct bttv_buffer *new;
 
                new = videobuf_alloc(sizeof(*new));
+               new->crop = btv->crop[!!fh->do_crop].rect;
                bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
                retval = bttv_switch_overlay(btv,fh,new);
        }
@@ -2080,7 +2574,7 @@ static int bttv_resource(struct bttv_fh *fh)
 
        switch (fh->type) {
        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               res = RESOURCE_VIDEO;
+               res = RESOURCE_VIDEO_STREAM;
                break;
        case V4L2_BUF_TYPE_VBI_CAPTURE:
                res = RESOURCE_VBI;
@@ -2138,7 +2632,7 @@ static int bttv_g_fmt(struct bttv_fh *fh, struct v4l2_format *f)
                f->fmt.win.field = fh->ov.field;
                return 0;
        case V4L2_BUF_TYPE_VBI_CAPTURE:
-               bttv_vbi_get_fmt(fh,f);
+               bttv_vbi_get_fmt(fh, &f->fmt.vbi);
                return 0;
        default:
                return -EINVAL;
@@ -2146,35 +2640,35 @@ static int bttv_g_fmt(struct bttv_fh *fh, struct v4l2_format *f)
 }
 
 static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv,
-                       struct v4l2_format *f)
+                       struct v4l2_format *f, int adjust_crop)
 {
        switch (f->type) {
        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
        {
                const struct bttv_format *fmt;
                enum v4l2_field field;
-               unsigned int maxw,maxh;
+               __s32 width, height;
+               int rc;
 
                fmt = format_by_fourcc(f->fmt.pix.pixelformat);
                if (NULL == fmt)
                        return -EINVAL;
 
-               /* fixup format */
-               maxw  = bttv_tvnorms[btv->tvnorm].swidth;
-               maxh  = bttv_tvnorms[btv->tvnorm].sheight;
                field = f->fmt.pix.field;
-               if (V4L2_FIELD_ANY == field)
-                       field = (f->fmt.pix.height > maxh/2)
+               if (V4L2_FIELD_ANY == field) {
+                       __s32 height2;
+
+                       height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
+                       field = (f->fmt.pix.height > height2)
                                ? V4L2_FIELD_INTERLACED
                                : V4L2_FIELD_BOTTOM;
+               }
                if (V4L2_FIELD_SEQ_BT == field)
                        field = V4L2_FIELD_SEQ_TB;
                switch (field) {
                case V4L2_FIELD_TOP:
                case V4L2_FIELD_BOTTOM:
                case V4L2_FIELD_ALTERNATE:
-                       maxh = maxh/2;
-                       break;
                case V4L2_FIELD_INTERLACED:
                        break;
                case V4L2_FIELD_SEQ_TB:
@@ -2185,28 +2679,29 @@ static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv,
                        return -EINVAL;
                }
 
+               width = f->fmt.pix.width;
+               height = f->fmt.pix.height;
+
+               rc = limit_scaled_size(fh, &width, &height, field,
+                                      /* width_mask: 4 pixels */ ~3,
+                                      /* width_bias: nearest */ 2,
+                                      /* adjust_size */ 1,
+                                      adjust_crop);
+               if (0 != rc)
+                       return rc;
+
                /* update data for the application */
                f->fmt.pix.field = field;
-               if (f->fmt.pix.width  < 48)
-                       f->fmt.pix.width  = 48;
-               if (f->fmt.pix.height < 32)
-                       f->fmt.pix.height = 32;
-               if (f->fmt.pix.width  > maxw)
-                       f->fmt.pix.width = maxw;
-               if (f->fmt.pix.height > maxh)
-                       f->fmt.pix.height = maxh;
-               pix_format_set_size (&f->fmt.pix, fmt,
-                                    f->fmt.pix.width & ~3,
-                                    f->fmt.pix.height);
+               pix_format_set_size(&f->fmt.pix, fmt, width, height);
 
                return 0;
        }
        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-               return verify_window(&bttv_tvnorms[btv->tvnorm],
-                                    &f->fmt.win, 1);
+               return verify_window(fh, &f->fmt.win,
+                                    /* adjust_size */ 1,
+                                    /* adjust_crop */ 0);
        case V4L2_BUF_TYPE_VBI_CAPTURE:
-               bttv_vbi_try_fmt(fh,f);
-               return 0;
+               return bttv_vbi_try_fmt(fh, &f->fmt.vbi);
        default:
                return -EINVAL;
        }
@@ -2225,7 +2720,7 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv,
                retval = bttv_switch_type(fh,f->type);
                if (0 != retval)
                        return retval;
-               retval = bttv_try_fmt(fh,btv,f);
+               retval = bttv_try_fmt(fh,btv,f, /* adjust_crop */ 1);
                if (0 != retval)
                        return retval;
                fmt = format_by_fourcc(f->fmt.pix.pixelformat);
@@ -2254,12 +2749,7 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv,
                retval = bttv_switch_type(fh,f->type);
                if (0 != retval)
                        return retval;
-               if (locked_btres(fh->btv, RESOURCE_VBI))
-                       return -EBUSY;
-               bttv_vbi_try_fmt(fh,f);
-               bttv_vbi_setlines(fh,btv,f->fmt.vbi.count[0]);
-               bttv_vbi_get_fmt(fh,f);
-               return 0;
+               return bttv_vbi_set_fmt(fh, &f->fmt.vbi);
        default:
                return -EINVAL;
        }
@@ -2517,6 +3007,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
                if (*on) {
                        fh->ov.tvnorm = btv->tvnorm;
                        new = videobuf_alloc(sizeof(*new));
+                       new->crop = btv->crop[!!fh->do_crop].rect;
                        bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
                } else {
                        new = NULL;
@@ -2551,10 +3042,16 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
                struct video_mmap *vm = arg;
                struct bttv_buffer *buf;
                enum v4l2_field field;
+               __s32 height2;
+               int res;
 
                if (vm->frame >= VIDEO_MAX_FRAME)
                        return -EINVAL;
 
+               res = bttv_resource(fh);
+               if (!check_alloc_btres(btv, fh, res))
+                       return -EBUSY;
+
                mutex_lock(&fh->cap.lock);
                retval = -EINVAL;
                buf = (struct bttv_buffer *)fh->cap.bufs[vm->frame];
@@ -2566,7 +3063,8 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
                    buf->vb.state == STATE_ACTIVE)
                        goto fh_unlock_and_return;
 
-               field = (vm->height > bttv_tvnorms[btv->tvnorm].sheight/2)
+               height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
+               field = (vm->height > height2)
                        ? V4L2_FIELD_INTERLACED
                        : V4L2_FIELD_BOTTOM;
                retval = bttv_prepare_buffer(&fh->cap,btv,buf,
@@ -2613,54 +3111,17 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
        }
 
        case VIDIOCGVBIFMT:
-       {
-               struct vbi_format *fmt = (void *) arg;
-               struct v4l2_format fmt2;
-
                if (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) {
                        retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE);
                        if (0 != retval)
                                return retval;
                }
-               bttv_vbi_get_fmt(fh, &fmt2);
-
-               memset(fmt,0,sizeof(*fmt));
-               fmt->sampling_rate    = fmt2.fmt.vbi.sampling_rate;
-               fmt->samples_per_line = fmt2.fmt.vbi.samples_per_line;
-               fmt->sample_format    = VIDEO_PALETTE_RAW;
-               fmt->start[0]         = fmt2.fmt.vbi.start[0];
-               fmt->count[0]         = fmt2.fmt.vbi.count[0];
-               fmt->start[1]         = fmt2.fmt.vbi.start[1];
-               fmt->count[1]         = fmt2.fmt.vbi.count[1];
-               if (fmt2.fmt.vbi.flags & V4L2_VBI_UNSYNC)
-                       fmt->flags   |= VBI_UNSYNC;
-               if (fmt2.fmt.vbi.flags & V4L2_VBI_INTERLACED)
-                       fmt->flags   |= VBI_INTERLACED;
-               return 0;
-       }
-       case VIDIOCSVBIFMT:
-       {
-               struct vbi_format *fmt = (void *) arg;
-               struct v4l2_format fmt2;
 
-               retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE);
-               if (0 != retval)
-                       return retval;
-               bttv_vbi_get_fmt(fh, &fmt2);
-
-               if (fmt->sampling_rate    != fmt2.fmt.vbi.sampling_rate     ||
-                   fmt->samples_per_line != fmt2.fmt.vbi.samples_per_line  ||
-                   fmt->sample_format    != VIDEO_PALETTE_RAW              ||
-                   fmt->start[0]         != fmt2.fmt.vbi.start[0]          ||
-                   fmt->start[1]         != fmt2.fmt.vbi.start[1]          ||
-                   fmt->count[0]         != fmt->count[1]                  ||
-                   fmt->count[0]         <  1                              ||
-                   fmt->count[0]         >  32 /* VBI_MAXLINES */)
-                       return -EINVAL;
+               /* fall through */
 
-               bttv_vbi_setlines(fh,btv,fmt->count[0]);
-               return 0;
-       }
+       case VIDIOCSVBIFMT:
+               return v4l_compat_translate_ioctl(inode, file, cmd,
+                                                 arg, bttv_do_ioctl);
 
        case BTTV_VERSION:
        case VIDIOCGFREQ:
@@ -2753,7 +3214,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
        case VIDIOC_TRY_FMT:
        {
                struct v4l2_format *f = arg;
-               return bttv_try_fmt(fh,btv,f);
+               return bttv_try_fmt(fh,btv,f, /* adjust_crop */ 0);
        }
        case VIDIOC_G_FMT:
        {
@@ -2792,16 +3253,23 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
                if (0 == (fmt->flags & FORMAT_FLAGS_PACKED))
                        return -EINVAL;
 
-               mutex_lock(&fh->cap.lock);
                retval = -EINVAL;
                if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
-                       if (fb->fmt.width > bttv_tvnorms[btv->tvnorm].swidth)
-                               goto fh_unlock_and_return;
-                       if (fb->fmt.height > bttv_tvnorms[btv->tvnorm].sheight)
-                               goto fh_unlock_and_return;
+                       __s32 width = fb->fmt.width;
+                       __s32 height = fb->fmt.height;
+
+                       retval = limit_scaled_size(fh, &width, &height,
+                                                  V4L2_FIELD_INTERLACED,
+                                                  /* width_mask */ ~3,
+                                                  /* width_bias */ 2,
+                                                  /* adjust_size */ 0,
+                                                  /* adjust_crop */ 0);
+                       if (0 != retval)
+                               return retval;
                }
 
                /* ok, accept it */
+               mutex_lock(&fh->cap.lock);
                btv->fbuf.base       = fb->base;
                btv->fbuf.fmt.width  = fb->fmt.width;
                btv->fbuf.fmt.height = fb->fmt.height;
@@ -2828,6 +3296,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
                                struct bttv_buffer *new;
 
                                new = videobuf_alloc(sizeof(*new));
+                               new->crop = btv->crop[!!fh->do_crop].rect;
                                bttv_overlay_risc(btv,&fh->ov,fh->ovfmt,new);
                                retval = bttv_switch_overlay(btv,fh,new);
                        }
@@ -2843,7 +3312,13 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
                return videobuf_querybuf(bttv_queue(fh),arg);
 
        case VIDIOC_QBUF:
+       {
+               int res = bttv_resource(fh);
+
+               if (!check_alloc_btres(btv, fh, res))
+                       return -EBUSY;
                return videobuf_qbuf(bttv_queue(fh),arg);
+       }
 
        case VIDIOC_DQBUF:
                return videobuf_dqbuf(bttv_queue(fh),arg,
@@ -2942,6 +3417,122 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
                return v4l2_prio_change(&btv->prio, &fh->prio, *prio);
        }
 
+       case VIDIOC_CROPCAP:
+       {
+               struct v4l2_cropcap *cap = arg;
+               enum v4l2_buf_type type;
+
+               type = cap->type;
+
+               if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+                   type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+                       return -EINVAL;
+
+               *cap = bttv_tvnorms[btv->tvnorm].cropcap;
+               cap->type = type;
+
+               return 0;
+       }
+       case VIDIOC_G_CROP:
+       {
+               struct v4l2_crop * crop = arg;
+
+               if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+                   crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+                       return -EINVAL;
+
+               /* No fh->do_crop = 1; because btv->crop[1] may be
+                  inconsistent with fh->width or fh->height and apps
+                  do not expect a change here. */
+
+               crop->c = btv->crop[!!fh->do_crop].rect;
+
+               return 0;
+       }
+       case VIDIOC_S_CROP:
+       {
+               struct v4l2_crop *crop = arg;
+               const struct v4l2_rect *b;
+               struct bttv_crop c;
+               __s32 b_left;
+               __s32 b_top;
+               __s32 b_right;
+               __s32 b_bottom;
+
+               if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+                   crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+                       return -EINVAL;
+
+               retval = v4l2_prio_check(&btv->prio,&fh->prio);
+               if (0 != retval)
+                       return retval;
+
+               /* Make sure tvnorm, vbi_end and the current cropping
+                  parameters remain consistent until we're done. Note
+                  read() may change vbi_end in check_alloc_btres(). */
+               mutex_lock(&btv->lock);
+
+               retval = -EBUSY;
+
+               if (locked_btres(fh->btv, VIDEO_RESOURCES))
+                       goto btv_unlock_and_return;
+
+               b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
+
+               b_left = b->left;
+               b_right = b_left + b->width;
+               b_bottom = b->top + b->height;
+
+               b_top = max(b->top, btv->vbi_end);
+               if (b_top + 32 >= b_bottom)
+                       goto btv_unlock_and_return;
+
+               /* Min. scaled size 48 x 32. */
+               c.rect.left = clamp(crop->c.left, b_left, b_right - 48);
+               c.rect.left = min(c.rect.left, (__s32) MAX_HDELAY);
+
+               c.rect.width = clamp(crop->c.width,
+                                    48, b_right - c.rect.left);
+
+               c.rect.top = clamp(crop->c.top, b_top, b_bottom - 32);
+               /* Top and height must be a multiple of two. */
+               c.rect.top = (c.rect.top + 1) & ~1;
+
+               c.rect.height = clamp(crop->c.height,
+                                     32, b_bottom - c.rect.top);
+               c.rect.height = (c.rect.height + 1) & ~1;
+
+               bttv_crop_calc_limits(&c);
+
+               btv->crop[1] = c;
+
+               mutex_unlock(&btv->lock);
+
+               fh->do_crop = 1;
+
+               mutex_lock(&fh->cap.lock);
+
+               if (fh->width < c.min_scaled_width) {
+                       fh->width = c.min_scaled_width;
+                       btv->init.width = c.min_scaled_width;
+               } else if (fh->width > c.max_scaled_width) {
+                       fh->width = c.max_scaled_width;
+                       btv->init.width = c.max_scaled_width;
+               }
+
+               if (fh->height < c.min_scaled_height) {
+                       fh->height = c.min_scaled_height;
+                       btv->init.height = c.min_scaled_height;
+               } else if (fh->height > c.max_scaled_height) {
+                       fh->height = c.max_scaled_height;
+                       btv->init.height = c.max_scaled_height;
+               }
+
+               mutex_unlock(&fh->cap.lock);
+
+               return 0;
+       }
+
        case VIDIOC_ENUMSTD:
        case VIDIOC_G_STD:
        case VIDIOC_S_STD:
@@ -2963,6 +3554,10 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
  fh_unlock_and_return:
        mutex_unlock(&fh->cap.lock);
        return retval;
+
+ btv_unlock_and_return:
+       mutex_unlock(&btv->lock);
+       return retval;
 }
 
 static int bttv_ioctl(struct inode *inode, struct file *file,
@@ -2972,8 +3567,26 @@ static int bttv_ioctl(struct inode *inode, struct file *file,
 
        switch (cmd) {
        case BTTV_VBISIZE:
+       {
+               const struct bttv_tvnorm *tvnorm;
+
+               tvnorm = fh->vbi_fmt.tvnorm;
+
+               if (fh->vbi_fmt.fmt.start[0] != tvnorm->vbistart[0] ||
+                   fh->vbi_fmt.fmt.start[1] != tvnorm->vbistart[1] ||
+                   fh->vbi_fmt.fmt.count[0] != fh->vbi_fmt.fmt.count[1]) {
+                       /* BTTV_VBISIZE cannot express these parameters,
+                          however open() resets the paramters to defaults
+                          and apps shouldn't call BTTV_VBISIZE after
+                          VIDIOC_S_FMT. */
+                       return -EINVAL;
+               }
+
                bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE);
-               return fh->lines * 2 * 2048;
+               return (fh->vbi_fmt.fmt.count[0] * 2
+                       * fh->vbi_fmt.fmt.samples_per_line);
+       }
+
        default:
                return video_usercopy(inode, file, cmd, arg, bttv_do_ioctl);
        }
@@ -2992,10 +3605,14 @@ static ssize_t bttv_read(struct file *file, char __user *data,
 
        switch (fh->type) {
        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               if (locked_btres(fh->btv,RESOURCE_VIDEO))
+               if (!check_alloc_btres(fh->btv, fh, RESOURCE_VIDEO_READ)) {
+                       /* VIDEO_READ in use by another fh,
+                          or VIDEO_STREAM by any fh. */
                        return -EBUSY;
+               }
                retval = videobuf_read_one(&fh->cap, data, count, ppos,
                                           file->f_flags & O_NONBLOCK);
+               free_btres(fh->btv, fh, RESOURCE_VIDEO_READ);
                break;
        case V4L2_BUF_TYPE_VBI_CAPTURE:
                if (!check_alloc_btres(fh->btv,fh,RESOURCE_VBI))
@@ -3021,7 +3638,7 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
                return videobuf_poll_stream(file, &fh->vbi, wait);
        }
 
-       if (check_btres(fh,RESOURCE_VIDEO)) {
+       if (check_btres(fh,RESOURCE_VIDEO_STREAM)) {
                /* streaming capture */
                if (list_empty(&fh->cap.stream))
                        return POLLERR;
@@ -3031,7 +3648,7 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
                mutex_lock(&fh->cap.lock);
                if (NULL == fh->cap.read_buf) {
                        /* need to capture a new frame */
-                       if (locked_btres(fh->btv,RESOURCE_VIDEO)) {
+                       if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM)) {
                                mutex_unlock(&fh->cap.lock);
                                return POLLERR;
                        }
@@ -3117,8 +3734,23 @@ static int bttv_open(struct inode *inode, struct file *file)
        i2c_vidiocschan(btv);
 
        btv->users++;
-       if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type)
-               bttv_vbi_setlines(fh,btv,16);
+
+       /* The V4L2 spec requires one global set of cropping parameters
+          which only change on request. These are stored in btv->crop[1].
+          However for compatibility with V4L apps and cropping unaware
+          V4L2 apps we now reset the cropping parameters as seen through
+          this fh, which is to say VIDIOC_G_CROP and scaling limit checks
+          will use btv->crop[0], the default cropping parameters for the
+          current video standard, and VIDIOC_S_FMT will not implicitely
+          change the cropping parameters until VIDIOC_S_CROP has been
+          called. */
+       fh->do_crop = !reset_crop; /* module parameter */
+
+       /* Likewise there should be one global set of VBI capture
+          parameters, but for compatibility with V4L apps and earlier
+          driver versions each fh has its own parameters. */
+       bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm);
+
        bttv_field_count(btv);
        return 0;
 }
@@ -3133,14 +3765,17 @@ static int bttv_release(struct inode *inode, struct file *file)
                bttv_switch_overlay(btv,fh,NULL);
 
        /* stop video capture */
-       if (check_btres(fh, RESOURCE_VIDEO)) {
+       if (check_btres(fh, RESOURCE_VIDEO_STREAM)) {
                videobuf_streamoff(&fh->cap);
-               free_btres(btv,fh,RESOURCE_VIDEO);
+               free_btres(btv,fh,RESOURCE_VIDEO_STREAM);
        }
        if (fh->cap.read_buf) {
                buffer_release(&fh->cap,fh->cap.read_buf);
                kfree(fh->cap.read_buf);
        }
+       if (check_btres(fh, RESOURCE_VIDEO_READ)) {
+               free_btres(btv, fh, RESOURCE_VIDEO_READ);
+       }
 
        /* stop vbi capture */
        if (check_btres(fh, RESOURCE_VBI)) {
@@ -3997,7 +4632,6 @@ static int __devinit bttv_probe(struct pci_dev *dev,
 
        /* initialize structs / fill in defaults */
        mutex_init(&btv->lock);
-       mutex_init(&btv->reslock);
        spin_lock_init(&btv->s_lock);
        spin_lock_init(&btv->gpio_lock);
        init_waitqueue_head(&btv->gpioq);
@@ -4095,7 +4729,6 @@ static int __devinit bttv_probe(struct pci_dev *dev,
        btv->init.fmt         = format_by_palette(VIDEO_PALETTE_RGB24);
        btv->init.width       = 320;
        btv->init.height      = 240;
-       btv->init.lines       = 16;
        btv->input = 0;
 
        /* initialize hardware */
@@ -4130,6 +4763,10 @@ static int __devinit bttv_probe(struct pci_dev *dev,
                bt848_sat(btv,32768);
                audio_mute(btv, 1);
                set_input(btv,0);
+               bttv_crop_reset(&btv->crop[0], btv->tvnorm);
+               btv->crop[1] = btv->crop[0]; /* current = default */
+               disclaim_vbi_lines(btv);
+               disclaim_video_lines(btv);
        }
 
        /* add subdevices */
index cbc012f71f5269e7b570195139ca88f426710286..6f74c8042bc346ff3df0bbe8d59557144b89408d 100644 (file)
@@ -36,13 +36,18 @@ module_param(repeat_delay, int, 0644);
 static int repeat_period = 33;
 module_param(repeat_period, int, 0644);
 
+static int ir_rc5_remote_gap = 885;
+module_param(ir_rc5_remote_gap, int, 0644);
+static int ir_rc5_key_timeout = 200;
+module_param(ir_rc5_key_timeout, int, 0644);
+
 #define DEVNAME "bttv-input"
 
 /* ---------------------------------------------------------------------- */
 
 static void ir_handle_key(struct bttv *btv)
 {
-       struct bttv_ir *ir = btv->remote;
+       struct card_ir *ir = btv->remote;
        u32 gpio,data;
 
        /* read gpio value */
@@ -72,7 +77,7 @@ static void ir_handle_key(struct bttv *btv)
 
 void bttv_input_irq(struct bttv *btv)
 {
-       struct bttv_ir *ir = btv->remote;
+       struct card_ir *ir = btv->remote;
 
        if (!ir->polling)
                ir_handle_key(btv);
@@ -81,65 +86,21 @@ void bttv_input_irq(struct bttv *btv)
 static void bttv_input_timer(unsigned long data)
 {
        struct bttv *btv = (struct bttv*)data;
-       struct bttv_ir *ir = btv->remote;
-       unsigned long timeout;
+       struct card_ir *ir = btv->remote;
 
        ir_handle_key(btv);
-       timeout = jiffies + (ir->polling * HZ / 1000);
-       mod_timer(&ir->timer, timeout);
+       mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
 }
 
 /* ---------------------------------------------------------------*/
 
-static int rc5_remote_gap = 885;
-module_param(rc5_remote_gap, int, 0644);
-static int rc5_key_timeout = 200;
-module_param(rc5_key_timeout, int, 0644);
-
-#define RC5_START(x)   (((x)>>12)&3)
-#define RC5_TOGGLE(x)  (((x)>>11)&1)
-#define RC5_ADDR(x)    (((x)>>6)&31)
-#define RC5_INSTR(x)   ((x)&63)
-
-/* decode raw bit pattern to RC5 code */
-static u32 rc5_decode(unsigned int code)
-{
-       unsigned int org_code = code;
-       unsigned int pair;
-       unsigned int rc5 = 0;
-       int i;
-
-       code = (code << 1) | 1;
-       for (i = 0; i < 14; ++i) {
-               pair = code & 0x3;
-               code >>= 2;
-
-               rc5 <<= 1;
-               switch (pair) {
-               case 0:
-               case 2:
-                       break;
-               case 1:
-                       rc5 |= 1;
-                       break;
-               case 3:
-                       dprintk(KERN_WARNING "bad code: %x\n", org_code);
-                       return 0;
-               }
-       }
-       dprintk(KERN_WARNING "code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
-               "instr=%x\n", rc5, org_code, RC5_START(rc5),
-               RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
-       return rc5;
-}
-
 static int bttv_rc5_irq(struct bttv *btv)
 {
-       struct bttv_ir *ir = btv->remote;
+       struct card_ir *ir = btv->remote;
        struct timeval tv;
        u32 gpio;
        u32 gap;
-       unsigned long current_jiffies, timeout;
+       unsigned long current_jiffies;
 
        /* read gpio port */
        gpio = bttv_gpio_read(&btv->c);
@@ -165,8 +126,8 @@ static int bttv_rc5_irq(struct bttv *btv)
                /* only if in the code (otherwise spurious IRQ or timer
                   late) */
                if (ir->last_bit < 28) {
-                       ir->last_bit = (gap - rc5_remote_gap / 2) /
-                           rc5_remote_gap;
+                       ir->last_bit = (gap - ir_rc5_remote_gap / 2) /
+                           ir_rc5_remote_gap;
                        ir->code |= 1 << ir->last_bit;
                }
                /* starting new code */
@@ -176,8 +137,8 @@ static int bttv_rc5_irq(struct bttv *btv)
                ir->base_time = tv;
                ir->last_bit = 0;
 
-               timeout = current_jiffies + (500 + 30 * HZ) / 1000;
-               mod_timer(&ir->timer_end, timeout);
+               mod_timer(&ir->timer_end,
+                         current_jiffies + msecs_to_jiffies(30));
        }
 
        /* toggle GPIO pin 4 to reset the irq */
@@ -186,96 +147,28 @@ static int bttv_rc5_irq(struct bttv *btv)
        return 1;
 }
 
-
-static void bttv_rc5_timer_end(unsigned long data)
-{
-       struct bttv_ir *ir = (struct bttv_ir *)data;
-       struct timeval tv;
-       unsigned long current_jiffies, timeout;
-       u32 gap;
-
-       /* get time */
-       current_jiffies = jiffies;
-       do_gettimeofday(&tv);
-
-       /* avoid overflow with gap >1s */
-       if (tv.tv_sec - ir->base_time.tv_sec > 1) {
-               gap = 200000;
-       } else {
-               gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
-                   tv.tv_usec - ir->base_time.tv_usec;
-       }
-
-       /* Allow some timmer jitter (RC5 is ~24ms anyway so this is ok) */
-       if (gap < 28000) {
-               dprintk(KERN_WARNING "spurious timer_end\n");
-               return;
-       }
-
-       ir->active = 0;
-       if (ir->last_bit < 20) {
-               /* ignore spurious codes (caused by light/other remotes) */
-               dprintk(KERN_WARNING "short code: %x\n", ir->code);
-       } else {
-               u32 rc5 = rc5_decode(ir->code);
-
-               /* two start bits? */
-               if (RC5_START(rc5) != 3) {
-                       dprintk(KERN_WARNING "rc5 start bits invalid: %u\n", RC5_START(rc5));
-
-                       /* right address? */
-               } else if (RC5_ADDR(rc5) == 0x0) {
-                       u32 toggle = RC5_TOGGLE(rc5);
-                       u32 instr = RC5_INSTR(rc5);
-
-                       /* Good code, decide if repeat/repress */
-                       if (toggle != RC5_TOGGLE(ir->last_rc5) ||
-                           instr != RC5_INSTR(ir->last_rc5)) {
-                               dprintk(KERN_WARNING "instruction %x, toggle %x\n", instr,
-                                       toggle);
-                               ir_input_nokey(ir->dev, &ir->ir);
-                               ir_input_keydown(ir->dev, &ir->ir, instr,
-                                                instr);
-                       }
-
-                       /* Set/reset key-up timer */
-                       timeout = current_jiffies + (500 + rc5_key_timeout
-                                                    * HZ) / 1000;
-                       mod_timer(&ir->timer_keyup, timeout);
-
-                       /* Save code for repeat test */
-                       ir->last_rc5 = rc5;
-               }
-       }
-}
-
-static void bttv_rc5_timer_keyup(unsigned long data)
-{
-       struct bttv_ir *ir = (struct bttv_ir *)data;
-
-       dprintk(KERN_DEBUG "key released\n");
-       ir_input_nokey(ir->dev, &ir->ir);
-}
-
 /* ---------------------------------------------------------------------- */
 
-static void bttv_ir_start(struct bttv *btv, struct bttv_ir *ir)
+static void bttv_ir_start(struct bttv *btv, struct card_ir *ir)
 {
        if (ir->polling) {
-               init_timer(&ir->timer);
-               ir->timer.function = bttv_input_timer;
-               ir->timer.data     = (unsigned long)btv;
+               setup_timer(&ir->timer, bttv_input_timer, (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.function = ir_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.function = ir_rc5_timer_keyup;
                ir->timer_keyup.data = (unsigned long)ir;
+               ir->shift_by = 1;
+               ir->start = 3;
+               ir->addr = 0x0;
+               ir->rc5_key_timeout = ir_rc5_key_timeout;
+               ir->rc5_remote_gap = ir_rc5_remote_gap;
        }
 }
 
@@ -299,7 +192,7 @@ static void bttv_ir_stop(struct bttv *btv)
 
 int bttv_input_init(struct bttv *btv)
 {
-       struct bttv_ir *ir;
+       struct card_ir *ir;
        IR_KEYTAB_TYPE *ir_codes = NULL;
        struct input_dev *input_dev;
        int ir_type = IR_TYPE_OTHER;
index afcfe71e37928ca7558a6dad33ef27dea609a0b4..e7104d9cb4bd14d14da412c4ac644e09cd6ab167 100644 (file)
@@ -43,7 +43,8 @@ int
 bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
                 struct scatterlist *sglist,
                 unsigned int offset, unsigned int bpl,
-                unsigned int padding, unsigned int lines)
+                unsigned int padding, unsigned int skip_lines,
+                unsigned int store_lines)
 {
        u32 instructions,line,todo;
        struct scatterlist *sg;
@@ -54,9 +55,11 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
           one write per scan line + sync + jump (all 2 dwords).  padding
           can cause next bpl to start close to a page border.  First DMA
           region may be smaller than PAGE_SIZE */
-       instructions  = 1 + ((bpl + padding) * lines) / PAGE_SIZE + lines;
-       instructions += 2;
-       if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*8)) < 0)
+       instructions  = skip_lines * 4;
+       instructions += (1 + ((bpl + padding) * store_lines)
+                        / PAGE_SIZE + store_lines) * 8;
+       instructions += 2 * 8;
+       if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions)) < 0)
                return rc;
 
        /* sync instruction */
@@ -64,11 +67,16 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
        *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
        *(rp++) = cpu_to_le32(0);
 
+       while (skip_lines-- > 0) {
+               *(rp++) = cpu_to_le32(BT848_RISC_SKIP | BT848_RISC_SOL |
+                                     BT848_RISC_EOL | bpl);
+       }
+
        /* scan lines */
        sg = sglist;
-       for (line = 0; line < lines; line++) {
+       for (line = 0; line < store_lines; line++) {
                if ((btv->opt_vcr_hack) &&
-                   (line >= (lines - VCR_HACK_LINES)))
+                   (line >= (store_lines - VCR_HACK_LINES)))
                        continue;
                while (offset && offset >= sg_dma_len(sg)) {
                        offset -= sg_dma_len(sg);
@@ -130,7 +138,8 @@ bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
        /* estimate risc mem: worst case is one write per page border +
           one write per scan line (5 dwords)
           plus sync + jump (2 dwords) */
-       instructions  = (ybpl * ylines * 2) / PAGE_SIZE + ylines;
+       instructions  = ((3 + (ybpl + ypadding) * ylines * 2)
+                        / PAGE_SIZE) + ylines;
        instructions += 2;
        if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0)
                return rc;
@@ -317,10 +326,10 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
 /* ---------------------------------------------------------- */
 
 static void
-bttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo,
-             int width, int height, int interleaved, int norm)
+bttv_calc_geo_old(struct bttv *btv, struct bttv_geometry *geo,
+                 int width, int height, int interleaved,
+                 const struct bttv_tvnorm *tvnorm)
 {
-       const struct bttv_tvnorm *tvnorm = &bttv_tvnorms[norm];
        u32 xsf, sr;
        int vdelay;
 
@@ -360,6 +369,62 @@ bttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo,
        }
 }
 
+static void
+bttv_calc_geo          (struct bttv *                  btv,
+                        struct bttv_geometry *         geo,
+                        unsigned int                   width,
+                        unsigned int                   height,
+                        int                            both_fields,
+                        const struct bttv_tvnorm *     tvnorm,
+                        const struct v4l2_rect *       crop)
+{
+       unsigned int c_width;
+       unsigned int c_height;
+       u32 sr;
+
+       if ((crop->left == tvnorm->cropcap.defrect.left
+            && crop->top == tvnorm->cropcap.defrect.top
+            && crop->width == tvnorm->cropcap.defrect.width
+            && crop->height == tvnorm->cropcap.defrect.height
+            && width <= tvnorm->swidth /* see PAL-Nc et al */)
+           || bttv_tvcards[btv->c.type].muxsel[btv->input] < 0) {
+               bttv_calc_geo_old(btv, geo, width, height,
+                                 both_fields, tvnorm);
+               return;
+       }
+
+       /* For bug compatibility the image size checks permit scale
+          factors > 16. See bttv_crop_calc_limits(). */
+       c_width = min((unsigned int) crop->width, width * 16);
+       c_height = min((unsigned int) crop->height, height * 16);
+
+       geo->width = width;
+       geo->hscale = (c_width * 4096U + (width >> 1)) / width - 4096;
+       /* Even to store Cb first, odd for Cr. */
+       geo->hdelay = ((crop->left * width + c_width) / c_width) & ~1;
+
+       geo->sheight = c_height;
+       geo->vdelay = crop->top - tvnorm->cropcap.bounds.top + MIN_VDELAY;
+       sr = c_height >> !both_fields;
+       sr = (sr * 512U + (height >> 1)) / height - 512;
+       geo->vscale = (0x10000UL - sr) & 0x1fff;
+       geo->vscale |= both_fields ? (BT848_VSCALE_INT << 8) : 0;
+       geo->vtotal = tvnorm->vtotal;
+
+       geo->crop = (((geo->width   >> 8) & 0x03) |
+                    ((geo->hdelay  >> 6) & 0x0c) |
+                    ((geo->sheight >> 4) & 0x30) |
+                    ((geo->vdelay  >> 2) & 0xc0));
+
+       if (btv->opt_combfilter) {
+               geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
+               geo->comb = (width < 769) ? 1 : 0;
+       } else {
+               geo->vtc  = 0;
+               geo->comb = 0;
+       }
+}
+
 static void
 bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
 {
@@ -522,16 +587,51 @@ int
 bttv_buffer_activate_vbi(struct bttv *btv,
                         struct bttv_buffer *vbi)
 {
-       /* vbi capture */
+       struct btcx_riscmem *top;
+       struct btcx_riscmem *bottom;
+       int top_irq_flags;
+       int bottom_irq_flags;
+
+       top = NULL;
+       bottom = NULL;
+       top_irq_flags = 0;
+       bottom_irq_flags = 0;
+
        if (vbi) {
+               unsigned int crop, vdelay;
+
                vbi->vb.state = STATE_ACTIVE;
                list_del(&vbi->vb.queue);
-               bttv_risc_hook(btv, RISC_SLOT_O_VBI, &vbi->top,    0);
-               bttv_risc_hook(btv, RISC_SLOT_E_VBI, &vbi->bottom, 4);
-       } else {
-               bttv_risc_hook(btv, RISC_SLOT_O_VBI, NULL, 0);
-               bttv_risc_hook(btv, RISC_SLOT_E_VBI, NULL, 0);
+
+               /* VDELAY is start of video, end of VBI capturing. */
+               crop = btread(BT848_E_CROP);
+               vdelay = btread(BT848_E_VDELAY_LO) + ((crop & 0xc0) << 2);
+
+               if (vbi->geo.vdelay > vdelay) {
+                       vdelay = vbi->geo.vdelay & 0xfe;
+                       crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);
+
+                       btwrite(vdelay, BT848_E_VDELAY_LO);
+                       btwrite(crop,   BT848_E_CROP);
+                       btwrite(vdelay, BT848_O_VDELAY_LO);
+                       btwrite(crop,   BT848_O_CROP);
+               }
+
+               if (vbi->vbi_count[0] > 0) {
+                       top = &vbi->top;
+                       top_irq_flags = 4;
+               }
+
+               if (vbi->vbi_count[1] > 0) {
+                       top_irq_flags = 0;
+                       bottom = &vbi->bottom;
+                       bottom_irq_flags = 4;
+               }
        }
+
+       bttv_risc_hook(btv, RISC_SLOT_O_VBI, top, top_irq_flags);
+       bttv_risc_hook(btv, RISC_SLOT_E_VBI, bottom, bottom_irq_flags);
+
        return 0;
 }
 
@@ -611,28 +711,31 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
                int bpf = bpl * (buf->vb.height >> 1);
 
                bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height,
-                             V4L2_FIELD_HAS_BOTH(buf->vb.field),buf->tvnorm);
+                             V4L2_FIELD_HAS_BOTH(buf->vb.field),
+                             tvnorm,&buf->crop);
 
                switch (buf->vb.field) {
                case V4L2_FIELD_TOP:
                        bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist,
-                                        0,bpl,0,buf->vb.height);
+                                        /* offset */ 0,bpl,
+                                        /* padding */ 0,/* skip_lines */ 0,
+                                        buf->vb.height);
                        break;
                case V4L2_FIELD_BOTTOM:
                        bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist,
-                                        0,bpl,0,buf->vb.height);
+                                        0,bpl,0,0,buf->vb.height);
                        break;
                case V4L2_FIELD_INTERLACED:
                        bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist,
-                                        0,bpl,bpl,buf->vb.height >> 1);
+                                        0,bpl,bpl,0,buf->vb.height >> 1);
                        bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist,
-                                        bpl,bpl,bpl,buf->vb.height >> 1);
+                                        bpl,bpl,bpl,0,buf->vb.height >> 1);
                        break;
                case V4L2_FIELD_SEQ_TB:
                        bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist,
-                                        0,bpl,0,buf->vb.height >> 1);
+                                        0,bpl,0,0,buf->vb.height >> 1);
                        bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist,
-                                        bpf,bpl,0,buf->vb.height >> 1);
+                                        bpf,bpl,0,0,buf->vb.height >> 1);
                        break;
                default:
                        BUG();
@@ -662,7 +765,8 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
                switch (buf->vb.field) {
                case V4L2_FIELD_TOP:
                        bttv_calc_geo(btv,&buf->geo,buf->vb.width,
-                                     buf->vb.height,0,buf->tvnorm);
+                                     buf->vb.height,/* both_fields */ 0,
+                                     tvnorm,&buf->crop);
                        bttv_risc_planar(btv, &buf->top, buf->vb.dma.sglist,
                                         0,buf->vb.width,0,buf->vb.height,
                                         uoffset,voffset,buf->fmt->hshift,
@@ -670,7 +774,8 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
                        break;
                case V4L2_FIELD_BOTTOM:
                        bttv_calc_geo(btv,&buf->geo,buf->vb.width,
-                                     buf->vb.height,0,buf->tvnorm);
+                                     buf->vb.height,0,
+                                     tvnorm,&buf->crop);
                        bttv_risc_planar(btv, &buf->bottom, buf->vb.dma.sglist,
                                         0,buf->vb.width,0,buf->vb.height,
                                         uoffset,voffset,buf->fmt->hshift,
@@ -678,7 +783,8 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
                        break;
                case V4L2_FIELD_INTERLACED:
                        bttv_calc_geo(btv,&buf->geo,buf->vb.width,
-                                     buf->vb.height,1,buf->tvnorm);
+                                     buf->vb.height,1,
+                                     tvnorm,&buf->crop);
                        lines    = buf->vb.height >> 1;
                        ypadding = buf->vb.width;
                        cpadding = buf->vb.width >> buf->fmt->hshift;
@@ -700,7 +806,8 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
                        break;
                case V4L2_FIELD_SEQ_TB:
                        bttv_calc_geo(btv,&buf->geo,buf->vb.width,
-                                     buf->vb.height,1,buf->tvnorm);
+                                     buf->vb.height,1,
+                                     tvnorm,&buf->crop);
                        lines    = buf->vb.height >> 1;
                        ypadding = buf->vb.width;
                        cpadding = buf->vb.width >> buf->fmt->hshift;
@@ -731,11 +838,12 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
                /* build risc code */
                buf->vb.field = V4L2_FIELD_SEQ_TB;
                bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight,
-                             1,buf->tvnorm);
+                             1,tvnorm,&buf->crop);
                bttv_risc_packed(btv, &buf->top,  buf->vb.dma.sglist,
-                                0, RAW_BPL, 0, RAW_LINES);
+                                /* offset */ 0, RAW_BPL, /* padding */ 0,
+                                /* skip_lines */ 0, RAW_LINES);
                bttv_risc_packed(btv, &buf->bottom, buf->vb.dma.sglist,
-                                buf->vb.size/2 , RAW_BPL, 0, RAW_LINES);
+                                buf->vb.size/2 , RAW_BPL, 0, 0, RAW_LINES);
        }
 
        /* copy format info */
@@ -761,7 +869,8 @@ bttv_overlay_risc(struct bttv *btv,
 
        /* calculate geometry */
        bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height,
-                     V4L2_FIELD_HAS_BOTH(ov->field), ov->tvnorm);
+                     V4L2_FIELD_HAS_BOTH(ov->field),
+                     &bttv_tvnorms[ov->tvnorm],&buf->crop);
 
        /* build risc code */
        switch (ov->field) {
index 6fc6b026005617815ad4d22533531798d2da2e4b..93e35de5a1811de578b03b5344ba173ab0d39263 100644 (file)
@@ -5,6 +5,9 @@
 
     (c) 2002 Gerd Knorr <kraxel@bytesex.org>
 
+    Copyright (C) 2005, 2006 Michael H. Schimek <mschimek@gmx.at>
+    Sponsored by OPQ Systems AB
+
     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
    to be about 244.  */
 #define VBI_OFFSET 244
 
+/* 2048 for compatibility with earlier driver versions. The driver
+   really stores 1024 + tvnorm->vbipack * 4 samples per line in the
+   buffer. Note tvnorm->vbipack is <= 0xFF (limit of VBIPACK_LO + HI
+   is 0x1FF DWORDs) and VBI read()s store a frame counter in the last
+   four bytes of the VBI image. */
+#define VBI_BPL 2048
+
+/* Compatibility. */
 #define VBI_DEFLINES 16
-#define VBI_MAXLINES 32
 
 static unsigned int vbibufs = 4;
 static unsigned int vbi_debug = 0;
@@ -58,21 +68,12 @@ MODULE_PARM_DESC(vbi_debug,"vbi code debug messages, default is 0 (no)");
 #define dprintk(fmt, arg...)   if (vbi_debug) \
        printk(KERN_DEBUG "bttv%d/vbi: " fmt, btv->c.nr , ## arg)
 
+#define IMAGE_SIZE(fmt) \
+       (((fmt)->count[0] + (fmt)->count[1]) * (fmt)->samples_per_line)
+
 /* ----------------------------------------------------------------------- */
 /* vbi risc code + mm                                                      */
 
-static int
-vbi_buffer_risc(struct bttv *btv, struct bttv_buffer *buf, int lines)
-{
-       int bpl = 2048;
-
-       bttv_risc_packed(btv, &buf->top, buf->vb.dma.sglist,
-                        0, bpl-4, 4, lines);
-       bttv_risc_packed(btv, &buf->bottom, buf->vb.dma.sglist,
-                        lines * bpl, bpl-4, 4, lines);
-       return 0;
-}
-
 static int vbi_buffer_setup(struct videobuf_queue *q,
                            unsigned int *count, unsigned int *size)
 {
@@ -81,8 +82,16 @@ static int vbi_buffer_setup(struct videobuf_queue *q,
 
        if (0 == *count)
                *count = vbibufs;
-       *size = fh->lines * 2 * 2048;
-       dprintk("setup: lines=%d\n",fh->lines);
+
+       *size = IMAGE_SIZE(&fh->vbi_fmt.fmt);
+
+       dprintk("setup: samples=%u start=%d,%d count=%u,%u\n",
+               fh->vbi_fmt.fmt.samples_per_line,
+               fh->vbi_fmt.fmt.start[0],
+               fh->vbi_fmt.fmt.start[1],
+               fh->vbi_fmt.fmt.count[0],
+               fh->vbi_fmt.fmt.count[1]);
+
        return 0;
 }
 
@@ -93,18 +102,93 @@ static int vbi_buffer_prepare(struct videobuf_queue *q,
        struct bttv_fh *fh = q->priv_data;
        struct bttv *btv = fh->btv;
        struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
+       const struct bttv_tvnorm *tvnorm;
+       unsigned int skip_lines0, skip_lines1, min_vdelay;
+       int redo_dma_risc;
        int rc;
 
-       buf->vb.size = fh->lines * 2 * 2048;
+       buf->vb.size = IMAGE_SIZE(&fh->vbi_fmt.fmt);
        if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
                return -EINVAL;
 
+       tvnorm = fh->vbi_fmt.tvnorm;
+
+       /* There's no VBI_VDELAY register, RISC must skip the lines
+          we don't want. With default parameters we skip zero lines
+          as earlier driver versions did. The driver permits video
+          standard changes while capturing, so we use vbi_fmt.tvnorm
+          instead of btv->tvnorm to skip zero lines after video
+          standard changes as well. */
+
+       skip_lines0 = 0;
+       skip_lines1 = 0;
+
+       if (fh->vbi_fmt.fmt.count[0] > 0)
+               skip_lines0 = max(0, (fh->vbi_fmt.fmt.start[0]
+                                     - tvnorm->vbistart[0]));
+       if (fh->vbi_fmt.fmt.count[1] > 0)
+               skip_lines1 = max(0, (fh->vbi_fmt.fmt.start[1]
+                                     - tvnorm->vbistart[1]));
+
+       redo_dma_risc = 0;
+
+       if (buf->vbi_skip[0] != skip_lines0 ||
+           buf->vbi_skip[1] != skip_lines1 ||
+           buf->vbi_count[0] != fh->vbi_fmt.fmt.count[0] ||
+           buf->vbi_count[1] != fh->vbi_fmt.fmt.count[1]) {
+               buf->vbi_skip[0] = skip_lines0;
+               buf->vbi_skip[1] = skip_lines1;
+               buf->vbi_count[0] = fh->vbi_fmt.fmt.count[0];
+               buf->vbi_count[1] = fh->vbi_fmt.fmt.count[1];
+               redo_dma_risc = 1;
+       }
+
        if (STATE_NEEDS_INIT == buf->vb.state) {
+               redo_dma_risc = 1;
                if (0 != (rc = videobuf_iolock(q, &buf->vb, NULL)))
                        goto fail;
-               if (0 != (rc = vbi_buffer_risc(btv,buf,fh->lines)))
-                       goto fail;
        }
+
+       if (redo_dma_risc) {
+               unsigned int bpl, padding, offset;
+
+               bpl = 2044; /* max. vbipack */
+               padding = VBI_BPL - bpl;
+
+               if (fh->vbi_fmt.fmt.count[0] > 0) {
+                       rc = bttv_risc_packed(btv, &buf->top,
+                                             buf->vb.dma.sglist,
+                                             /* offset */ 0, bpl,
+                                             padding, skip_lines0,
+                                             fh->vbi_fmt.fmt.count[0]);
+                       if (0 != rc)
+                               goto fail;
+               }
+
+               if (fh->vbi_fmt.fmt.count[1] > 0) {
+                       offset = fh->vbi_fmt.fmt.count[0] * VBI_BPL;
+
+                       rc = bttv_risc_packed(btv, &buf->bottom,
+                                             buf->vb.dma.sglist,
+                                             offset, bpl,
+                                             padding, skip_lines1,
+                                             fh->vbi_fmt.fmt.count[1]);
+                       if (0 != rc)
+                               goto fail;
+               }
+       }
+
+       /* VBI capturing ends at VDELAY, start of video capturing,
+          no matter where the RISC program ends. VDELAY minimum is 2,
+          bounds.top is the corresponding first field line number
+          times two. VDELAY counts half field lines. */
+       min_vdelay = MIN_VDELAY;
+       if (fh->vbi_fmt.end >= tvnorm->cropcap.bounds.top)
+               min_vdelay += fh->vbi_fmt.end - tvnorm->cropcap.bounds.top;
+
+       /* For bttv_buffer_activate_vbi(). */
+       buf->geo.vdelay = min_vdelay;
+
        buf->vb.state = STATE_PREPARED;
        buf->vb.field = field;
        dprintk("buf prepare %p: top=%p bottom=%p field=%s\n",
@@ -140,7 +224,7 @@ static void vbi_buffer_release(struct videobuf_queue *q, struct videobuf_buffer
        struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
 
        dprintk("free %p\n",vb);
-       bttv_dma_free(&fh->cap,fh->btv,buf);
+       bttv_dma_free(q,fh->btv,buf);
 }
 
 struct videobuf_queue_ops bttv_vbi_qops = {
@@ -152,69 +236,215 @@ struct videobuf_queue_ops bttv_vbi_qops = {
 
 /* ----------------------------------------------------------------------- */
 
-void bttv_vbi_setlines(struct bttv_fh *fh, struct bttv *btv, int lines)
+static int
+try_fmt                        (struct v4l2_vbi_format *       f,
+                        const struct bttv_tvnorm *     tvnorm,
+                        __s32                          crop_start)
 {
-       int vdelay;
-
-       if (lines < 1)
-               lines = 1;
-       if (lines > VBI_MAXLINES)
-               lines = VBI_MAXLINES;
-       fh->lines = lines;
-
-       vdelay = btread(BT848_E_VDELAY_LO);
-       if (vdelay < lines*2) {
-               vdelay = lines*2;
-               btwrite(vdelay,BT848_E_VDELAY_LO);
-               btwrite(vdelay,BT848_O_VDELAY_LO);
+       __s32 min_start, max_start, max_end, f2_offset;
+       unsigned int i;
+
+       /* For compatibility with earlier driver versions we must pretend
+          the VBI and video capture window may overlap. In reality RISC
+          magic aborts VBI capturing at the first line of video capturing,
+          leaving the rest of the buffer unchanged, usually all zero.
+          VBI capturing must always start before video capturing. >> 1
+          because cropping counts field lines times two. */
+       min_start = tvnorm->vbistart[0];
+       max_start = (crop_start >> 1) - 1;
+       max_end = (tvnorm->cropcap.bounds.top
+                  + tvnorm->cropcap.bounds.height) >> 1;
+
+       if (min_start > max_start)
+               return -EBUSY;
+
+       BUG_ON(max_start >= max_end);
+
+       f->sampling_rate    = tvnorm->Fsc;
+       f->samples_per_line = VBI_BPL;
+       f->sample_format    = V4L2_PIX_FMT_GREY;
+       f->offset           = VBI_OFFSET;
+
+       f2_offset = tvnorm->vbistart[1] - tvnorm->vbistart[0];
+
+       for (i = 0; i < 2; ++i) {
+               if (0 == f->count[i]) {
+                       /* No data from this field. We leave f->start[i]
+                          alone because VIDIOCSVBIFMT is w/o and EINVALs
+                          when a driver does not support exactly the
+                          requested parameters. */
+               } else {
+                       s64 start, count;
+
+                       start = clamp(f->start[i], min_start, max_start);
+                       /* s64 to prevent overflow. */
+                       count = (s64) f->start[i] + f->count[i] - start;
+                       f->start[i] = start;
+                       f->count[i] = clamp(count, (s64) 1,
+                                           max_end - start);
+               }
+
+               min_start += f2_offset;
+               max_start += f2_offset;
+               max_end += f2_offset;
        }
+
+       if (0 == (f->count[0] | f->count[1])) {
+               /* As in earlier driver versions. */
+               f->start[0] = tvnorm->vbistart[0];
+               f->start[1] = tvnorm->vbistart[1];
+               f->count[0] = 1;
+               f->count[1] = 1;
+       }
+
+       f->flags = 0;
+
+       f->reserved[0] = 0;
+       f->reserved[1] = 0;
+
+       return 0;
 }
 
-void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f)
+int
+bttv_vbi_try_fmt       (struct bttv_fh *               fh,
+                        struct v4l2_vbi_format *       f)
 {
+       struct bttv *btv = fh->btv;
        const struct bttv_tvnorm *tvnorm;
-       s64 count0,count1,count;
+       __s32 crop_start;
 
-       tvnorm = &bttv_tvnorms[fh->btv->tvnorm];
-       f->type = V4L2_BUF_TYPE_VBI_CAPTURE;
-       f->fmt.vbi.sampling_rate    = tvnorm->Fsc;
-       f->fmt.vbi.samples_per_line = 2048;
-       f->fmt.vbi.sample_format    = V4L2_PIX_FMT_GREY;
-       f->fmt.vbi.offset           = VBI_OFFSET;
-       f->fmt.vbi.flags            = 0;
-
-       /* s64 to prevent overflow. */
-       count0 = (s64) f->fmt.vbi.start[0] + f->fmt.vbi.count[0]
-               - tvnorm->vbistart[0];
-       count1 = (s64) f->fmt.vbi.start[1] + f->fmt.vbi.count[1]
-               - tvnorm->vbistart[1];
-       count  = clamp (max (count0, count1), (s64) 1, (s64) VBI_MAXLINES);
-
-       f->fmt.vbi.start[0] = tvnorm->vbistart[0];
-       f->fmt.vbi.start[1] = tvnorm->vbistart[1];
-       f->fmt.vbi.count[0] = count;
-       f->fmt.vbi.count[1] = count;
-
-       f->fmt.vbi.reserved[0] = 0;
-       f->fmt.vbi.reserved[1] = 0;
+       mutex_lock(&btv->lock);
+
+       tvnorm = &bttv_tvnorms[btv->tvnorm];
+       crop_start = btv->crop_start;
+
+       mutex_unlock(&btv->lock);
+
+       return try_fmt(f, tvnorm, crop_start);
 }
 
-void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f)
+int
+bttv_vbi_set_fmt       (struct bttv_fh *               fh,
+                        struct v4l2_vbi_format *       f)
 {
+       struct bttv *btv = fh->btv;
        const struct bttv_tvnorm *tvnorm;
+       __s32 start1, end;
+       int rc;
+
+       mutex_lock(&btv->lock);
+
+       rc = -EBUSY;
+       if (fh->resources & RESOURCE_VBI)
+               goto fail;
+
+       tvnorm = &bttv_tvnorms[btv->tvnorm];
+
+       rc = try_fmt(f, tvnorm, btv->crop_start);
+       if (0 != rc)
+               goto fail;
+
+       start1 = f->start[1] - tvnorm->vbistart[1] + tvnorm->vbistart[0];
+
+       /* First possible line of video capturing. Should be
+          max(f->start[0] + f->count[0], start1 + f->count[1]) * 2
+          when capturing both fields. But for compatibility we must
+          pretend the VBI and video capture window may overlap,
+          so end = start + 1, the lowest possible value, times two
+          because vbi_fmt.end counts field lines times two. */
+       end = max(f->start[0], start1) * 2 + 2;
+
+       mutex_lock(&fh->vbi.lock);
+
+       fh->vbi_fmt.fmt    = *f;
+       fh->vbi_fmt.tvnorm = tvnorm;
+       fh->vbi_fmt.end    = end;
+
+       mutex_unlock(&fh->vbi.lock);
+
+       rc = 0;
+
+ fail:
+       mutex_unlock(&btv->lock);
+
+       return rc;
+}
+
+void
+bttv_vbi_get_fmt       (struct bttv_fh *               fh,
+                        struct v4l2_vbi_format *       f)
+{
+       const struct bttv_tvnorm *tvnorm;
+
+       *f = fh->vbi_fmt.fmt;
 
        tvnorm = &bttv_tvnorms[fh->btv->tvnorm];
-       memset(f,0,sizeof(*f));
-       f->type = V4L2_BUF_TYPE_VBI_CAPTURE;
-       f->fmt.vbi.sampling_rate    = tvnorm->Fsc;
-       f->fmt.vbi.samples_per_line = 2048;
-       f->fmt.vbi.sample_format    = V4L2_PIX_FMT_GREY;
-       f->fmt.vbi.offset           = VBI_OFFSET;
-       f->fmt.vbi.start[0]         = tvnorm->vbistart[0];
-       f->fmt.vbi.start[1]         = tvnorm->vbistart[1];
-       f->fmt.vbi.count[0]         = fh->lines;
-       f->fmt.vbi.count[1]         = fh->lines;
-       f->fmt.vbi.flags            = 0;
+
+       if (tvnorm != fh->vbi_fmt.tvnorm) {
+               __s32 max_end;
+               unsigned int i;
+
+               /* As in vbi_buffer_prepare() this imitates the
+                  behaviour of earlier driver versions after video
+                  standard changes, with default parameters anyway. */
+
+               max_end = (tvnorm->cropcap.bounds.top
+                          + tvnorm->cropcap.bounds.height) >> 1;
+
+               f->sampling_rate = tvnorm->Fsc;
+
+               for (i = 0; i < 2; ++i) {
+                       __s32 new_start;
+
+                       new_start = f->start[i]
+                               + tvnorm->vbistart[i]
+                               - fh->vbi_fmt.tvnorm->vbistart[i];
+
+                       f->start[i] = min(new_start, max_end - 1);
+                       f->count[i] = min((__s32) f->count[i],
+                                         max_end - f->start[i]);
+
+                       max_end += tvnorm->vbistart[1]
+                               - tvnorm->vbistart[0];
+               }
+       }
+}
+
+void
+bttv_vbi_fmt_reset     (struct bttv_vbi_fmt *          f,
+                        int                            norm)
+{
+       const struct bttv_tvnorm *tvnorm;
+       unsigned int real_samples_per_line;
+       unsigned int real_count;
+
+       tvnorm = &bttv_tvnorms[norm];
+
+       f->fmt.sampling_rate    = tvnorm->Fsc;
+       f->fmt.samples_per_line = VBI_BPL;
+       f->fmt.sample_format    = V4L2_PIX_FMT_GREY;
+       f->fmt.offset           = VBI_OFFSET;
+       f->fmt.start[0]         = tvnorm->vbistart[0];
+       f->fmt.start[1]         = tvnorm->vbistart[1];
+       f->fmt.count[0]         = VBI_DEFLINES;
+       f->fmt.count[1]         = VBI_DEFLINES;
+       f->fmt.flags            = 0;
+       f->fmt.reserved[0]      = 0;
+       f->fmt.reserved[1]      = 0;
+
+       /* For compatibility the buffer size must be 2 * VBI_DEFLINES *
+          VBI_BPL regardless of the current video standard. */
+       real_samples_per_line   = 1024 + tvnorm->vbipack * 4;
+       real_count              = ((tvnorm->cropcap.defrect.top >> 1)
+                                  - tvnorm->vbistart[0]);
+
+       BUG_ON(real_samples_per_line > VBI_BPL);
+       BUG_ON(real_count > VBI_DEFLINES);
+
+       f->tvnorm               = tvnorm;
+
+       /* See bttv_vbi_fmt_set(). */
+       f->end                  = tvnorm->vbistart[0] * 2 + 2;
 }
 
 /* ----------------------------------------------------------------------- */
index f9c9e3c4d111944cf2c42d93c45513b5a28304da..5491acbdaf6387426e6292c3974d664a5bed10e3 100644 (file)
@@ -197,33 +197,6 @@ struct bttv_core {
 struct bttv;
 
 
-struct bttv_ir {
-       struct input_dev        *dev;
-       struct ir_input_state   ir;
-       char                    name[32];
-       char                    phys[32];
-
-       /* Usual gpio signalling */
-
-       u32                     mask_keycode;
-       u32                     mask_keydown;
-       u32                     mask_keyup;
-       u32                     polling;
-       u32                     last_gpio;
-       struct work_struct      work;
-       struct timer_list       timer;
-
-       /* RC5 gpio */
-       u32 rc5_gpio;
-       struct timer_list timer_end;    /* timer_end for code completion */
-       struct timer_list timer_keyup;  /* timer_end for key release */
-       u32 last_rc5;                   /* last good rc5 code */
-       u32 last_bit;                   /* last raw bit seen */
-       u32 code;                       /* raw code under construction */
-       struct timeval base_time;       /* time of last seen code */
-       int active;                     /* building raw code */
-};
-
 struct tvcard
 {
        char *name;
index 311c4c541e01d554f3b396248bdf18419ce99afa..ad79b8d534308febeaaee6770825061c28ab692e 100644 (file)
@@ -26,7 +26,7 @@
 #define _BTTVP_H_
 
 #include <linux/version.h>
-#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,16)
+#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,17)
 
 #include <linux/types.h>
 #include <linux/wait.h>
 #define RISC_SLOT_LOOP        14
 
 #define RESOURCE_OVERLAY       1
-#define RESOURCE_VIDEO         2
+#define RESOURCE_VIDEO_STREAM  2
 #define RESOURCE_VBI           4
+#define RESOURCE_VIDEO_READ    8
 
 #define RAW_LINES            640
 #define RAW_BPL             1024
 
 #define UNSET (-1U)
 
+/* Min. value in VDELAY register. */
+#define MIN_VDELAY 2
+/* Even to get Cb first, odd for Cr. */
+#define MAX_HDELAY (0x3FF & -2)
+/* Limits scaled width, which must be a multiple of 4. */
+#define MAX_HACTIVE (0x3FF & -4)
+
 #define clamp(x, low, high) min (max (low, x), high)
 
 /* ---------------------------------------------------------- */
@@ -92,8 +100,13 @@ struct bttv_tvnorm {
        u16   vtotal;
        int   sram;
        /* ITU-R frame line number of the first VBI line we can
-          capture, of the first and second field. */
+          capture, of the first and second field. The last possible line
+          is determined by cropcap.bounds. */
        u16   vbistart[2];
+       /* Horizontally this counts fCLKx1 samples following the leading
+          edge of the horizontal sync pulse, vertically ITU-R frame line
+          numbers of the first field times two (2, 4, 6, ... 524 or 624). */
+       struct v4l2_cropcap cropcap;
 };
 extern const struct bttv_tvnorm bttv_tvnorms[];
 
@@ -128,6 +141,9 @@ struct bttv_buffer {
        struct bttv_geometry       geo;
        struct btcx_riscmem        top;
        struct btcx_riscmem        bottom;
+       struct v4l2_rect           crop;
+       unsigned int               vbi_skip[2];
+       unsigned int               vbi_count[2];
 };
 
 struct bttv_buffer_set {
@@ -146,6 +162,34 @@ struct bttv_overlay {
        int                    setup_ok;
 };
 
+struct bttv_vbi_fmt {
+       struct v4l2_vbi_format fmt;
+
+       /* fmt.start[] and count[] refer to this video standard. */
+       const struct bttv_tvnorm *tvnorm;
+
+       /* Earliest possible start of video capturing with this
+          v4l2_vbi_format, in struct bttv_crop.rect units. */
+       __s32                  end;
+};
+
+/* bttv-vbi.c */
+void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, int norm);
+
+struct bttv_crop {
+       /* A cropping rectangle in struct bttv_tvnorm.cropcap units. */
+       struct v4l2_rect       rect;
+
+       /* Scaled image size limits with this crop rect. Divide
+          max_height, but not min_height, by two when capturing
+          single fields. See also bttv_crop_reset() and
+          bttv_crop_adjust() in bttv-driver.c. */
+       __s32                  min_scaled_width;
+       __s32                  min_scaled_height;
+       __s32                  max_scaled_width;
+       __s32                  max_scaled_height;
+};
+
 struct bttv_fh {
        struct bttv              *btv;
        int resources;
@@ -160,13 +204,19 @@ struct bttv_fh {
        int                      width;
        int                      height;
 
-       /* current settings */
+       /* video overlay */
        const struct bttv_format *ovfmt;
        struct bttv_overlay      ov;
 
-       /* video overlay */
+       /* Application called VIDIOC_S_CROP. */
+       int                      do_crop;
+
+       /* vbi capture */
        struct videobuf_queue    vbi;
-       int                      lines;
+       /* Current VBI capture window as seen through this fh (cannot
+          be global for compatibility with earlier drivers). Protected
+          by struct bttv.lock and struct bttv_fh.vbi.lock. */
+       struct bttv_vbi_fmt      vbi_fmt;
 };
 
 /* ---------------------------------------------------------- */
@@ -176,7 +226,8 @@ struct bttv_fh {
 int bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
                     struct scatterlist *sglist,
                     unsigned int offset, unsigned int bpl,
-                    unsigned int pitch, unsigned int lines);
+                    unsigned int pitch, unsigned int skip_lines,
+                    unsigned int store_lines);
 
 /* control dma register + risc main loop */
 void bttv_set_dma(struct bttv *btv, int override);
@@ -202,9 +253,9 @@ int bttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov,
 /* ---------------------------------------------------------- */
 /* bttv-vbi.c                                                 */
 
-void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f);
-void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f);
-void bttv_vbi_setlines(struct bttv_fh *fh, struct bttv *btv, int lines);
+int bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_vbi_format *f);
+void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_vbi_format *f);
+int bttv_vbi_set_fmt(struct bttv_fh *fh, struct v4l2_vbi_format *f);
 
 extern struct videobuf_queue_ops bttv_vbi_qops;
 
@@ -233,7 +284,6 @@ extern int fini_bttv_i2c(struct bttv *btv);
 #define d2printk if (bttv_debug >= 2) printk
 
 #define BTTV_MAX_FBUF   0x208000
-#define VBIBUF_SIZE     (2048*VBI_MAXLINES*2)
 #define BTTV_TIMEOUT    (HZ/2) /* 0.5 seconds */
 #define BTTV_FREE_IDLE  (HZ)   /* one second */
 
@@ -308,13 +358,12 @@ struct bttv {
 
        /* infrared remote */
        int has_remote;
-       struct bttv_ir *remote;
+       struct card_ir *remote;
 
        /* locking */
        spinlock_t s_lock;
        struct mutex lock;
        int resources;
-       struct mutex reslock;
 #ifdef VIDIOC_G_PRIORITY
        struct v4l2_prio_state prio;
 #endif
@@ -384,6 +433,21 @@ struct bttv {
 
        unsigned int users;
        struct bttv_fh init;
+
+       /* Default (0) and current (1) video capturing and overlay
+          cropping parameters in bttv_tvnorm.cropcap units. Protected
+          by bttv.lock. */
+       struct bttv_crop crop[2];
+
+       /* Earliest possible start of video capturing in
+          bttv_tvnorm.cropcap line units. Set by check_alloc_btres()
+          and free_btres(). Protected by bttv.lock. */
+       __s32                   vbi_end;
+
+       /* Latest possible end of VBI capturing (= crop[x].rect.top when
+          VIDEO_RESOURCES are locked). Set by check_alloc_btres()
+          and free_btres(). Protected by bttv.lock. */
+       __s32                   crop_start;
 };
 
 /* our devices */
index 4dae8925667f77cd2cbfb9919321b3d00d87d265..710c11a682964b88f525a0517b9f3a2032f5ad70 100644 (file)
@@ -1022,7 +1022,7 @@ 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;
+       int ret = 0;
 
        /*
         * Perhaps we're in speculative read mode and already
@@ -1195,7 +1195,7 @@ static int cafe_vidioc_reqbufs(struct file *filp, void *priv,
                struct v4l2_requestbuffers *req)
 {
        struct cafe_camera *cam = filp->private_data;
-       int ret;
+       int ret = 0;  /* Silence warning */
 
        /*
         * Make sure it's something we can do.  User pointers could be
@@ -1251,8 +1251,6 @@ static int cafe_vidioc_reqbufs(struct file *filp, void *priv,
 
        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:
index 7e8d5ef58b61f09ecd3a5e3ec592354a1f31e2af..78c9699eafbbe46e791cc7c228c413b47182394c 100644 (file)
@@ -1350,13 +1350,13 @@ out:
 
 static void create_proc_cpia_cam(struct cam_data *cam)
 {
-       char name[7];
+       char name[5 + 1 + 10 + 1];
        struct proc_dir_entry *ent;
 
        if (!cpia_proc_root || !cam)
                return;
 
-       sprintf(name, "video%d", cam->vdev.minor);
+       snprintf(name, sizeof(name), "video%d", cam->vdev.minor);
 
        ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, cpia_proc_root);
        if (!ent)
@@ -1376,12 +1376,12 @@ static void create_proc_cpia_cam(struct cam_data *cam)
 
 static void destroy_proc_cpia_cam(struct cam_data *cam)
 {
-       char name[7];
+       char name[5 + 1 + 10 + 1];
 
        if (!cam || !cam->proc_entry)
                return;
 
-       sprintf(name, "video%d", cam->vdev.minor);
+       snprintf(name, sizeof(name), "video%d", cam->vdev.minor);
        remove_proc_entry(name, cpia_proc_root);
        cam->proc_entry = NULL;
 }
@@ -3153,8 +3153,7 @@ static int reset_camera(struct cam_data *cam)
 
 static void put_cam(struct cpia_camera_ops* ops)
 {
-       if (ops->owner)
-               module_put(ops->owner);
+       module_put(ops->owner);
 }
 
 /* ------------------------- V4L interface --------------------- */
index 2f5ca71e0261c8c60aeac4a237f7fdbf717b2b0f..d60cd5ecf821ceefa530459bc220e069abd9f149 100644 (file)
@@ -56,7 +56,6 @@ const u32 cx2341x_mpeg_ctrls[] = {
        V4L2_CID_MPEG_VIDEO_B_FRAMES,
        V4L2_CID_MPEG_VIDEO_GOP_SIZE,
        V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
-       V4L2_CID_MPEG_VIDEO_PULLDOWN,
        V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
        V4L2_CID_MPEG_VIDEO_BITRATE,
        V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
@@ -118,9 +117,6 @@ static int cx2341x_get_ctrl(struct cx2341x_mpeg_params *params,
        case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
                ctrl->value = params->video_gop_closure;
                break;
-       case V4L2_CID_MPEG_VIDEO_PULLDOWN:
-               ctrl->value = params->video_pulldown;
-               break;
        case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
                ctrl->value = params->video_bitrate_mode;
                break;
@@ -231,9 +227,6 @@ static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params,
        case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
                params->video_gop_closure = ctrl->value;
                break;
-       case V4L2_CID_MPEG_VIDEO_PULLDOWN:
-               params->video_pulldown = ctrl->value;
-               break;
        case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
                /* MPEG-1 only allows CBR */
                if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&
@@ -679,7 +672,6 @@ void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
        .video_b_frames = 2,
        .video_gop_size = 12,
        .video_gop_closure = 1,
-       .video_pulldown = 0,
        .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
        .video_bitrate = 6000000,
        .video_bitrate_peak = 8000000,
@@ -783,10 +775,6 @@ int cx2341x_update(void *priv, cx2341x_mbox_func func,
                err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1, new->video_gop_closure);
                if (err) return err;
        }
-       if (old == NULL || old->video_pulldown != new->video_pulldown) {
-               err = cx2341x_api(priv, func, CX2341X_ENC_SET_3_2_PULLDOWN, 1, new->video_pulldown);
-               if (err) return err;
-       }
        if (old == NULL || old->audio_properties != new->audio_properties) {
                err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, new->audio_properties);
                if (err) return err;
@@ -888,11 +876,10 @@ void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix)
                printk(", Peak %d", p->video_bitrate_peak);
        }
        printk("\n");
-       printk(KERN_INFO "%s: Video:  GOP Size %d, %d B-Frames, %sGOP Closure, %s3:2 Pulldown\n",
+       printk(KERN_INFO "%s: Video:  GOP Size %d, %d B-Frames, %sGOP Closure\n",
                prefix,
                p->video_gop_size, p->video_b_frames,
-               p->video_gop_closure ? "" : "No ",
-               p->video_pulldown ? "" : "No ");
+               p->video_gop_closure ? "" : "No ");
        if (p->video_temporal_decimation) {
                printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
                        prefix, p->video_temporal_decimation);
index 7bb7589a07c30719f7796e78081d01cc0e878ee7..774d2536555b8d6dbe7001c1c6f8b7b6928e4020 100644 (file)
@@ -628,25 +628,19 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        /* ioctls to allow direct access to the
         * cx25840 registers for testing */
-       case VIDIOC_INT_G_REGISTER:
+       case VIDIOC_DBG_G_REGISTER:
+       case VIDIOC_DBG_S_REGISTER:
        {
                struct v4l2_register *reg = arg;
 
-               if (reg->i2c_id != I2C_DRIVERID_CX25840)
-                       return -EINVAL;
-               reg->val = cx25840_read(client, reg->reg & 0x0fff);
-               break;
-       }
-
-       case VIDIOC_INT_S_REGISTER:
-       {
-               struct v4l2_register *reg = arg;
-
-               if (reg->i2c_id != I2C_DRIVERID_CX25840)
+               if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip))
                        return -EINVAL;
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
-               cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff);
+               if (cmd == VIDIOC_DBG_G_REGISTER)
+                       reg->val = cx25840_read(client, reg->reg & 0x0fff);
+               else
+                       cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff);
                break;
        }
 #endif
@@ -893,9 +887,11 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
                return 0;
        }
 
+       /* Note: revision '(device_id & 0x0f) == 2' was never built. The
+          marking skips from 0x1 == 22 to 0x3 == 23. */
        v4l_info(client, "cx25%3x-2%x found @ 0x%x (%s)\n",
                    (device_id & 0xfff0) >> 4,
-                   (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : 3,
+                   (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : (device_id & 0x0f),
                    address << 1, adapter->name);
 
        i2c_set_clientdata(client, state);
@@ -907,13 +903,13 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
        state->vbi_line_offset = 8;
        state->id = id;
 
+       i2c_attach_client(client);
+
        if (state->is_cx25836)
                cx25836_initialize(client);
        else
                cx25840_initialize(client, 1);
 
-       i2c_attach_client(client);
-
        return 0;
 }
 
index 1958d4016ea15c4bb5b9e7faa59377fe80d9a4f6..0e86b9d033ac8b6cb2bb302152d4e6ac3f0203ea 100644 (file)
@@ -37,7 +37,7 @@
  */
 #define FWSEND 48
 
-#define FWDEV(x) &((x)->adapter->dev)
+#define FWDEV(x) &((x)->dev)
 
 static char *firmware = FWFILE;
 
index 639c3b659d0ecf098c4805d70ced3038fc5bc270..532cee35eb3c4f49962cc4b627792f18798a113a 100644 (file)
@@ -12,8 +12,3 @@ obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
 EXTRA_CFLAGS += -Idrivers/media/video
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
-
-extra-cflags-$(CONFIG_VIDEO_BUF_DVB) += -DHAVE_VIDEO_BUF_DVB=1
-extra-cflags-$(CONFIG_VIDEO_CX88_VP3054)+= -DHAVE_VP3054_I2C=1
-
-EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
index 9a7a2996f20fb75af0a438e331fc567342481b12..b0466b88f52cd209680ee1a52c3aa9eacf3319f6 100644 (file)
@@ -6,6 +6,9 @@
  *    (c) 2004 Jelle Foks <jelle@foks.8m.com>
  *    (c) 2004 Gerd Knorr <kraxel@bytesex.org>
  *
+ *    (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *        - video_ioctl2 conversion
+ *
  *  Includes parts from the ivtv driver( http://ivtv.sourceforge.net/),
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -53,7 +56,8 @@ MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
 
 /* ------------------------------------------------------------------ */
 
-#define BLACKBIRD_FIRM_IMAGE_SIZE 256*1024
+#define OLD_BLACKBIRD_FIRM_IMAGE_SIZE 262144
+#define     BLACKBIRD_FIRM_IMAGE_SIZE 376836
 
 /* defines below are from ivtv-driver.h */
 
@@ -401,7 +405,7 @@ static int blackbird_find_mailbox(struct cx8802_dev *dev)
        u32 value;
        int i;
 
-       for (i = 0; i < BLACKBIRD_FIRM_IMAGE_SIZE; i++) {
+       for (i = 0; i < dev->fw_size; i++) {
                memory_read(dev->core, i, &value);
                if (value == signature[signaturecnt])
                        signaturecnt++;
@@ -449,12 +453,15 @@ static int blackbird_load_firmware(struct cx8802_dev *dev)
                return -1;
        }
 
-       if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) {
-               dprintk(0, "ERROR: Firmware size mismatch (have %zd, expected %d)\n",
-                       firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE);
+       if ((firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) &&
+           (firmware->size != OLD_BLACKBIRD_FIRM_IMAGE_SIZE)) {
+               dprintk(0, "ERROR: Firmware size mismatch (have %zd, expected %d or %d)\n",
+                       firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE,
+                       OLD_BLACKBIRD_FIRM_IMAGE_SIZE);
                release_firmware(firmware);
                return -1;
        }
+       dev->fw_size = firmware->size;
 
        if (0 != memcmp(firmware->data, magic, 8)) {
                dprintk(0, "ERROR: Firmware magic mismatch, wrong file?\n");
@@ -520,7 +527,7 @@ static void blackbird_codec_settings(struct cx8802_dev *dev)
 
        dev->params.width = dev->width;
        dev->params.height = dev->height;
-       dev->params.is_50hz = (dev->core->tvnorm->id & V4L2_STD_625_50) != 0;
+       dev->params.is_50hz = (dev->core->tvnorm & V4L2_STD_625_50) != 0;
 
        cx2341x_update(dev, blackbird_mbox_func, NULL, &dev->params);
 }
@@ -710,8 +717,13 @@ static int blackbird_queryctrl(struct cx8802_dev *dev, struct v4l2_queryctrl *qc
        return 0;
 }
 
-static int blackbird_querymenu(struct cx8802_dev *dev, struct v4l2_querymenu *qmenu)
+/* ------------------------------------------------------------------ */
+/* IOCTL Handlers                                                     */
+
+static int vidioc_querymenu (struct file *file, void *priv,
+                               struct v4l2_querymenu *qmenu)
 {
+       struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
        struct v4l2_queryctrl qctrl;
 
        qctrl.id = qmenu->id;
@@ -719,221 +731,347 @@ static int blackbird_querymenu(struct cx8802_dev *dev, struct v4l2_querymenu *qm
        return v4l2_ctrl_query_menu(qmenu, &qctrl, cx2341x_ctrl_get_menu(qmenu->id));
 }
 
-/* ------------------------------------------------------------------ */
+static int vidioc_querycap (struct file *file, void  *priv,
+                                       struct v4l2_capability *cap)
+{
+       struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
+       struct cx88_core  *core = dev->core;
 
-static int mpeg_do_ioctl(struct inode *inode, struct file *file,
-                        unsigned int cmd, void *arg)
+       strcpy(cap->driver, "cx88_blackbird");
+       strlcpy(cap->card, cx88_boards[core->board].name,sizeof(cap->card));
+       sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
+       cap->version = CX88_VERSION_CODE;
+       cap->capabilities =
+               V4L2_CAP_VIDEO_CAPTURE |
+               V4L2_CAP_READWRITE     |
+               V4L2_CAP_STREAMING;
+       if (UNSET != core->tuner_type)
+               cap->capabilities |= V4L2_CAP_TUNER;
+       return 0;
+}
+
+static int vidioc_enum_fmt_cap (struct file *file, void  *priv,
+                                       struct v4l2_fmtdesc *f)
 {
-       struct cx8802_fh  *fh  = file->private_data;
-       struct cx8802_dev *dev = fh->dev;
+       if (f->index != 0)
+               return -EINVAL;
+
+       strlcpy(f->description, "MPEG", sizeof(f->description));
+       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       f->pixelformat = V4L2_PIX_FMT_MPEG;
+       return 0;
+}
+
+static int vidioc_g_fmt_cap (struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct cx8802_fh  *fh   = priv;
+       struct cx8802_dev *dev  = fh->dev;
+
+       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+       f->fmt.pix.bytesperline = 0;
+       f->fmt.pix.sizeimage    = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */
+       f->fmt.pix.colorspace   = 0;
+       f->fmt.pix.width        = dev->width;
+       f->fmt.pix.height       = dev->height;
+       f->fmt.pix.field        = fh->mpegq.field;
+       dprintk(0,"VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
+               dev->width, dev->height, fh->mpegq.field );
+       return 0;
+}
+
+static int vidioc_try_fmt_cap (struct file *file, void *priv,
+                       struct v4l2_format *f)
+{
+       struct cx8802_fh  *fh   = priv;
+       struct cx8802_dev *dev  = fh->dev;
+
+       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+       f->fmt.pix.bytesperline = 0;
+       f->fmt.pix.sizeimage    = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
+       f->fmt.pix.colorspace   = 0;
+       dprintk(0,"VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
+               dev->width, dev->height, fh->mpegq.field );
+       return 0;
+}
+
+static int vidioc_s_fmt_cap (struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct cx8802_fh  *fh   = priv;
+       struct cx8802_dev *dev  = fh->dev;
        struct cx88_core  *core = dev->core;
 
-       if (debug > 1)
-               v4l_print_ioctl(core->name,cmd);
-
-       switch (cmd) {
-
-       /* --- capabilities ------------------------------------------ */
-       case VIDIOC_QUERYCAP:
-       {
-               struct v4l2_capability *cap = arg;
-
-               memset(cap,0,sizeof(*cap));
-               strcpy(cap->driver, "cx88_blackbird");
-               strlcpy(cap->card, cx88_boards[core->board].name,sizeof(cap->card));
-               sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
-               cap->version = CX88_VERSION_CODE;
-               cap->capabilities =
-                       V4L2_CAP_VIDEO_CAPTURE |
-                       V4L2_CAP_READWRITE     |
-                       V4L2_CAP_STREAMING     |
-                       0;
-               if (UNSET != core->tuner_type)
-                       cap->capabilities |= V4L2_CAP_TUNER;
+       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+       f->fmt.pix.bytesperline = 0;
+       f->fmt.pix.sizeimage    = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
+       f->fmt.pix.colorspace   = 0;
+       dev->width              = f->fmt.pix.width;
+       dev->height             = f->fmt.pix.height;
+       fh->mpegq.field         = f->fmt.pix.field;
+       cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
+       blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
+                               f->fmt.pix.height, f->fmt.pix.width);
+       dprintk(0,"VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
+               f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field );
+       return 0;
+}
 
-               return 0;
-       }
+static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
+{
+       struct cx8802_fh  *fh   = priv;
+       return (videobuf_reqbufs(&fh->mpegq, p));
+}
 
-       /* --- capture ioctls ---------------------------------------- */
-       case VIDIOC_ENUM_FMT:
-       {
-               struct v4l2_fmtdesc *f = arg;
-               int index;
-
-               index = f->index;
-               if (index != 0)
-                       return -EINVAL;
-
-               memset(f,0,sizeof(*f));
-               f->index = index;
-               strlcpy(f->description, "MPEG", sizeof(f->description));
-               f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               f->pixelformat = V4L2_PIX_FMT_MPEG;
-               return 0;
-       }
-       case VIDIOC_G_FMT:
-       {
-               struct v4l2_format *f = arg;
-
-               memset(f,0,sizeof(*f));
-               f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-               f->fmt.pix.bytesperline = 0;
-               f->fmt.pix.sizeimage    = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */
-               f->fmt.pix.colorspace   = 0;
-               f->fmt.pix.width        = dev->width;
-               f->fmt.pix.height       = dev->height;
-               f->fmt.pix.field        = fh->mpegq.field;
-               dprintk(0,"VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
-                       dev->width, dev->height, fh->mpegq.field );
-               return 0;
-       }
-       case VIDIOC_TRY_FMT:
-       {
-               struct v4l2_format *f = arg;
-
-               f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-               f->fmt.pix.bytesperline = 0;
-               f->fmt.pix.sizeimage    = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
-               f->fmt.pix.colorspace   = 0;
-               dprintk(0,"VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
-                       dev->width, dev->height, fh->mpegq.field );
-               return 0;
-       }
-       case VIDIOC_S_FMT:
-       {
-               struct v4l2_format *f = arg;
-
-               f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-               f->fmt.pix.bytesperline = 0;
-               f->fmt.pix.sizeimage    = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
-               f->fmt.pix.colorspace   = 0;
-               dprintk(0,"VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
-                       f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field );
-               return 0;
-       }
+static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct cx8802_fh  *fh   = priv;
+       return (videobuf_querybuf(&fh->mpegq, p));
+}
 
-       /* --- streaming capture ------------------------------------- */
-       case VIDIOC_REQBUFS:
-               return videobuf_reqbufs(&fh->mpegq, arg);
+static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct cx8802_fh  *fh   = priv;
+       return (videobuf_qbuf(&fh->mpegq, p));
+}
 
-       case VIDIOC_QUERYBUF:
-               return videobuf_querybuf(&fh->mpegq, arg);
+static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct cx8802_fh  *fh   = priv;
+       return (videobuf_dqbuf(&fh->mpegq, p,
+                               file->f_flags & O_NONBLOCK));
+}
 
-       case VIDIOC_QBUF:
-               return videobuf_qbuf(&fh->mpegq, arg);
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct cx8802_fh  *fh   = priv;
+       return videobuf_streamon(&fh->mpegq);
+}
 
-       case VIDIOC_DQBUF:
-               return videobuf_dqbuf(&fh->mpegq, arg,
-                                     file->f_flags & O_NONBLOCK);
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct cx8802_fh  *fh   = priv;
+       return videobuf_streamoff(&fh->mpegq);
+}
 
-       case VIDIOC_STREAMON:
-               return videobuf_streamon(&fh->mpegq);
+static int vidioc_g_mpegcomp (struct file *file, void *fh,
+                             struct v4l2_mpeg_compression *f)
+{
+       printk(KERN_WARNING "VIDIOC_G_MPEGCOMP is obsolete. "
+                               "Replace with VIDIOC_G_EXT_CTRLS!");
+       memcpy(f,&default_mpeg_params,sizeof(*f));
+       return 0;
+}
 
-       case VIDIOC_STREAMOFF:
-               return videobuf_streamoff(&fh->mpegq);
+static int vidioc_s_mpegcomp (struct file *file, void *fh,
+                             struct v4l2_mpeg_compression *f)
+{
+       printk(KERN_WARNING "VIDIOC_S_MPEGCOMP is obsolete. "
+                               "Replace with VIDIOC_S_EXT_CTRLS!");
+       return 0;
+}
 
-       /* --- mpeg compression -------------------------------------- */
-       case VIDIOC_G_MPEGCOMP:
-       {
-               struct v4l2_mpeg_compression *f = arg;
+static int vidioc_g_ext_ctrls (struct file *file, void *priv,
+                              struct v4l2_ext_controls *f)
+{
+       struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
 
-               printk(KERN_WARNING "VIDIOC_G_MPEGCOMP is obsolete. "
-                                   "Replace with VIDIOC_G_EXT_CTRLS!");
-               memcpy(f,&default_mpeg_params,sizeof(*f));
-               return 0;
-       }
-       case VIDIOC_S_MPEGCOMP:
-               printk(KERN_WARNING "VIDIOC_S_MPEGCOMP is obsolete. "
-                                   "Replace with VIDIOC_S_EXT_CTRLS!");
-               return 0;
-       case VIDIOC_G_EXT_CTRLS:
-       {
-               struct v4l2_ext_controls *f = arg;
+       if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+               return -EINVAL;
+       return cx2341x_ext_ctrls(&dev->params, f, VIDIOC_G_EXT_CTRLS);
+}
 
-               if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
-                       return -EINVAL;
-               return cx2341x_ext_ctrls(&dev->params, f, cmd);
-       }
-       case VIDIOC_S_EXT_CTRLS:
-       case VIDIOC_TRY_EXT_CTRLS:
-       {
-               struct v4l2_ext_controls *f = arg;
-               struct cx2341x_mpeg_params p;
-               int err;
-
-               if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
-                       return -EINVAL;
-               p = dev->params;
-               err = cx2341x_ext_ctrls(&p, f, cmd);
-               if (err == 0 && cmd == VIDIOC_S_EXT_CTRLS) {
-                       err = cx2341x_update(dev, blackbird_mbox_func, &dev->params, &p);
-                       dev->params = p;
-               }
-               return err;
-       }
-       case VIDIOC_S_FREQUENCY:
-       {
-               blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
-                                 BLACKBIRD_END_NOW,
-                                 BLACKBIRD_MPEG_CAPTURE,
-                                 BLACKBIRD_RAW_BITS_NONE);
-
-               cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook);
-
-               blackbird_initialize_codec(dev);
-               cx88_set_scale(dev->core, dev->width, dev->height,
-                              fh->mpegq.field);
-               return 0;
+static int vidioc_s_ext_ctrls (struct file *file, void *priv,
+                              struct v4l2_ext_controls *f)
+{
+       struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
+       struct cx2341x_mpeg_params p;
+       int err;
+
+       if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+               return -EINVAL;
+       p = dev->params;
+       err = cx2341x_ext_ctrls(&p, f, VIDIOC_S_EXT_CTRLS);
+       if (!err) {
+               err = cx2341x_update(dev, blackbird_mbox_func, &dev->params, &p);
+               dev->params = p;
        }
-       case VIDIOC_LOG_STATUS:
-       {
-               char name[32 + 2];
-
-               snprintf(name, sizeof(name), "%s/2", core->name);
-               printk("%s/2: ============  START LOG STATUS  ============\n",
-                      core->name);
-               cx88_call_i2c_clients(core, VIDIOC_LOG_STATUS, NULL);
-               cx2341x_log_status(&dev->params, name);
-               printk("%s/2: =============  END LOG STATUS  =============\n",
-                      core->name);
+       return err;
+}
+
+static int vidioc_try_ext_ctrls (struct file *file, void *priv,
+                              struct v4l2_ext_controls *f)
+{
+       struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
+       struct cx2341x_mpeg_params p;
+       int err;
+
+       if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+               return -EINVAL;
+       p = dev->params;
+       err = cx2341x_ext_ctrls(&p, f, VIDIOC_TRY_EXT_CTRLS);
+
+       return err;
+}
+
+static int vidioc_s_frequency (struct file *file, void *priv,
+                               struct v4l2_frequency *f)
+{
+       struct cx8802_fh  *fh   = priv;
+       struct cx8802_dev *dev  = fh->dev;
+       struct cx88_core  *core = dev->core;
+
+       blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
+                               BLACKBIRD_END_NOW,
+                               BLACKBIRD_MPEG_CAPTURE,
+                               BLACKBIRD_RAW_BITS_NONE);
+       cx88_set_freq (core,f);
+       blackbird_initialize_codec(dev);
+       cx88_set_scale(dev->core, dev->width, dev->height,
+                       fh->mpegq.field);
+       return 0;
+}
+
+static int vidioc_log_status (struct file *file, void *priv)
+{
+       struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
+       struct cx88_core  *core = dev->core;
+       char name[32 + 2];
+
+       snprintf(name, sizeof(name), "%s/2", core->name);
+       printk("%s/2: ============  START LOG STATUS  ============\n",
+               core->name);
+       cx88_call_i2c_clients(core, VIDIOC_LOG_STATUS, NULL);
+       cx2341x_log_status(&dev->params, name);
+       printk("%s/2: =============  END LOG STATUS  =============\n",
+               core->name);
+       return 0;
+}
+
+static int vidioc_queryctrl (struct file *file, void *priv,
+                               struct v4l2_queryctrl *qctrl)
+{
+       struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
+
+       if (blackbird_queryctrl(dev, qctrl) == 0)
                return 0;
-       }
-       case VIDIOC_QUERYMENU:
-               return blackbird_querymenu(dev, arg);
-       case VIDIOC_QUERYCTRL:
-       {
-               struct v4l2_queryctrl *c = arg;
 
-               if (blackbird_queryctrl(dev, c) == 0)
-                       return 0;
-               return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl);
-       }
+       qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
+       if (unlikely(qctrl->id == 0))
+               return -EINVAL;
+       return cx8800_ctrl_query(qctrl);
+}
 
-       default:
-               return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook);
-       }
+static int vidioc_enum_input (struct file *file, void *priv,
+                               struct v4l2_input *i)
+{
+       struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+       return cx88_enum_input (core,i);
+}
+
+static int vidioc_g_ctrl (struct file *file, void *priv,
+                               struct v4l2_control *ctl)
+{
+       struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+       return
+               cx88_get_control(core,ctl);
+}
+
+static int vidioc_s_ctrl (struct file *file, void *priv,
+                               struct v4l2_control *ctl)
+{
+       struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+       return
+               cx88_set_control(core,ctl);
+}
+
+static int vidioc_g_frequency (struct file *file, void *priv,
+                               struct v4l2_frequency *f)
+{
+       struct cx8802_fh  *fh   = priv;
+       struct cx88_core  *core = fh->dev->core;
+
+       if (unlikely(UNSET == core->tuner_type))
+               return -EINVAL;
+
+       f->type = V4L2_TUNER_ANALOG_TV;
+       f->frequency = core->freq;
+       cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f);
+
+       return 0;
+}
+
+static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
+{
+       struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+
+       *i = core->input;
+       return 0;
+}
+
+static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
+{
+       struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+
+       if (i >= 4)
+               return -EINVAL;
+
+       mutex_lock(&core->lock);
+       cx88_newstation(core);
+       cx88_video_mux(core,i);
+       mutex_unlock(&core->lock);
        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 int vidioc_g_tuner (struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+       u32 reg;
+
+       if (unlikely(UNSET == core->tuner_type))
+               return -EINVAL;
+
+       strcpy(t->name, "Television");
+       t->type       = V4L2_TUNER_ANALOG_TV;
+       t->capability = V4L2_TUNER_CAP_NORM;
+       t->rangehigh  = 0xffffffffUL;
+
+       cx88_get_stereo(core ,t);
+       reg = cx_read(MO_DEVICE_STATUS);
+       t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
+       return 0;
+}
 
-static unsigned int mpeg_translate_ioctl(unsigned int cmd)
+static int vidioc_s_tuner (struct file *file, void *priv,
+                               struct v4l2_tuner *t)
 {
-       return cmd;
+       struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+
+       if (UNSET == core->tuner_type)
+               return -EINVAL;
+       if (0 != t->index)
+               return -EINVAL;
+
+       cx88_set_stereo(core, t->audmode, 1);
+       return 0;
 }
 
-static int mpeg_ioctl(struct inode *inode, struct file *file,
-                       unsigned int cmd, unsigned long arg)
+static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id)
 {
-       cmd = cx88_ioctl_translator( cmd );
-       return video_usercopy(inode, file, cmd, arg, cx88_ioctl_hook);
+       struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+
+       mutex_lock(&core->lock);
+       cx88_set_tvnorm(core,*id);
+       mutex_unlock(&core->lock);
+       return 0;
 }
 
+/* FIXME: cx88_ioctl_hook not implemented */
+
 static int mpeg_open(struct inode *inode, struct file *file)
 {
        int minor = iminor(inode);
@@ -1059,17 +1197,47 @@ static const struct file_operations mpeg_fops =
        .read          = mpeg_read,
        .poll          = mpeg_poll,
        .mmap          = mpeg_mmap,
-       .ioctl         = mpeg_ioctl,
+       .ioctl         = video_ioctl2,
        .llseek        = no_llseek,
 };
 
 static struct video_device cx8802_mpeg_template =
 {
-       .name          = "cx8802",
-       .type          = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES|VID_TYPE_MPEG_ENCODER,
-       .hardware      = 0,
-       .fops          = &mpeg_fops,
-       .minor         = -1,
+       .name                 = "cx8802",
+       .type                 = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES|VID_TYPE_MPEG_ENCODER,
+       .fops                 = &mpeg_fops,
+       .minor                = -1,
+       .vidioc_querymenu     = vidioc_querymenu,
+       .vidioc_querycap      = vidioc_querycap,
+       .vidioc_enum_fmt_cap  = vidioc_enum_fmt_cap,
+       .vidioc_g_fmt_cap     = vidioc_g_fmt_cap,
+       .vidioc_try_fmt_cap   = vidioc_try_fmt_cap,
+       .vidioc_s_fmt_cap     = vidioc_s_fmt_cap,
+       .vidioc_reqbufs       = vidioc_reqbufs,
+       .vidioc_querybuf      = vidioc_querybuf,
+       .vidioc_qbuf          = vidioc_qbuf,
+       .vidioc_dqbuf         = vidioc_dqbuf,
+       .vidioc_streamon      = vidioc_streamon,
+       .vidioc_streamoff     = vidioc_streamoff,
+       .vidioc_g_mpegcomp    = vidioc_g_mpegcomp,
+       .vidioc_s_mpegcomp    = vidioc_s_mpegcomp,
+       .vidioc_g_ext_ctrls   = vidioc_g_ext_ctrls,
+       .vidioc_s_ext_ctrls   = vidioc_s_ext_ctrls,
+       .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls,
+       .vidioc_s_frequency   = vidioc_s_frequency,
+       .vidioc_log_status    = vidioc_log_status,
+       .vidioc_queryctrl     = vidioc_queryctrl,
+       .vidioc_enum_input    = vidioc_enum_input,
+       .vidioc_g_ctrl        = vidioc_g_ctrl,
+       .vidioc_s_ctrl        = vidioc_s_ctrl,
+       .vidioc_g_frequency   = vidioc_g_frequency,
+       .vidioc_g_input       = vidioc_g_input,
+       .vidioc_s_input       = vidioc_s_input,
+       .vidioc_g_tuner       = vidioc_g_tuner,
+       .vidioc_s_tuner       = vidioc_s_tuner,
+       .vidioc_s_std         = vidioc_s_std,
+       .tvnorms              = CX88_NORMS,
+       .current_norm         = V4L2_STD_NTSC_M,
 };
 
 /* ------------------------------------------------------------------ */
@@ -1164,7 +1332,9 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
        cx2341x_fill_defaults(&dev->params);
        dev->params.port = CX2341X_PORT_STREAMING;
 
-       if (core->tvnorm->id & V4L2_STD_525_60) {
+       cx8802_mpeg_template.current_norm = core->tvnorm;
+
+       if (core->tvnorm & V4L2_STD_525_60) {
                dev->height = 480;
        } else {
                dev->height = 576;
@@ -1178,6 +1348,11 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
        blackbird_register_video(dev);
 
        /* initial device configuration: needed ? */
+       mutex_lock(&dev->core->lock);
+//     init_controls(core);
+       cx88_set_tvnorm(core,core->tvnorm);
+       cx88_video_mux(core,0);
+       mutex_unlock(&dev->core->lock);
 
        return 0;
 
@@ -1212,8 +1387,6 @@ 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);
 }
 
@@ -1225,8 +1398,8 @@ static void blackbird_fini(void)
 module_init(blackbird_init);
 module_exit(blackbird_fini);
 
-EXPORT_SYMBOL(cx88_ioctl_hook);
-EXPORT_SYMBOL(cx88_ioctl_translator);
+module_param_named(video_debug,cx8802_mpeg_template.debug, int, 0644);
+MODULE_PARM_DESC(debug,"enable debug messages [video]");
 
 /* ----------------------------------------------------------- */
 /*
index 434b78ab37d83032391776af106ba4cc412e6642..65e9d8096b74ddf9cb0c750a903979a28a7a4a0f 100644 (file)
@@ -764,6 +764,12 @@ struct cx88_board cx88_boards[] = {
                .input          = {{
                        .type   = CX88_VMUX_DVB,
                        .vmux   = 0,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 2,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
                }},
                .mpeg           = CX88_MPEG_DVB,
        },
index 18997361c75ab574e9807d5918e999625e91d069..d86813be56de33fa8df22e3402ba94fa669af524 100644 (file)
@@ -5,6 +5,11 @@
  *
  * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
  *
+ * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *     - Multituner support
+ *     - video_ioctl2 conversion
+ *     - PAL/M fixes
+ *
  *  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
@@ -631,30 +636,30 @@ int cx88_reset(struct cx88_core *core)
 
 /* ------------------------------------------------------------------ */
 
-static unsigned int inline norm_swidth(struct cx88_tvnorm *norm)
+static unsigned int inline norm_swidth(v4l2_std_id norm)
 {
-       return (norm->id & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
+       return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
 }
 
-static unsigned int inline norm_hdelay(struct cx88_tvnorm *norm)
+static unsigned int inline norm_hdelay(v4l2_std_id norm)
 {
-       return (norm->id & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186;
+       return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186;
 }
 
-static unsigned int inline norm_vdelay(struct cx88_tvnorm *norm)
+static unsigned int inline norm_vdelay(v4l2_std_id norm)
 {
-       return (norm->id & V4L2_STD_625_50) ? 0x24 : 0x18;
+       return (norm & V4L2_STD_625_50) ? 0x24 : 0x18;
 }
 
-static unsigned int inline norm_fsc8(struct cx88_tvnorm *norm)
+static unsigned int inline norm_fsc8(v4l2_std_id norm)
 {
-       if (norm->id & V4L2_STD_PAL_M)
+       if (norm & V4L2_STD_PAL_M)
                return 28604892;      // 3.575611 MHz
 
-       if (norm->id & (V4L2_STD_PAL_Nc))
+       if (norm & (V4L2_STD_PAL_Nc))
                return 28656448;      // 3.582056 MHz
 
-       if (norm->id & V4L2_STD_NTSC) // All NTSC/M and variants
+       if (norm & V4L2_STD_NTSC) // All NTSC/M and variants
                return 28636360;      // 3.57954545 MHz +/- 10 Hz
 
        /* SECAM have also different sub carrier for chroma,
@@ -666,20 +671,20 @@ static unsigned int inline norm_fsc8(struct cx88_tvnorm *norm)
        return 35468950;      // 4.43361875 MHz +/- 5 Hz
 }
 
-static unsigned int inline norm_htotal(struct cx88_tvnorm *norm)
+static unsigned int inline norm_htotal(v4l2_std_id norm)
 {
 
        unsigned int fsc4=norm_fsc8(norm)/2;
 
        /* returns 4*FSC / vtotal / frames per seconds */
-       return (norm->id & V4L2_STD_625_50) ?
+       return (norm & V4L2_STD_625_50) ?
                                ((fsc4+312)/625+12)/25 :
                                ((fsc4+262)/525*1001+15000)/30000;
 }
 
-static unsigned int inline norm_vbipack(struct cx88_tvnorm *norm)
+static unsigned int inline norm_vbipack(v4l2_std_id norm)
 {
-       return (norm->id & V4L2_STD_625_50) ? 511 : 400;
+       return (norm & V4L2_STD_625_50) ? 511 : 400;
 }
 
 int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height,
@@ -692,7 +697,7 @@ int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int heig
        dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height,
                V4L2_FIELD_HAS_TOP(field)    ? "T" : "",
                V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "",
-               core->tvnorm->name);
+               v4l2_norm_to_name(core->tvnorm));
        if (!V4L2_FIELD_HAS_BOTH(field))
                height *= 2;
 
@@ -729,7 +734,7 @@ int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int heig
        // setup filters
        value = 0;
        value |= (1 << 19);        // CFILT (default)
-       if (core->tvnorm->id & V4L2_STD_SECAM) {
+       if (core->tvnorm & V4L2_STD_SECAM) {
                value |= (1 << 15);
                value |= (1 << 16);
        }
@@ -826,36 +831,36 @@ int cx88_stop_audio_dma(struct cx88_core *core)
 
 static int set_tvaudio(struct cx88_core *core)
 {
-       struct cx88_tvnorm *norm = core->tvnorm;
+       v4l2_std_id norm = core->tvnorm;
 
        if (CX88_VMUX_TELEVISION != INPUT(core->input)->type)
                return 0;
 
-       if (V4L2_STD_PAL_BG & norm->id) {
+       if (V4L2_STD_PAL_BG & norm) {
                core->tvaudio = WW_BG;
 
-       } else if (V4L2_STD_PAL_DK & norm->id) {
+       } else if (V4L2_STD_PAL_DK & norm) {
                core->tvaudio = WW_DK;
 
-       } else if (V4L2_STD_PAL_I & norm->id) {
+       } else if (V4L2_STD_PAL_I & norm) {
                core->tvaudio = WW_I;
 
-       } else if (V4L2_STD_SECAM_L & norm->id) {
+       } else if (V4L2_STD_SECAM_L & norm) {
                core->tvaudio = WW_L;
 
-       } else if (V4L2_STD_SECAM_DK & norm->id) {
+       } else if (V4L2_STD_SECAM_DK & norm) {
                core->tvaudio = WW_DK;
 
-       } else if ((V4L2_STD_NTSC_M & norm->id) ||
-                  (V4L2_STD_PAL_M  & norm->id)) {
+       } else if ((V4L2_STD_NTSC_M & norm) ||
+                  (V4L2_STD_PAL_M  & norm)) {
                core->tvaudio = WW_BTSC;
 
-       } else if (V4L2_STD_NTSC_M_JP & norm->id) {
+       } else if (V4L2_STD_NTSC_M_JP & norm) {
                core->tvaudio = WW_EIAJ;
 
        } else {
                printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n",
-                      core->name, norm->name);
+                      core->name, v4l2_norm_to_name(core->tvnorm));
                core->tvaudio = 0;
                return 0;
        }
@@ -874,7 +879,7 @@ static int set_tvaudio(struct cx88_core *core)
 
 
 
-int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm)
+int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
 {
        u32 fsc8;
        u32 adc_clock;
@@ -882,6 +887,7 @@ int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm)
        u32 step_db,step_dr;
        u64 tmp64;
        u32 bdelay,agcdelay,htotal;
+       u32 cxiformat, cxoformat;
 
        core->tvnorm = norm;
        fsc8       = norm_fsc8(norm);
@@ -890,23 +896,51 @@ int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm)
        step_db    = fsc8;
        step_dr    = fsc8;
 
-       if (norm->id & V4L2_STD_SECAM) {
+       if (norm & V4L2_STD_NTSC_M_JP) {
+               cxiformat = VideoFormatNTSCJapan;
+               cxoformat = 0x181f0008;
+       } else if (norm & V4L2_STD_NTSC_443) {
+               cxiformat = VideoFormatNTSC443;
+               cxoformat = 0x181f0008;
+       } else if (norm & V4L2_STD_PAL_M) {
+               cxiformat = VideoFormatPALM;
+               cxoformat = 0x1c1f0008;
+       } else if (norm & V4L2_STD_PAL_N) {
+               cxiformat = VideoFormatPALN;
+               cxoformat = 0x1c1f0008;
+       } else if (norm & V4L2_STD_PAL_Nc) {
+               cxiformat = VideoFormatPALNC;
+               cxoformat = 0x1c1f0008;
+       } else if (norm & V4L2_STD_PAL_60) {
+               cxiformat = VideoFormatPAL60;
+               cxoformat = 0x181f0008;
+       } else if (norm & V4L2_STD_NTSC) {
+               cxiformat = VideoFormatNTSC;
+               cxoformat = 0x181f0008;
+       } else if (norm & V4L2_STD_SECAM) {
                step_db = 4250000 * 8;
                step_dr = 4406250 * 8;
+
+               cxiformat = VideoFormatSECAM;
+               cxoformat = 0x181f0008;
+       } else { /* PAL */
+               cxiformat = VideoFormatPAL;
+               cxoformat = 0x181f0008;
        }
 
        dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n",
-               norm->name, fsc8, adc_clock, vdec_clock, step_db, step_dr);
+               v4l2_norm_to_name(core->tvnorm), fsc8, adc_clock, vdec_clock,
+               step_db, step_dr);
        set_pll(core,2,vdec_clock);
 
        dprintk(1,"set_tvnorm: MO_INPUT_FORMAT  0x%08x [old=0x%08x]\n",
-               norm->cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
-       cx_andor(MO_INPUT_FORMAT, 0xf, norm->cxiformat);
+               cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
+       cx_andor(MO_INPUT_FORMAT, 0xf, cxiformat);
 
        // FIXME: as-is from DScaler
        dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
-               norm->cxoformat, cx_read(MO_OUTPUT_FORMAT));
-       cx_write(MO_OUTPUT_FORMAT, norm->cxoformat);
+               cxoformat, cx_read(MO_OUTPUT_FORMAT));
+       cx_write(MO_OUTPUT_FORMAT, cxoformat);
 
        // MO_SCONV_REG = adc clock / video dec clock * 2^17
        tmp64  = adc_clock * (u64)(1 << 17);
@@ -955,7 +989,7 @@ int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm)
        set_tvaudio(core);
 
        // tell i2c chips
-       cx88_call_i2c_clients(core,VIDIOC_S_STD,&norm->id);
+       cx88_call_i2c_clients(core,VIDIOC_S_STD,&norm);
 
        // done
        return 0;
index 8b203354fccdff8f533702fba23610a6a9f0f3c8..4f556028577037622f80c4eec28fba463ffc8521 100644 (file)
@@ -35,7 +35,7 @@
 
 #include "mt352.h"
 #include "mt352_priv.h"
-#ifdef HAVE_VP3054_I2C
+#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE)
 # include "cx88-vp3054-i2c.h"
 #endif
 #include "zl10353.h"
@@ -200,7 +200,7 @@ static struct mt352_config dvico_fusionhdtv_dual = {
        .demod_init    = dvico_dual_demod_init,
 };
 
-#ifdef HAVE_VP3054_I2C
+#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE)
 static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe)
 {
        static u8 clock_config []  = { 0x89, 0x38, 0x38 };
@@ -543,7 +543,7 @@ static int dvb_register(struct cx8802_dev *dev)
                }
                break;
        case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
-#ifdef HAVE_VP3054_I2C
+#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE)
                dev->core->pll_addr = 0x61;
                dev->core->pll_desc = &dvb_pll_fmd1216me;
                dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
@@ -793,7 +793,7 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
        if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB))
                goto fail_core;
 
-#ifdef HAVE_VP3054_I2C
+#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE)
        err = vp3054_i2c_probe(dev);
        if (0 != err)
                goto fail_core;
@@ -822,7 +822,7 @@ static int cx8802_dvb_remove(struct cx8802_driver *drv)
        /* dvb */
        videobuf_dvb_unregister(&dev->dvb);
 
-#ifdef HAVE_VP3054_I2C
+#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE)
        vp3054_i2c_remove(dev);
 #endif
 
index 88af23a938702335697fb18bb1ce33526fa79dad..9830d5c43921daa1753afdcfab230bf9166f1d94 100644 (file)
@@ -145,6 +145,7 @@ void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg)
        if (0 != core->i2c_rc)
                return;
 
+#if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE)
        if ( (core->dvbdev) && (core->dvbdev->dvb.frontend) ) {
                if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl)
                        core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1);
@@ -154,6 +155,7 @@ void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg)
                if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl)
                        core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 0);
        } else
+#endif
                i2c_clients_command(&core->i2c_adap, cmd, arg);
 }
 
index 063df03dcf2ee54c3f6232b42ca23fc93ce25dd1..97ef421dd0931b7673f2cdc1650cd0fab590da45 100644 (file)
@@ -797,55 +797,6 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
        Add some code here later.
 */
 
-# if 0
-       t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP |
-           V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
-       t->rxsubchans = V4L2_TUNER_SUB_MONO;
-       t->audmode = V4L2_TUNER_MODE_MONO;
-
-       switch (core->tvaudio) {
-       case WW_BTSC:
-               t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP;
-               t->rxsubchans = V4L2_TUNER_SUB_STEREO;
-               if (1 == pilot) {
-                       /* SAP */
-                       t->rxsubchans |= V4L2_TUNER_SUB_SAP;
-               }
-               break;
-       case WW_A2_BG:
-       case WW_A2_DK:
-       case WW_A2_M:
-               if (1 == pilot) {
-                       /* stereo */
-                       t->rxsubchans =
-                           V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
-                       if (0 == mode)
-                               t->audmode = V4L2_TUNER_MODE_STEREO;
-               }
-               if (2 == pilot) {
-                       /* dual language -- FIXME */
-                       t->rxsubchans =
-                           V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
-                       t->audmode = V4L2_TUNER_MODE_LANG1;
-               }
-               break;
-       case WW_NICAM_BGDKL:
-               if (0 == mode) {
-                       t->audmode = V4L2_TUNER_MODE_STEREO;
-                       t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
-               }
-               break;
-       case WW_SYSTEM_L_AM:
-               if (0x0 == mode && !(cx_read(AUD_INIT) & 0x04)) {
-                       t->audmode = V4L2_TUNER_MODE_STEREO;
-                       t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
-               }
-               break;
-       default:
-               /* nothing */
-               break;
-       }
-# endif
        return;
 }
 
index aa2a69770098cf48b085d9f35c79f154ec20c9b6..86c1cf8334bc144a41c49ed81ea1f8d4fe215ceb 100644 (file)
@@ -21,9 +21,11 @@ MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");
 
 /* ------------------------------------------------------------------ */
 
-void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f)
+int cx8800_vbi_fmt (struct file *file, void *priv,
+                                       struct v4l2_format *f)
 {
-       memset(&f->fmt.vbi,0,sizeof(f->fmt.vbi));
+       struct cx8800_fh  *fh   = priv;
+       struct cx8800_dev *dev  = fh->dev;
 
        f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
        f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
@@ -31,18 +33,19 @@ void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f)
        f->fmt.vbi.count[0] = VBI_LINE_COUNT;
        f->fmt.vbi.count[1] = VBI_LINE_COUNT;
 
-       if (dev->core->tvnorm->id & V4L2_STD_525_60) {
+       if (dev->core->tvnorm & V4L2_STD_525_60) {
                /* ntsc */
                f->fmt.vbi.sampling_rate = 28636363;
                f->fmt.vbi.start[0] = 10;
                f->fmt.vbi.start[1] = 273;
 
-       } else if (dev->core->tvnorm->id & V4L2_STD_625_50) {
+       } else if (dev->core->tvnorm & V4L2_STD_625_50) {
                /* pal */
                f->fmt.vbi.sampling_rate = 35468950;
                f->fmt.vbi.start[0] = 7 -1;
                f->fmt.vbi.start[1] = 319 -1;
        }
+       return 0;
 }
 
 static int cx8800_start_vbi_dma(struct cx8800_dev    *dev,
index c86a7e06235b35f36411c726f9e83ac2ceb5bbb9..bdfe2af70124c8ecac34a22bd4e184227c204ec1 100644 (file)
@@ -1,3 +1,4 @@
+
 /*
  *
  * device driver for Conexant 2388x based TV cards
@@ -5,6 +6,11 @@
  *
  * (c) 2003-04 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
  *
+ * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *     - Multituner support
+ *     - video_ioctl2 conversion
+ *     - PAL/M fixes
+ *
  *  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
@@ -80,65 +86,6 @@ static LIST_HEAD(cx8800_devlist);
 /* ------------------------------------------------------------------- */
 /* static data                                                         */
 
-static struct cx88_tvnorm tvnorms[] = {
-       {
-               .name      = "NTSC-M",
-               .id        = V4L2_STD_NTSC_M,
-               .cxiformat = VideoFormatNTSC,
-               .cxoformat = 0x181f0008,
-       },{
-               .name      = "NTSC-JP",
-               .id        = V4L2_STD_NTSC_M_JP,
-               .cxiformat = VideoFormatNTSCJapan,
-               .cxoformat = 0x181f0008,
-       },{
-               .name      = "PAL-BG",
-               .id        = V4L2_STD_PAL_BG,
-               .cxiformat = VideoFormatPAL,
-               .cxoformat = 0x181f0008,
-       },{
-               .name      = "PAL-DK",
-               .id        = V4L2_STD_PAL_DK,
-               .cxiformat = VideoFormatPAL,
-               .cxoformat = 0x181f0008,
-       },{
-               .name      = "PAL-I",
-               .id        = V4L2_STD_PAL_I,
-               .cxiformat = VideoFormatPAL,
-               .cxoformat = 0x181f0008,
-       },{
-               .name      = "PAL-M",
-               .id        = V4L2_STD_PAL_M,
-               .cxiformat = VideoFormatPALM,
-               .cxoformat = 0x1c1f0008,
-       },{
-               .name      = "PAL-N",
-               .id        = V4L2_STD_PAL_N,
-               .cxiformat = VideoFormatPALN,
-               .cxoformat = 0x1c1f0008,
-       },{
-               .name      = "PAL-Nc",
-               .id        = V4L2_STD_PAL_Nc,
-               .cxiformat = VideoFormatPALNC,
-               .cxoformat = 0x1c1f0008,
-       },{
-               .name      = "PAL-60",
-               .id        = V4L2_STD_PAL_60,
-               .cxiformat = VideoFormatPAL60,
-               .cxoformat = 0x181f0008,
-       },{
-               .name      = "SECAM-L",
-               .id        = V4L2_STD_SECAM_L,
-               .cxiformat = VideoFormatSECAM,
-               .cxoformat = 0x181f0008,
-       },{
-               .name      = "SECAM-DK",
-               .id        = V4L2_STD_SECAM_DK,
-               .cxiformat = VideoFormatSECAM,
-               .cxoformat = 0x181f0008,
-       }
-};
-
 static struct cx8800_fmt formats[] = {
        {
                .name     = "8 bpp, gray",
@@ -364,14 +311,6 @@ int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl)
 }
 EXPORT_SYMBOL(cx8800_ctrl_query);
 
-static int cx88_queryctrl(struct v4l2_queryctrl *qctrl)
-{
-       qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
-       if (qctrl->id == 0)
-               return -EINVAL;
-       return cx8800_ctrl_query(qctrl);
-}
-
 /* ------------------------------------------------------------------- */
 /* resource management                                                 */
 
@@ -424,8 +363,7 @@ void res_free(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bits)
 
 /* ------------------------------------------------------------------ */
 
-/* static int video_mux(struct cx8800_dev *dev, unsigned int input) */
-static int video_mux(struct cx88_core *core, unsigned int input)
+int cx88_video_mux(struct cx88_core *core, unsigned int input)
 {
        /* struct cx88_core *core = dev->core; */
 
@@ -464,6 +402,7 @@ static int video_mux(struct cx88_core *core, unsigned int input)
        }
        return 0;
 }
+EXPORT_SYMBOL(cx88_video_mux);
 
 /* ------------------------------------------------------------------ */
 
@@ -944,19 +883,18 @@ video_mmap(struct file *file, struct vm_area_struct * vma)
 }
 
 /* ------------------------------------------------------------------ */
+/* VIDEO CTRL IOCTLS                                                  */
 
-/* static int get_control(struct cx8800_dev *dev, struct v4l2_control *ctl) */
-static int get_control(struct cx88_core *core, struct v4l2_control *ctl)
+int cx88_get_control (struct cx88_core  *core, struct v4l2_control *ctl)
 {
-       /* struct cx88_core *core = dev->core; */
-       struct cx88_ctrl *c = NULL;
+       struct cx88_ctrl  *c    = NULL;
        u32 value;
        int i;
 
        for (i = 0; i < CX8800_CTLS; i++)
                if (cx8800_ctls[i].v.id == ctl->id)
                        c = &cx8800_ctls[i];
-       if (NULL == c)
+       if (unlikely(NULL == c))
                return -EINVAL;
 
        value = c->sreg ? cx_sread(c->sreg) : cx_read(c->reg);
@@ -977,20 +915,20 @@ static int get_control(struct cx88_core *core, struct v4l2_control *ctl)
                                value,c->mask, c->sreg ? " [shadowed]" : "");
        return 0;
 }
+EXPORT_SYMBOL(cx88_get_control);
 
-/* static int set_control(struct cx8800_dev *dev, struct v4l2_control *ctl) */
-static int set_control(struct cx88_core *core, struct v4l2_control *ctl)
+int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl)
 {
-       /* struct cx88_core *core = dev->core; */
        struct cx88_ctrl *c = NULL;
        u32 value,mask;
        int i;
+
        for (i = 0; i < CX8800_CTLS; i++) {
                if (cx8800_ctls[i].v.id == ctl->id) {
                        c = &cx8800_ctls[i];
                }
        }
-       if (NULL == c)
+       if (unlikely(NULL == c))
                return -EINVAL;
 
        if (ctl->value < c->v.minimum)
@@ -1010,7 +948,7 @@ static int set_control(struct cx88_core *core, struct v4l2_control *ctl)
 
                value = ((ctl->value - c->off) << c->shift) & c->mask;
 
-               if (core->tvnorm->id & V4L2_STD_SECAM) {
+               if (core->tvnorm & V4L2_STD_SECAM) {
                        /* For SECAM, both U and V sat should be equal */
                        value=value<<8|value;
                } else {
@@ -1033,6 +971,7 @@ static int set_control(struct cx88_core *core, struct v4l2_control *ctl)
        }
        return 0;
 }
+EXPORT_SYMBOL(cx88_set_control);
 
 static void init_controls(struct cx88_core *core)
 {
@@ -1042,648 +981,531 @@ static void init_controls(struct cx88_core *core)
        for (i = 0; i < CX8800_CTLS; i++) {
                ctrl.id=cx8800_ctls[i].v.id;
                ctrl.value=cx8800_ctls[i].v.default_value;
-               set_control(core, &ctrl);
+
+               cx88_set_control(core, &ctrl);
        }
 }
 
 /* ------------------------------------------------------------------ */
+/* VIDEO IOCTLS                                                       */
 
-static int cx8800_g_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh,
+static int vidioc_g_fmt_cap (struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct cx8800_fh  *fh   = priv;
+
+       f->fmt.pix.width        = fh->width;
+       f->fmt.pix.height       = fh->height;
+       f->fmt.pix.field        = fh->vidq.field;
+       f->fmt.pix.pixelformat  = fh->fmt->fourcc;
+       f->fmt.pix.bytesperline =
+               (f->fmt.pix.width * fh->fmt->depth) >> 3;
+       f->fmt.pix.sizeimage =
+               f->fmt.pix.height * f->fmt.pix.bytesperline;
+       return 0;
+}
+
+static int vidioc_try_fmt_cap (struct file *file, void *priv,
                        struct v4l2_format *f)
 {
-       switch (f->type) {
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               memset(&f->fmt.pix,0,sizeof(f->fmt.pix));
-               f->fmt.pix.width        = fh->width;
-               f->fmt.pix.height       = fh->height;
-               f->fmt.pix.field        = fh->vidq.field;
-               f->fmt.pix.pixelformat  = fh->fmt->fourcc;
-               f->fmt.pix.bytesperline =
-                       (f->fmt.pix.width * fh->fmt->depth) >> 3;
-               f->fmt.pix.sizeimage =
-                       f->fmt.pix.height * f->fmt.pix.bytesperline;
-               return 0;
-       case V4L2_BUF_TYPE_VBI_CAPTURE:
-               cx8800_vbi_fmt(dev, f);
-               return 0;
+       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+       struct cx8800_fmt *fmt;
+       enum v4l2_field   field;
+       unsigned int      maxw, maxh;
+
+       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+       if (NULL == fmt)
+               return -EINVAL;
+
+       field = f->fmt.pix.field;
+       maxw  = norm_maxw(core->tvnorm);
+       maxh  = norm_maxh(core->tvnorm);
+
+       if (V4L2_FIELD_ANY == field) {
+               field = (f->fmt.pix.height > maxh/2)
+                       ? V4L2_FIELD_INTERLACED
+                       : V4L2_FIELD_BOTTOM;
+       }
+
+       switch (field) {
+       case V4L2_FIELD_TOP:
+       case V4L2_FIELD_BOTTOM:
+               maxh = maxh / 2;
+               break;
+       case V4L2_FIELD_INTERLACED:
+               break;
        default:
                return -EINVAL;
        }
+
+       f->fmt.pix.field = field;
+       if (f->fmt.pix.height < 32)
+               f->fmt.pix.height = 32;
+       if (f->fmt.pix.height > maxh)
+               f->fmt.pix.height = maxh;
+       if (f->fmt.pix.width < 48)
+               f->fmt.pix.width = 48;
+       if (f->fmt.pix.width > maxw)
+               f->fmt.pix.width = maxw;
+       f->fmt.pix.width &= ~0x03;
+       f->fmt.pix.bytesperline =
+               (f->fmt.pix.width * fmt->depth) >> 3;
+       f->fmt.pix.sizeimage =
+               f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+       return 0;
 }
 
-static int cx8800_try_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh,
-                         struct v4l2_format *f)
+static int vidioc_s_fmt_cap (struct file *file, void *priv,
+                                       struct v4l2_format *f)
 {
-       struct cx88_core *core = dev->core;
+       struct cx8800_fh  *fh   = priv;
+       int err = vidioc_try_fmt_cap (file,priv,f);
 
-       switch (f->type) {
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-       {
-               struct cx8800_fmt *fmt;
-               enum v4l2_field field;
-               unsigned int maxw, maxh;
-
-               fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-               if (NULL == fmt)
-                       return -EINVAL;
-
-               field = f->fmt.pix.field;
-               maxw  = norm_maxw(core->tvnorm);
-               maxh  = norm_maxh(core->tvnorm);
-
-               if (V4L2_FIELD_ANY == field) {
-                       field = (f->fmt.pix.height > maxh/2)
-                               ? V4L2_FIELD_INTERLACED
-                               : V4L2_FIELD_BOTTOM;
-               }
+       if (0 != err)
+               return err;
+       fh->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);
+       fh->width      = f->fmt.pix.width;
+       fh->height     = f->fmt.pix.height;
+       fh->vidq.field = f->fmt.pix.field;
+       return 0;
+}
 
-               switch (field) {
-               case V4L2_FIELD_TOP:
-               case V4L2_FIELD_BOTTOM:
-                       maxh = maxh / 2;
-                       break;
-               case V4L2_FIELD_INTERLACED:
-                       break;
-               default:
-                       return -EINVAL;
-               }
+static int vidioc_querycap (struct file *file, void  *priv,
+                                       struct v4l2_capability *cap)
+{
+       struct cx8800_dev *dev  = ((struct cx8800_fh *)priv)->dev;
+       struct cx88_core  *core = dev->core;
 
-               f->fmt.pix.field = field;
-               if (f->fmt.pix.height < 32)
-                       f->fmt.pix.height = 32;
-               if (f->fmt.pix.height > maxh)
-                       f->fmt.pix.height = maxh;
-               if (f->fmt.pix.width < 48)
-                       f->fmt.pix.width = 48;
-               if (f->fmt.pix.width > maxw)
-                       f->fmt.pix.width = maxw;
-               f->fmt.pix.width &= ~0x03;
-               f->fmt.pix.bytesperline =
-                       (f->fmt.pix.width * fmt->depth) >> 3;
-               f->fmt.pix.sizeimage =
-                       f->fmt.pix.height * f->fmt.pix.bytesperline;
+       strcpy(cap->driver, "cx8800");
+       strlcpy(cap->card, cx88_boards[core->board].name,
+               sizeof(cap->card));
+       sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
+       cap->version = CX88_VERSION_CODE;
+       cap->capabilities =
+               V4L2_CAP_VIDEO_CAPTURE |
+               V4L2_CAP_READWRITE     |
+               V4L2_CAP_STREAMING     |
+               V4L2_CAP_VBI_CAPTURE;
+       if (UNSET != core->tuner_type)
+               cap->capabilities |= V4L2_CAP_TUNER;
+       return 0;
+}
 
-               return 0;
-       }
-       case V4L2_BUF_TYPE_VBI_CAPTURE:
-               cx8800_vbi_fmt(dev, f);
-               return 0;
-       default:
+static int vidioc_enum_fmt_cap (struct file *file, void  *priv,
+                                       struct v4l2_fmtdesc *f)
+{
+       if (unlikely(f->index >= ARRAY_SIZE(formats)))
                return -EINVAL;
-       }
+
+       strlcpy(f->description,formats[f->index].name,sizeof(f->description));
+       f->pixelformat = formats[f->index].fourcc;
+
+       return 0;
 }
 
-static int cx8800_s_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh,
-                       struct v4l2_format *f)
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf)
 {
+       struct cx8800_fh           *fh   = priv;
+       struct videobuf_queue      *q;
+       struct v4l2_requestbuffers req;
+       unsigned int i;
        int err;
 
-       switch (f->type) {
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               err = cx8800_try_fmt(dev,fh,f);
-               if (0 != err)
-                       return err;
+       q = get_queue(fh);
+       memset(&req,0,sizeof(req));
+       req.type   = q->type;
+       req.count  = 8;
+       req.memory = V4L2_MEMORY_MMAP;
+       err = videobuf_reqbufs(q,&req);
+       if (err < 0)
+               return err;
 
-               fh->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);
-               fh->width      = f->fmt.pix.width;
-               fh->height     = f->fmt.pix.height;
-               fh->vidq.field = f->fmt.pix.field;
-               return 0;
-       case V4L2_BUF_TYPE_VBI_CAPTURE:
-               cx8800_vbi_fmt(dev, f);
-               return 0;
-       default:
-               return -EINVAL;
+       mbuf->frames = req.count;
+       mbuf->size   = 0;
+       for (i = 0; i < mbuf->frames; i++) {
+               mbuf->offsets[i]  = q->bufs[i]->boff;
+               mbuf->size       += q->bufs[i]->bsize;
        }
+       return 0;
 }
+#endif
 
-/*
- * This function is _not_ called directly, but from
- * video_generic_ioctl (and maybe others).  userspace
- * copying is done already, arg is a kernel pointer.
- */
-static int video_do_ioctl(struct inode *inode, struct file *file,
-                         unsigned int cmd, void *arg)
+static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
+{
+       struct cx8800_fh  *fh   = priv;
+       return (videobuf_reqbufs(get_queue(fh), p));
+}
+
+static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct cx8800_fh  *fh   = priv;
+       return (videobuf_querybuf(get_queue(fh), p));
+}
+
+static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct cx8800_fh  *fh   = priv;
+       return (videobuf_qbuf(get_queue(fh), p));
+}
+
+static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct cx8800_fh  *fh   = priv;
+       return (videobuf_dqbuf(get_queue(fh), p,
+                               file->f_flags & O_NONBLOCK));
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
 {
-       struct cx8800_fh  *fh   = file->private_data;
+       struct cx8800_fh  *fh   = priv;
        struct cx8800_dev *dev  = fh->dev;
-       struct cx88_core  *core = dev->core;
-       int err;
 
-       if (video_debug > 1)
-               v4l_print_ioctl(core->name,cmd);
-       switch (cmd) {
+       if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+               return -EINVAL;
+       if (unlikely(i != fh->type))
+               return -EINVAL;
 
-       /* --- capabilities ------------------------------------------ */
-       case VIDIOC_QUERYCAP:
-       {
-               struct v4l2_capability *cap = arg;
-
-               memset(cap,0,sizeof(*cap));
-               strcpy(cap->driver, "cx8800");
-               strlcpy(cap->card, cx88_boards[core->board].name,
-                       sizeof(cap->card));
-               sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
-               cap->version = CX88_VERSION_CODE;
-               cap->capabilities =
-                       V4L2_CAP_VIDEO_CAPTURE |
-                       V4L2_CAP_READWRITE     |
-                       V4L2_CAP_STREAMING     |
-                       V4L2_CAP_VBI_CAPTURE   |
-                       0;
-               if (UNSET != core->tuner_type)
-                       cap->capabilities |= V4L2_CAP_TUNER;
-               return 0;
-       }
+       if (unlikely(!res_get(dev,fh,get_ressource(fh))))
+               return -EBUSY;
+       return videobuf_streamon(get_queue(fh));
+}
 
-       /* --- capture ioctls ---------------------------------------- */
-       case VIDIOC_ENUM_FMT:
-       {
-               struct v4l2_fmtdesc *f = arg;
-               enum v4l2_buf_type type;
-               unsigned int index;
-
-               index = f->index;
-               type  = f->type;
-               switch (type) {
-               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-                       if (index >= ARRAY_SIZE(formats))
-                               return -EINVAL;
-                       memset(f,0,sizeof(*f));
-                       f->index = index;
-                       f->type  = type;
-                       strlcpy(f->description,formats[index].name,sizeof(f->description));
-                       f->pixelformat = formats[index].fourcc;
-                       break;
-               default:
-                       return -EINVAL;
-               }
-               return 0;
-       }
-       case VIDIOC_G_FMT:
-       {
-               struct v4l2_format *f = arg;
-               return cx8800_g_fmt(dev,fh,f);
-       }
-       case VIDIOC_S_FMT:
-       {
-               struct v4l2_format *f = arg;
-               return cx8800_s_fmt(dev,fh,f);
-       }
-       case VIDIOC_TRY_FMT:
-       {
-               struct v4l2_format *f = arg;
-               return cx8800_try_fmt(dev,fh,f);
-       }
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-       /* --- streaming capture ------------------------------------- */
-       case VIDIOCGMBUF:
-       {
-               struct video_mbuf *mbuf = arg;
-               struct videobuf_queue *q;
-               struct v4l2_requestbuffers req;
-               unsigned int i;
-
-               q = get_queue(fh);
-               memset(&req,0,sizeof(req));
-               req.type   = q->type;
-               req.count  = 8;
-               req.memory = V4L2_MEMORY_MMAP;
-               err = videobuf_reqbufs(q,&req);
-               if (err < 0)
-                       return err;
-               memset(mbuf,0,sizeof(*mbuf));
-               mbuf->frames = req.count;
-               mbuf->size   = 0;
-               for (i = 0; i < mbuf->frames; i++) {
-                       mbuf->offsets[i]  = q->bufs[i]->boff;
-                       mbuf->size       += q->bufs[i]->bsize;
-               }
-               return 0;
-       }
-#endif
-       case VIDIOC_REQBUFS:
-               return videobuf_reqbufs(get_queue(fh), arg);
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct cx8800_fh  *fh   = priv;
+       struct cx8800_dev *dev  = fh->dev;
+       int               err, res;
 
-       case VIDIOC_QUERYBUF:
-               return videobuf_querybuf(get_queue(fh), arg);
+       if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       if (i != fh->type)
+               return -EINVAL;
 
-       case VIDIOC_QBUF:
-               return videobuf_qbuf(get_queue(fh), arg);
+       res = get_ressource(fh);
+       err = videobuf_streamoff(get_queue(fh));
+       if (err < 0)
+               return err;
+       res_free(dev,fh,res);
+       return 0;
+}
 
-       case VIDIOC_DQBUF:
-               return videobuf_dqbuf(get_queue(fh), arg,
-                                       file->f_flags & O_NONBLOCK);
+static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *tvnorms)
+{
+       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
 
-       case VIDIOC_STREAMON:
-       {
-               int res = get_ressource(fh);
+       mutex_lock(&core->lock);
+       cx88_set_tvnorm(core,*tvnorms);
+       mutex_unlock(&core->lock);
 
-               if (!res_get(dev,fh,res))
-                       return -EBUSY;
-               return videobuf_streamon(get_queue(fh));
-       }
-       case VIDIOC_STREAMOFF:
-       {
-               int res = get_ressource(fh);
+       return 0;
+}
 
-               err = videobuf_streamoff(get_queue(fh));
-               if (err < 0)
-                       return err;
-               res_free(dev,fh,res);
-               return 0;
-       }
-       default:
-               return cx88_do_ioctl( inode, file, fh->radio, core, cmd, arg, video_do_ioctl );
-       }
+/* only one input in this sample driver */
+int cx88_enum_input (struct cx88_core  *core,struct v4l2_input *i)
+{
+       static const char *iname[] = {
+               [ CX88_VMUX_COMPOSITE1 ] = "Composite1",
+               [ CX88_VMUX_COMPOSITE2 ] = "Composite2",
+               [ CX88_VMUX_COMPOSITE3 ] = "Composite3",
+               [ CX88_VMUX_COMPOSITE4 ] = "Composite4",
+               [ CX88_VMUX_SVIDEO     ] = "S-Video",
+               [ CX88_VMUX_TELEVISION ] = "Television",
+               [ CX88_VMUX_CABLE      ] = "Cable TV",
+               [ CX88_VMUX_DVB        ] = "DVB",
+               [ CX88_VMUX_DEBUG      ] = "for debug only",
+       };
+       unsigned int n;
+
+       n = i->index;
+       if (n >= 4)
+               return -EINVAL;
+       if (0 == INPUT(n)->type)
+               return -EINVAL;
+       memset(i,0,sizeof(*i));
+       i->index = n;
+       i->type  = V4L2_INPUT_TYPE_CAMERA;
+       strcpy(i->name,iname[INPUT(n)->type]);
+       if ((CX88_VMUX_TELEVISION == INPUT(n)->type) ||
+               (CX88_VMUX_CABLE      == INPUT(n)->type))
+               i->type = V4L2_INPUT_TYPE_TUNER;
+               i->std = CX88_NORMS;
        return 0;
 }
+EXPORT_SYMBOL(cx88_enum_input);
 
-int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
-                 struct cx88_core *core, unsigned int cmd, void *arg, v4l2_kioctl driver_ioctl)
+static int vidioc_enum_input (struct file *file, void *priv,
+                               struct v4l2_input *i)
 {
-       int err;
+       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+       return cx88_enum_input (core,i);
+}
 
-       if (video_debug) {
-              if (video_debug > 1) {
-                      if (_IOC_DIR(cmd) & _IOC_WRITE)
-                              v4l_printk_ioctl_arg("cx88(w)",cmd, arg);
-                      else if (!_IOC_DIR(cmd) & _IOC_READ) {
-                              v4l_print_ioctl("cx88", cmd);
-                      }
-              } else
-                      v4l_print_ioctl(core->name,cmd);
-
-       }
-
-       switch (cmd) {
-       /* ---------- tv norms ---------- */
-       case VIDIOC_ENUMSTD:
-       {
-               struct v4l2_standard *e = arg;
-               unsigned int i;
-
-               i = e->index;
-               if (i >= ARRAY_SIZE(tvnorms))
-                       return -EINVAL;
-               err = v4l2_video_std_construct(e, tvnorms[e->index].id,
-                                              tvnorms[e->index].name);
-               e->index = i;
-               if (err < 0)
-                       return err;
-               return 0;
-       }
-       case VIDIOC_G_STD:
-       {
-               v4l2_std_id *id = arg;
+static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
+{
+       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
 
-               *id = core->tvnorm->id;
-               return 0;
-       }
-       case VIDIOC_S_STD:
-       {
-               v4l2_std_id *id = arg;
-               unsigned int i;
+       *i = core->input;
+       return 0;
+}
 
-               for(i = 0; i < ARRAY_SIZE(tvnorms); i++)
-                       if (*id & tvnorms[i].id)
-                               break;
-               if (i == ARRAY_SIZE(tvnorms))
-                       return -EINVAL;
+static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
+{
+       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
 
-               mutex_lock(&core->lock);
-               cx88_set_tvnorm(core,&tvnorms[i]);
-               mutex_unlock(&core->lock);
-               return 0;
-       }
+       if (i >= 4)
+               return -EINVAL;
 
-       /* ------ input switching ---------- */
-       case VIDIOC_ENUMINPUT:
-       {
-               static const char *iname[] = {
-                       [ CX88_VMUX_COMPOSITE1 ] = "Composite1",
-                       [ CX88_VMUX_COMPOSITE2 ] = "Composite2",
-                       [ CX88_VMUX_COMPOSITE3 ] = "Composite3",
-                       [ CX88_VMUX_COMPOSITE4 ] = "Composite4",
-                       [ CX88_VMUX_SVIDEO     ] = "S-Video",
-                       [ CX88_VMUX_TELEVISION ] = "Television",
-                       [ CX88_VMUX_CABLE      ] = "Cable TV",
-                       [ CX88_VMUX_DVB        ] = "DVB",
-                       [ CX88_VMUX_DEBUG      ] = "for debug only",
-               };
-               struct v4l2_input *i = arg;
-               unsigned int n;
-
-               n = i->index;
-               if (n >= 4)
-                       return -EINVAL;
-               if (0 == INPUT(n)->type)
-                       return -EINVAL;
-               memset(i,0,sizeof(*i));
-               i->index = n;
-               i->type  = V4L2_INPUT_TYPE_CAMERA;
-               strcpy(i->name,iname[INPUT(n)->type]);
-               if ((CX88_VMUX_TELEVISION == INPUT(n)->type) ||
-                   (CX88_VMUX_CABLE      == INPUT(n)->type))
-                       i->type = V4L2_INPUT_TYPE_TUNER;
-               for (n = 0; n < ARRAY_SIZE(tvnorms); n++)
-                       i->std |= tvnorms[n].id;
-               return 0;
-       }
-       case VIDIOC_G_INPUT:
-       {
-               unsigned int *i = arg;
+       mutex_lock(&core->lock);
+       cx88_newstation(core);
+       cx88_video_mux(core,i);
+       mutex_unlock(&core->lock);
+       return 0;
+}
 
-               *i = core->input;
-               return 0;
-       }
-       case VIDIOC_S_INPUT:
-       {
-               unsigned int *i = arg;
 
-               if (*i >= 4)
-                       return -EINVAL;
-               mutex_lock(&core->lock);
-               cx88_newstation(core);
-               video_mux(core,*i);
-               mutex_unlock(&core->lock);
-               return 0;
-       }
 
+static int vidioc_queryctrl (struct file *file, void *priv,
+                               struct v4l2_queryctrl *qctrl)
+{
+       qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
+       if (unlikely(qctrl->id == 0))
+               return -EINVAL;
+       return cx8800_ctrl_query(qctrl);
+}
 
+static int vidioc_g_ctrl (struct file *file, void *priv,
+                               struct v4l2_control *ctl)
+{
+       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+       return
+               cx88_get_control(core,ctl);
+}
 
-       /* --- controls ---------------------------------------------- */
-       case VIDIOC_QUERYCTRL:
-       {
-               struct v4l2_queryctrl *c = arg;
+static int vidioc_s_ctrl (struct file *file, void *priv,
+                               struct v4l2_control *ctl)
+{
+       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+       return
+               cx88_set_control(core,ctl);
+}
 
-               return cx88_queryctrl(c);
-       }
-       case VIDIOC_G_CTRL:
-               return get_control(core,arg);
-       case VIDIOC_S_CTRL:
-               return set_control(core,arg);
+static int vidioc_g_tuner (struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+       u32 reg;
 
-       /* --- tuner ioctls ------------------------------------------ */
-       case VIDIOC_G_TUNER:
-       {
-               struct v4l2_tuner *t = arg;
-               u32 reg;
-
-               if (UNSET == core->tuner_type)
-                       return -EINVAL;
-               if (0 != t->index)
-                       return -EINVAL;
-
-               memset(t,0,sizeof(*t));
-               strcpy(t->name, "Television");
-               t->type       = V4L2_TUNER_ANALOG_TV;
-               t->capability = V4L2_TUNER_CAP_NORM;
-               t->rangehigh  = 0xffffffffUL;
-
-               cx88_get_stereo(core ,t);
-               reg = cx_read(MO_DEVICE_STATUS);
-               t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
-               return 0;
-       }
-       case VIDIOC_S_TUNER:
-       {
-               struct v4l2_tuner *t = arg;
+       if (unlikely(UNSET == core->tuner_type))
+               return -EINVAL;
+       if (0 != t->index)
+               return -EINVAL;
 
-               if (UNSET == core->tuner_type)
-                       return -EINVAL;
-               if (0 != t->index)
-                       return -EINVAL;
-               cx88_set_stereo(core, t->audmode, 1);
-               return 0;
-       }
-       case VIDIOC_G_FREQUENCY:
-       {
-               struct v4l2_frequency *f = arg;
+       strcpy(t->name, "Television");
+       t->type       = V4L2_TUNER_ANALOG_TV;
+       t->capability = V4L2_TUNER_CAP_NORM;
+       t->rangehigh  = 0xffffffffUL;
 
-               memset(f,0,sizeof(*f));
+       cx88_get_stereo(core ,t);
+       reg = cx_read(MO_DEVICE_STATUS);
+       t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
+       return 0;
+}
 
-               if (UNSET == core->tuner_type)
-                       return -EINVAL;
+static int vidioc_s_tuner (struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
 
-               /* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */
-               f->type = radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
-               f->frequency = core->freq;
+       if (UNSET == core->tuner_type)
+               return -EINVAL;
+       if (0 != t->index)
+               return -EINVAL;
 
-               cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f);
+       cx88_set_stereo(core, t->audmode, 1);
+       return 0;
+}
 
-               return 0;
-       }
-       case VIDIOC_S_FREQUENCY:
-       {
-               struct v4l2_frequency *f = arg;
-
-               if (UNSET == core->tuner_type)
-                       return -EINVAL;
-               if (f->tuner != 0)
-                       return -EINVAL;
-               if (0 == radio && f->type != V4L2_TUNER_ANALOG_TV)
-                       return -EINVAL;
-               if (1 == radio && f->type != V4L2_TUNER_RADIO)
-                       return -EINVAL;
-               mutex_lock(&core->lock);
-               core->freq = f->frequency;
-               cx88_newstation(core);
-               cx88_call_i2c_clients(core,VIDIOC_S_FREQUENCY,f);
-
-               /* When changing channels it is required to reset TVAUDIO */
-               msleep (10);
-               cx88_set_tvaudio(core);
+static int vidioc_g_frequency (struct file *file, void *priv,
+                               struct v4l2_frequency *f)
+{
+       struct cx8800_fh  *fh   = priv;
+       struct cx88_core  *core = fh->dev->core;
 
-               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 (unlikely(UNSET == core->tuner_type))
+               return -EINVAL;
 
-               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;
+       /* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */
+       f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+       f->frequency = core->freq;
 
-               if (reg->i2c_id != 0)
-                       return -EINVAL;
-               if (!capable(CAP_SYS_ADMIN))
-                       return -EPERM;
-               cx_write(reg->reg&0xffffff, reg->val);
-               return 0;
-       }
-#endif
+       cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f);
 
-       default:
-               return v4l_compat_translate_ioctl(inode,file,cmd,arg,
-                                                 driver_ioctl);
-       }
        return 0;
 }
 
-static int video_ioctl(struct inode *inode, struct file *file,
-                      unsigned int cmd, unsigned long arg)
+int cx88_set_freq (struct cx88_core  *core,
+                               struct v4l2_frequency *f)
 {
-       int retval;
+       if (unlikely(UNSET == core->tuner_type))
+               return -EINVAL;
+       if (unlikely(f->tuner != 0))
+               return -EINVAL;
 
-       retval=video_usercopy(inode, file, cmd, arg, video_do_ioctl);
+       mutex_lock(&core->lock);
+       core->freq = f->frequency;
+       cx88_newstation(core);
+       cx88_call_i2c_clients(core,VIDIOC_S_FREQUENCY,f);
+
+       /* When changing channels it is required to reset TVAUDIO */
+       msleep (10);
+       cx88_set_tvaudio(core);
 
-       if (video_debug > 1) {
-              if (retval < 0) {
-                      v4l_print_ioctl("cx88(err)", cmd);
-                      printk(KERN_DEBUG "cx88(err): errcode=%d\n",retval);
-              } else if (_IOC_DIR(cmd) & _IOC_READ)
-                      v4l_printk_ioctl_arg("cx88(r)",cmd, (void *)arg);
-       }
+       mutex_unlock(&core->lock);
+
+       return 0;
+}
+EXPORT_SYMBOL(cx88_set_freq);
+
+static int vidioc_s_frequency (struct file *file, void *priv,
+                               struct v4l2_frequency *f)
+{
+       struct cx8800_fh  *fh   = priv;
+       struct cx88_core  *core = fh->dev->core;
 
-       return retval;
+       if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV))
+               return -EINVAL;
+       if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO))
+               return -EINVAL;
+
+       return
+               cx88_set_freq (core,f);
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int vidioc_g_register (struct file *file, void *fh,
+                               struct v4l2_register *reg)
+{
+       struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
+
+       if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+               return -EINVAL;
+       /* cx2388x has a 24-bit register space */
+       reg->val = cx_read(reg->reg&0xffffff);
+       return 0;
 }
 
+static int vidioc_s_register (struct file *file, void *fh,
+                               struct v4l2_register *reg)
+{
+       struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
+
+       if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+               return -EINVAL;
+       cx_write(reg->reg&0xffffff, reg->val);
+       return 0;
+}
+#endif
+
+/* ----------------------------------------------------------- */
+/* RADIO ESPECIFIC IOCTLS                                      */
 /* ----------------------------------------------------------- */
 
-static int radio_do_ioctl(struct inode *inode, struct file *file,
-                       unsigned int cmd, void *arg)
+static int radio_querycap (struct file *file, void  *priv,
+                                       struct v4l2_capability *cap)
 {
-       struct cx8800_fh *fh    = file->private_data;
-       struct cx8800_dev *dev  = fh->dev;
+       struct cx8800_dev *dev  = ((struct cx8800_fh *)priv)->dev;
        struct cx88_core  *core = dev->core;
 
-       if (video_debug > 1)
-               v4l_print_ioctl(core->name,cmd);
-
-       switch (cmd) {
-       case VIDIOC_QUERYCAP:
-       {
-               struct v4l2_capability *cap = arg;
-
-               memset(cap,0,sizeof(*cap));
-               strcpy(cap->driver, "cx8800");
-               strlcpy(cap->card, cx88_boards[core->board].name,
-                       sizeof(cap->card));
-               sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci));
-               cap->version = CX88_VERSION_CODE;
-               cap->capabilities = V4L2_CAP_TUNER;
-               return 0;
-       }
-       case VIDIOC_G_TUNER:
-       {
-               struct v4l2_tuner *t = arg;
+       strcpy(cap->driver, "cx8800");
+       strlcpy(cap->card, cx88_boards[core->board].name,
+               sizeof(cap->card));
+       sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci));
+       cap->version = CX88_VERSION_CODE;
+       cap->capabilities = V4L2_CAP_TUNER;
+       return 0;
+}
 
-               if (t->index > 0)
-                       return -EINVAL;
+static int radio_g_tuner (struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
 
-               memset(t,0,sizeof(*t));
-               strcpy(t->name, "Radio");
-               t->type = V4L2_TUNER_RADIO;
+       if (unlikely(t->index > 0))
+               return -EINVAL;
 
-               cx88_call_i2c_clients(core,VIDIOC_G_TUNER,t);
-               return 0;
-       }
-       case VIDIOC_ENUMINPUT:
-       {
-               struct v4l2_input *i = arg;
+       strcpy(t->name, "Radio");
+       t->type = V4L2_TUNER_RADIO;
 
-               if (i->index != 0)
-                       return -EINVAL;
-               strcpy(i->name,"Radio");
-               i->type = V4L2_INPUT_TYPE_TUNER;
-               return 0;
-       }
-       case VIDIOC_G_INPUT:
-       {
-               int *i = arg;
-               *i = 0;
-               return 0;
-       }
-       case VIDIOC_G_AUDIO:
-       {
-               struct v4l2_audio *a = arg;
+       cx88_call_i2c_clients(core,VIDIOC_G_TUNER,t);
+       return 0;
+}
 
-               memset(a,0,sizeof(*a));
-               strcpy(a->name,"Radio");
-               return 0;
-       }
-       case VIDIOC_G_STD:
-       {
-               v4l2_std_id *id = arg;
-               *id = 0;
-               return 0;
-       }
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-       case VIDIOCSTUNER:
-       {
-               struct video_tuner *v = arg;
+static int radio_enum_input (struct file *file, void *priv,
+                               struct v4l2_input *i)
+{
+       if (i->index != 0)
+               return -EINVAL;
+       strcpy(i->name,"Radio");
+       i->type = V4L2_INPUT_TYPE_TUNER;
 
-               if (v->tuner) /* Only tuner 0 */
-                       return -EINVAL;
+       return 0;
+}
 
-               cx88_call_i2c_clients(core,VIDIOCSTUNER,v);
-               return 0;
-       }
-#endif
-       case VIDIOC_S_TUNER:
-       {
-               struct v4l2_tuner *t = arg;
+static int radio_g_audio (struct file *file, void *priv, struct v4l2_audio *a)
+{
+       if (unlikely(a->index))
+               return -EINVAL;
 
-               if (0 != t->index)
-                       return -EINVAL;
+       memset(a,0,sizeof(*a));
+       strcpy(a->name,"Radio");
+       return 0;
+}
 
-               cx88_call_i2c_clients(core,VIDIOC_S_TUNER,t);
+/* FIXME: Should add a standard for radio */
 
-               return 0;
-       }
+static int radio_s_tuner (struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
 
-       case VIDIOC_S_AUDIO:
-       case VIDIOC_S_INPUT:
-       case VIDIOC_S_STD:
-               return 0;
+       if (0 != t->index)
+               return -EINVAL;
 
-       case VIDIOC_QUERYCTRL:
-       {
-               struct v4l2_queryctrl *c = arg;
-               int i;
-
-               if (c->id <  V4L2_CID_BASE ||
-                   c->id >= V4L2_CID_LASTP1)
-                       return -EINVAL;
-               if (c->id == V4L2_CID_AUDIO_MUTE) {
-                       for (i = 0; i < CX8800_CTLS; i++)
-                               if (cx8800_ctls[i].v.id == c->id)
-                                       break;
-                       *c = cx8800_ctls[i].v;
-               } else
-                       *c = no_ctl;
-               return 0;
-       }
+       cx88_call_i2c_clients(core,VIDIOC_S_TUNER,t);
 
+       return 0;
+}
 
-       case VIDIOC_G_CTRL:
-       case VIDIOC_S_CTRL:
-       case VIDIOC_G_FREQUENCY:
-       case VIDIOC_S_FREQUENCY:
-               return video_do_ioctl(inode,file,cmd,arg);
+static int radio_s_audio (struct file *file, void *fh,
+                         struct v4l2_audio *a)
+{
+       return 0;
+}
 
-       default:
-               return v4l_compat_translate_ioctl(inode,file,cmd,arg,
-                                                 radio_do_ioctl);
-       }
+static int radio_s_input (struct file *file, void *fh, unsigned int i)
+{
        return 0;
-};
+}
 
-static int radio_ioctl(struct inode *inode, struct file *file,
-                       unsigned int cmd, unsigned long arg)
+static int radio_queryctrl (struct file *file, void *priv,
+                           struct v4l2_queryctrl *c)
 {
-       return video_usercopy(inode, file, cmd, arg, radio_do_ioctl);
-};
+       int i;
+
+       if (c->id <  V4L2_CID_BASE ||
+               c->id >= V4L2_CID_LASTP1)
+               return -EINVAL;
+       if (c->id == V4L2_CID_AUDIO_MUTE) {
+               for (i = 0; i < CX8800_CTLS; i++)
+                       if (cx8800_ctls[i].v.id == c->id)
+                               break;
+               *c = cx8800_ctls[i].v;
+       } else
+               *c = no_ctl;
+       return 0;
+}
 
 /* ----------------------------------------------------------- */
 
@@ -1816,27 +1638,52 @@ static const struct file_operations video_fops =
        .read          = video_read,
        .poll          = video_poll,
        .mmap          = video_mmap,
-       .ioctl         = video_ioctl,
+       .ioctl         = video_ioctl2,
        .compat_ioctl  = v4l_compat_ioctl32,
        .llseek        = no_llseek,
 };
 
+static struct video_device cx8800_vbi_template;
 static struct video_device cx8800_video_template =
 {
-       .name          = "cx8800-video",
-       .type          = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES,
-       .hardware      = 0,
-       .fops          = &video_fops,
-       .minor         = -1,
-};
-
-static struct video_device cx8800_vbi_template =
-{
-       .name          = "cx8800-vbi",
-       .type          = VID_TYPE_TELETEXT|VID_TYPE_TUNER,
-       .hardware      = 0,
-       .fops          = &video_fops,
-       .minor         = -1,
+       .name                 = "cx8800-video",
+       .type                 = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES,
+       .fops                 = &video_fops,
+       .minor                = -1,
+       .vidioc_querycap      = vidioc_querycap,
+       .vidioc_enum_fmt_cap  = vidioc_enum_fmt_cap,
+       .vidioc_g_fmt_cap     = vidioc_g_fmt_cap,
+       .vidioc_try_fmt_cap   = vidioc_try_fmt_cap,
+       .vidioc_s_fmt_cap     = vidioc_s_fmt_cap,
+       .vidioc_g_fmt_vbi     = cx8800_vbi_fmt,
+       .vidioc_try_fmt_vbi   = cx8800_vbi_fmt,
+       .vidioc_s_fmt_vbi     = cx8800_vbi_fmt,
+       .vidioc_reqbufs       = vidioc_reqbufs,
+       .vidioc_querybuf      = vidioc_querybuf,
+       .vidioc_qbuf          = vidioc_qbuf,
+       .vidioc_dqbuf         = vidioc_dqbuf,
+       .vidioc_s_std         = vidioc_s_std,
+       .vidioc_enum_input    = vidioc_enum_input,
+       .vidioc_g_input       = vidioc_g_input,
+       .vidioc_s_input       = vidioc_s_input,
+       .vidioc_queryctrl     = vidioc_queryctrl,
+       .vidioc_g_ctrl        = vidioc_g_ctrl,
+       .vidioc_s_ctrl        = vidioc_s_ctrl,
+       .vidioc_streamon      = vidioc_streamon,
+       .vidioc_streamoff     = vidioc_streamoff,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+       .vidiocgmbuf          = vidiocgmbuf,
+#endif
+       .vidioc_g_tuner       = vidioc_g_tuner,
+       .vidioc_s_tuner       = vidioc_s_tuner,
+       .vidioc_g_frequency   = vidioc_g_frequency,
+       .vidioc_s_frequency   = vidioc_s_frequency,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register    = vidioc_g_register,
+       .vidioc_s_register    = vidioc_s_register,
+#endif
+       .tvnorms              = CX88_NORMS,
+       .current_norm         = V4L2_STD_NTSC_M,
 };
 
 static const struct file_operations radio_fops =
@@ -1844,18 +1691,30 @@ static const struct file_operations radio_fops =
        .owner         = THIS_MODULE,
        .open          = video_open,
        .release       = video_release,
-       .ioctl         = radio_ioctl,
+       .ioctl         = video_ioctl2,
        .compat_ioctl  = v4l_compat_ioctl32,
        .llseek        = no_llseek,
 };
 
 static struct video_device cx8800_radio_template =
 {
-       .name          = "cx8800-radio",
-       .type          = VID_TYPE_TUNER,
-       .hardware      = 0,
-       .fops          = &radio_fops,
-       .minor         = -1,
+       .name                 = "cx8800-radio",
+       .type                 = VID_TYPE_TUNER,
+       .hardware             = 0,
+       .fops                 = &radio_fops,
+       .minor                = -1,
+       .vidioc_querycap      = radio_querycap,
+       .vidioc_g_tuner       = radio_g_tuner,
+       .vidioc_enum_input    = radio_enum_input,
+       .vidioc_g_audio       = radio_g_audio,
+       .vidioc_s_tuner       = radio_s_tuner,
+       .vidioc_s_audio       = radio_s_audio,
+       .vidioc_s_input       = radio_s_input,
+       .vidioc_queryctrl     = radio_queryctrl,
+       .vidioc_g_ctrl        = vidioc_g_ctrl,
+       .vidioc_s_ctrl        = vidioc_s_ctrl,
+       .vidioc_g_frequency   = vidioc_g_frequency,
+       .vidioc_s_frequency   = vidioc_s_frequency,
 };
 
 /* ----------------------------------------------------------- */
@@ -1890,6 +1749,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
 {
        struct cx8800_dev *dev;
        struct cx88_core *core;
+
        int err;
 
        dev = kzalloc(sizeof(*dev),GFP_KERNEL);
@@ -1924,9 +1784,15 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
                goto fail_core;
        }
 
+       /* Initialize VBI template */
+       memcpy( &cx8800_vbi_template, &cx8800_video_template,
+               sizeof(cx8800_vbi_template) );
+       strcpy(cx8800_vbi_template.name,"cx8800-vbi");
+       cx8800_vbi_template.type = VID_TYPE_TELETEXT|VID_TYPE_TUNER;
+
        /* initialize driver struct */
        spin_lock_init(&dev->slock);
-       core->tvnorm = tvnorms;
+       core->tvnorm = cx8800_video_template.current_norm;
 
        /* init video dma queues */
        INIT_LIST_HEAD(&dev->vidq.active);
@@ -2007,9 +1873,9 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
 
        /* initial device configuration */
        mutex_lock(&core->lock);
-       cx88_set_tvnorm(core,tvnorms);
+       cx88_set_tvnorm(core,core->tvnorm);
        init_controls(core);
-       video_mux(core,0);
+       cx88_video_mux(core,0);
        mutex_unlock(&core->lock);
 
        /* start tvaudio thread */
@@ -2178,8 +2044,6 @@ static void cx8800_fini(void)
 module_init(cx8800_init);
 module_exit(cx8800_fini);
 
-EXPORT_SYMBOL(cx88_do_ioctl);
-
 /* ----------------------------------------------------------- */
 /*
  * Local variables:
index a9575ad8ca27b2b0127e140d6d5d8b00a325495d..a4f7befda5b01688f4f90a737d4de0b3eb0d7856 100644 (file)
@@ -31,7 +31,9 @@
 #include <media/video-buf.h>
 #include <media/cx2341x.h>
 #include <media/audiochip.h>
+#if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE)
 #include <media/video-buf-dvb.h>
+#endif
 
 #include "btcx-risc.h"
 #include "cx88-reg.h"
 /* ----------------------------------------------------------- */
 /* defines and enums                                           */
 
+/* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */
+#define CX88_NORMS (\
+       V4L2_STD_NTSC_M|  V4L2_STD_NTSC_M_JP|  V4L2_STD_NTSC_443 | \
+       V4L2_STD_PAL_BG|  V4L2_STD_PAL_DK   |  V4L2_STD_PAL_I    | \
+       V4L2_STD_PAL_M |  V4L2_STD_PAL_N    |  V4L2_STD_PAL_Nc   | \
+       V4L2_STD_PAL_60|  V4L2_STD_SECAM_L  |  V4L2_STD_SECAM_DK )
+
 #define FORMAT_FLAGS_PACKED       0x01
 #define FORMAT_FLAGS_PLANAR       0x02
 
@@ -82,22 +91,15 @@ enum cx8802_board_access {
 /* ----------------------------------------------------------- */
 /* tv norms                                                    */
 
-struct cx88_tvnorm {
-       char                   *name;
-       v4l2_std_id            id;
-       u32                    cxiformat;
-       u32                    cxoformat;
-};
-
-static unsigned int inline norm_maxw(struct cx88_tvnorm *norm)
+static unsigned int inline norm_maxw(v4l2_std_id norm)
 {
-       return (norm->id & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768;
+       return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768;
 }
 
 
-static unsigned int inline norm_maxh(struct cx88_tvnorm *norm)
+static unsigned int inline norm_maxh(v4l2_std_id norm)
 {
-       return (norm->id & V4L2_STD_625_50) ? 576 : 480;
+       return (norm & V4L2_STD_625_50) ? 576 : 480;
 }
 
 /* ----------------------------------------------------------- */
@@ -313,13 +315,15 @@ struct cx88_core {
        unsigned int               tuner_formats;
 
        /* config info -- dvb */
+#if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE)
        struct dvb_pll_desc        *pll_desc;
        unsigned int               pll_addr;
        int                        (*prev_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
+#endif
 
        /* state info */
        struct task_struct         *kthread;
-       struct cx88_tvnorm         *tvnorm;
+       v4l2_std_id                tvnorm;
        u32                        tvaudio;
        u32                        audiomode_manual;
        u32                        audiomode_current;
@@ -459,13 +463,16 @@ struct cx8802_dev {
        u32                        mailbox;
        int                        width;
        int                        height;
+       int                        fw_size;
 
+#if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE)
        /* for dvb only */
        struct videobuf_dvb        dvb;
        void*                      fe_handle;
        int                        (*fe_release)(void *handle);
 
        void                       *card_priv;
+#endif
        /* for switching modulation types */
        unsigned char              ts_gen_cntrl;
 
@@ -536,7 +543,7 @@ extern void cx88_sram_channel_dump(struct cx88_core *core,
 
 extern int cx88_set_scale(struct cx88_core *core, unsigned int width,
                          unsigned int height, enum v4l2_field field);
-extern int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm);
+extern int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm);
 
 extern struct video_device *cx88_vdev_init(struct cx88_core *core,
                                           struct pci_dev *pci,
@@ -553,7 +560,10 @@ extern int cx88_stop_audio_dma(struct cx88_core *core);
 /* ----------------------------------------------------------- */
 /* cx88-vbi.c                                                  */
 
-void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f);
+/* Can be used as g_vbi_fmt, try_vbi_fmt and s_vbi_fmt */
+int cx8800_vbi_fmt (struct file *file, void *priv,
+                                       struct v4l2_format *f);
+
 /*
 int cx8800_start_vbi_dma(struct cx8800_dev    *dev,
                         struct cx88_dmaqueue *q,
@@ -633,19 +643,14 @@ int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state);
 int cx8802_resume_common(struct pci_dev *pci_dev);
 
 /* ----------------------------------------------------------- */
-/* cx88-video.c                                                */
-extern int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
-                               struct cx88_core *core, unsigned int cmd,
-                               void *arg, v4l2_kioctl driver_ioctl);
+/* cx88-video.c*/
 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);
+int cx88_enum_input (struct cx88_core  *core,struct v4l2_input *i);
+int cx88_set_freq (struct cx88_core  *core,struct v4l2_frequency *f);
+int cx88_get_control(struct cx88_core *core, struct v4l2_control *ctl);
+int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl);
+int cx88_video_mux(struct cx88_core *core, unsigned int input);
 
 /*
  * Local variables:
index 2e5ca40324891444b95fed48a0c3a5711533dad2..262f98e124099ad381db8c461ab8b1527c156e88 100644 (file)
@@ -171,10 +171,7 @@ struct et61x251_device {
 struct et61x251_device*
 et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id)
 {
-       if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id))
-               return cam;
-
-       return NULL;
+       return usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id) ? cam : NULL;
 }
 
 
index 49792ae8c61c15253b291a0d63e3058e1e3f936f..a6525513cd1e12492248ade25f8274949003cfd8 100644 (file)
@@ -1,7 +1,7 @@
 /***************************************************************************
  * V4L2 driver for ET61X[12]51 PC Camera Controllers                       *
  *                                                                         *
- * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -48,8 +48,8 @@
 #define ET61X251_MODULE_AUTHOR  "(C) 2006 Luca Risolia"
 #define ET61X251_AUTHOR_EMAIL   "<luca.risolia@studio.unibo.it>"
 #define ET61X251_MODULE_LICENSE "GPL"
-#define ET61X251_MODULE_VERSION "1:1.02"
-#define ET61X251_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 2)
+#define ET61X251_MODULE_VERSION "1:1.04"
+#define ET61X251_MODULE_VERSION_CODE  KERNEL_VERSION(1, 1, 4)
 
 /*****************************************************************************/
 
@@ -85,7 +85,7 @@ MODULE_PARM_DESC(force_munmap,
                 "\ndetected camera."
                 "\n 0 = do not force memory unmapping"
                 "\n 1 = force memory unmapping (save memory)"
-                "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
+                "\nDefault value is "__MODULE_STRING(ET61X251_FORCE_MUNMAP)"."
                 "\n");
 
 static unsigned int frame_timeout[] = {[0 ... ET61X251_MAX_DEVICES-1] =
@@ -133,7 +133,8 @@ et61x251_request_buffers(struct et61x251_device* cam, u32 count,
 
        cam->nbuffers = count;
        while (cam->nbuffers > 0) {
-               if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize))))
+               if ((buff = vmalloc_32_user(cam->nbuffers *
+                                           PAGE_ALIGN(imagesize))))
                        break;
                cam->nbuffers--;
        }
@@ -543,10 +544,11 @@ static int et61x251_start_transfer(struct et61x251_device* cam)
 {
        struct usb_device *udev = cam->usbdev;
        struct urb* urb;
-       const unsigned int wMaxPacketSize[] = {0, 256, 384, 512, 640, 768, 832,
-                                              864, 896, 920, 956, 980, 1000,
-                                              1022};
-       const unsigned int psz = wMaxPacketSize[ET61X251_ALTERNATE_SETTING];
+       struct usb_host_interface* altsetting = usb_altnum_to_altsetting(
+                                                  usb_ifnum_to_if(udev, 0),
+                                                  ET61X251_ALTERNATE_SETTING);
+       const unsigned int psz = le16_to_cpu(altsetting->
+                                            endpoint[0].desc.wMaxPacketSize);
        s8 i, j;
        int err = 0;
 
@@ -976,29 +978,31 @@ static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
 static int et61x251_create_sysfs(struct et61x251_device* cam)
 {
        struct video_device *v4ldev = cam->v4ldev;
-       int rc;
+       int err = 0;
+
+       if ((err = video_device_create_file(v4ldev, &class_device_attr_reg)))
+               goto err_out;
+       if ((err = video_device_create_file(v4ldev, &class_device_attr_val)))
+               goto err_reg;
 
-       rc = video_device_create_file(v4ldev, &class_device_attr_reg);
-       if (rc) goto err;
-       rc = video_device_create_file(v4ldev, &class_device_attr_val);
-       if (rc) goto err_reg;
        if (cam->sensor.sysfs_ops) {
-               rc = video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
-               if (rc) goto err_val;
-               rc = video_device_create_file(v4ldev, &class_device_attr_i2c_val);
-               if (rc) goto err_i2c_reg;
+               if ((err = video_device_create_file(v4ldev,
+                                                 &class_device_attr_i2c_reg)))
+                       goto err_val;
+               if ((err = video_device_create_file(v4ldev,
+                                                 &class_device_attr_i2c_val)))
+                       goto err_i2c_reg;
        }
 
-       return 0;
-
 err_i2c_reg:
+       if (cam->sensor.sysfs_ops)
        video_device_remove_file(v4ldev, &class_device_attr_i2c_reg);
 err_val:
        video_device_remove_file(v4ldev, &class_device_attr_val);
 err_reg:
        video_device_remove_file(v4ldev, &class_device_attr_reg);
-err:
-       return rc;
+err_out:
+       return err;
 }
 #endif /* CONFIG_VIDEO_ADV_DEBUG */
 
@@ -1767,10 +1771,10 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg)
        rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L;
        rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L;
 
-       if (rect->width < 4)
-               rect->width = 4;
-       if (rect->height < 4)
-               rect->height = 4;
+       if (rect->width < 16)
+               rect->width = 16;
+       if (rect->height < 16)
+               rect->height = 16;
        if (rect->width > bounds->width)
                rect->width = bounds->width;
        if (rect->height > bounds->height)
@@ -1784,8 +1788,8 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg)
        if (rect->top + rect->height > bounds->top + bounds->height)
                rect->top = bounds->top+bounds->height - rect->height;
 
-       rect->width &= ~3L;
-       rect->height &= ~3L;
+       rect->width &= ~15L;
+       rect->height &= ~15L;
 
        if (ET61X251_PRESERVE_IMGSCALE) {
                /* Calculate the actual scaling factor */
@@ -1845,6 +1849,35 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg)
 }
 
 
+static int
+et61x251_vidioc_enum_framesizes(struct et61x251_device* cam, void __user * arg)
+{
+       struct v4l2_frmsizeenum frmsize;
+
+       if (copy_from_user(&frmsize, arg, sizeof(frmsize)))
+               return -EFAULT;
+
+       if (frmsize.index != 0)
+               return -EINVAL;
+
+       if (frmsize.pixel_format != V4L2_PIX_FMT_ET61X251 &&
+           frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
+               return -EINVAL;
+
+       frmsize.type = V4L2_FRMSIZE_TYPE_STEPWISE;
+       frmsize.stepwise.min_width = frmsize.stepwise.step_width = 16;
+       frmsize.stepwise.min_height = frmsize.stepwise.step_height = 16;
+       frmsize.stepwise.max_width = cam->sensor.cropcap.bounds.width;
+       frmsize.stepwise.max_height = cam->sensor.cropcap.bounds.height;
+       memset(&frmsize.reserved, 0, sizeof(frmsize.reserved));
+
+       if (copy_to_user(arg, &frmsize, sizeof(frmsize)))
+               return -EFAULT;
+
+       return 0;
+}
+
+
 static int
 et61x251_vidioc_enum_fmt(struct et61x251_device* cam, void __user * arg)
 {
@@ -1853,6 +1886,9 @@ et61x251_vidioc_enum_fmt(struct et61x251_device* cam, void __user * arg)
        if (copy_from_user(&fmtd, arg, sizeof(fmtd)))
                return -EFAULT;
 
+       if (fmtd.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
        if (fmtd.index == 0) {
                strcpy(fmtd.description, "bayer rgb");
                fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8;
@@ -1934,17 +1970,17 @@ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd,
        rect.width = scale * pix->width;
        rect.height = scale * pix->height;
 
-       if (rect.width < 4)
-               rect.width = 4;
-       if (rect.height < 4)
-               rect.height = 4;
+       if (rect.width < 16)
+               rect.width = 16;
+       if (rect.height < 16)
+               rect.height = 16;
        if (rect.width > bounds->left + bounds->width - rect.left)
                rect.width = bounds->left + bounds->width - rect.left;
        if (rect.height > bounds->top + bounds->height - rect.top)
                rect.height = bounds->top + bounds->height - rect.top;
 
-       rect.width &= ~3L;
-       rect.height &= ~3L;
+       rect.width &= ~15L;
+       rect.height &= ~15L;
 
        { /* adjust the scaling factor */
                u32 a, b;
@@ -2378,6 +2414,9 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp,
        case VIDIOC_S_FMT:
                return et61x251_vidioc_try_s_fmt(cam, cmd, arg);
 
+       case VIDIOC_ENUM_FRAMESIZES:
+               return et61x251_vidioc_enum_framesizes(cam, arg);
+
        case VIDIOC_G_JPEGCOMP:
                return et61x251_vidioc_g_jpegcomp(cam, arg);
 
@@ -2413,6 +2452,7 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp,
        case VIDIOC_QUERYSTD:
        case VIDIOC_ENUMSTD:
        case VIDIOC_QUERYMENU:
+       case VIDIOC_ENUM_FRAMEINTERVALS:
                return -EINVAL;
 
        default:
@@ -2459,6 +2499,7 @@ static const struct file_operations et61x251_fops = {
        .open =    et61x251_open,
        .release = et61x251_release,
        .ioctl =   et61x251_ioctl,
+       .compat_ioctl = v4l_compat_ioctl32,
        .read =    et61x251_read,
        .poll =    et61x251_poll,
        .mmap =    et61x251_mmap,
@@ -2497,7 +2538,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
        mutex_init(&cam->dev_mutex);
 
        DBG(2, "ET61X[12]51 PC Camera Controller detected "
-              "(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct);
+              "(vid/pid 0x%04X:0x%04X)",id->idVendor, id->idProduct);
 
        for  (i = 0; et61x251_sensor_table[i]; i++) {
                err = et61x251_sensor_table[i](cam);
@@ -2550,9 +2591,14 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        err = et61x251_create_sysfs(cam);
-       if (err)
-               goto fail2;
-       DBG(2, "Optional device control through 'sysfs' interface ready");
+       if (!err)
+               DBG(2, "Optional device control through 'sysfs' "
+                      "interface ready");
+       else
+               DBG(2, "Failed to create 'sysfs' interface for optional "
+                      "device controlling. Error #%d", err);
+#else
+       DBG(2, "Optional device control through 'sysfs' interface disabled");
 #endif
 
        usb_set_intfdata(intf, cam);
@@ -2561,13 +2607,6 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
 
        return 0;
 
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-fail2:
-       video_nr[dev_nr] = -1;
-       dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0;
-       mutex_unlock(&cam->dev_mutex);
-       video_unregister_device(cam->v4ldev);
-#endif
 fail:
        if (cam) {
                kfree(cam->control_buffer);
index 65edd08dc386bb18cb184037ed1aaa2ba342b8da..5fadb5de68bf65e85d16784b7eb484509bf19247 100644 (file)
@@ -1,7 +1,7 @@
 /***************************************************************************
  * API for image sensors connected to ET61X[12]51 PC Camera Controllers    *
  *                                                                         *
- * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -82,7 +82,7 @@ enum et61x251_i2c_rsta {
        ET61X251_I2C_RSTA_REPEAT = 0x01, /* repeat start */
 };
 
-#define ET61X251_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10
+#define ET61X251_MAX_CTRLS (V4L2_CID_LASTP1-V4L2_CID_BASE+10)
 
 struct et61x251_sensor {
        char name[32];
index a7d65b82b2fbd4c92022118e3f1c15b1af38632c..b066434098426d57859b4f73615a49f4c157cb26 100644 (file)
@@ -2,7 +2,7 @@
  * Plug-in for TAS5130D1B image sensor connected to the ET61X[12]51        *
  * PC Camera Controllers                                                   *
  *                                                                         *
- * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
index 122496f368458f71161743a537c3c1924853660f..379645e481c6ff830cab9e7dcaec13758c8131ec 100644 (file)
@@ -31,7 +31,6 @@ struct pvr2_msp3400_handler {
        struct pvr2_hdw *hdw;
        struct pvr2_i2c_client *client;
        struct pvr2_i2c_handler i2c_handler;
-       struct pvr2_audio_stat astat;
        unsigned long stale_mask;
 };
 
@@ -44,13 +43,6 @@ static void set_stereo(struct pvr2_msp3400_handler *ctxt)
 
        pvr2_trace(PVR2_TRACE_CHIPS,"i2c msp3400 v4l2 set_stereo");
 
-       if (hdw->input_val == PVR2_CVAL_INPUT_TV) {
-               struct v4l2_tuner vt;
-               memset(&vt,0,sizeof(vt));
-               vt.audmode = hdw->audiomode_val;
-               pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_TUNER,&vt);
-       }
-
        route.input = MSP_INPUT_DEFAULT;
        route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
        switch (hdw->input_val) {
@@ -78,8 +70,7 @@ static void set_stereo(struct pvr2_msp3400_handler *ctxt)
 static int check_stereo(struct pvr2_msp3400_handler *ctxt)
 {
        struct pvr2_hdw *hdw = ctxt->hdw;
-       return (hdw->input_dirty ||
-               hdw->audiomode_dirty);
+       return hdw->input_dirty;
 }
 
 
@@ -99,8 +90,7 @@ static int msp3400_check(struct pvr2_msp3400_handler *ctxt)
        unsigned long msk;
        unsigned int idx;
 
-       for (idx = 0; idx < sizeof(msp3400_ops)/sizeof(msp3400_ops[0]);
-            idx++) {
+       for (idx = 0; idx < ARRAY_SIZE(msp3400_ops); idx++) {
                msk = 1 << idx;
                if (ctxt->stale_mask & msk) continue;
                if (msp3400_ops[idx].check(ctxt)) {
@@ -116,8 +106,7 @@ static void msp3400_update(struct pvr2_msp3400_handler *ctxt)
        unsigned long msk;
        unsigned int idx;
 
-       for (idx = 0; idx < sizeof(msp3400_ops)/sizeof(msp3400_ops[0]);
-            idx++) {
+       for (idx = 0; idx < ARRAY_SIZE(msp3400_ops); idx++) {
                msk = 1 << idx;
                if (!(ctxt->stale_mask & msk)) continue;
                ctxt->stale_mask &= ~msk;
@@ -126,27 +115,9 @@ static void msp3400_update(struct pvr2_msp3400_handler *ctxt)
 }
 
 
-/* This reads back the current signal type */
-static int get_audio_status(struct pvr2_msp3400_handler *ctxt)
-{
-       struct v4l2_tuner vt;
-       int stat;
-
-       memset(&vt,0,sizeof(vt));
-       stat = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt);
-       if (stat < 0) return stat;
-
-       ctxt->hdw->flag_stereo = (vt.audmode & V4L2_TUNER_MODE_STEREO) != 0;
-       ctxt->hdw->flag_bilingual =
-               (vt.audmode & V4L2_TUNER_MODE_LANG2) != 0;
-       return 0;
-}
-
-
 static void pvr2_msp3400_detach(struct pvr2_msp3400_handler *ctxt)
 {
        ctxt->client->handler = NULL;
-       ctxt->hdw->audio_stat = NULL;
        kfree(ctxt);
 }
 
@@ -169,24 +140,17 @@ static const struct pvr2_i2c_handler_functions msp3400_funcs = {
 int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
 {
        struct pvr2_msp3400_handler *ctxt;
-       if (hdw->audio_stat) return 0;
        if (cp->handler) return 0;
 
-       ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
+       ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL);
        if (!ctxt) return 0;
-       memset(ctxt,0,sizeof(*ctxt));
 
        ctxt->i2c_handler.func_data = ctxt;
        ctxt->i2c_handler.func_table = &msp3400_funcs;
        ctxt->client = cp;
        ctxt->hdw = hdw;
-       ctxt->astat.ctxt = ctxt;
-       ctxt->astat.status = (int (*)(void *))get_audio_status;
-       ctxt->astat.detach = (void (*)(void *))pvr2_msp3400_detach;
-       ctxt->stale_mask = (1 << (sizeof(msp3400_ops)/
-                                 sizeof(msp3400_ops[0]))) - 1;
+       ctxt->stale_mask = (1 << ARRAY_SIZE(msp3400_ops)) - 1;
        cp->handler = &ctxt->i2c_handler;
-       hdw->audio_stat = &ctxt->astat;
        pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x msp3400 V4L2 handler set up",
                   cp->client->addr);
        return !0;
index cf129746205dbae6e1775cd8fb7d0350b9ea5bcd..6bbed88d7867af00ae9de1cafe2751ec35d56bee 100644 (file)
@@ -83,9 +83,8 @@ struct pvr2_context *pvr2_context_create(
        void (*setup_func)(struct pvr2_context *))
 {
        struct pvr2_context *mp = NULL;
-       mp = kmalloc(sizeof(*mp),GFP_KERNEL);
+       mp = kzalloc(sizeof(*mp),GFP_KERNEL);
        if (!mp) goto done;
-       memset(mp,0,sizeof(*mp));
        pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_main id=%p",mp);
        mp->setup_func = setup_func;
        mutex_init(&mp->mutex);
index c77de859cc8e109989b6ebc0ec55d45c496747f8..f569b00201ddb09924e854cf84f4977795fee729 100644 (file)
 #include <linux/mutex.h>
 
 
+static int pvr2_ctrl_range_check(struct pvr2_ctrl *cptr,int val)
+{
+       if (cptr->info->check_value) {
+               if (!cptr->info->check_value(cptr,val)) return -ERANGE;
+       } else {
+               int lim;
+               lim = cptr->info->def.type_int.min_value;
+               if (cptr->info->get_min_value) {
+                       cptr->info->get_min_value(cptr,&lim);
+               }
+               if (val < lim) return -ERANGE;
+               lim = cptr->info->def.type_int.max_value;
+               if (cptr->info->get_max_value) {
+                       cptr->info->get_max_value(cptr,&lim);
+               }
+               if (val > lim) return -ERANGE;
+       }
+       return 0;
+}
+
+
 /* Set the given control. */
 int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val)
 {
@@ -43,17 +64,8 @@ int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
                        if (cptr->info->type == pvr2_ctl_bitmask) {
                                mask &= cptr->info->def.type_bitmask.valid_bits;
                        } else if (cptr->info->type == pvr2_ctl_int) {
-                               int lim;
-                               lim = cptr->info->def.type_int.min_value;
-                               if (cptr->info->get_min_value) {
-                                       cptr->info->get_min_value(cptr,&lim);
-                               }
-                               if (val < lim) break;
-                               lim = cptr->info->def.type_int.max_value;
-                               if (cptr->info->get_max_value) {
-                                       cptr->info->get_max_value(cptr,&lim);
-                               }
-                               if (val > lim) break;
+                               ret = pvr2_ctrl_range_check(cptr,val);
+                               if (ret < 0) break;
                        } else if (cptr->info->type == pvr2_ctl_enum) {
                                if (val >= cptr->info->def.type_enum.count) {
                                        break;
@@ -498,16 +510,13 @@ int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
        LOCK_TAKE(cptr->hdw->big_lock); do {
                if (cptr->info->type == pvr2_ctl_int) {
                        ret = parse_token(ptr,len,valptr,NULL,0);
-                       if ((ret >= 0) &&
-                           ((*valptr < cptr->info->def.type_int.min_value) ||
-                            (*valptr > cptr->info->def.type_int.max_value))) {
-                               ret = -ERANGE;
+                       if (ret >= 0) {
+                               ret = pvr2_ctrl_range_check(cptr,*valptr);
                        }
                        if (maskptr) *maskptr = ~0;
                } else if (cptr->info->type == pvr2_ctl_bool) {
-                       ret = parse_token(
-                               ptr,len,valptr,boolNames,
-                               sizeof(boolNames)/sizeof(boolNames[0]));
+                       ret = parse_token(ptr,len,valptr,boolNames,
+                                         ARRAY_SIZE(boolNames));
                        if (ret == 1) {
                                *valptr = *valptr ? !0 : 0;
                        } else if (ret == 0) {
index 8df969c4874c7a7dcddd8b5232ccf87f0a84115e..e8a9252c7df6a2250cb301f7c8f792fd50527c5f 100644 (file)
@@ -63,6 +63,7 @@ static void set_input(struct pvr2_v4l_cx2584x *ctxt)
                vid_input = CX25840_COMPOSITE7;
                aud_input = CX25840_AUDIO8;
                break;
+       case PVR2_CVAL_INPUT_RADIO: // Treat same as composite
        case PVR2_CVAL_INPUT_COMPOSITE:
                vid_input = CX25840_COMPOSITE3;
                aud_input = CX25840_AUDIO_SERIAL;
@@ -71,7 +72,6 @@ static void set_input(struct pvr2_v4l_cx2584x *ctxt)
                vid_input = CX25840_SVIDEO1;
                aud_input = CX25840_AUDIO_SERIAL;
                break;
-       case PVR2_CVAL_INPUT_RADIO:
        default:
                // Just set it to be composite input for now...
                vid_input = CX25840_COMPOSITE3;
@@ -150,8 +150,7 @@ static int decoder_check(struct pvr2_v4l_cx2584x *ctxt)
        unsigned long msk;
        unsigned int idx;
 
-       for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]);
-            idx++) {
+       for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) {
                msk = 1 << idx;
                if (ctxt->stale_mask & msk) continue;
                if (decoder_ops[idx].check(ctxt)) {
@@ -167,8 +166,7 @@ static void decoder_update(struct pvr2_v4l_cx2584x *ctxt)
        unsigned long msk;
        unsigned int idx;
 
-       for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]);
-            idx++) {
+       for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) {
                msk = 1 << idx;
                if (!(ctxt->stale_mask & msk)) continue;
                ctxt->stale_mask &= ~msk;
@@ -199,18 +197,6 @@ static int decoder_detect(struct pvr2_i2c_client *cp)
 }
 
 
-static int decoder_is_tuned(struct pvr2_v4l_cx2584x *ctxt)
-{
-       struct v4l2_tuner vt;
-       int ret;
-
-       memset(&vt,0,sizeof(vt));
-       ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt);
-       if (ret < 0) return -EINVAL;
-       return vt.signal ? 1 : 0;
-}
-
-
 static unsigned int decoder_describe(struct pvr2_v4l_cx2584x *ctxt,
                                     char *buf,unsigned int cnt)
 {
@@ -243,21 +229,18 @@ int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw,
        if (cp->handler) return 0;
        if (!decoder_detect(cp)) return 0;
 
-       ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
+       ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL);
        if (!ctxt) return 0;
-       memset(ctxt,0,sizeof(*ctxt));
 
        ctxt->handler.func_data = ctxt;
        ctxt->handler.func_table = &hfuncs;
        ctxt->ctrl.ctxt = ctxt;
        ctxt->ctrl.detach = (void (*)(void *))decoder_detach;
        ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable;
-       ctxt->ctrl.tuned = (int (*)(void *))decoder_is_tuned;
        ctxt->ctrl.force_reset = (void (*)(void*))decoder_reset;
        ctxt->client = cp;
        ctxt->hdw = hdw;
-       ctxt->stale_mask = (1 << (sizeof(decoder_ops)/
-                                 sizeof(decoder_ops[0]))) - 1;
+       ctxt->stale_mask = (1 << ARRAY_SIZE(decoder_ops)) - 1;
        hdw->decoder_ctrl = &ctxt->ctrl;
        cp->handler = &ctxt->handler;
        {
index f985f00d885ad5914e80d16be6a5fd60252b287a..e9da9bb8f8dea1f8901b1428c48b2cc1ce95c8cc 100644 (file)
@@ -152,7 +152,7 @@ static unsigned long debugifc_find_mask(const char *buf,unsigned int count)
 {
        struct debugifc_mask_item *mip;
        unsigned int idx;
-       for (idx = 0; idx < sizeof(mask_items)/sizeof(mask_items[0]); idx++) {
+       for (idx = 0; idx < ARRAY_SIZE(mask_items); idx++) {
                mip = mask_items + idx;
                if (debugifc_match_keyword(buf,count,mip->name)) {
                        return mip->msk;
@@ -169,7 +169,7 @@ static int debugifc_print_mask(char *buf,unsigned int sz,
        unsigned int idx;
        int bcnt = 0;
        int ccnt;
-       for (idx = 0; idx < sizeof(mask_items)/sizeof(mask_items[0]); idx++) {
+       for (idx = 0; idx < ARRAY_SIZE(mask_items); idx++) {
                mip = mask_items + idx;
                if (!(mip->msk & msk)) continue;
                ccnt = scnprintf(buf,sz,"%s%c%s",
index 6cff8e75f4264bde5e471a02836c80b4ce2f0cae..45cbca0143ca7a62ad4fe7356cb04e87e94f97d1 100644 (file)
@@ -102,9 +102,8 @@ static u8 *pvr2_eeprom_fetch(struct pvr2_hdw *hdw)
                }
                msg[1].len = pcnt;
                msg[1].buf = eeprom+tcnt;
-               if ((ret = i2c_transfer(
-                            &hdw->i2c_adap,
-                            msg,sizeof(msg)/sizeof(msg[0]))) != 2) {
+               if ((ret = i2c_transfer(&hdw->i2c_adap,
+                                       msg,ARRAY_SIZE(msg))) != 2) {
                        pvr2_trace(PVR2_TRACE_ERROR_LEGS,
                                   "eeprom fetch set offs err=%d",ret);
                        kfree(eeprom);
index c94f97b7939246ff0dd61e6ad417f438861a621d..5786faf9b3b862756f1da08bd967f62b6fe1a7ab 100644 (file)
@@ -26,6 +26,7 @@
 #include "pvrusb2-encoder.h"
 #include "pvrusb2-hdw-internal.h"
 #include "pvrusb2-debug.h"
+#include "pvrusb2-fx2-cmd.h"
 
 
 
 #define IVTV_MBOX_DRIVER_DONE 0x00000002
 #define IVTV_MBOX_DRIVER_BUSY 0x00000001
 
+#define MBOX_BASE 0x44
+
 
 static int pvr2_encoder_write_words(struct pvr2_hdw *hdw,
+                                   unsigned int offs,
                                    const u32 *data, unsigned int dlen)
 {
-       unsigned int idx;
+       unsigned int idx,addr;
+       unsigned int bAddr;
        int ret;
-       unsigned int offs = 0;
        unsigned int chunkCnt;
 
        /*
 
        Format: First byte must be 0x01.  Remaining 32 bit words are
-       spread out into chunks of 7 bytes each, little-endian ordered,
-       offset at zero within each 2 blank bytes following and a
-       single byte that is 0x44 plus the offset of the word.  Repeat
-       request for additional words, with offset adjusted
-       accordingly.
+       spread out into chunks of 7 bytes each, with the first 4 bytes
+       being the data word (little endian), and the next 3 bytes
+       being the address where that data word is to be written (big
+       endian).  Repeat request for additional words, with offset
+       adjusted accordingly.
 
        */
        while (dlen) {
                chunkCnt = 8;
                if (chunkCnt > dlen) chunkCnt = dlen;
                memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer));
-               hdw->cmd_buffer[0] = 0x01;
+               bAddr = 0;
+               hdw->cmd_buffer[bAddr++] = FX2CMD_MEM_WRITE_DWORD;
                for (idx = 0; idx < chunkCnt; idx++) {
-                       hdw->cmd_buffer[1+(idx*7)+6] = 0x44 + idx + offs;
-                       PVR2_DECOMPOSE_LE(hdw->cmd_buffer, 1+(idx*7),
-                                         data[idx]);
+                       addr = idx + offs;
+                       hdw->cmd_buffer[bAddr+6] = (addr & 0xffu);
+                       hdw->cmd_buffer[bAddr+5] = ((addr>>8) & 0xffu);
+                       hdw->cmd_buffer[bAddr+4] = ((addr>>16) & 0xffu);
+                       PVR2_DECOMPOSE_LE(hdw->cmd_buffer, bAddr,data[idx]);
+                       bAddr += 7;
                }
                ret = pvr2_send_request(hdw,
                                        hdw->cmd_buffer,1+(chunkCnt*7),
@@ -76,33 +84,42 @@ static int pvr2_encoder_write_words(struct pvr2_hdw *hdw,
 }
 
 
-static int pvr2_encoder_read_words(struct pvr2_hdw *hdw,int statusFl,
+static int pvr2_encoder_read_words(struct pvr2_hdw *hdw,
+                                  unsigned int offs,
                                   u32 *data, unsigned int dlen)
 {
        unsigned int idx;
        int ret;
-       unsigned int offs = 0;
        unsigned int chunkCnt;
 
        /*
 
        Format: First byte must be 0x02 (status check) or 0x28 (read
        back block of 32 bit words).  Next 6 bytes must be zero,
-       followed by a single byte of 0x44+offset for portion to be
-       read.  Returned data is packed set of 32 bits words that were
-       read.
+       followed by a single byte of MBOX_BASE+offset for portion to
+       be read.  Returned data is packed set of 32 bits words that
+       were read.
 
        */
 
        while (dlen) {
                chunkCnt = 16;
                if (chunkCnt > dlen) chunkCnt = dlen;
-               memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer));
-               hdw->cmd_buffer[0] = statusFl ? 0x02 : 0x28;
-               hdw->cmd_buffer[7] = 0x44 + offs;
+               if (chunkCnt < 16) chunkCnt = 1;
+               hdw->cmd_buffer[0] =
+                       ((chunkCnt == 1) ?
+                        FX2CMD_MEM_READ_DWORD : FX2CMD_MEM_READ_64BYTES);
+               hdw->cmd_buffer[1] = 0;
+               hdw->cmd_buffer[2] = 0;
+               hdw->cmd_buffer[3] = 0;
+               hdw->cmd_buffer[4] = 0;
+               hdw->cmd_buffer[5] = ((offs>>16) & 0xffu);
+               hdw->cmd_buffer[6] = ((offs>>8) & 0xffu);
+               hdw->cmd_buffer[7] = (offs & 0xffu);
                ret = pvr2_send_request(hdw,
                                        hdw->cmd_buffer,8,
-                                       hdw->cmd_buffer,chunkCnt * 4);
+                                       hdw->cmd_buffer,
+                                       (chunkCnt == 1 ? 4 : 16 * 4));
                if (ret) return ret;
 
                for (idx = 0; idx < chunkCnt; idx++) {
@@ -129,6 +146,8 @@ static int pvr2_encoder_cmd(void *ctxt,
                            u32 *argp)
 {
        unsigned int poll_count;
+       unsigned int try_count = 0;
+       int retry_flag;
        int ret = 0;
        unsigned int idx;
        /* These sizes look to be limited by the FX2 firmware implementation */
@@ -140,14 +159,15 @@ static int pvr2_encoder_cmd(void *ctxt,
        /*
 
        The encoder seems to speak entirely using blocks 32 bit words.
-       In ivtv driver terms, this is a mailbox which we populate with
-       data and watch what the hardware does with it.  The first word
-       is a set of flags used to control the transaction, the second
-       word is the command to execute, the third byte is zero (ivtv
-       driver suggests that this is some kind of return value), and
-       the fourth byte is a specified timeout (windows driver always
-       uses 0x00060000 except for one case when it is zero).  All
-       successive words are the argument words for the command.
+       In ivtv driver terms, this is a mailbox at MBOX_BASE which we
+       populate with data and watch what the hardware does with it.
+       The first word is a set of flags used to control the
+       transaction, the second word is the command to execute, the
+       third byte is zero (ivtv driver suggests that this is some
+       kind of return value), and the fourth byte is a specified
+       timeout (windows driver always uses 0x00060000 except for one
+       case when it is zero).  All successive words are the argument
+       words for the command.
 
        First, write out the entire set of words, with the first word
        being zero.
@@ -156,44 +176,42 @@ static int pvr2_encoder_cmd(void *ctxt,
        IVTV_MBOX_DRIVER_DONE | IVTV_DRIVER_BUSY this time (which
        probably means "go").
 
-       Next, read back 16 words as status.  Check the first word,
+       Next, read back the return count words.  Check the first word,
        which should have IVTV_MBOX_FIRMWARE_DONE set.  If however
        that bit is not set, then the command isn't done so repeat the
-       read.
-
-       Next, read back 32 words and compare with the original
-       arugments.  Hopefully they will match.
+       read until it is set.
 
        Finally, write out just the first word again, but set it to
        0x0 this time (which probably means "idle").
 
        */
 
-       if (arg_cnt_send > (sizeof(wrData)/sizeof(wrData[0]))-4) {
+       if (arg_cnt_send > (ARRAY_SIZE(wrData) - 4)) {
                pvr2_trace(
                        PVR2_TRACE_ERROR_LEGS,
                        "Failed to write cx23416 command"
                        " - too many input arguments"
-                       " (was given %u limit %u)",
-                       arg_cnt_send,
-                       (unsigned int)(sizeof(wrData)/sizeof(wrData[0])) - 4);
+                       " (was given %u limit %lu)",
+                       arg_cnt_send, (long unsigned) ARRAY_SIZE(wrData) - 4);
                return -EINVAL;
        }
 
-       if (arg_cnt_recv > (sizeof(rdData)/sizeof(rdData[0]))-4) {
+       if (arg_cnt_recv > (ARRAY_SIZE(rdData) - 4)) {
                pvr2_trace(
                        PVR2_TRACE_ERROR_LEGS,
                        "Failed to write cx23416 command"
                        " - too many return arguments"
-                       " (was given %u limit %u)",
-                       arg_cnt_recv,
-                       (unsigned int)(sizeof(rdData)/sizeof(rdData[0])) - 4);
+                       " (was given %u limit %lu)",
+                       arg_cnt_recv, (long unsigned) ARRAY_SIZE(rdData) - 4);
                return -EINVAL;
        }
 
 
        LOCK_TAKE(hdw->ctl_lock); do {
 
+               retry_flag = 0;
+               try_count++;
+               ret = 0;
                wrData[0] = 0;
                wrData[1] = cmd;
                wrData[2] = 0;
@@ -201,59 +219,74 @@ static int pvr2_encoder_cmd(void *ctxt,
                for (idx = 0; idx < arg_cnt_send; idx++) {
                        wrData[idx+4] = argp[idx];
                }
-               for (; idx < (sizeof(wrData)/sizeof(wrData[0]))-4; idx++) {
+               for (; idx < ARRAY_SIZE(wrData) - 4; idx++) {
                        wrData[idx+4] = 0;
                }
 
-               ret = pvr2_encoder_write_words(hdw,wrData,idx);
+               ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,idx);
                if (ret) break;
                wrData[0] = IVTV_MBOX_DRIVER_DONE|IVTV_MBOX_DRIVER_BUSY;
-               ret = pvr2_encoder_write_words(hdw,wrData,1);
+               ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,1);
                if (ret) break;
                poll_count = 0;
                while (1) {
-                       if (poll_count < 10000000) poll_count++;
-                       ret = pvr2_encoder_read_words(hdw,!0,rdData,1);
-                       if (ret) break;
+                       poll_count++;
+                       ret = pvr2_encoder_read_words(hdw,MBOX_BASE,rdData,
+                                                     arg_cnt_recv+4);
+                       if (ret) {
+                               break;
+                       }
                        if (rdData[0] & IVTV_MBOX_FIRMWARE_DONE) {
                                break;
                        }
-                       if (poll_count == 100) {
+                       if (rdData[0] && (poll_count < 1000)) continue;
+                       if (!rdData[0]) {
+                               retry_flag = !0;
                                pvr2_trace(
                                        PVR2_TRACE_ERROR_LEGS,
-                                       "***WARNING*** device's encoder"
-                                       " appears to be stuck"
-                                       " (status=0%08x)",rdData[0]);
+                                       "Encoder timed out waiting for us"
+                                       "; arranging to retry");
+                       } else {
                                pvr2_trace(
                                        PVR2_TRACE_ERROR_LEGS,
-                                       "Encoder command: 0x%02x",cmd);
-                               for (idx = 4; idx < arg_cnt_send; idx++) {
-                                       pvr2_trace(
-                                               PVR2_TRACE_ERROR_LEGS,
-                                               "Encoder arg%d: 0x%08x",
-                                               idx-3,wrData[idx]);
-                               }
+                                       "***WARNING*** device's encoder"
+                                       " appears to be stuck"
+                                       " (status=0x%08x)",rdData[0]);
+                       }
+                       pvr2_trace(
+                               PVR2_TRACE_ERROR_LEGS,
+                               "Encoder command: 0x%02x",cmd);
+                       for (idx = 4; idx < arg_cnt_send; idx++) {
                                pvr2_trace(
                                        PVR2_TRACE_ERROR_LEGS,
-                                       "Giving up waiting."
-                                       "  It is likely that"
-                                       " this is a bad idea...");
-                               ret = -EBUSY;
-                               break;
+                                       "Encoder arg%d: 0x%08x",
+                                       idx-3,wrData[idx]);
                        }
+                       ret = -EBUSY;
+                       break;
+               }
+               if (retry_flag) {
+                       if (try_count < 20) continue;
+                       pvr2_trace(
+                               PVR2_TRACE_ERROR_LEGS,
+                               "Too many retries...");
+                       ret = -EBUSY;
+               }
+               if (ret) {
+                       pvr2_trace(
+                               PVR2_TRACE_ERROR_LEGS,
+                               "Giving up on command."
+                               "  It is likely that"
+                               " this is a bad idea...");
+                       break;
                }
-               if (ret) break;
                wrData[0] = 0x7;
-               ret = pvr2_encoder_read_words(
-                       hdw,0,rdData,
-                       sizeof(rdData)/sizeof(rdData[0]));
-               if (ret) break;
                for (idx = 0; idx < arg_cnt_recv; idx++) {
                        argp[idx] = rdData[idx+4];
                }
 
                wrData[0] = 0x0;
-               ret = pvr2_encoder_write_words(hdw,wrData,1);
+               ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,1);
                if (ret) break;
 
        } while(0); LOCK_GIVE(hdw->ctl_lock);
@@ -269,13 +302,13 @@ static int pvr2_encoder_vcmd(struct pvr2_hdw *hdw, int cmd,
        unsigned int idx;
        u32 data[12];
 
-       if (args > sizeof(data)/sizeof(data[0])) {
+       if (args > ARRAY_SIZE(data)) {
                pvr2_trace(
                        PVR2_TRACE_ERROR_LEGS,
                        "Failed to write cx23416 command"
                        " - too many arguments"
-                       " (was given %u limit %u)",
-                       args,(unsigned int)(sizeof(data)/sizeof(data[0])));
+                       " (was given %u limit %lu)",
+                       args, (long unsigned) ARRAY_SIZE(data));
                return -EINVAL;
        }
 
@@ -288,6 +321,73 @@ static int pvr2_encoder_vcmd(struct pvr2_hdw *hdw, int cmd,
        return pvr2_encoder_cmd(hdw,cmd,args,0,data);
 }
 
+
+/* This implements some extra setup for the encoder that seems to be
+   specific to the PVR USB2 hardware. */
+int pvr2_encoder_prep_config(struct pvr2_hdw *hdw)
+{
+       int ret = 0;
+       int encMisc3Arg = 0;
+
+#if 0
+       /* This inexplicable bit happens in the Hauppage windows
+          driver (for both 24xxx and 29xxx devices).  However I
+          currently see no difference in behavior with or without
+          this stuff.  Leave this here as a note of its existence,
+          but don't use it. */
+       LOCK_TAKE(hdw->ctl_lock); do {
+               u32 dat[1];
+               dat[0] = 0x80000640;
+               pvr2_encoder_write_words(hdw,0x01fe,dat,1);
+               pvr2_encoder_write_words(hdw,0x023e,dat,1);
+       } while(0); LOCK_GIVE(hdw->ctl_lock);
+#endif
+
+       /* Mike Isely <isely@pobox.com> 26-Jan-2006 The windows driver
+          sends the following list of ENC_MISC commands (for both
+          24xxx and 29xxx devices).  Meanings are not entirely clear,
+          however without the ENC_MISC(3,1) command then we risk
+          random perpetual video corruption whenever the video input
+          breaks up for a moment (like when switching channels). */
+
+
+#if 0
+       /* This ENC_MISC(5,0) command seems to hurt 29xxx sync
+          performance on channel changes, but is not a problem on
+          24xxx devices. */
+       ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 5,0,0,0);
+#endif
+
+       /* This ENC_MISC(3,encMisc3Arg) command is critical - without
+          it there will eventually be video corruption.  Also, the
+          29xxx case is strange - the Windows driver is passing 1
+          regardless of device type but if we have 1 for 29xxx device
+          the video turns sluggish.  */
+       switch (hdw->hdw_type) {
+       case PVR2_HDW_TYPE_24XXX: encMisc3Arg = 1; break;
+       case PVR2_HDW_TYPE_29XXX: encMisc3Arg = 0; break;
+       default: break;
+       }
+       ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 3,
+                                encMisc3Arg,0,0);
+
+       ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 8,0,0,0);
+
+#if 0
+       /* This ENC_MISC(4,1) command is poisonous, so it is commented
+          out.  But I'm leaving it here anyway to document its
+          existence in the Windows driver.  The effect of this
+          command is that apps displaying the stream become sluggish
+          with stuttering video. */
+       ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 4,1,0,0);
+#endif
+
+       ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 0,3,0,0);
+       ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4,15,0,0,0);
+
+       return ret;
+}
+
 int pvr2_encoder_configure(struct pvr2_hdw *hdw)
 {
        int ret;
@@ -302,6 +402,8 @@ int pvr2_encoder_configure(struct pvr2_hdw *hdw)
 
        ret = 0;
 
+       ret |= pvr2_encoder_prep_config(hdw);
+
        if (!ret) ret = pvr2_encoder_vcmd(
                hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2,
                0xf0, 0xf0);
@@ -360,15 +462,22 @@ int pvr2_encoder_start(struct pvr2_hdw *hdw)
        pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000481);
        pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
 
-       if (hdw->config == pvr2_config_vbi) {
+       pvr2_encoder_vcmd(hdw,CX2341X_ENC_MUTE_VIDEO,1,
+                         hdw->input_val == PVR2_CVAL_INPUT_RADIO ? 1 : 0);
+
+       switch (hdw->config) {
+       case pvr2_config_vbi:
                status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
                                           0x01,0x14);
-       } else if (hdw->config == pvr2_config_mpeg) {
+               break;
+       case pvr2_config_mpeg:
                status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
                                           0,0x13);
-       } else {
+               break;
+       default: /* Unhandled cases for now */
                status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
                                           0,0x13);
+               break;
        }
        if (!status) {
                hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_RUN);
@@ -383,15 +492,19 @@ int pvr2_encoder_stop(struct pvr2_hdw *hdw)
        /* mask all interrupts */
        pvr2_write_register(hdw, 0x0048, 0xffffffff);
 
-       if (hdw->config == pvr2_config_vbi) {
+       switch (hdw->config) {
+       case pvr2_config_vbi:
                status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
                                           0x01,0x01,0x14);
-       } else if (hdw->config == pvr2_config_mpeg) {
+               break;
+       case pvr2_config_mpeg:
                status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
                                           0x01,0,0x13);
-       } else {
+               break;
+       default: /* Unhandled cases for now */
                status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
                                           0x01,0,0x13);
+               break;
        }
 
        /* change some GPIO data */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h b/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h
new file mode 100644 (file)
index 0000000..ffbc6d0
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2007 Michael Krufky <mkrufky@linuxtv.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either 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
+ *
+ */
+
+#ifndef _PVRUSB2_FX2_CMD_H_
+#define _PVRUSB2_FX2_CMD_H_
+
+#define FX2CMD_MEM_WRITE_DWORD  0x01
+#define FX2CMD_MEM_READ_DWORD   0x02
+
+#define FX2CMD_MEM_READ_64BYTES 0x28
+
+#define FX2CMD_REG_WRITE        0x04
+#define FX2CMD_REG_READ         0x05
+#define FX2CMD_MEMSEL           0x06
+
+#define FX2CMD_I2C_WRITE        0x08
+#define FX2CMD_I2C_READ         0x09
+
+#define FX2CMD_GET_USB_SPEED    0x0b
+
+#define FX2CMD_STREAMING_ON     0x36
+#define FX2CMD_STREAMING_OFF    0x37
+
+#define FX2CMD_FWPOST1          0x52
+
+#define FX2CMD_POWER_OFF        0xdc
+#define FX2CMD_POWER_ON         0xde
+
+#define FX2CMD_DEEP_RESET       0xdd
+
+#define FX2CMD_GET_EEPROM_ADDR  0xeb
+#define FX2CMD_GET_IR_CODE      0xec
+
+#endif /* _PVRUSB2_FX2_CMD_H_ */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
index 34b08fbcc6eaf8ca0beb49417408a8c17f66cfad..16bd74199601908f3eec15fe42510322da4f9b89 100644 (file)
@@ -60,6 +60,7 @@ struct pvr2_decoder;
 
 typedef int (*pvr2_ctlf_is_dirty)(struct pvr2_ctrl *);
 typedef void (*pvr2_ctlf_clear_dirty)(struct pvr2_ctrl *);
+typedef int (*pvr2_ctlf_check_value)(struct pvr2_ctrl *,int);
 typedef int (*pvr2_ctlf_get_value)(struct pvr2_ctrl *,int *);
 typedef int (*pvr2_ctlf_set_value)(struct pvr2_ctrl *,int msk,int val);
 typedef int (*pvr2_ctlf_val_to_sym)(struct pvr2_ctrl *,int msk,int val,
@@ -83,6 +84,7 @@ struct pvr2_ctl_info {
        pvr2_ctlf_get_value get_min_value;  /* Get minimum allowed value */
        pvr2_ctlf_get_value get_max_value;  /* Get maximum allowed value */
        pvr2_ctlf_set_value set_value;      /* Set its value */
+       pvr2_ctlf_check_value check_value;  /* Check that value is valid */
        pvr2_ctlf_val_to_sym val_to_sym;    /* Custom convert value->symbol */
        pvr2_ctlf_sym_to_val sym_to_val;    /* Custom convert symbol->value */
        pvr2_ctlf_is_dirty is_dirty;        /* Return true if dirty */
@@ -135,17 +137,10 @@ struct pvr2_ctrl {
 };
 
 
-struct pvr2_audio_stat {
-       void *ctxt;
-       void (*detach)(void *);
-       int (*status)(void *);
-};
-
 struct pvr2_decoder_ctrl {
        void *ctxt;
        void (*detach)(void *);
        void (*enable)(void *,int);
-       int (*tuned)(void *);
        void (*force_reset)(void *);
 };
 
@@ -212,7 +207,6 @@ struct pvr2_hdw {
        /* Frequency table */
        unsigned int freqTable[FREQTABLE_SIZE];
        unsigned int freqProgSlot;
-       unsigned int freqSlot;
 
        /* Stuff for handling low level control interaction with device */
        struct mutex ctl_lock_mutex;
@@ -258,9 +252,17 @@ struct pvr2_hdw {
        /* Tuner / frequency control stuff */
        unsigned int tuner_type;
        int tuner_updated;
-       unsigned int freqVal;
+       unsigned int freqValTelevision;  /* Current freq for tv mode */
+       unsigned int freqValRadio;       /* Current freq for radio mode */
+       unsigned int freqSlotTelevision; /* Current slot for tv mode */
+       unsigned int freqSlotRadio;      /* Current slot for radio mode */
+       unsigned int freqSelector;       /* 0=radio 1=television */
        int freqDirty;
 
+       /* Current tuner info - this information is polled from the I2C bus */
+       struct v4l2_tuner tuner_signal_info;
+       int tuner_signal_stale;
+
        /* Video standard handling */
        v4l2_std_id std_mask_eeprom; // Hardware supported selections
        v4l2_std_id std_mask_avail;  // Which standards we may select from
@@ -281,20 +283,17 @@ struct pvr2_hdw {
        int unit_number;             /* ID for driver instance */
        unsigned long serial_number; /* ID for hardware itself */
 
-       /* Minor number used by v4l logic (yes, this is a hack, as there should
-          be no v4l junk here).  Probably a better way to do this. */
-       int v4l_minor_number;
+       /* Minor numbers used by v4l logic (yes, this is a hack, as there
+          should be no v4l junk here).  Probably a better way to do this. */
+       int v4l_minor_number_video;
+       int v4l_minor_number_vbi;
+       int v4l_minor_number_radio;
 
        /* Location of eeprom or a negative number if none */
        int eeprom_addr;
 
        enum pvr2_config config;
 
-       /* Information about what audio signal we're hearing */
-       int flag_stereo;
-       int flag_bilingual;
-       struct pvr2_audio_stat *audio_stat;
-
        /* Control state needed for cx2341x module */
        struct cx2341x_mpeg_params enc_cur_state;
        struct cx2341x_mpeg_params enc_ctl_state;
@@ -327,6 +326,9 @@ struct pvr2_hdw {
        unsigned int control_cnt;
 };
 
+/* This function gets the current frequency */
+unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *);
+
 #endif /* __PVRUSB2_HDW_INTERNAL_H */
 
 /*
index d2004965187bf54e47455a067881abf27f444950..1ff5138e4bb6c9ffe884d7dd43a7409af89a8bf3 100644 (file)
 #include "pvrusb2-hdw-internal.h"
 #include "pvrusb2-encoder.h"
 #include "pvrusb2-debug.h"
+#include "pvrusb2-fx2-cmd.h"
+
+#define TV_MIN_FREQ     55250000L
+#define TV_MAX_FREQ    850000000L
 
 struct usb_device_id pvr2_device_table[] = {
        [PVR2_HDW_TYPE_29XXX] = { USB_DEVICE(0x2040, 0x2900) },
@@ -71,12 +75,10 @@ static const char *pvr2_client_29xxx[] = {
 
 static struct pvr2_string_table pvr2_client_lists[] = {
        [PVR2_HDW_TYPE_29XXX] = {
-               pvr2_client_29xxx,
-               sizeof(pvr2_client_29xxx)/sizeof(pvr2_client_29xxx[0]),
+               pvr2_client_29xxx, ARRAY_SIZE(pvr2_client_29xxx)
        },
        [PVR2_HDW_TYPE_24XXX] = {
-               pvr2_client_24xxx,
-               sizeof(pvr2_client_24xxx)/sizeof(pvr2_client_24xxx[0]),
+               pvr2_client_24xxx, ARRAY_SIZE(pvr2_client_24xxx)
        },
 };
 
@@ -159,9 +161,6 @@ static const struct pvr2_mpeg_ids mpeg_ids[] = {
        },{
                .strid = "video_gop_closure",
                .id = V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
-       },{
-               .strid = "video_pulldown",
-               .id = V4L2_CID_MPEG_VIDEO_PULLDOWN,
        },{
                .strid = "video_bitrate_mode",
                .id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
@@ -212,7 +211,7 @@ static const struct pvr2_mpeg_ids mpeg_ids[] = {
                .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
        }
 };
-#define MPEGDEF_COUNT (sizeof(mpeg_ids)/sizeof(mpeg_ids[0]))
+#define MPEGDEF_COUNT ARRAY_SIZE(mpeg_ids)
 
 
 static const char *control_values_srate[] = {
@@ -255,10 +254,10 @@ static const char *control_values_subsystem[] = {
        [PVR2_SUBSYS_B_ENC_RUN] = "enc_run",
 };
 
+static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long);
 static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl);
 static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw);
 static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw);
-static unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw);
 static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw);
 static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw);
 static void pvr2_hdw_render_useless_unlocked(struct pvr2_hdw *hdw);
@@ -272,8 +271,6 @@ static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
                                unsigned int timeout,int probe_fl,
                                void *write_data,unsigned int write_len,
                                void *read_data,unsigned int read_len);
-static int pvr2_write_u16(struct pvr2_hdw *hdw, u16 data, int res);
-static int pvr2_write_u8(struct pvr2_hdw *hdw, u8 data, int res);
 
 static int ctrl_channelfreq_get(struct pvr2_ctrl *cptr,int *vp)
 {
@@ -289,8 +286,21 @@ static int ctrl_channelfreq_get(struct pvr2_ctrl *cptr,int *vp)
 static int ctrl_channelfreq_set(struct pvr2_ctrl *cptr,int m,int v)
 {
        struct pvr2_hdw *hdw = cptr->hdw;
-       if ((hdw->freqProgSlot > 0) && (hdw->freqProgSlot <= FREQTABLE_SIZE)) {
-               hdw->freqTable[hdw->freqProgSlot-1] = v;
+       unsigned int slotId = hdw->freqProgSlot;
+       if ((slotId > 0) && (slotId <= FREQTABLE_SIZE)) {
+               hdw->freqTable[slotId-1] = v;
+               /* Handle side effects correctly - if we're tuned to this
+                  slot, then forgot the slot id relation since the stored
+                  frequency has been changed. */
+               if (hdw->freqSelector) {
+                       if (hdw->freqSlotRadio == slotId) {
+                               hdw->freqSlotRadio = 0;
+                       }
+               } else {
+                       if (hdw->freqSlotTelevision == slotId) {
+                               hdw->freqSlotTelevision = 0;
+                       }
+               }
        }
        return 0;
 }
@@ -312,28 +322,32 @@ static int ctrl_channelprog_set(struct pvr2_ctrl *cptr,int m,int v)
 
 static int ctrl_channel_get(struct pvr2_ctrl *cptr,int *vp)
 {
-       *vp = cptr->hdw->freqSlot;
+       struct pvr2_hdw *hdw = cptr->hdw;
+       *vp = hdw->freqSelector ? hdw->freqSlotRadio : hdw->freqSlotTelevision;
        return 0;
 }
 
-static int ctrl_channel_set(struct pvr2_ctrl *cptr,int m,int v)
+static int ctrl_channel_set(struct pvr2_ctrl *cptr,int m,int slotId)
 {
        unsigned freq = 0;
        struct pvr2_hdw *hdw = cptr->hdw;
-       hdw->freqSlot = v;
-       if ((hdw->freqSlot > 0) && (hdw->freqSlot <= FREQTABLE_SIZE)) {
-               freq = hdw->freqTable[hdw->freqSlot-1];
-       }
-       if (freq && (freq != hdw->freqVal)) {
-               hdw->freqVal = freq;
-               hdw->freqDirty = !0;
+       if ((slotId < 0) || (slotId > FREQTABLE_SIZE)) return 0;
+       if (slotId > 0) {
+               freq = hdw->freqTable[slotId-1];
+               if (!freq) return 0;
+               pvr2_hdw_set_cur_freq(hdw,freq);
+       }
+       if (hdw->freqSelector) {
+               hdw->freqSlotRadio = slotId;
+       } else {
+               hdw->freqSlotTelevision = slotId;
        }
        return 0;
 }
 
 static int ctrl_freq_get(struct pvr2_ctrl *cptr,int *vp)
 {
-       *vp = cptr->hdw->freqVal;
+       *vp = pvr2_hdw_get_cur_freq(cptr->hdw);
        return 0;
 }
 
@@ -349,10 +363,7 @@ static void ctrl_freq_clear_dirty(struct pvr2_ctrl *cptr)
 
 static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v)
 {
-       struct pvr2_hdw *hdw = cptr->hdw;
-       hdw->freqVal = v;
-       hdw->freqDirty = !0;
-       hdw->freqSlot = 0;
+       pvr2_hdw_set_cur_freq(cptr->hdw,v);
        return 0;
 }
 
@@ -378,6 +389,89 @@ static int ctrl_vres_min_get(struct pvr2_ctrl *cptr,int *vp)
        return 0;
 }
 
+static int ctrl_get_input(struct pvr2_ctrl *cptr,int *vp)
+{
+       *vp = cptr->hdw->input_val;
+       return 0;
+}
+
+static int ctrl_set_input(struct pvr2_ctrl *cptr,int m,int v)
+{
+       struct pvr2_hdw *hdw = cptr->hdw;
+
+       if (hdw->input_val != v) {
+               hdw->input_val = v;
+               hdw->input_dirty = !0;
+       }
+
+       /* Handle side effects - if we switch to a mode that needs the RF
+          tuner, then select the right frequency choice as well and mark
+          it dirty. */
+       if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+               hdw->freqSelector = 0;
+               hdw->freqDirty = !0;
+       } else if (hdw->input_val == PVR2_CVAL_INPUT_TV) {
+               hdw->freqSelector = 1;
+               hdw->freqDirty = !0;
+       }
+       return 0;
+}
+
+static int ctrl_isdirty_input(struct pvr2_ctrl *cptr)
+{
+       return cptr->hdw->input_dirty != 0;
+}
+
+static void ctrl_cleardirty_input(struct pvr2_ctrl *cptr)
+{
+       cptr->hdw->input_dirty = 0;
+}
+
+
+static int ctrl_freq_max_get(struct pvr2_ctrl *cptr, int *vp)
+{
+       unsigned long fv;
+       struct pvr2_hdw *hdw = cptr->hdw;
+       if (hdw->tuner_signal_stale) {
+               pvr2_i2c_core_status_poll(hdw);
+       }
+       fv = hdw->tuner_signal_info.rangehigh;
+       if (!fv) {
+               /* Safety fallback */
+               *vp = TV_MAX_FREQ;
+               return 0;
+       }
+       if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) {
+               fv = (fv * 125) / 2;
+       } else {
+               fv = fv * 62500;
+       }
+       *vp = fv;
+       return 0;
+}
+
+static int ctrl_freq_min_get(struct pvr2_ctrl *cptr, int *vp)
+{
+       unsigned long fv;
+       struct pvr2_hdw *hdw = cptr->hdw;
+       if (hdw->tuner_signal_stale) {
+               pvr2_i2c_core_status_poll(hdw);
+       }
+       fv = hdw->tuner_signal_info.rangelow;
+       if (!fv) {
+               /* Safety fallback */
+               *vp = TV_MIN_FREQ;
+               return 0;
+       }
+       if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) {
+               fv = (fv * 125) / 2;
+       } else {
+               fv = fv * 62500;
+       }
+       *vp = fv;
+       return 0;
+}
+
 static int ctrl_cx2341x_is_dirty(struct pvr2_ctrl *cptr)
 {
        return cptr->hdw->enc_stale != 0;
@@ -534,8 +628,32 @@ static void ctrl_stdcur_clear_dirty(struct pvr2_ctrl *cptr)
 
 static int ctrl_signal_get(struct pvr2_ctrl *cptr,int *vp)
 {
-       *vp = ((pvr2_hdw_get_signal_status_internal(cptr->hdw) &
-               PVR2_SIGNAL_OK) ? 1 : 0);
+       struct pvr2_hdw *hdw = cptr->hdw;
+       pvr2_i2c_core_status_poll(hdw);
+       *vp = hdw->tuner_signal_info.signal;
+       return 0;
+}
+
+static int ctrl_audio_modes_present_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       int val = 0;
+       unsigned int subchan;
+       struct pvr2_hdw *hdw = cptr->hdw;
+       pvr2_i2c_core_status_poll(hdw);
+       subchan = hdw->tuner_signal_info.rxsubchans;
+       if (subchan & V4L2_TUNER_SUB_MONO) {
+               val |= (1 << V4L2_TUNER_MODE_MONO);
+       }
+       if (subchan & V4L2_TUNER_SUB_STEREO) {
+               val |= (1 << V4L2_TUNER_MODE_STEREO);
+       }
+       if (subchan & V4L2_TUNER_SUB_LANG1) {
+               val |= (1 << V4L2_TUNER_MODE_LANG1);
+       }
+       if (subchan & V4L2_TUNER_SUB_LANG2) {
+               val |= (1 << V4L2_TUNER_MODE_LANG2);
+       }
+       *vp = val;
        return 0;
 }
 
@@ -604,7 +722,7 @@ static void ctrl_stdenumcur_clear_dirty(struct pvr2_ctrl *cptr)
 
 #define DEFENUM(tab) \
        .type = pvr2_ctl_enum, \
-       .def.type_enum.count = (sizeof(tab)/sizeof((tab)[0])), \
+       .def.type_enum.count = ARRAY_SIZE(tab), \
        .def.type_enum.value_names = tab
 
 #define DEFBOOL \
@@ -641,15 +759,11 @@ VCREATE_FUNCS(balance)
 VCREATE_FUNCS(bass)
 VCREATE_FUNCS(treble)
 VCREATE_FUNCS(mute)
-VCREATE_FUNCS(input)
 VCREATE_FUNCS(audiomode)
 VCREATE_FUNCS(res_hor)
 VCREATE_FUNCS(res_ver)
 VCREATE_FUNCS(srate)
 
-#define MIN_FREQ 55250000L
-#define MAX_FREQ 850000000L
-
 /* Table definition of all controls which can be manipulated */
 static const struct pvr2_ctl_info control_defs[] = {
        {
@@ -684,7 +798,7 @@ static const struct pvr2_ctl_info control_defs[] = {
                .v4l_id = V4L2_CID_AUDIO_VOLUME,
                .desc = "Volume",
                .name = "volume",
-               .default_value = 65535,
+               .default_value = 62000,
                DEFREF(volume),
                DEFINT(0,65535),
        },{
@@ -758,12 +872,16 @@ static const struct pvr2_ctl_info control_defs[] = {
                .desc = "Tuner Frequency (Hz)",
                .name = "frequency",
                .internal_id = PVR2_CID_FREQUENCY,
-               .default_value = 175250000L,
+               .default_value = 0,
                .set_value = ctrl_freq_set,
                .get_value = ctrl_freq_get,
                .is_dirty = ctrl_freq_is_dirty,
                .clear_dirty = ctrl_freq_clear_dirty,
-               DEFINT(MIN_FREQ,MAX_FREQ),
+               DEFINT(0,0),
+               /* Hook in check for input value (tv/radio) and adjust
+                  max/min values accordingly */
+               .get_max_value = ctrl_freq_max_get,
+               .get_min_value = ctrl_freq_min_get,
        },{
                .desc = "Channel",
                .name = "channel",
@@ -775,7 +893,11 @@ static const struct pvr2_ctl_info control_defs[] = {
                .name = "freq_table_value",
                .set_value = ctrl_channelfreq_set,
                .get_value = ctrl_channelfreq_get,
-               DEFINT(MIN_FREQ,MAX_FREQ),
+               DEFINT(0,0),
+               /* Hook in check for input value (tv/radio) and adjust
+                  max/min values accordingly */
+               .get_max_value = ctrl_freq_max_get,
+               .get_min_value = ctrl_freq_min_get,
        },{
                .desc = "Channel Program ID",
                .name = "freq_table_channel",
@@ -796,7 +918,20 @@ static const struct pvr2_ctl_info control_defs[] = {
                .desc = "Signal Present",
                .name = "signal_present",
                .get_value = ctrl_signal_get,
-               DEFBOOL,
+               DEFINT(0,65535),
+       },{
+               .desc = "Audio Modes Present",
+               .name = "audio_modes_present",
+               .get_value = ctrl_audio_modes_present_get,
+               /* For this type we "borrow" the V4L2_TUNER_MODE enum from
+                  v4l.  Nothing outside of this module cares about this,
+                  but I reuse it in order to also reuse the
+                  control_values_audiomode string table. */
+               DEFMASK(((1 << V4L2_TUNER_MODE_MONO)|
+                        (1 << V4L2_TUNER_MODE_STEREO)|
+                        (1 << V4L2_TUNER_MODE_LANG1)|
+                        (1 << V4L2_TUNER_MODE_LANG2)),
+                       control_values_audiomode),
        },{
                .desc = "Video Standards Available Mask",
                .name = "video_standard_mask_available",
@@ -846,7 +981,7 @@ static const struct pvr2_ctl_info control_defs[] = {
        }
 };
 
-#define CTRLDEF_COUNT (sizeof(control_defs)/sizeof(control_defs[0]))
+#define CTRLDEF_COUNT ARRAY_SIZE(control_defs)
 
 
 const char *pvr2_config_get_name(enum pvr2_config cfg)
@@ -855,7 +990,8 @@ const char *pvr2_config_get_name(enum pvr2_config cfg)
        case pvr2_config_empty: return "empty";
        case pvr2_config_mpeg: return "mpeg";
        case pvr2_config_vbi: return "vbi";
-       case pvr2_config_radio: return "radio";
+       case pvr2_config_pcm: return "pcm";
+       case pvr2_config_rawvideo: return "raw video";
        }
        return "<unknown>";
 }
@@ -872,6 +1008,40 @@ unsigned long pvr2_hdw_get_sn(struct pvr2_hdw *hdw)
        return hdw->serial_number;
 }
 
+unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *hdw)
+{
+       return hdw->freqSelector ? hdw->freqValTelevision : hdw->freqValRadio;
+}
+
+/* Set the currently tuned frequency and account for all possible
+   driver-core side effects of this action. */
+void pvr2_hdw_set_cur_freq(struct pvr2_hdw *hdw,unsigned long val)
+{
+       if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+               if (hdw->freqSelector) {
+                       /* Swing over to radio frequency selection */
+                       hdw->freqSelector = 0;
+                       hdw->freqDirty = !0;
+               }
+               if (hdw->freqValRadio != val) {
+                       hdw->freqValRadio = val;
+                       hdw->freqSlotRadio = 0;
+                       hdw->freqDirty = !0;
+               }
+       } else {
+               if (!(hdw->freqSelector)) {
+                       /* Swing over to television frequency selection */
+                       hdw->freqSelector = 1;
+                       hdw->freqDirty = !0;
+               }
+               if (hdw->freqValTelevision != val) {
+                       hdw->freqValTelevision = val;
+                       hdw->freqSlotTelevision = 0;
+                       hdw->freqDirty = !0;
+               }
+       }
+}
+
 int pvr2_hdw_get_unit_number(struct pvr2_hdw *hdw)
 {
        return hdw->unit_number;
@@ -960,12 +1130,10 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw)
        };
        static const struct pvr2_string_table fw_file_defs[] = {
                [PVR2_HDW_TYPE_29XXX] = {
-                       fw_files_29xxx,
-                       sizeof(fw_files_29xxx)/sizeof(fw_files_29xxx[0]),
+                       fw_files_29xxx, ARRAY_SIZE(fw_files_29xxx)
                },
                [PVR2_HDW_TYPE_24XXX] = {
-                       fw_files_24xxx,
-                       sizeof(fw_files_24xxx)/sizeof(fw_files_24xxx[0]),
+                       fw_files_24xxx, ARRAY_SIZE(fw_files_24xxx)
                },
        };
        hdw->fw1_state = FW1_STATE_FAILED; // default result
@@ -1041,7 +1209,7 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
 {
        const struct firmware *fw_entry = NULL;
        void  *fw_ptr;
-       unsigned int pipe, fw_len, fw_done;
+       unsigned int pipe, fw_len, fw_done, bcnt, icnt;
        int actual_length;
        int ret = 0;
        int fwidx;
@@ -1052,8 +1220,7 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
        trace_firmware("pvr2_upload_firmware2");
 
        ret = pvr2_locate_firmware(hdw,&fw_entry,"encoder",
-                                  sizeof(fw_files)/sizeof(fw_files[0]),
-                                  fw_files);
+                                  ARRAY_SIZE(fw_files), fw_files);
        if (ret < 0) return ret;
        fwidx = ret;
        ret = 0;
@@ -1079,8 +1246,13 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
        ret |= pvr2_write_register(hdw, 0xaa04, 0x00057810); /*unknown*/
        ret |= pvr2_write_register(hdw, 0xaa10, 0x00148500); /*unknown*/
        ret |= pvr2_write_register(hdw, 0xaa18, 0x00840000); /*unknown*/
-       ret |= pvr2_write_u8(hdw, 0x52, 0);
-       ret |= pvr2_write_u16(hdw, 0x0600, 0);
+       LOCK_TAKE(hdw->ctl_lock); do {
+               hdw->cmd_buffer[0] = FX2CMD_FWPOST1;
+               ret |= pvr2_send_request(hdw,hdw->cmd_buffer,1,0,0);
+               hdw->cmd_buffer[0] = FX2CMD_MEMSEL;
+               hdw->cmd_buffer[1] = 0;
+               ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,0,0);
+       } while (0); LOCK_GIVE(hdw->ctl_lock);
 
        if (ret) {
                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
@@ -1093,11 +1265,11 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
 
        fw_len = fw_entry->size;
 
-       if (fw_len % FIRMWARE_CHUNK_SIZE) {
+       if (fw_len % sizeof(u32)) {
                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
                           "size of %s firmware"
-                          " must be a multiple of 8192B",
-                          fw_files[fwidx]);
+                          " must be a multiple of %zu bytes",
+                          fw_files[fwidx],sizeof(u32));
                release_firmware(fw_entry);
                return -1;
        }
@@ -1112,18 +1284,21 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
 
        pipe = usb_sndbulkpipe(hdw->usb_dev, PVR2_FIRMWARE_ENDPOINT);
 
-       for (fw_done = 0 ; (fw_done < fw_len) && !ret ;
-            fw_done += FIRMWARE_CHUNK_SIZE ) {
-               int i;
-               memcpy(fw_ptr, fw_entry->data + fw_done, FIRMWARE_CHUNK_SIZE);
-               /* Usbsnoop log  shows that we must swap bytes... */
-               for (i = 0; i < FIRMWARE_CHUNK_SIZE/4 ; i++)
-                       ((u32 *)fw_ptr)[i] = ___swab32(((u32 *)fw_ptr)[i]);
-
-               ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr,
-                                   FIRMWARE_CHUNK_SIZE,
+       fw_done = 0;
+       for (fw_done = 0; fw_done < fw_len;) {
+               bcnt = fw_len - fw_done;
+               if (bcnt > FIRMWARE_CHUNK_SIZE) bcnt = FIRMWARE_CHUNK_SIZE;
+               memcpy(fw_ptr, fw_entry->data + fw_done, bcnt);
+               /* Usbsnoop log shows that we must swap bytes... */
+               for (icnt = 0; icnt < bcnt/4 ; icnt++)
+                       ((u32 *)fw_ptr)[icnt] =
+                               ___swab32(((u32 *)fw_ptr)[icnt]);
+
+               ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr,bcnt,
                                    &actual_length, HZ);
-               ret |= (actual_length != FIRMWARE_CHUNK_SIZE);
+               ret |= (actual_length != bcnt);
+               if (ret) break;
+               fw_done += bcnt;
        }
 
        trace_firmware("upload of %s : %i / %i ",
@@ -1142,7 +1317,11 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
 
        ret |= pvr2_write_register(hdw, 0x9054, 0xffffffff); /*reset hw blocks*/
        ret |= pvr2_write_register(hdw, 0x9058, 0xffffffe8); /*VPU ctrl*/
-       ret |= pvr2_write_u16(hdw, 0x0600, 0);
+       LOCK_TAKE(hdw->ctl_lock); do {
+               hdw->cmd_buffer[0] = FX2CMD_MEMSEL;
+               hdw->cmd_buffer[1] = 0;
+               ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,0,0);
+       } while (0); LOCK_GIVE(hdw->ctl_lock);
 
        if (ret) {
                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
@@ -1479,7 +1658,7 @@ static int pvr2_hdw_check_firmware(struct pvr2_hdw *hdw)
           firmware needs be loaded. */
        int result;
        LOCK_TAKE(hdw->ctl_lock); do {
-               hdw->cmd_buffer[0] = 0xeb;
+               hdw->cmd_buffer[0] = FX2CMD_GET_EEPROM_ADDR;
                result = pvr2_send_request_ex(hdw,HZ*1,!0,
                                           hdw->cmd_buffer,1,
                                           hdw->cmd_buffer,1);
@@ -1611,6 +1790,16 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
                cptr->info->set_value(cptr,~0,cptr->info->default_value);
        }
 
+       /* Set up special default values for the television and radio
+          frequencies here.  It's not really important what these defaults
+          are, but I set them to something usable in the Chicago area just
+          to make driver testing a little easier. */
+
+       /* US Broadcast channel 7 (175.25 MHz) */
+       hdw->freqValTelevision = 175250000L;
+       /* 104.3 MHz, a usable FM station for my area */
+       hdw->freqValRadio = 104300000L;
+
        // Do not use pvr2_reset_ctl_endpoints() here.  It is not
        // thread-safe against the normal pvr2_send_request() mechanism.
        // (We should make it thread safe).
@@ -1750,26 +1939,24 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
        struct pvr2_ctl_info *ciptr;
 
        hdw_type = devid - pvr2_device_table;
-       if (hdw_type >=
-           sizeof(pvr2_device_names)/sizeof(pvr2_device_names[0])) {
+       if (hdw_type >= ARRAY_SIZE(pvr2_device_names)) {
                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
                           "Bogus device type of %u reported",hdw_type);
                return NULL;
        }
 
-       hdw = kmalloc(sizeof(*hdw),GFP_KERNEL);
+       hdw = kzalloc(sizeof(*hdw),GFP_KERNEL);
        pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"",
                   hdw,pvr2_device_names[hdw_type]);
        if (!hdw) goto fail;
-       memset(hdw,0,sizeof(*hdw));
+       hdw->tuner_signal_stale = !0;
        cx2341x_fill_defaults(&hdw->enc_ctl_state);
 
        hdw->control_cnt = CTRLDEF_COUNT;
        hdw->control_cnt += MPEGDEF_COUNT;
-       hdw->controls = kmalloc(sizeof(struct pvr2_ctrl) * hdw->control_cnt,
+       hdw->controls = kzalloc(sizeof(struct pvr2_ctrl) * hdw->control_cnt,
                                GFP_KERNEL);
        if (!hdw->controls) goto fail;
-       memset(hdw->controls,0,sizeof(struct pvr2_ctrl) * hdw->control_cnt);
        hdw->hdw_type = hdw_type;
        for (idx = 0; idx < hdw->control_cnt; idx++) {
                cptr = hdw->controls + idx;
@@ -1783,11 +1970,9 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
                cptr->info = control_defs+idx;
        }
        /* Define and configure additional controls from cx2341x module. */
-       hdw->mpeg_ctrl_info = kmalloc(
+       hdw->mpeg_ctrl_info = kzalloc(
                sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT, GFP_KERNEL);
        if (!hdw->mpeg_ctrl_info) goto fail;
-       memset(hdw->mpeg_ctrl_info,0,
-              sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT);
        for (idx = 0; idx < MPEGDEF_COUNT; idx++) {
                cptr = hdw->controls + idx + CTRLDEF_COUNT;
                ciptr = &(hdw->mpeg_ctrl_info[idx].info);
@@ -1872,7 +2057,9 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
 
        hdw->eeprom_addr = -1;
        hdw->unit_number = -1;
-       hdw->v4l_minor_number = -1;
+       hdw->v4l_minor_number_video = -1;
+       hdw->v4l_minor_number_vbi = -1;
+       hdw->v4l_minor_number_radio = -1;
        hdw->ctl_write_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL);
        if (!hdw->ctl_write_buffer) goto fail;
        hdw->ctl_read_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL);
@@ -1929,10 +2116,10 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
        if (hdw) {
                usb_free_urb(hdw->ctl_read_urb);
                usb_free_urb(hdw->ctl_write_urb);
-               if (hdw->ctl_read_buffer) kfree(hdw->ctl_read_buffer);
-               if (hdw->ctl_write_buffer) kfree(hdw->ctl_write_buffer);
-               if (hdw->controls) kfree(hdw->controls);
-               if (hdw->mpeg_ctrl_info) kfree(hdw->mpeg_ctrl_info);
+               kfree(hdw->ctl_read_buffer);
+               kfree(hdw->ctl_write_buffer);
+               kfree(hdw->controls);
+               kfree(hdw->mpeg_ctrl_info);
                kfree(hdw);
        }
        return NULL;
@@ -1982,9 +2169,6 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw)
                pvr2_stream_destroy(hdw->vid_stream);
                hdw->vid_stream = NULL;
        }
-       if (hdw->audio_stat) {
-               hdw->audio_stat->detach(hdw->audio_stat->ctxt);
-       }
        if (hdw->decoder_ctrl) {
                hdw->decoder_ctrl->detach(hdw->decoder_ctrl->ctxt);
        }
@@ -1997,10 +2181,10 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw)
                        unit_pointers[hdw->unit_number] = NULL;
                }
        } while (0); up(&pvr2_unit_sem);
-       if (hdw->controls) kfree(hdw->controls);
-       if (hdw->mpeg_ctrl_info) kfree(hdw->mpeg_ctrl_info);
-       if (hdw->std_defs) kfree(hdw->std_defs);
-       if (hdw->std_enum_names) kfree(hdw->std_enum_names);
+       kfree(hdw->controls);
+       kfree(hdw->mpeg_ctrl_info);
+       kfree(hdw->std_defs);
+       kfree(hdw->std_enum_names);
        kfree(hdw);
 }
 
@@ -2210,10 +2394,9 @@ static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw)
                cptr = hdw->controls + idx;
                if (cptr->info->is_dirty == 0) continue;
                if (!cptr->info->is_dirty(cptr)) continue;
-               if (!commit_flag) {
-                       commit_flag = !0;
-               }
+               commit_flag = !0;
 
+               if (!(pvrusb2_debug & PVR2_TRACE_CTL)) continue;
                bcnt = scnprintf(buf,sizeof(buf),"\"%s\" <-- ",
                                 cptr->info->name);
                value = 0;
@@ -2263,6 +2446,13 @@ static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw)
                stale_subsys_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG);
        }
 
+       if (hdw->input_dirty) {
+               /* pk: If input changes to or from radio, then the encoder
+                  needs to be restarted (for ENC_MUTE_VIDEO to work) */
+               stale_subsys_mask |= (1<<PVR2_SUBSYS_B_ENC_RUN);
+       }
+
+
        if (hdw->srate_dirty) {
                /* Write new sample rate into control structure since
                 * the master copy is stale.  We must track srate
@@ -2343,39 +2533,11 @@ const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw)
 }
 
 
-/* Return bit mask indicating signal status */
-static unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw)
-{
-       unsigned int msk = 0;
-       switch (hdw->input_val) {
-       case PVR2_CVAL_INPUT_TV:
-       case PVR2_CVAL_INPUT_RADIO:
-               if (hdw->decoder_ctrl &&
-                   hdw->decoder_ctrl->tuned(hdw->decoder_ctrl->ctxt)) {
-                       msk |= PVR2_SIGNAL_OK;
-                       if (hdw->audio_stat &&
-                           hdw->audio_stat->status(hdw->audio_stat->ctxt)) {
-                               if (hdw->flag_stereo) {
-                                       msk |= PVR2_SIGNAL_STEREO;
-                               }
-                               if (hdw->flag_bilingual) {
-                                       msk |= PVR2_SIGNAL_SAP;
-                               }
-                       }
-               }
-               break;
-       default:
-               msk |= PVR2_SIGNAL_OK | PVR2_SIGNAL_STEREO;
-       }
-       return msk;
-}
-
-
 int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw)
 {
        int result;
        LOCK_TAKE(hdw->ctl_lock); do {
-               hdw->cmd_buffer[0] = 0x0b;
+               hdw->cmd_buffer[0] = FX2CMD_GET_USB_SPEED;
                result = pvr2_send_request(hdw,
                                           hdw->cmd_buffer,1,
                                           hdw->cmd_buffer,1);
@@ -2386,14 +2548,25 @@ int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw)
 }
 
 
-/* Return bit mask indicating signal status */
-unsigned int pvr2_hdw_get_signal_status(struct pvr2_hdw *hdw)
+/* Execute poll of tuner status */
+void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *hdw)
 {
-       unsigned int msk = 0;
        LOCK_TAKE(hdw->big_lock); do {
-               msk = pvr2_hdw_get_signal_status_internal(hdw);
+               pvr2_i2c_core_status_poll(hdw);
        } while (0); LOCK_GIVE(hdw->big_lock);
-       return msk;
+}
+
+
+/* Return information about the tuner */
+int pvr2_hdw_get_tuner_status(struct pvr2_hdw *hdw,struct v4l2_tuner *vtp)
+{
+       LOCK_TAKE(hdw->big_lock); do {
+               if (hdw->tuner_signal_stale) {
+                       pvr2_i2c_core_status_poll(hdw);
+               }
+               memcpy(vtp,&hdw->tuner_signal_info,sizeof(struct v4l2_tuner));
+       } while (0); LOCK_GIVE(hdw->big_lock);
+       return 0;
 }
 
 
@@ -2442,14 +2615,12 @@ void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, int enable_flag)
                pvr2_trace(PVR2_TRACE_FIRMWARE,
                           "Preparing to suck out CPU firmware");
                hdw->fw_size = 0x2000;
-               hdw->fw_buffer = kmalloc(hdw->fw_size,GFP_KERNEL);
+               hdw->fw_buffer = kzalloc(hdw->fw_size,GFP_KERNEL);
                if (!hdw->fw_buffer) {
                        hdw->fw_size = 0;
                        break;
                }
 
-               memset(hdw->fw_buffer,0,hdw->fw_size);
-
                /* We have to hold the CPU during firmware upload. */
                pvr2_hdw_cpureset_assert(hdw,1);
 
@@ -2513,16 +2684,28 @@ int pvr2_hdw_cpufw_get(struct pvr2_hdw *hdw,unsigned int offs,
 }
 
 
-int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *hdw)
+int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *hdw,
+                                 enum pvr2_v4l_type index)
 {
-       return hdw->v4l_minor_number;
+       switch (index) {
+       case pvr2_v4l_type_video: return hdw->v4l_minor_number_video;
+       case pvr2_v4l_type_vbi: return hdw->v4l_minor_number_vbi;
+       case pvr2_v4l_type_radio: return hdw->v4l_minor_number_radio;
+       default: return -1;
+       }
 }
 
 
-/* Store the v4l minor device number */
-void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *hdw,int v)
+/* Store a v4l minor device number */
+void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *hdw,
+                                    enum pvr2_v4l_type index,int v)
 {
-       hdw->v4l_minor_number = v;
+       switch (index) {
+       case pvr2_v4l_type_video: hdw->v4l_minor_number_video = v;
+       case pvr2_v4l_type_vbi: hdw->v4l_minor_number_vbi = v;
+       case pvr2_v4l_type_radio: hdw->v4l_minor_number_radio = v;
+       default: break;
+       }
 }
 
 
@@ -2804,7 +2987,7 @@ int pvr2_write_register(struct pvr2_hdw *hdw, u16 reg, u32 data)
 
        LOCK_TAKE(hdw->ctl_lock);
 
-       hdw->cmd_buffer[0] = 0x04;  /* write register prefix */
+       hdw->cmd_buffer[0] = FX2CMD_REG_WRITE;  /* write register prefix */
        PVR2_DECOMPOSE_LE(hdw->cmd_buffer,1,data);
        hdw->cmd_buffer[5] = 0;
        hdw->cmd_buffer[6] = (reg >> 8) & 0xff;
@@ -2825,7 +3008,7 @@ static int pvr2_read_register(struct pvr2_hdw *hdw, u16 reg, u32 *data)
 
        LOCK_TAKE(hdw->ctl_lock);
 
-       hdw->cmd_buffer[0] = 0x05;  /* read register prefix */
+       hdw->cmd_buffer[0] = FX2CMD_REG_READ;  /* read register prefix */
        hdw->cmd_buffer[1] = 0;
        hdw->cmd_buffer[2] = 0;
        hdw->cmd_buffer[3] = 0;
@@ -2843,39 +3026,6 @@ static int pvr2_read_register(struct pvr2_hdw *hdw, u16 reg, u32 *data)
 }
 
 
-static int pvr2_write_u16(struct pvr2_hdw *hdw, u16 data, int res)
-{
-       int ret;
-
-       LOCK_TAKE(hdw->ctl_lock);
-
-       hdw->cmd_buffer[0] = (data >> 8) & 0xff;
-       hdw->cmd_buffer[1] = data & 0xff;
-
-       ret = pvr2_send_request(hdw, hdw->cmd_buffer, 2, hdw->cmd_buffer, res);
-
-       LOCK_GIVE(hdw->ctl_lock);
-
-       return ret;
-}
-
-
-static int pvr2_write_u8(struct pvr2_hdw *hdw, u8 data, int res)
-{
-       int ret;
-
-       LOCK_TAKE(hdw->ctl_lock);
-
-       hdw->cmd_buffer[0] = data;
-
-       ret = pvr2_send_request(hdw, hdw->cmd_buffer, 1, hdw->cmd_buffer, res);
-
-       LOCK_GIVE(hdw->ctl_lock);
-
-       return ret;
-}
-
-
 static void pvr2_hdw_render_useless_unlocked(struct pvr2_hdw *hdw)
 {
        if (!hdw->flag_ok) return;
@@ -2949,7 +3099,7 @@ int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *hdw)
        LOCK_TAKE(hdw->ctl_lock); do {
                pvr2_trace(PVR2_TRACE_INIT,"Requesting uproc hard reset");
                hdw->flag_ok = !0;
-               hdw->cmd_buffer[0] = 0xdd;
+               hdw->cmd_buffer[0] = FX2CMD_DEEP_RESET;
                status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
        } while (0); LOCK_GIVE(hdw->ctl_lock);
        return status;
@@ -2961,7 +3111,7 @@ int pvr2_hdw_cmd_powerup(struct pvr2_hdw *hdw)
        int status;
        LOCK_TAKE(hdw->ctl_lock); do {
                pvr2_trace(PVR2_TRACE_INIT,"Requesting powerup");
-               hdw->cmd_buffer[0] = 0xde;
+               hdw->cmd_buffer[0] = FX2CMD_POWER_ON;
                status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
        } while (0); LOCK_GIVE(hdw->ctl_lock);
        return status;
@@ -2994,7 +3144,8 @@ static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl)
 {
        int status;
        LOCK_TAKE(hdw->ctl_lock); do {
-               hdw->cmd_buffer[0] = (runFl ? 0x36 : 0x37);
+               hdw->cmd_buffer[0] =
+                       (runFl ? FX2CMD_STREAMING_ON : FX2CMD_STREAMING_OFF);
                status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
        } while (0); LOCK_GIVE(hdw->ctl_lock);
        if (!status) {
@@ -3093,7 +3244,7 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
 {
        int result;
        LOCK_TAKE(hdw->ctl_lock); do {
-               hdw->cmd_buffer[0] = 0xeb;
+               hdw->cmd_buffer[0] = FX2CMD_GET_EEPROM_ADDR;
                result = pvr2_send_request(hdw,
                                           hdw->cmd_buffer,1,
                                           hdw->cmd_buffer,1);
@@ -3105,8 +3256,8 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
 
 
 int pvr2_hdw_register_access(struct pvr2_hdw *hdw,
-                            u32 chip_id,unsigned long reg_id,
-                            int setFl,u32 *val_ptr)
+                            u32 match_type, u32 match_chip, u64 reg_id,
+                            int setFl,u64 *val_ptr)
 {
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        struct list_head *item;
@@ -3115,16 +3266,21 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw,
        int stat = 0;
        int okFl = 0;
 
-       req.i2c_id = chip_id;
+       if (!capable(CAP_SYS_ADMIN)) return -EPERM;
+
+       req.match_type = match_type;
+       req.match_chip = match_chip;
        req.reg = reg_id;
        if (setFl) req.val = *val_ptr;
        mutex_lock(&hdw->i2c_list_lock); do {
                list_for_each(item,&hdw->i2c_clients) {
                        cp = list_entry(item,struct pvr2_i2c_client,list);
-                       if (cp->client->driver->id != chip_id) continue;
+                       if (!v4l2_chip_match_i2c_client(cp->client, req.match_type, req.match_chip)) {
+                               continue;
+                       }
                        stat = pvr2_i2c_client_cmd(
-                               cp,(setFl ? VIDIOC_INT_S_REGISTER :
-                                   VIDIOC_INT_G_REGISTER),&req);
+                               cp,(setFl ? VIDIOC_DBG_S_REGISTER :
+                                   VIDIOC_DBG_G_REGISTER),&req);
                        if (!setFl) *val_ptr = req.val;
                        okFl = !0;
                        break;
index 29979bb2a7689fd3d43bb9d2f5634ade6fb4c1c1..0c9cca43ff854042fc97a94c9006d60ccdd83d06 100644 (file)
 #define PVR2_CVAL_INPUT_COMPOSITE 2
 #define PVR2_CVAL_INPUT_RADIO 3
 
-/* Values that pvr2_hdw_get_signal_status() returns */
-#define PVR2_SIGNAL_OK     0x0001
-#define PVR2_SIGNAL_STEREO 0x0002
-#define PVR2_SIGNAL_SAP    0x0004
-
-
 /* Subsystem definitions - these are various pieces that can be
    independently stopped / started.  Usually you don't want to mess with
    this directly (let the driver handle things itself), but it is useful
        PVR2_SUBSYS_RUN_ALL )
 
 enum pvr2_config {
-       pvr2_config_empty,
-       pvr2_config_mpeg,
-       pvr2_config_vbi,
-       pvr2_config_radio,
+       pvr2_config_empty,    /* No configuration */
+       pvr2_config_mpeg,     /* Encoded / compressed video */
+       pvr2_config_vbi,      /* Standard vbi info */
+       pvr2_config_pcm,      /* Audio raw pcm stream */
+       pvr2_config_rawvideo, /* Video raw frames */
+};
+
+enum pvr2_v4l_type {
+       pvr2_v4l_type_video,
+       pvr2_v4l_type_vbi,
+       pvr2_v4l_type_radio,
 };
 
 const char *pvr2_config_get_name(enum pvr2_config);
@@ -148,8 +149,11 @@ int pvr2_hdw_commit_ctl(struct pvr2_hdw *);
 /* Return name for this driver instance */
 const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *);
 
-/* Return PVR2_SIGNAL_XXXX bit mask indicating signal status */
-unsigned int pvr2_hdw_get_signal_status(struct pvr2_hdw *);
+/* Mark tuner status stale so that it will be re-fetched */
+void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *);
+
+/* Return information about the tuner */
+int pvr2_hdw_get_tuner_status(struct pvr2_hdw *,struct v4l2_tuner *);
 
 /* Query device and see if it thinks it is on a high-speed USB link */
 int pvr2_hdw_is_hsm(struct pvr2_hdw *);
@@ -205,20 +209,22 @@ int pvr2_hdw_cpufw_get_enabled(struct pvr2_hdw *);
 int pvr2_hdw_cpufw_get(struct pvr2_hdw *,unsigned int offs,
                       char *buf,unsigned int cnt);
 
-/* Retrieve previously stored v4l minor device number */
-int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *);
+/* Retrieve previously stored v4l minor device number */
+int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *,enum pvr2_v4l_type index);
 
-/* Store the v4l minor device number */
-void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *,int);
+/* Store a v4l minor device number */
+void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *,
+                                    enum pvr2_v4l_type index,int);
 
 /* Direct read/write access to chip's registers:
-   chip_id - unique id of chip (e.g. I2C_DRIVERD_xxxx)
+   match_type - how to interpret match_chip (e.g. driver ID, i2c address)
+   match_chip - chip match value (e.g. I2C_DRIVERD_xxxx)
    reg_id  - register number to access
    setFl   - true to set the register, false to read it
    val_ptr - storage location for source / result. */
 int pvr2_hdw_register_access(struct pvr2_hdw *,
-                            u32 chip_id,unsigned long reg_id,
-                            int setFl,u32 *val_ptr);
+                            u32 match_type, u32 match_chip,u64 reg_id,
+                            int setFl,u64 *val_ptr);
 
 /* The following entry points are all lower level things you normally don't
    want to worry about. */
index 05121666b9ba5c6a516dcf76023c7a4602ac8401..49773764383b73eac164ba6e768f34405aa0d20f 100644 (file)
 #define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__)
 
 #define OP_STANDARD 0
-#define OP_BCSH 1
-#define OP_VOLUME 2
-#define OP_FREQ 3
-#define OP_AUDIORATE 4
-#define OP_SIZE 5
-#define OP_LOG 6
+#define OP_AUDIOMODE 1
+#define OP_BCSH 2
+#define OP_VOLUME 3
+#define OP_FREQ 4
+#define OP_AUDIORATE 5
+#define OP_SIZE 6
+#define OP_LOG 7
 
 static const struct pvr2_i2c_op * const ops[] = {
        [OP_STANDARD] = &pvr2_i2c_op_v4l2_standard,
+       [OP_AUDIOMODE] = &pvr2_i2c_op_v4l2_audiomode,
        [OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh,
        [OP_VOLUME] = &pvr2_i2c_op_v4l2_volume,
        [OP_FREQ] = &pvr2_i2c_op_v4l2_frequency,
@@ -54,11 +56,13 @@ void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
        int id;
        id = cp->client->driver->id;
        cp->ctl_mask = ((1 << OP_STANDARD) |
+                       (1 << OP_AUDIOMODE) |
                        (1 << OP_BCSH) |
                        (1 << OP_VOLUME) |
                        (1 << OP_FREQ) |
                        (1 << OP_SIZE) |
                        (1 << OP_LOG));
+       cp->status_poll = pvr2_v4l2_cmd_status_poll;
 
        if (id == I2C_DRIVERID_MSP3400) {
                if (pvr2_i2c_msp3400_setup(hdw,cp)) {
index 05ea17afe9037817567c710b4c06e3dae94ddc6b..c650e02ccd005d13fe4f8c9debc73d07fbc374f3 100644 (file)
 #include "pvrusb2-hdw-internal.h"
 #include "pvrusb2-debug.h"
 #include <linux/videodev2.h>
-
+#include <media/v4l2-common.h>
 
 static void set_standard(struct pvr2_hdw *hdw)
 {
-       v4l2_std_id vs;
-       vs = hdw->std_mask_cur;
-       pvr2_trace(PVR2_TRACE_CHIPS,
-                  "i2c v4l2 set_standard(0x%llx)",(long long unsigned)vs);
-
-       pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs);
+       pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_standard");
+
+       if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+               pvr2_i2c_core_cmd(hdw,AUDC_SET_RADIO,NULL);
+       } else {
+               v4l2_std_id vs;
+               vs = hdw->std_mask_cur;
+               pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs);
+       }
+       hdw->tuner_signal_stale = !0;
 }
 
 
 static int check_standard(struct pvr2_hdw *hdw)
 {
-       return hdw->std_dirty != 0;
+       return (hdw->input_dirty != 0) || (hdw->std_dirty != 0);
 }
 
 
@@ -136,16 +140,53 @@ const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume = {
 };
 
 
+static void set_audiomode(struct pvr2_hdw *hdw)
+{
+       struct v4l2_tuner vt;
+       memset(&vt,0,sizeof(vt));
+       vt.audmode = hdw->audiomode_val;
+       pvr2_i2c_core_cmd(hdw,VIDIOC_S_TUNER,&vt);
+}
+
+
+static int check_audiomode(struct pvr2_hdw *hdw)
+{
+       return (hdw->input_dirty ||
+               hdw->audiomode_dirty);
+}
+
+
+const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode = {
+       .check = check_audiomode,
+       .update = set_audiomode,
+       .name = "v4l2_audiomode",
+};
+
+
 static void set_frequency(struct pvr2_hdw *hdw)
 {
        unsigned long fv;
        struct v4l2_frequency freq;
-       fv = hdw->freqVal;
+       fv = pvr2_hdw_get_cur_freq(hdw);
        pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_freq(%lu)",fv);
+       if (hdw->tuner_signal_stale) {
+               pvr2_i2c_core_status_poll(hdw);
+       }
        memset(&freq,0,sizeof(freq));
-       freq.frequency = fv / 62500;
+       if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) {
+               // ((fv * 1000) / 62500)
+               freq.frequency = (fv * 2) / 125;
+       } else {
+               freq.frequency = fv / 62500;
+       }
+       /* tuner-core currently doesn't seem to care about this, but
+          let's set it anyway for completeness. */
+       if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+               freq.type = V4L2_TUNER_RADIO;
+       } else {
+               freq.type = V4L2_TUNER_ANALOG_TV;
+       }
        freq.tuner = 0;
-       freq.type = V4L2_TUNER_ANALOG_TV;
        pvr2_i2c_core_cmd(hdw,VIDIOC_S_FREQUENCY,&freq);
 }
 
@@ -221,6 +262,12 @@ void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *cp,int fl)
 }
 
 
+void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *cp)
+{
+       pvr2_i2c_client_cmd(cp,VIDIOC_G_TUNER,&cp->hdw->tuner_signal_info);
+}
+
+
 /*
   Stuff for Emacs to see, in order to encourage consistent editing style:
   *** Local Variables: ***
index ecabddba1ec50a1d0e9c675d22a4598f70fc1986..c838df6167f96ad4f715d95fd2e8018a9d4d5447 100644 (file)
 #include "pvrusb2-i2c-core.h"
 
 extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard;
+extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_radio;
 extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh;
 extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume;
 extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency;
 extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size;
+extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode;
 extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log;
 
 void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *,int);
+void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *);
 
 #endif /* __PVRUSB2_CMD_V4L2_H */
 
index 62a7cfca837dae7846a5faf299f88ccb4977527e..58fc3c730fe189bb5f608f42a04a9316fd10be41 100644 (file)
@@ -22,6 +22,7 @@
 #include "pvrusb2-i2c-core.h"
 #include "pvrusb2-hdw-internal.h"
 #include "pvrusb2-debug.h"
+#include "pvrusb2-fx2-cmd.h"
 
 #define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__)
 
@@ -66,7 +67,7 @@ static int pvr2_i2c_write(struct pvr2_hdw *hdw, /* Context */
        memset(hdw->cmd_buffer, 0, sizeof(hdw->cmd_buffer));
 
        /* Set up command buffer for an I2C write */
-       hdw->cmd_buffer[0] = 0x08;      /* write prefix */
+       hdw->cmd_buffer[0] = FX2CMD_I2C_WRITE;      /* write prefix */
        hdw->cmd_buffer[1] = i2c_addr;  /* i2c addr of chip */
        hdw->cmd_buffer[2] = length;    /* length of what follows */
        if (length) memcpy(hdw->cmd_buffer + 3, data, length);
@@ -128,7 +129,7 @@ static int pvr2_i2c_read(struct pvr2_hdw *hdw, /* Context */
        memset(hdw->cmd_buffer, 0, sizeof(hdw->cmd_buffer));
 
        /* Set up command buffer for an I2C write followed by a read */
-       hdw->cmd_buffer[0] = 0x09;  /* read prefix */
+       hdw->cmd_buffer[0] = FX2CMD_I2C_READ;  /* read prefix */
        hdw->cmd_buffer[1] = dlen;  /* arg length */
        hdw->cmd_buffer[2] = rlen;  /* answer length. Device will send one
                                       more byte (status). */
@@ -221,7 +222,7 @@ static int i2c_24xxx_ir(struct pvr2_hdw *hdw,
 
        /* Issue a command to the FX2 to read the IR receiver. */
        LOCK_TAKE(hdw->ctl_lock); do {
-               hdw->cmd_buffer[0] = 0xec;
+               hdw->cmd_buffer[0] = FX2CMD_GET_IR_CODE;
                stat = pvr2_send_request(hdw,
                                         hdw->cmd_buffer,1,
                                         hdw->cmd_buffer,4);
@@ -590,6 +591,33 @@ static int handler_check(struct pvr2_i2c_client *cp)
 
 #define BUFSIZE 500
 
+
+void pvr2_i2c_core_status_poll(struct pvr2_hdw *hdw)
+{
+       struct list_head *item;
+       struct pvr2_i2c_client *cp;
+       mutex_lock(&hdw->i2c_list_lock); do {
+               struct v4l2_tuner *vtp = &hdw->tuner_signal_info;
+               memset(vtp,0,sizeof(*vtp));
+               list_for_each(item,&hdw->i2c_clients) {
+                       cp = list_entry(item,struct pvr2_i2c_client,list);
+                       if (!cp->detected_flag) continue;
+                       if (!cp->status_poll) continue;
+                       cp->status_poll(cp);
+               }
+               hdw->tuner_signal_stale = 0;
+               pvr2_trace(PVR2_TRACE_CHIPS,"i2c status poll"
+                          " type=%u strength=%u audio=0x%x cap=0x%x"
+                          " low=%u hi=%u",
+                          vtp->type,
+                          vtp->signal,vtp->rxsubchans,vtp->capability,
+                          vtp->rangelow,vtp->rangehigh);
+       } while (0); mutex_unlock(&hdw->i2c_list_lock);
+}
+
+
+/* Issue various I2C operations to bring chip-level drivers into sync with
+   state stored in this driver. */
 void pvr2_i2c_core_sync(struct pvr2_hdw *hdw)
 {
        unsigned long msk;
@@ -870,12 +898,12 @@ static int pvr2_i2c_attach_inform(struct i2c_client *client)
        struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data);
        struct pvr2_i2c_client *cp;
        int fl = !(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL);
-       cp = kmalloc(sizeof(*cp),GFP_KERNEL);
+       cp = kzalloc(sizeof(*cp),GFP_KERNEL);
        trace_i2c("i2c_attach [client=%s @ 0x%x ctxt=%p]",
                  client->name,
                  client->addr,cp);
        if (!cp) return -ENOMEM;
-       memset(cp,0,sizeof(*cp));
+       cp->hdw = hdw;
        INIT_LIST_HEAD(&cp->list);
        cp->client = client;
        mutex_lock(&hdw->i2c_list_lock); do {
@@ -948,8 +976,7 @@ static void do_i2c_scan(struct pvr2_hdw *hdw)
        printk("%s: i2c scan beginning\n",hdw->name);
        for (i = 0; i < 128; i++) {
                msg[0].addr = i;
-               rc = i2c_transfer(&hdw->i2c_adap,msg,
-                                 sizeof(msg)/sizeof(msg[0]));
+               rc = i2c_transfer(&hdw->i2c_adap,msg, ARRAY_SIZE(msg));
                if (rc != 1) continue;
                printk("%s: i2c scan: found device @ 0x%x\n",hdw->name,i);
        }
index 6d7e252475760fd2dbb5f20986d11ab7991f1b85..bd0807b905bbdb9ce4d4039ab7be099c59d1ea84 100644 (file)
@@ -35,10 +35,12 @@ struct pvr2_i2c_client {
        struct i2c_client *client;
        struct pvr2_i2c_handler *handler;
        struct list_head list;
+       struct pvr2_hdw *hdw;
        int detected_flag;
        int recv_enable;
        unsigned long pend_mask;
        unsigned long ctl_mask;
+       void (*status_poll)(struct pvr2_i2c_client *);
 };
 
 struct pvr2_i2c_handler {
@@ -67,6 +69,7 @@ int pvr2_i2c_core_cmd(struct pvr2_hdw *,unsigned int cmd,void *arg);
 
 int pvr2_i2c_core_check_stale(struct pvr2_hdw *);
 void pvr2_i2c_core_sync(struct pvr2_hdw *);
+void pvr2_i2c_core_status_poll(struct pvr2_hdw *);
 unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen);
 #define PVR2_I2C_DETAIL_DEBUG   0x0001
 #define PVR2_I2C_DETAIL_HANDLER 0x0002
index 57fb32033543a1b4749cb429e8eb607b2f636f24..ce3c8982ffe088aa6378da27ef18a9af4e6e9545 100644 (file)
@@ -474,9 +474,8 @@ static void buffer_complete(struct urb *urb)
 struct pvr2_stream *pvr2_stream_create(void)
 {
        struct pvr2_stream *sp;
-       sp = kmalloc(sizeof(*sp),GFP_KERNEL);
+       sp = kzalloc(sizeof(*sp),GFP_KERNEL);
        if (!sp) return sp;
-       memset(sp,0,sizeof(*sp));
        pvr2_trace(PVR2_TRACE_INIT,"pvr2_stream_create: sp=%p",sp);
        pvr2_stream_init(sp);
        return sp;
index b71f9a961f8ac20461df5043b5487741607128c0..f782418afa45db71c6a07e27382db0e5a5637b3e 100644 (file)
@@ -87,10 +87,9 @@ static void pvr2_ioread_done(struct pvr2_ioread *cp)
 struct pvr2_ioread *pvr2_ioread_create(void)
 {
        struct pvr2_ioread *cp;
-       cp = kmalloc(sizeof(*cp),GFP_KERNEL);
+       cp = kzalloc(sizeof(*cp),GFP_KERNEL);
        if (!cp) return NULL;
        pvr2_trace(PVR2_TRACE_STRUCT,"pvr2_ioread_create id=%p",cp);
-       memset(cp,0,sizeof(*cp));
        if (pvr2_ioread_init(cp) < 0) {
                kfree(cp);
                return NULL;
index c08925557ed45755232f9e83c8b49f8534a4f076..81de26ba41d9af1527f87f6a68d7bf9cda025a7b 100644 (file)
@@ -141,10 +141,8 @@ int pvr2_std_str_to_id(v4l2_std_id *idPtr,const char *bufPtr,
                        cnt = 0;
                        while ((cnt < bufSize) && (bufPtr[cnt] != '-')) cnt++;
                        if (cnt >= bufSize) return 0; // No more characters
-                       sp = find_std_name(
-                               std_groups,
-                               sizeof(std_groups)/sizeof(std_groups[0]),
-                               bufPtr,cnt);
+                       sp = find_std_name(std_groups, ARRAY_SIZE(std_groups),
+                                          bufPtr,cnt);
                        if (!sp) return 0; // Illegal color system name
                        cnt++;
                        bufPtr += cnt;
@@ -163,8 +161,7 @@ int pvr2_std_str_to_id(v4l2_std_id *idPtr,const char *bufPtr,
                        if (ch == '/') break;
                        cnt++;
                }
-               sp = find_std_name(std_items,
-                                  sizeof(std_items)/sizeof(std_items[0]),
+               sp = find_std_name(std_items, ARRAY_SIZE(std_items),
                                   bufPtr,cnt);
                if (!sp) return 0; // Illegal modulation system ID
                t = sp->id & cmsk;
@@ -189,14 +186,10 @@ unsigned int pvr2_std_id_to_str(char *bufPtr, unsigned int bufSize,
        unsigned int c1,c2;
        cfl = 0;
        c1 = 0;
-       for (idx1 = 0;
-            idx1 < sizeof(std_groups)/sizeof(std_groups[0]);
-            idx1++) {
+       for (idx1 = 0; idx1 < ARRAY_SIZE(std_groups); idx1++) {
                gp = std_groups + idx1;
                gfl = 0;
-               for (idx2 = 0;
-                    idx2 < sizeof(std_items)/sizeof(std_items[0]);
-                    idx2++) {
+               for (idx2 = 0; idx2 < ARRAY_SIZE(std_items); idx2++) {
                        ip = std_items + idx2;
                        if (!(gp->id & ip->id & id)) continue;
                        if (!gfl) {
@@ -279,7 +272,7 @@ static struct v4l2_standard generic_standards[] = {
        }
 };
 
-#define generic_standards_cnt (sizeof(generic_standards)/sizeof(generic_standards[0]))
+#define generic_standards_cnt ARRAY_SIZE(generic_standards)
 
 static struct v4l2_standard *match_std(v4l2_std_id id)
 {
@@ -348,7 +341,7 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
                fmsk |= idmsk;
        }
 
-       for (idx2 = 0; idx2 < sizeof(std_mixes)/sizeof(std_mixes[0]); idx2++) {
+       for (idx2 = 0; idx2 < ARRAY_SIZE(std_mixes); idx2++) {
                if ((id & std_mixes[idx2]) == std_mixes[idx2]) std_cnt++;
        }
 
@@ -366,16 +359,15 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
                   std_cnt);
        if (!std_cnt) return NULL; // paranoia
 
-       stddefs = kmalloc(sizeof(struct v4l2_standard) * std_cnt,
+       stddefs = kzalloc(sizeof(struct v4l2_standard) * std_cnt,
                          GFP_KERNEL);
-       memset(stddefs,0,sizeof(struct v4l2_standard) * std_cnt);
        for (idx = 0; idx < std_cnt; idx++) stddefs[idx].index = idx;
 
        idx = 0;
 
        /* Enumerate potential special cases */
-       for (idx2 = 0; ((idx2 < sizeof(std_mixes)/sizeof(std_mixes[0])) &&
-                       (idx < std_cnt)); idx2++) {
+       for (idx2 = 0; (idx2 < ARRAY_SIZE(std_mixes)) && (idx < std_cnt);
+            idx2++) {
                if (!(id & std_mixes[idx2])) continue;
                if (pvr2_std_fill(stddefs+idx,std_mixes[idx2])) idx++;
        }
index c294f46db9b9f421c0a7648ec3cdc9e567098fe1..91396fd573e4a2c2a04f2b518d8a2811a8c60248 100644 (file)
@@ -40,8 +40,10 @@ struct pvr2_sysfs {
        struct pvr2_sysfs_ctl_item *item_first;
        struct pvr2_sysfs_ctl_item *item_last;
        struct class_device_attribute attr_v4l_minor_number;
+       struct class_device_attribute attr_v4l_radio_minor_number;
        struct class_device_attribute attr_unit_number;
        int v4l_minor_number_created_ok;
+       int v4l_radio_minor_number_created_ok;
        int unit_number_created_ok;
 };
 
@@ -491,7 +493,7 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
        unsigned int cnt,acnt;
        int ret;
 
-       if ((ctl_id < 0) || (ctl_id >= (sizeof(funcs)/sizeof(funcs[0])))) {
+       if ((ctl_id < 0) || (ctl_id >= ARRAY_SIZE(funcs))) {
                return;
        }
 
@@ -499,9 +501,8 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
        cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,ctl_id);
        if (!cptr) return;
 
-       cip = kmalloc(sizeof(*cip),GFP_KERNEL);
+       cip = kzalloc(sizeof(*cip),GFP_KERNEL);
        if (!cip) return;
-       memset(cip,0,sizeof(*cip));
        pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip);
 
        cip->cptr = cptr;
@@ -611,9 +612,8 @@ static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
        struct pvr2_sysfs_debugifc *dip;
        int ret;
 
-       dip = kmalloc(sizeof(*dip),GFP_KERNEL);
+       dip = kzalloc(sizeof(*dip),GFP_KERNEL);
        if (!dip) return;
-       memset(dip,0,sizeof(*dip));
        dip->attr_debugcmd.attr.owner = THIS_MODULE;
        dip->attr_debugcmd.attr.name = "debugcmd";
        dip->attr_debugcmd.attr.mode = S_IRUGO|S_IWUSR|S_IWGRP;
@@ -709,6 +709,10 @@ static void class_dev_destroy(struct pvr2_sysfs *sfp)
                class_device_remove_file(sfp->class_dev,
                                         &sfp->attr_v4l_minor_number);
        }
+       if (sfp->v4l_radio_minor_number_created_ok) {
+               class_device_remove_file(sfp->class_dev,
+                                        &sfp->attr_v4l_radio_minor_number);
+       }
        if (sfp->unit_number_created_ok) {
                class_device_remove_file(sfp->class_dev,
                                         &sfp->attr_unit_number);
@@ -726,7 +730,20 @@ static ssize_t v4l_minor_number_show(struct class_device *class_dev,char *buf)
        sfp = (struct pvr2_sysfs *)class_dev->class_data;
        if (!sfp) return -EINVAL;
        return scnprintf(buf,PAGE_SIZE,"%d\n",
-                        pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw));
+                        pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw,
+                                                      pvr2_v4l_type_video));
+}
+
+
+static ssize_t v4l_radio_minor_number_show(struct class_device *class_dev,
+                                          char *buf)
+{
+       struct pvr2_sysfs *sfp;
+       sfp = (struct pvr2_sysfs *)class_dev->class_data;
+       if (!sfp) return -EINVAL;
+       return scnprintf(buf,PAGE_SIZE,"%d\n",
+                        pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw,
+                                                      pvr2_v4l_type_radio));
 }
 
 
@@ -749,9 +766,8 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
 
        usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw);
        if (!usb_dev) return;
-       class_dev = kmalloc(sizeof(*class_dev),GFP_KERNEL);
+       class_dev = kzalloc(sizeof(*class_dev),GFP_KERNEL);
        if (!class_dev) return;
-       memset(class_dev,0,sizeof(*class_dev));
 
        pvr2_sysfs_trace("Creating class_dev id=%p",class_dev);
 
@@ -793,6 +809,20 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
                sfp->v4l_minor_number_created_ok = !0;
        }
 
+       sfp->attr_v4l_radio_minor_number.attr.owner = THIS_MODULE;
+       sfp->attr_v4l_radio_minor_number.attr.name = "v4l_radio_minor_number";
+       sfp->attr_v4l_radio_minor_number.attr.mode = S_IRUGO;
+       sfp->attr_v4l_radio_minor_number.show = v4l_radio_minor_number_show;
+       sfp->attr_v4l_radio_minor_number.store = NULL;
+       ret = class_device_create_file(sfp->class_dev,
+                                      &sfp->attr_v4l_radio_minor_number);
+       if (ret < 0) {
+               printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+                      __FUNCTION__, ret);
+       } else {
+               sfp->v4l_radio_minor_number_created_ok = !0;
+       }
+
        sfp->attr_unit_number.attr.owner = THIS_MODULE;
        sfp->attr_unit_number.attr.name = "unit_number";
        sfp->attr_unit_number.attr.mode = S_IRUGO;
@@ -829,9 +859,8 @@ struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *mp,
                                     struct pvr2_sysfs_class *class_ptr)
 {
        struct pvr2_sysfs *sfp;
-       sfp = kmalloc(sizeof(*sfp),GFP_KERNEL);
+       sfp = kzalloc(sizeof(*sfp),GFP_KERNEL);
        if (!sfp) return sfp;
-       memset(sfp,0,sizeof(*sfp));
        pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_sysfs id=%p",sfp);
        pvr2_channel_init(&sfp->channel,mp);
        sfp->channel.check_func = pvr2_sysfs_internal_check;
@@ -852,9 +881,8 @@ static int pvr2_sysfs_hotplug(struct class_device *cd,char **envp,
 struct pvr2_sysfs_class *pvr2_sysfs_class_create(void)
 {
        struct pvr2_sysfs_class *clp;
-       clp = kmalloc(sizeof(*clp),GFP_KERNEL);
+       clp = kzalloc(sizeof(*clp),GFP_KERNEL);
        if (!clp) return clp;
-       memset(clp,0,sizeof(*clp));
        pvr2_sysfs_trace("Creating pvr2_sysfs_class id=%p",clp);
        clp->class.name = "pvrusb2";
        clp->class.class_release = pvr2_sysfs_class_release;
index bb17db3f6434a6e50f1bfea5bffe2095145bf26d..05e65ce2e3a96109684695c841b2cb06675cbc58 100644 (file)
@@ -93,9 +93,8 @@ int pvr2_i2c_tuner_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
        struct pvr2_tuner_handler *ctxt;
        if (cp->handler) return 0;
 
-       ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
+       ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL);
        if (!ctxt) return 0;
-       memset(ctxt,0,sizeof(*ctxt));
 
        ctxt->i2c_handler.func_data = ctxt;
        ctxt->i2c_handler.func_table = &tuner_funcs;
index 6cf17080eb49c5deaf29f53d2feb40700612800e..5313d342666e4e4a0b2507d20df67d83ec42a375 100644 (file)
@@ -40,7 +40,10 @@ struct pvr2_v4l2_dev {
        struct video_device devbase; /* MUST be first! */
        struct pvr2_v4l2 *v4lp;
        struct pvr2_context_stream *stream;
-       enum pvr2_config config;
+       /* Information about this device: */
+       enum pvr2_config config; /* Expected stream format */
+       int v4l_type; /* V4L defined type for this device node */
+       enum pvr2_v4l_type minor_type; /* pvr2-understood minor device type */
 };
 
 struct pvr2_v4l2_fh {
@@ -54,6 +57,7 @@ struct pvr2_v4l2_fh {
        struct pvr2_v4l2_fh *vprev;
        wait_queue_head_t wait_data;
        int fw_mode_flag;
+       int prev_input_val;
 };
 
 struct pvr2_v4l2 {
@@ -63,13 +67,22 @@ struct pvr2_v4l2 {
 
        struct v4l2_prio_state prio;
 
-       /* streams */
-       struct pvr2_v4l2_dev *vdev;
+       /* streams - Note that these must be separately, individually,
+        * allocated pointers.  This is because the v4l core is going to
+        * manage their deletion - separately, individually...  */
+       struct pvr2_v4l2_dev *dev_video;
+       struct pvr2_v4l2_dev *dev_radio;
 };
 
 static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
 module_param_array(video_nr, int, NULL, 0444);
-MODULE_PARM_DESC(video_nr, "Offset for device's minor");
+MODULE_PARM_DESC(video_nr, "Offset for device's video dev minor");
+static int radio_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
+module_param_array(radio_nr, int, NULL, 0444);
+MODULE_PARM_DESC(radio_nr, "Offset for device's radio dev minor");
+static int vbi_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
+module_param_array(vbi_nr, int, NULL, 0444);
+MODULE_PARM_DESC(vbi_nr, "Offset for device's vbi dev minor");
 
 static struct v4l2_capability pvr_capability ={
        .driver         = "pvrusb2",
@@ -77,30 +90,11 @@ static struct v4l2_capability pvr_capability ={
        .bus_info       = "usb",
        .version        = KERNEL_VERSION(0,8,0),
        .capabilities   = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
-                          V4L2_CAP_TUNER | V4L2_CAP_AUDIO |
+                          V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
                           V4L2_CAP_READWRITE),
        .reserved       = {0,0,0,0}
 };
 
-static struct v4l2_tuner pvr_v4l2_tuners[]= {
-       {
-               .index      = 0,
-               .name       = "TV Tuner",
-               .type           = V4L2_TUNER_ANALOG_TV,
-               .capability     = (V4L2_TUNER_CAP_NORM |
-                                  V4L2_TUNER_CAP_STEREO |
-                                  V4L2_TUNER_CAP_LANG1 |
-                                  V4L2_TUNER_CAP_LANG2),
-               .rangelow   = 0,
-               .rangehigh  = 0,
-               .rxsubchans     = V4L2_TUNER_SUB_STEREO,
-               .audmode        = V4L2_TUNER_MODE_STEREO,
-               .signal         = 0,
-               .afc            = 0,
-               .reserved       = {0,0,0,0}
-       }
-};
-
 static struct v4l2_fmtdesc pvr_fmtdesc [] = {
        {
                .index          = 0,
@@ -154,6 +148,18 @@ static struct v4l2_format pvr_format [] = {
        }
 };
 
+
+static const char *get_v4l_name(int v4l_type)
+{
+       switch (v4l_type) {
+       case VFL_TYPE_GRABBER: return "video";
+       case VFL_TYPE_RADIO: return "radio";
+       case VFL_TYPE_VBI: return "vbi";
+       default: return "?";
+       }
+}
+
+
 /*
  * pvr_ioctl()
  *
@@ -315,13 +321,39 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
 
        case VIDIOC_ENUMAUDIO:
        {
+               /* pkt: FIXME: We are returning one "fake" input here
+                  which could very well be called "whatever_we_like".
+                  This is for apps that want to see an audio input
+                  just to feel comfortable, as well as to test if
+                  it can do stereo or sth. There is actually no guarantee
+                  that the actual audio input cannot change behind the app's
+                  back, but most applications should not mind that either.
+
+                  Hopefully, mplayer people will work with us on this (this
+                  whole mess is to support mplayer pvr://), or Hans will come
+                  up with a more standard way to say "we have inputs but we
+                  don 't want you to change them independent of video" which
+                  will sort this mess.
+                */
+               struct v4l2_audio *vin = arg;
                ret = -EINVAL;
+               if (vin->index > 0) break;
+               strncpy(vin->name, "PVRUSB2 Audio",14);
+               vin->capability = V4L2_AUDCAP_STEREO;
+               ret = 0;
+               break;
                break;
        }
 
        case VIDIOC_G_AUDIO:
        {
-               ret = -EINVAL;
+               /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
+               struct v4l2_audio *vin = arg;
+               memset(vin,0,sizeof(*vin));
+               vin->index = 0;
+               strncpy(vin->name, "PVRUSB2 Audio",14);
+               vin->capability = V4L2_AUDCAP_STEREO;
+               ret = 0;
                break;
        }
 
@@ -333,34 +365,11 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
        case VIDIOC_G_TUNER:
        {
                struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
-               unsigned int status_mask;
-               int val;
-               if (vt->index !=0) break;
 
-               status_mask = pvr2_hdw_get_signal_status(hdw);
+               if (vt->index != 0) break; /* Only answer for the 1st tuner */
 
-               memcpy(vt, &pvr_v4l2_tuners[vt->index],
-                      sizeof(struct v4l2_tuner));
-
-               vt->signal = 0;
-               if (status_mask & PVR2_SIGNAL_OK) {
-                       if (status_mask & PVR2_SIGNAL_STEREO) {
-                               vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
-                       } else {
-                               vt->rxsubchans = V4L2_TUNER_SUB_MONO;
-                       }
-                       if (status_mask & PVR2_SIGNAL_SAP) {
-                               vt->rxsubchans |= (V4L2_TUNER_SUB_LANG1 |
-                                                  V4L2_TUNER_SUB_LANG2);
-                       }
-                       vt->signal = 65535;
-               }
-
-               val = 0;
-               ret = pvr2_ctrl_get_value(
-                       pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
-                       &val);
-               vt->audmode = val;
+               pvr2_hdw_execute_tuner_poll(hdw);
+               ret = pvr2_hdw_get_tuner_status(hdw,vt);
                break;
        }
 
@@ -374,14 +383,40 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
                ret = pvr2_ctrl_set_value(
                        pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
                        vt->audmode);
+               break;
        }
 
        case VIDIOC_S_FREQUENCY:
        {
                const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
+               unsigned long fv;
+               struct v4l2_tuner vt;
+               int cur_input;
+               struct pvr2_ctrl *ctrlp;
+               ret = pvr2_hdw_get_tuner_status(hdw,&vt);
+               if (ret != 0) break;
+               ctrlp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
+               ret = pvr2_ctrl_get_value(ctrlp,&cur_input);
+               if (ret != 0) break;
+               if (vf->type == V4L2_TUNER_RADIO) {
+                       if (cur_input != PVR2_CVAL_INPUT_RADIO) {
+                               pvr2_ctrl_set_value(ctrlp,
+                                                   PVR2_CVAL_INPUT_RADIO);
+                       }
+               } else {
+                       if (cur_input == PVR2_CVAL_INPUT_RADIO) {
+                               pvr2_ctrl_set_value(ctrlp,
+                                                   PVR2_CVAL_INPUT_TV);
+                       }
+               }
+               fv = vf->frequency;
+               if (vt.capability & V4L2_TUNER_CAP_LOW) {
+                       fv = (fv * 125) / 2;
+               } else {
+                       fv = fv * 62500;
+               }
                ret = pvr2_ctrl_set_value(
-                       pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
-                       vf->frequency * 62500);
+                       pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
                break;
        }
 
@@ -389,10 +424,27 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
        {
                struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
                int val = 0;
+               int cur_input;
+               struct v4l2_tuner vt;
+               ret = pvr2_hdw_get_tuner_status(hdw,&vt);
+               if (ret != 0) break;
                ret = pvr2_ctrl_get_value(
                        pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
                        &val);
-               val /= 62500;
+               if (ret != 0) break;
+               pvr2_ctrl_get_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
+                       &cur_input);
+               if (cur_input == PVR2_CVAL_INPUT_RADIO) {
+                       vf->type = V4L2_TUNER_RADIO;
+               } else {
+                       vf->type = V4L2_TUNER_ANALOG_TV;
+               }
+               if (vt.capability & V4L2_TUNER_CAP_LOW) {
+                       val = (val * 2) / 125;
+               } else {
+                       val /= 62500;
+               }
                vf->frequency = val;
                break;
        }
@@ -449,7 +501,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
                ret = 0;
                switch(vf->type) {
                case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
-                       int lmin,lmax;
+                       int lmin,lmax,ldef;
                        struct pvr2_ctrl *hcp,*vcp;
                        int h = vf->fmt.pix.height;
                        int w = vf->fmt.pix.width;
@@ -458,14 +510,20 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
 
                        lmin = pvr2_ctrl_get_min(hcp);
                        lmax = pvr2_ctrl_get_max(hcp);
-                       if (w < lmin) {
+                       ldef = pvr2_ctrl_get_def(hcp);
+                       if (w == -1) {
+                               w = ldef;
+                       } else if (w < lmin) {
                                w = lmin;
                        } else if (w > lmax) {
                                w = lmax;
                        }
                        lmin = pvr2_ctrl_get_min(vcp);
                        lmax = pvr2_ctrl_get_max(vcp);
-                       if (h < lmin) {
+                       ldef = pvr2_ctrl_get_def(vcp);
+                       if (h == -1) {
+                               h = ldef;
+                       } else if (h < lmin) {
                                h = lmin;
                        } else if (h > lmax) {
                                h = lmax;
@@ -494,6 +552,13 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
 
        case VIDIOC_STREAMON:
        {
+               if (!fh->dev_info->stream) {
+                       /* No stream defined for this node.  This means
+                          that we're not currently allowed to stream from
+                          this node. */
+                       ret = -EPERM;
+                       break;
+               }
                ret = pvr2_hdw_set_stream_type(hdw,dev_info->config);
                if (ret < 0) return ret;
                ret = pvr2_hdw_set_streaming(hdw,!0);
@@ -502,6 +567,13 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
 
        case VIDIOC_STREAMOFF:
        {
+               if (!fh->dev_info->stream) {
+                       /* No stream defined for this node.  This means
+                          that we're not currently allowed to stream from
+                          this node. */
+                       ret = -EPERM;
+                       break;
+               }
                ret = pvr2_hdw_set_streaming(hdw,0);
                break;
        }
@@ -599,6 +671,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
                struct v4l2_ext_control *ctrl;
                unsigned int idx;
                int val;
+               ret = 0;
                for (idx = 0; idx < ctls->count; idx++) {
                        ctrl = ctls->controls + idx;
                        ret = pvr2_ctrl_get_value(
@@ -621,6 +694,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
                        (struct v4l2_ext_controls *)arg;
                struct v4l2_ext_control *ctrl;
                unsigned int idx;
+               ret = 0;
                for (idx = 0; idx < ctls->count; idx++) {
                        ctrl = ctls->controls + idx;
                        ret = pvr2_ctrl_set_value(
@@ -643,6 +717,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
                unsigned int idx;
                /* For the moment just validate that the requested control
                   actually exists. */
+               ret = 0;
                for (idx = 0; idx < ctls->count; idx++) {
                        ctrl = ctls->controls + idx;
                        pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
@@ -662,16 +737,16 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
                break;
        }
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-       case VIDIOC_INT_G_REGISTER:
-       case VIDIOC_INT_S_REGISTER:
+       case VIDIOC_DBG_S_REGISTER:
+       case VIDIOC_DBG_G_REGISTER:
        {
-               u32 val;
+               u64 val;
                struct v4l2_register *req = (struct v4l2_register *)arg;
-               if (cmd == VIDIOC_INT_S_REGISTER) val = req->val;
+               if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val;
                ret = pvr2_hdw_register_access(
-                       hdw,req->i2c_id,req->reg,
-                       cmd == VIDIOC_INT_S_REGISTER,&val);
-               if (cmd == VIDIOC_INT_G_REGISTER) req->val = val;
+                       hdw,req->match_type,req->match_chip,req->reg,
+                       cmd == VIDIOC_DBG_S_REGISTER,&val);
+               if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val;
                break;
        }
 #endif
@@ -707,8 +782,12 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
 
 static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
 {
-       printk(KERN_INFO "pvrusb2: unregistering device video%d [%s]\n",
-              dip->devbase.minor,pvr2_config_get_name(dip->config));
+       int minor_id = dip->devbase.minor;
+       struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
+       enum pvr2_config cfg = dip->config;
+       int v4l_type = dip->v4l_type;
+
+       pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
 
        /* Paranoia */
        dip->v4lp = NULL;
@@ -717,13 +796,24 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
        /* Actual deallocation happens later when all internal references
           are gone. */
        video_unregister_device(&dip->devbase);
+
+       printk(KERN_INFO "pvrusb2: unregistered device %s%u [%s]\n",
+              get_v4l_name(v4l_type),minor_id & 0x1f,
+              pvr2_config_get_name(cfg));
+
 }
 
 
 static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
 {
-       pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,-1);
-       pvr2_v4l2_dev_destroy(vp->vdev);
+       if (vp->dev_video) {
+               pvr2_v4l2_dev_destroy(vp->dev_video);
+               vp->dev_video = 0;
+       }
+       if (vp->dev_radio) {
+               pvr2_v4l2_dev_destroy(vp->dev_radio);
+               vp->dev_radio = 0;
+       }
 
        pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
        pvr2_channel_done(&vp->channel);
@@ -766,23 +856,37 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file)
        struct pvr2_v4l2_fh *fhp = file->private_data;
        struct pvr2_v4l2 *vp = fhp->vhead;
        struct pvr2_context *mp = fhp->vhead->channel.mc_head;
+       struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
 
        pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
 
        if (fhp->rhp) {
                struct pvr2_stream *sp;
-               struct pvr2_hdw *hdw;
-               hdw = fhp->channel.mc_head->hdw;
                pvr2_hdw_set_streaming(hdw,0);
                sp = pvr2_ioread_get_stream(fhp->rhp);
                if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
                pvr2_ioread_destroy(fhp->rhp);
                fhp->rhp = NULL;
        }
+
        v4l2_prio_close(&vp->prio, &fhp->prio);
        file->private_data = NULL;
 
        pvr2_context_enter(mp); do {
+               /* Restore the previous input selection, if it makes sense
+                  to do so. */
+               if (fhp->dev_info->v4l_type == VFL_TYPE_RADIO) {
+                       struct pvr2_ctrl *cp;
+                       int pval;
+                       cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
+                       pvr2_ctrl_get_value(cp,&pval);
+                       /* Only restore if we're still selecting the radio */
+                       if (pval == PVR2_CVAL_INPUT_RADIO) {
+                               pvr2_ctrl_set_value(cp,fhp->prev_input_val);
+                               pvr2_hdw_commit_ctl(hdw);
+                       }
+               }
+
                if (fhp->vnext) {
                        fhp->vnext->vprev = fhp->vprev;
                } else {
@@ -828,11 +932,10 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file)
                return -EIO;
        }
 
-       fhp = kmalloc(sizeof(*fhp),GFP_KERNEL);
+       fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
        if (!fhp) {
                return -ENOMEM;
        }
-       memset(fhp,0,sizeof(*fhp));
 
        init_waitqueue_head(&fhp->wait_data);
        fhp->dev_info = dip;
@@ -840,6 +943,7 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file)
        pvr2_context_enter(vp->channel.mc_head); do {
                pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
                pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
+
                fhp->vnext = NULL;
                fhp->vprev = vp->vlast;
                if (vp->vlast) {
@@ -849,6 +953,18 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file)
                }
                vp->vlast = fhp;
                fhp->vhead = vp;
+
+               /* Opening the /dev/radioX device implies a mode switch.
+                  So execute that here.  Note that you can get the
+                  IDENTICAL effect merely by opening the normal video
+                  device and setting the input appropriately. */
+               if (dip->v4l_type == VFL_TYPE_RADIO) {
+                       struct pvr2_ctrl *cp;
+                       cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
+                       pvr2_ctrl_get_value(cp,&fhp->prev_input_val);
+                       pvr2_ctrl_set_value(cp,PVR2_CVAL_INPUT_RADIO);
+                       pvr2_hdw_commit_ctl(hdw);
+               }
        } while (0); pvr2_context_exit(vp->channel.mc_head);
 
        fhp->file = file;
@@ -873,6 +989,12 @@ static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
        struct pvr2_hdw *hdw;
        if (fh->rhp) return 0;
 
+       if (!fh->dev_info->stream) {
+               /* No stream defined for this node.  This means that we're
+                  not currently allowed to stream from this node. */
+               return -EPERM;
+       }
+
        /* First read() attempt.  Try to claim the stream and start
           it... */
        if ((ret = pvr2_channel_claim_stream(&fh->channel,
@@ -1012,25 +1134,37 @@ static struct video_device vdev_template = {
 
 static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
                               struct pvr2_v4l2 *vp,
-                              enum pvr2_config cfg)
+                              int v4l_type)
 {
        int mindevnum;
        int unit_number;
-       int v4l_type;
+       int *nr_ptr = 0;
        dip->v4lp = vp;
-       dip->config = cfg;
 
 
-       switch (cfg) {
-       case pvr2_config_mpeg:
-               v4l_type = VFL_TYPE_GRABBER;
+       dip->v4l_type = v4l_type;
+       switch (v4l_type) {
+       case VFL_TYPE_GRABBER:
                dip->stream = &vp->channel.mc_head->video_stream;
+               dip->config = pvr2_config_mpeg;
+               dip->minor_type = pvr2_v4l_type_video;
+               nr_ptr = video_nr;
+               if (!dip->stream) {
+                       err("Failed to set up pvrusb2 v4l video dev"
+                           " due to missing stream instance");
+                       return;
+               }
                break;
-       case pvr2_config_vbi:
-               v4l_type = VFL_TYPE_VBI;
+       case VFL_TYPE_VBI:
+               dip->config = pvr2_config_vbi;
+               dip->minor_type = pvr2_v4l_type_vbi;
+               nr_ptr = vbi_nr;
                break;
-       case pvr2_config_radio:
-               v4l_type = VFL_TYPE_RADIO;
+       case VFL_TYPE_RADIO:
+               dip->stream = &vp->channel.mc_head->video_stream;
+               dip->config = pvr2_config_mpeg;
+               dip->minor_type = pvr2_v4l_type_radio;
+               nr_ptr = radio_nr;
                break;
        default:
                /* Bail out (this should be impossible) */
@@ -1039,30 +1173,27 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
                return;
        }
 
-       if (!dip->stream) {
-               err("Failed to set up pvrusb2 v4l dev"
-                   " due to missing stream instance");
-               return;
-       }
-
        memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
        dip->devbase.release = pvr2_video_device_release;
 
        mindevnum = -1;
        unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
-       if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
-               mindevnum = video_nr[unit_number];
+       if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
+               mindevnum = nr_ptr[unit_number];
        }
-       if ((video_register_device(&dip->devbase, v4l_type, mindevnum) < 0) &&
-           (video_register_device(&dip->devbase, v4l_type, -1) < 0)) {
-               err("Failed to register pvrusb2 v4l video device");
-       } else {
-               printk(KERN_INFO "pvrusb2: registered device video%d [%s]\n",
-                      dip->devbase.minor,pvr2_config_get_name(dip->config));
+       if ((video_register_device(&dip->devbase,
+                                  dip->v4l_type, mindevnum) < 0) &&
+           (video_register_device(&dip->devbase,
+                                  dip->v4l_type, -1) < 0)) {
+               err("Failed to register pvrusb2 v4l device");
        }
 
+       printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n",
+              get_v4l_name(dip->v4l_type),dip->devbase.minor & 0x1f,
+              pvr2_config_get_name(dip->config));
+
        pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
-                                       dip->devbase.minor);
+                                       dip->minor_type,dip->devbase.minor);
 }
 
 
@@ -1070,22 +1201,24 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
 {
        struct pvr2_v4l2 *vp;
 
-       vp = kmalloc(sizeof(*vp),GFP_KERNEL);
+       vp = kzalloc(sizeof(*vp),GFP_KERNEL);
        if (!vp) return vp;
-       memset(vp,0,sizeof(*vp));
-       vp->vdev = kmalloc(sizeof(*vp->vdev),GFP_KERNEL);
-       if (!vp->vdev) {
+       vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
+       vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
+       if (!(vp->dev_video && vp->dev_radio)) {
+               kfree(vp->dev_video);
+               kfree(vp->dev_radio);
                kfree(vp);
                return NULL;
        }
-       memset(vp->vdev,0,sizeof(*vp->vdev));
        pvr2_channel_init(&vp->channel,mnp);
        pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
 
        vp->channel.check_func = pvr2_v4l2_internal_check;
 
        /* register streams */
-       pvr2_v4l2_dev_init(vp->vdev,vp,pvr2_config_mpeg);
+       pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
+       pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
 
        return vp;
 }
index 2a826464911a7e6d0f553c029970b19f60d8c0f3..61efa6f02200e74dee598bf1d1ee765aed3faea9 100644 (file)
@@ -66,7 +66,9 @@ static void set_input(struct pvr2_v4l_decoder *ctxt)
                route.input = SAA7115_SVIDEO2;
                break;
        case PVR2_CVAL_INPUT_RADIO:
-               // ????? No idea yet what to do here
+               // In radio mode, we mute the video, but point at one
+               // spot just to stay consistent
+               route.input = SAA7115_COMPOSITE5;
        default:
                return;
        }
@@ -137,8 +139,7 @@ static int decoder_check(struct pvr2_v4l_decoder *ctxt)
        unsigned long msk;
        unsigned int idx;
 
-       for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]);
-            idx++) {
+       for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) {
                msk = 1 << idx;
                if (ctxt->stale_mask & msk) continue;
                if (decoder_ops[idx].check(ctxt)) {
@@ -154,8 +155,7 @@ static void decoder_update(struct pvr2_v4l_decoder *ctxt)
        unsigned long msk;
        unsigned int idx;
 
-       for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]);
-            idx++) {
+       for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) {
                msk = 1 << idx;
                if (!(ctxt->stale_mask & msk)) continue;
                ctxt->stale_mask &= ~msk;
@@ -183,18 +183,6 @@ static void decoder_enable(struct pvr2_v4l_decoder *ctxt,int fl)
 }
 
 
-static int decoder_is_tuned(struct pvr2_v4l_decoder *ctxt)
-{
-       struct v4l2_tuner vt;
-       int ret;
-
-       memset(&vt,0,sizeof(vt));
-       ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt);
-       if (ret < 0) return -EINVAL;
-       return vt.signal ? 1 : 0;
-}
-
-
 static unsigned int decoder_describe(struct pvr2_v4l_decoder *ctxt,char *buf,unsigned int cnt)
 {
        return scnprintf(buf,cnt,"handler: pvrusb2-video-v4l");
@@ -218,20 +206,17 @@ int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *hdw,
        if (cp->handler) return 0;
        if (!decoder_detect(cp)) return 0;
 
-       ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
+       ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL);
        if (!ctxt) return 0;
-       memset(ctxt,0,sizeof(*ctxt));
 
        ctxt->handler.func_data = ctxt;
        ctxt->handler.func_table = &hfuncs;
        ctxt->ctrl.ctxt = ctxt;
        ctxt->ctrl.detach = (void (*)(void *))decoder_detach;
        ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable;
-       ctxt->ctrl.tuned = (int (*)(void *))decoder_is_tuned;
        ctxt->client = cp;
        ctxt->hdw = hdw;
-       ctxt->stale_mask = (1 << (sizeof(decoder_ops)/
-                                 sizeof(decoder_ops[0]))) - 1;
+       ctxt->stale_mask = (1 << ARRAY_SIZE(decoder_ops)) - 1;
        hdw->decoder_ctrl = &ctxt->ctrl;
        cp->handler = &ctxt->handler;
        pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x saa711x V4L2 handler set up",
index 7794c34c355e18e248970a11de55a5e4c8c9c986..66b4d36ef76585f23af0c7e44cc7334e15490c17 100644 (file)
@@ -50,15 +50,21 @@ static void set_input(struct pvr2_v4l_wm8775 *ctxt)
 {
        struct v4l2_routing route;
        struct pvr2_hdw *hdw = ctxt->hdw;
-       int msk = 0;
 
        memset(&route,0,sizeof(route));
 
-       pvr2_trace(PVR2_TRACE_CHIPS,"i2c wm8775 set_input(val=%d msk=0x%x)",
-                  hdw->input_val,msk);
+       switch(hdw->input_val) {
+       case PVR2_CVAL_INPUT_RADIO:
+               route.input = 1;
+               break;
+       default:
+               /* All other cases just use the second input */
+               route.input = 2;
+               break;
+       }
+       pvr2_trace(PVR2_TRACE_CHIPS,"i2c wm8775 set_input(val=%d route=0x%x)",
+                  hdw->input_val,route.input);
 
-       // Always point to input #1 no matter what
-       route.input = 2;
        pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route);
 }
 
@@ -99,8 +105,7 @@ static int wm8775_check(struct pvr2_v4l_wm8775 *ctxt)
        unsigned long msk;
        unsigned int idx;
 
-       for (idx = 0; idx < sizeof(wm8775_ops)/sizeof(wm8775_ops[0]);
-            idx++) {
+       for (idx = 0; idx < ARRAY_SIZE(wm8775_ops); idx++) {
                msk = 1 << idx;
                if (ctxt->stale_mask & msk) continue;
                if (wm8775_ops[idx].check(ctxt)) {
@@ -116,8 +121,7 @@ static void wm8775_update(struct pvr2_v4l_wm8775 *ctxt)
        unsigned long msk;
        unsigned int idx;
 
-       for (idx = 0; idx < sizeof(wm8775_ops)/sizeof(wm8775_ops[0]);
-            idx++) {
+       for (idx = 0; idx < ARRAY_SIZE(wm8775_ops); idx++) {
                msk = 1 << idx;
                if (!(ctxt->stale_mask & msk)) continue;
                ctxt->stale_mask &= ~msk;
@@ -140,16 +144,14 @@ int pvr2_i2c_wm8775_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
 
        if (cp->handler) return 0;
 
-       ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
+       ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL);
        if (!ctxt) return 0;
-       memset(ctxt,0,sizeof(*ctxt));
 
        ctxt->handler.func_data = ctxt;
        ctxt->handler.func_table = &hfuncs;
        ctxt->client = cp;
        ctxt->hdw = hdw;
-       ctxt->stale_mask = (1 << (sizeof(wm8775_ops)/
-                                 sizeof(wm8775_ops[0]))) - 1;
+       ctxt->stale_mask = (1 << ARRAY_SIZE(wm8775_ops)) - 1;
        cp->handler = &ctxt->handler;
        pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x wm8775 V4L2 handler set up",
                   cp->client->addr);
index 9db2260d10ccb345c59845f7dd9ba33e5b1a8384..f5c8ec261e87d1cf64412c6bfbaf31529ceeb82c 100644 (file)
@@ -2,11 +2,3 @@ pwc-objs       := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-v4l.o pwc-uncompress.o
 pwc-objs       += pwc-dec1.o pwc-dec23.o pwc-kiara.o pwc-timon.o
 
 obj-$(CONFIG_USB_PWC) += pwc.o
-
-ifeq ($(CONFIG_USB_PWC_DEBUG),y)
-EXTRA_CFLAGS += -DCONFIG_PWC_DEBUG=1
-else
-EXTRA_CFLAGS += -DCONFIG_PWC_DEBUG=0
-endif
-
-
index 9825fd3481085cf3d0c921ad9b7460633acab64d..27ed76986ca27e837eefa0203b480dd945e5cc74 100644 (file)
@@ -128,7 +128,7 @@ static int default_size = PSZ_QCIF;
 static int default_fps = 10;
 static int default_fbufs = 3;   /* Default number of frame buffers */
        int pwc_mbufs = 2;      /* Default number of mmap() buffers */
-#if CONFIG_PWC_DEBUG
+#ifdef CONFIG_USB_PWC_DEBUG
        int pwc_trace = PWC_DEBUG_LEVEL;
 #endif
 static int power_save = 0;
@@ -1051,7 +1051,7 @@ static void pwc_remove_sysfs_files(struct video_device *vdev)
        video_device_remove_file(vdev, &class_device_attr_button);
 }
 
-#if CONFIG_PWC_DEBUG
+#ifdef CONFIG_USB_PWC_DEBUG
 static const char *pwc_sensor_type_to_string(unsigned int sensor_type)
 {
        switch(sensor_type) {
@@ -1835,7 +1835,7 @@ module_param(size, charp, 0444);
 module_param(fps, int, 0444);
 module_param(fbufs, int, 0444);
 module_param(mbufs, int, 0444);
-#if CONFIG_PWC_DEBUG
+#ifdef CONFIG_USB_PWC_DEBUG
 module_param_named(trace, pwc_trace, int, 0644);
 #endif
 module_param(power_save, int, 0444);
@@ -1908,7 +1908,7 @@ static int __init usb_pwc_init(void)
                default_fbufs = fbufs;
                PWC_DEBUG_MODULE("Number of frame buffers set to %d.\n", default_fbufs);
        }
-#if CONFIG_PWC_DEBUG
+#ifdef CONFIG_USB_PWC_DEBUG
        if (pwc_trace >= 0) {
                PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace);
        }
index b7eb3ce3b968122868de2dd206eef648f55ac7cb..d5e6bc850643a7ca7f3cce05bb03971183494b70 100644 (file)
@@ -350,7 +350,7 @@ int pwc_video_do_ioctl(struct inode *inode, struct file *file,
        if (pdev == NULL)
                return -EFAULT;
 
-#if CONFIG_PWC_DEBUG
+#ifdef CONFIG_USB_PWC_DEBUG
        if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace)
                v4l_printk_ioctl(cmd);
 #endif
index 7e9c4237d1e8ad145835c88d4a9e0625e8eb3ed5..e778a2b8c2807e2e0a68f4630fab6f9485b04503 100644 (file)
 #include "pwc-uncompress.h"
 #include <media/pwc-ioctl.h>
 
-/* Turn some debugging options on/off */
-#ifndef CONFIG_PWC_DEBUG
-#define CONFIG_PWC_DEBUG 1
-#endif
-
 /* Version block */
 #define PWC_MAJOR      10
 #define PWC_MINOR      0
@@ -76,7 +71,7 @@
 #define PWC_DEBUG_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args)
 
 
-#if CONFIG_PWC_DEBUG
+#ifdef CONFIG_USB_PWC_DEBUG
 
 #define PWC_DEBUG_LEVEL        (PWC_DEBUG_LEVEL_MODULE)
 
@@ -270,7 +265,7 @@ extern "C" {
 #endif
 
 /* Global variables */
-#if CONFIG_PWC_DEBUG
+#ifdef CONFIG_USB_PWC_DEBUG
 extern int pwc_trace;
 #endif
 extern int pwc_mbufs;
index 76f5f5d49dae8ed162abdf3066e9962af2426aa6..e20aa3612a7c86699053cdd512be1e286e4b3506 100644 (file)
@@ -111,7 +111,7 @@ static int saa5246a_attach(struct i2c_adapter *adap, int addr, int kind)
        for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++)
        {
                memset(t->pgbuf[pgbuf], ' ', sizeof(t->pgbuf[0]));
-               t->is_searching[pgbuf] = FALSE;
+               t->is_searching[pgbuf] = false;
        }
        vd->priv=t;
 
@@ -198,7 +198,7 @@ static int i2c_senddata(struct saa5246a_device *t, ...)
 
 /* Get count number of bytes from I²C-device at address adr, store them in buf.
  * Start & stop handshaking is done by this routine, ack will be sent after the
- * last byte to inhibit further sending of data. If uaccess is TRUE, data is
+ * last byte to inhibit further sending of data. If uaccess is 'true', data is
  * written to user-space with put_user. Returns -1 if I²C-device didn't send
  * acknowledge, 0 otherwise
  */
@@ -338,7 +338,7 @@ static int saa5246a_request_page(struct saa5246a_device *t,
                return -EIO;
        }
 
-       t->is_searching[req->pgbuf] = TRUE;
+       t->is_searching[req->pgbuf] = true;
        return 0;
 }
 
@@ -452,7 +452,7 @@ static inline int saa5246a_get_status(struct saa5246a_device *t,
                }
        }
        if (!info->hamming && !info->notfound)
-               t->is_searching[dau_no] = FALSE;
+               t->is_searching[dau_no] = false;
        return 0;
 }
 
@@ -564,7 +564,7 @@ static inline int saa5246a_stop_dau(struct saa5246a_device *t,
        {
                return -EIO;
        }
-       t->is_searching[dau_no] = FALSE;
+       t->is_searching[dau_no] = false;
        return 0;
 }
 
index 7b91112304e037f1248beae6a20cf50af08b71b5..64394c036c601ea850c855aea39abd6e5ec4cf05 100644 (file)
 #define POS_HEADER_START 7
 #define POS_HEADER_END 31
 
-/* Returns TRUE if the part of the videotext page described with req contains
+/* Returns 'true' if the part of the videotext page described with req contains
    (at least parts of) the time field */
 #define REQ_CONTAINS_TIME(p_req) \
        ((p_req)->start <= POS_TIME_END && \
         (p_req)->end   >= POS_TIME_START)
 
-/* Returns TRUE if the part of the videotext page described with req contains
+/* Returns 'true' if the part of the videotext page described with req contains
    (at least parts of) the page header */
 #define REQ_CONTAINS_HEADER(p_req) \
        ((p_req)->start <= POS_HEADER_END && \
         (p_req)->end   >= POS_HEADER_START)
 
-#ifndef FALSE
-#define FALSE 0
-#define TRUE 1
-#endif
-
 /*****************************************************************************/
 /* Mode register numbers of the SAA5246A                                    */
 /*****************************************************************************/
index 3e84737878a866871fb86fec2244b0ba067b761c..f2a2f34cd6261cf6e909d2fc9c278c5eed584a4b 100644 (file)
@@ -124,11 +124,6 @@ struct saa5249_device
 
 /* General defines and debugging support */
 
-#ifndef FALSE
-#define FALSE 0
-#define TRUE 1
-#endif
-
 #define RESCHED do { cond_resched(); } while(0)
 
 static struct video_device saa_template;       /* Declared near bottom */
@@ -183,9 +178,9 @@ static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind)
                memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs));
                memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat));
                t->vdau[pgbuf].expire = 0;
-               t->vdau[pgbuf].clrfound = TRUE;
-               t->vdau[pgbuf].stopped = TRUE;
-               t->is_searching[pgbuf] = FALSE;
+               t->vdau[pgbuf].clrfound = true;
+               t->vdau[pgbuf].stopped = true;
+               t->is_searching[pgbuf] = false;
        }
        vd->priv=t;
 
@@ -298,7 +293,7 @@ static int i2c_senddata(struct saa5249_device *t, ...)
 
 /* Get count number of bytes from I²C-device at address adr, store them in buf. Start & stop
  * handshaking is done by this routine, ack will be sent after the last byte to inhibit further
- * sending of data. If uaccess is TRUE, data is written to user-space with put_user.
+ * sending of data. If uaccess is 'true', data is written to user-space with put_user.
  * Returns -1 if I²C-device didn't send acknowledge, 0 otherwise
  */
 
@@ -317,7 +312,7 @@ static int i2c_getdata(struct saa5249_device *t, int count, u8 *buf)
 static int do_saa5249_ioctl(struct inode *inode, struct file *file,
                            unsigned int cmd, void *arg)
 {
-       static int virtual_mode = FALSE;
+       static int virtual_mode = false;
        struct video_device *vd = video_devdata(file);
        struct saa5249_device *t=vd->priv;
 
@@ -340,7 +335,7 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file,
                        if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
                                return -EINVAL;
                        memset(t->vdau[req->pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf));
-                       t->vdau[req->pgbuf].clrfound = TRUE;
+                       t->vdau[req->pgbuf].clrfound = true;
                        return 0;
                }
 
@@ -350,7 +345,7 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file,
 
                        if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
                                return -EINVAL;
-                       t->vdau[req->pgbuf].clrfound = TRUE;
+                       t->vdau[req->pgbuf].clrfound = true;
                        return 0;
                }
 
@@ -376,9 +371,9 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file,
                        t->vdau[req->pgbuf].sregs[4] = (req->pagemask & HR_UNIT ? 0x10 : 0) | (req->hour & 0xf);
                        t->vdau[req->pgbuf].sregs[5] = (req->pagemask & MIN_TEN ? 0x10 : 0) | (req->minute / 0x10);
                        t->vdau[req->pgbuf].sregs[6] = (req->pagemask & MIN_UNIT ? 0x10 : 0) | (req->minute & 0xf);
-                       t->vdau[req->pgbuf].stopped = FALSE;
-                       t->vdau[req->pgbuf].clrfound = TRUE;
-                       t->is_searching[req->pgbuf] = TRUE;
+                       t->vdau[req->pgbuf].stopped = false;
+                       t->vdau[req->pgbuf].clrfound = true;
+                       t->is_searching[req->pgbuf] = true;
                        return 0;
                }
 
@@ -430,7 +425,7 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file,
                                                        i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 23 * 40))
                                                        return -EIO;
                                        }
-                                       t->vdau[req->pgbuf].clrfound = FALSE;
+                                       t->vdau[req->pgbuf].clrfound = false;
                                        memcpy(t->vdau[req->pgbuf].laststat, infobits, sizeof(infobits));
                                }
                                else
@@ -474,7 +469,7 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file,
                                return -EFAULT;
                        if (!info.hamming && !info.notfound)
                        {
-                               t->is_searching[req->pgbuf] = FALSE;
+                               t->is_searching[req->pgbuf] = false;
                        }
                        return 0;
                }
@@ -530,8 +525,8 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file,
 
                        if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
                                return -EINVAL;
-                       t->vdau[req->pgbuf].stopped = TRUE;
-                       t->is_searching[req->pgbuf] = FALSE;
+                       t->vdau[req->pgbuf].stopped = true;
+                       t->is_searching[req->pgbuf] = false;
                        return 0;
                }
 
@@ -660,11 +655,11 @@ static int saa5249_open(struct inode *inode, struct file *file)
                memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs));
                memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat));
                t->vdau[pgbuf].expire = 0;
-               t->vdau[pgbuf].clrfound = TRUE;
-               t->vdau[pgbuf].stopped = TRUE;
-               t->is_searching[pgbuf] = FALSE;
+               t->vdau[pgbuf].clrfound = true;
+               t->vdau[pgbuf].stopped = true;
+               t->is_searching[pgbuf] = false;
        }
-       t->virtual_mode=FALSE;
+       t->virtual_mode = false;
        return 0;
 
  fail:
index c2374ed7ba9fe31c35b37197bfd6b4a234911446..7735b6758921f6cda72663474b71be3b767fb517 100644 (file)
@@ -71,6 +71,7 @@ I2C_CLIENT_INSMOD;
 struct saa711x_state {
        v4l2_std_id std;
        int input;
+       int output;
        int enable;
        int radio;
        int bright;
@@ -1301,7 +1302,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar
                struct v4l2_routing *route = arg;
 
                route->input = state->input;
-               route->output = 0;
+               route->output = state->output;
                break;
        }
 
@@ -1309,7 +1310,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar
        {
                struct v4l2_routing *route = arg;
 
-               v4l_dbg(1, debug, client, "decoder set input %d\n", route->input);
+               v4l_dbg(1, debug, client, "decoder set input %d output %d\n", route->input, route->output);
                /* saa7113 does not have these inputs */
                if (state->ident == V4L2_IDENT_SAA7113 &&
                    (route->input == SAA7115_COMPOSITE4 ||
@@ -1318,10 +1319,12 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar
                }
                if (route->input > SAA7115_SVIDEO3)
                        return -EINVAL;
-               if (state->input == route->input)
+               if (route->output > SAA7115_IPORT_ON)
+                       return -EINVAL;
+               if (state->input == route->input && state->output == route->output)
                        break;
-               v4l_dbg(1, debug, client, "now setting %s input\n",
-                       (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite");
+               v4l_dbg(1, debug, client, "now setting %s input %s output\n",
+                       (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite", (route->output == SAA7115_IPORT_ON) ? "iport on" : "iport off");
                state->input = route->input;
 
                /* select mode */
@@ -1333,6 +1336,14 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar
                saa711x_write(client, R_09_LUMA_CNTL,
                              (saa711x_read(client, R_09_LUMA_CNTL) & 0x7f) |
                               (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));
+
+               state->output = route->output;
+               if (state->ident == V4L2_IDENT_SAA7114 ||
+                       state->ident == V4L2_IDENT_SAA7115) {
+                       saa711x_write(client, R_83_X_PORT_I_O_ENA_AND_OUT_CLK,
+                             (saa711x_read(client, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) |
+                              (state->output & 0x01));
+               }
                break;
        }
 
@@ -1377,6 +1388,9 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar
        {
                struct v4l2_sliced_vbi_data *data = arg;
 
+               /* Note: the internal field ID is inverted for NTSC,
+                  so data->field 0 maps to the saa7115 even field,
+                  whereas for PAL it maps to the saa7115 odd field. */
                switch (data->id) {
                case V4L2_SLICED_WSS_625:
                        if (saa711x_read(client, 0x6b) & 0xc0)
@@ -1387,17 +1401,17 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar
                case V4L2_SLICED_CAPTION_525:
                        if (data->field == 0) {
                                /* CC */
-                               if (saa711x_read(client, 0x66) & 0xc0)
+                               if (saa711x_read(client, 0x66) & 0x30)
                                        return -EIO;
-                               data->data[0] = saa711x_read(client, 0x67);
-                               data->data[1] = saa711x_read(client, 0x68);
+                               data->data[0] = saa711x_read(client, 0x69);
+                               data->data[1] = saa711x_read(client, 0x6a);
                                return 0;
                        }
                        /* XDS */
-                       if (saa711x_read(client, 0x66) & 0x30)
+                       if (saa711x_read(client, 0x66) & 0xc0)
                                return -EIO;
-                       data->data[0] = saa711x_read(client, 0x69);
-                       data->data[1] = saa711x_read(client, 0x6a);
+                       data->data[0] = saa711x_read(client, 0x67);
+                       data->data[1] = saa711x_read(client, 0x68);
                        return 0;
                default:
                        return -EINVAL;
@@ -1406,25 +1420,19 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar
        }
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-       case VIDIOC_INT_G_REGISTER:
+       case VIDIOC_DBG_G_REGISTER:
+       case VIDIOC_DBG_S_REGISTER:
        {
                struct v4l2_register *reg = arg;
 
-               if (reg->i2c_id != I2C_DRIVERID_SAA711X)
-                       return -EINVAL;
-               reg->val = saa711x_read(client, reg->reg & 0xff);
-               break;
-       }
-
-       case VIDIOC_INT_S_REGISTER:
-       {
-               struct v4l2_register *reg = arg;
-
-               if (reg->i2c_id != I2C_DRIVERID_SAA711X)
+               if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip))
                        return -EINVAL;
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
-               saa711x_write(client, reg->reg & 0xff, reg->val & 0xff);
+               if (cmd == VIDIOC_DBG_G_REGISTER)
+                       reg->val = saa711x_read(client, reg->reg & 0xff);
+               else
+                       saa711x_write(client, reg->reg & 0xff, reg->val & 0xff);
                break;
        }
 #endif
@@ -1492,6 +1500,7 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind)
                return -ENOMEM;
        }
        state->input = -1;
+       state->output = SAA7115_IPORT_ON;
        state->enable = 1;
        state->radio = 0;
        state->bright = 128;
@@ -1550,7 +1559,7 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind)
 
 static int saa711x_probe(struct i2c_adapter *adapter)
 {
-       if (adapter->class & I2C_CLASS_TV_ANALOG)
+       if (adapter->class & I2C_CLASS_TV_ANALOG || adapter->class & I2C_CLASS_TV_DIGITAL)
                return i2c_probe(adapter, &addr_data, &saa711x_attach);
        return 0;
 }
index ad401bdefeaf39f30b566bffd8510f49f052925a..654863db15919b4e5a9c7d891195d75b3afaa4fa 100644 (file)
@@ -614,25 +614,19 @@ static int saa7127_command(struct i2c_client *client,
                break;
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-       case VIDIOC_INT_G_REGISTER:
+       case VIDIOC_DBG_G_REGISTER:
+       case VIDIOC_DBG_S_REGISTER:
        {
                struct v4l2_register *reg = arg;
 
-               if (reg->i2c_id != I2C_DRIVERID_SAA7127)
-                       return -EINVAL;
-               reg->val = saa7127_read(client, reg->reg & 0xff);
-               break;
-       }
-
-       case VIDIOC_INT_S_REGISTER:
-       {
-               struct v4l2_register *reg = arg;
-
-               if (reg->i2c_id != I2C_DRIVERID_SAA7127)
+               if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip))
                        return -EINVAL;
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
-               saa7127_write(client, reg->reg & 0xff, reg->val & 0xff);
+               if (cmd == VIDIOC_DBG_G_REGISTER)
+                       reg->val = saa7127_read(client, reg->reg & 0xff);
+               else
+                       saa7127_write(client, reg->reg & 0xff, reg->val & 0xff);
                break;
        }
 #endif
index 89a1565b4256e11398ef54152314ab95ca18f57a..c85c8a8ec36119b0f3714d6c8b440b70004d18ae 100644 (file)
@@ -14,7 +14,3 @@ obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o
 EXTRA_CFLAGS += -Idrivers/media/video
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
-
-extra-cflags-$(CONFIG_VIDEO_BUF_DVB) += -DHAVE_VIDEO_BUF_DVB=1
-
-EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
index ae984bbe36b6104bd209085d89dad26c62f1c02e..89f32107f46bd6b4c43e2102b47e584c4a608abc 100644 (file)
@@ -2468,6 +2468,11 @@ struct saa7134_board saa7134_boards[] = {
                        .vmux = 3,
                        .amux = LINE2,
                        .gpio = 0x0200000,
+               },{
+                       .name = name_comp2,
+                       .vmux = 0,
+                       .amux = LINE2,
+                       .gpio = 0x0200000,
                },{
                        .name = name_svideo,
                        .vmux = 8,
@@ -3183,6 +3188,107 @@ struct saa7134_board saa7134_boards[] = {
                        .amux   = LINE1,
                }},
        },
+       [SAA7134_BOARD_ENCORE_ENLTV] = {
+       /* Steven Walter <stevenrwalter@gmail.com>
+          Juan Pablo Sormani <sorman@gmail.com> */
+               .name           = "Encore ENLTV",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_TNF_5335MF,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = 3,
+                       .tv   = 1,
+               },{
+                       .name = name_tv_mono,
+                       .vmux = 7,
+                       .amux = 4,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = 2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 0,
+                       .amux = 2,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+/*                     .gpio = 0x00300001,*/
+                       .gpio = 0x20000,
+
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = 0,
+               },
+       },
+       [SAA7134_BOARD_ENCORE_ENLTV_FM] = {
+  /*   Juan Pablo Sormani <sorman@gmail.com> */
+               .name           = "Encore ENLTV-FM",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_ATSC,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = 3,
+                       .tv   = 1,
+               },{
+                       .name = name_tv_mono,
+                       .vmux = 7,
+                       .amux = 4,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = 2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 0,
+                       .amux = 2,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+                       .gpio = 0x20000,
+
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = 0,
+               },
+       },
+       [SAA7134_BOARD_CINERGY_HT_PCI] = {
+               .name           = "Terratec Cinergy HT PCI",
+               .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);
@@ -3821,6 +3927,36 @@ struct pci_device_id saa7134_pci_tbl[] = {
                .subvendor    = 0x153b,
                .subdevice    = 0x1172,
                .driver_data  = SAA7134_BOARD_CINERGY_HT_PCMCIA,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = PCI_VENDOR_ID_PHILIPS,
+               .subdevice    = 0x2342,
+               .driver_data  = SAA7134_BOARD_ENCORE_ENLTV,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x1131,
+               .subdevice    = 0x2341,
+               .driver_data  = SAA7134_BOARD_ENCORE_ENLTV,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x3016,
+               .subdevice    = 0x2344,
+               .driver_data  = SAA7134_BOARD_ENCORE_ENLTV,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x1131,
+               .subdevice    = 0x230f,
+               .driver_data  = SAA7134_BOARD_ENCORE_ENLTV_FM,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x153b,
+               .subdevice    = 0x1175,
+               .driver_data  = SAA7134_BOARD_CINERGY_HT_PCI,
        },{
                /* --- boards without eeprom + subsystem ID --- */
                .vendor       = PCI_VENDOR_ID_PHILIPS,
@@ -3926,9 +4062,12 @@ int saa7134_board_init1(struct saa7134_dev *dev)
        case SAA7134_BOARD_KWORLD_TERMINATOR:
        case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS:
        case SAA7134_BOARD_FLYDVBT_LR301:
+       case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
        case SAA7134_BOARD_FLYDVBTDUO:
        case SAA7134_BOARD_PROTEUS_2309:
        case SAA7134_BOARD_AVERMEDIA_A16AR:
+       case SAA7134_BOARD_ENCORE_ENLTV:
+       case SAA7134_BOARD_ENCORE_ENLTV_FM:
                dev->has_remote = SAA7134_REMOTE_GPIO;
                break;
        case SAA7134_BOARD_FLYDVBS_LR300:
@@ -4150,6 +4289,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
                }
                break;
        case SAA7134_BOARD_CINERGY_HT_PCMCIA:
+       case SAA7134_BOARD_CINERGY_HT_PCI:
                /* make the tda10046 find its eeprom */
                {
                u8 data[] = { 0x3c, 0x33, 0x60};
index c33f6a69a2471d517c73256a9d469e82a541179a..e3059fd339510968861e96839e85a686a9949dc4 100644 (file)
@@ -1424,6 +1424,18 @@ static int dvb_init(struct saa7134_dev *dev)
                        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;
+       case SAA7134_BOARD_CINERGY_HT_PCI:
+               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 = md8800_dvbt_pll_set;
+
                }
                break;
        default:
index 6f9fe86fed9838c26c45bda2ae0759f8de30e124..cce8da6a4f94dceb456b8893bb35a0ebbd2a905e 100644 (file)
@@ -120,9 +120,9 @@ static inline int i2c_is_error(enum i2c_status status)
        case ARB_LOST:
        case SEQ_ERR:
        case ST_ERR:
-               return TRUE;
+               return true;
        default:
-               return FALSE;
+               return false;
        }
 }
 
@@ -131,9 +131,9 @@ static inline int i2c_is_idle(enum i2c_status status)
        switch (status) {
        case IDLE:
        case DONE_STOP:
-               return TRUE;
+               return true;
        default:
-               return FALSE;
+               return false;
        }
 }
 
@@ -141,9 +141,9 @@ static inline int i2c_is_busy(enum i2c_status status)
 {
        switch (status) {
        case BUSY:
-               return TRUE;
+               return true;
        default:
-               return FALSE;
+               return false;
        }
 }
 
@@ -159,8 +159,8 @@ static int i2c_is_busy_wait(struct saa7134_dev *dev)
                saa_wait(I2C_WAIT_DELAY);
        }
        if (I2C_WAIT_RETRY == count)
-               return FALSE;
-       return TRUE;
+               return false;
+       return true;
 }
 
 static int i2c_reset(struct saa7134_dev *dev)
@@ -171,7 +171,7 @@ static int i2c_reset(struct saa7134_dev *dev)
        d2printk(KERN_DEBUG "%s: i2c reset\n",dev->name);
        status = i2c_get_status(dev);
        if (!i2c_is_error(status))
-               return TRUE;
+               return true;
        i2c_set_status(dev,status);
 
        for (count = 0; count < I2C_WAIT_RETRY; count++) {
@@ -181,13 +181,13 @@ static int i2c_reset(struct saa7134_dev *dev)
                udelay(I2C_WAIT_DELAY);
        }
        if (I2C_WAIT_RETRY == count)
-               return FALSE;
+               return false;
 
        if (!i2c_is_idle(status))
-               return FALSE;
+               return false;
 
        i2c_set_attr(dev,NOP);
-       return TRUE;
+       return true;
 }
 
 static inline int i2c_send_byte(struct saa7134_dev *dev,
index e4252683a597018741ca63b57b5c1730b46891f2..46c583f1e78813da272216a3ceeffd41892d9c7c 100644 (file)
@@ -40,16 +40,24 @@ static int pinnacle_remote = 0;
 module_param(pinnacle_remote, int, 0644);    /* Choose Pinnacle PCTV remote */
 MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)");
 
+static int ir_rc5_remote_gap = 885;
+module_param(ir_rc5_remote_gap, int, 0644);
+static int ir_rc5_key_timeout = 115;
+module_param(ir_rc5_key_timeout, int, 0644);
+
 #define dprintk(fmt, arg...)   if (ir_debug) \
        printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg)
 #define i2cdprintk(fmt, arg...)    if (ir_debug) \
        printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg)
 
+/** rc5 functions */
+static int saa7134_rc5_irq(struct saa7134_dev *dev);
+
 /* -------------------- GPIO generic keycode builder -------------------- */
 
 static int build_key(struct saa7134_dev *dev)
 {
-       struct saa7134_ir *ir = dev->remote;
+       struct card_ir *ir = dev->remote;
        u32 gpio, data;
 
        /* rising SAA7134_GPIO_GPRESCAN reads the status */
@@ -134,16 +142,19 @@ static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
 
 void saa7134_input_irq(struct saa7134_dev *dev)
 {
-       struct saa7134_ir *ir = dev->remote;
+       struct card_ir *ir = dev->remote;
 
-       if (!ir->polling)
+       if (!ir->polling && !ir->rc5_gpio) {
                build_key(dev);
+       } else if (ir->rc5_gpio) {
+               saa7134_rc5_irq(dev);
+       }
 }
 
 static void saa7134_input_timer(unsigned long data)
 {
        struct saa7134_dev *dev = (struct saa7134_dev*)data;
-       struct saa7134_ir *ir = dev->remote;
+       struct card_ir *ir = dev->remote;
        unsigned long timeout;
 
        build_key(dev);
@@ -151,7 +162,7 @@ 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)
+static void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir)
 {
        if (ir->polling) {
                init_timer(&ir->timer);
@@ -159,6 +170,19 @@ static void saa7134_ir_start(struct saa7134_dev *dev, struct saa7134_ir *ir)
                ir->timer.data     = (unsigned long)dev;
                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 = ir_rc5_timer_end;
+               ir->timer_end.data = (unsigned long)ir;
+               init_timer(&ir->timer_keyup);
+               ir->timer_keyup.function = ir_rc5_timer_keyup;
+               ir->timer_keyup.data = (unsigned long)ir;
+               ir->shift_by = 2;
+               ir->start = 0x2;
+               ir->addr = 0x17;
+               ir->rc5_key_timeout = ir_rc5_key_timeout;
+               ir->rc5_remote_gap = ir_rc5_remote_gap;
        }
 }
 
@@ -170,13 +194,14 @@ static void saa7134_ir_stop(struct saa7134_dev *dev)
 
 int saa7134_input_init1(struct saa7134_dev *dev)
 {
-       struct saa7134_ir *ir;
+       struct card_ir *ir;
        struct input_dev *input_dev;
        IR_KEYTAB_TYPE *ir_codes = NULL;
        u32 mask_keycode = 0;
        u32 mask_keydown = 0;
        u32 mask_keyup   = 0;
        int polling      = 0;
+       int rc5_gpio     = 0;
        int ir_type      = IR_TYPE_OTHER;
        int err;
 
@@ -295,6 +320,18 @@ int saa7134_input_init1(struct saa7134_dev *dev)
                mask_keycode = 0x0001F00;
                mask_keydown = 0x0040000;
                break;
+       case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
+               ir_codes     = ir_codes_asus_pc39;
+               mask_keydown = 0x0040000;
+               rc5_gpio = 1;
+               break;
+       case SAA7134_BOARD_ENCORE_ENLTV:
+       case SAA7134_BOARD_ENCORE_ENLTV_FM:
+               ir_codes     = ir_codes_encore_enltv;
+               mask_keycode = 0x00007f;
+               mask_keyup   = 0x040000;
+               polling      = 50; // ms
+               break;
        }
        if (NULL == ir_codes) {
                printk("%s: Oops: IR config error [card=%d]\n",
@@ -316,6 +353,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
        ir->mask_keydown = mask_keydown;
        ir->mask_keyup   = mask_keyup;
        ir->polling      = polling;
+       ir->rc5_gpio     = rc5_gpio;
 
        /* init input device */
        snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)",
@@ -402,6 +440,49 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir)
        }
 
 }
+
+static int saa7134_rc5_irq(struct saa7134_dev *dev)
+{
+       struct card_ir *ir = dev->remote;
+       struct timeval tv;
+       u32 gap;
+       unsigned long current_jiffies, timeout;
+
+       /* get time of bit */
+       current_jiffies = jiffies;
+       do_gettimeofday(&tv);
+
+       /* avoid overflow with gap >1s */
+       if (tv.tv_sec - ir->base_time.tv_sec > 1) {
+               gap = 200000;
+       } else {
+               gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
+                   tv.tv_usec - ir->base_time.tv_usec;
+       }
+
+       /* active code => add bit */
+       if (ir->active) {
+               /* only if in the code (otherwise spurious IRQ or timer
+                  late) */
+               if (ir->last_bit < 28) {
+                       ir->last_bit = (gap - ir_rc5_remote_gap / 2) /
+                           ir_rc5_remote_gap;
+                       ir->code |= 1 << ir->last_bit;
+               }
+               /* starting new code */
+       } else {
+               ir->active = 1;
+               ir->code = 0;
+               ir->base_time = tv;
+               ir->last_bit = 0;
+
+               timeout = current_jiffies + (500 + 30 * HZ) / 1000;
+               mod_timer(&ir->timer_end, timeout);
+       }
+
+       return 1;
+}
+
 /* ----------------------------------------------------------------------
  * Local variables:
  * c-basic-offset: 8
index 88cd1297df133f4ec0df4e9bea5928004e12ed72..b3e3957c89b5f0104496c61a8fc8bf638ce972dc 100644 (file)
 #include <sound/driver.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
+#if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE)
 #include <media/video-buf-dvb.h>
-
-#ifndef TRUE
-# define TRUE (1==1)
-#endif
-#ifndef FALSE
-# define FALSE (1==0)
 #endif
+
 #define UNSET (-1U)
 
 /* ----------------------------------------------------------- */
@@ -232,6 +228,9 @@ struct saa7134_format {
 #define SAA7134_BOARD_VIDEOMATE_DVBT_200A  103
 #define SAA7134_BOARD_HAUPPAUGE_HVR1110    104
 #define SAA7134_BOARD_CINERGY_HT_PCMCIA    105
+#define SAA7134_BOARD_ENCORE_ENLTV         106
+#define SAA7134_BOARD_ENCORE_ENLTV_FM      107
+#define SAA7134_BOARD_CINERGY_HT_PCI       108
 
 #define SAA7134_MAXBOARDS 8
 #define SAA7134_INPUT_MAX 8
@@ -411,20 +410,6 @@ struct saa7134_dmasound {
        struct snd_pcm_substream   *substream;
 };
 
-/* IR input */
-struct saa7134_ir {
-       struct input_dev           *dev;
-       struct ir_input_state      ir;
-       char                       name[32];
-       char                       phys[32];
-       u32                        mask_keycode;
-       u32                        mask_keydown;
-       u32                        mask_keyup;
-       int                        polling;
-       u32                        last_gpio;
-       struct timer_list          timer;
-};
-
 /* ts/mpeg status */
 struct saa7134_ts {
        /* TS capture */
@@ -463,7 +448,7 @@ struct saa7134_dev {
 
        /* infrared remote */
        int                        has_remote;
-       struct saa7134_ir          *remote;
+       struct card_ir             *remote;
 
        /* pci i/o */
        char                       name[32];
@@ -543,9 +528,11 @@ struct saa7134_dev {
        struct work_struct         empress_workqueue;
        int                        empress_started;
 
+#if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE)
        /* SAA7134_MPEG_DVB only */
        struct videobuf_dvb        dvb;
        int (*original_demod_sleep)(struct dvb_frontend* fe);
+#endif
 };
 
 /* ----------------------------------------------------------- */
@@ -698,6 +685,7 @@ void saa7134_input_fini(struct saa7134_dev *dev);
 void saa7134_input_irq(struct saa7134_dev *dev);
 void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir);
 
+
 /*
  * Local variables:
  * c-basic-offset: 8
index cf552e6b8ecfb20ef5b7ed89b591afaeba7ccf18..1a7ccb666ab0eb7a41b9add3cd0940c3d2ed30b5 100644 (file)
@@ -1,9 +1,9 @@
 config USB_SN9C102
-       tristate "USB SN9C10x PC Camera Controller support"
+       tristate "USB SN9C1xx PC Camera Controller support"
        depends on USB && VIDEO_V4L1
        ---help---
          Say Y here if you want support for cameras based on SONiX SN9C101,
-         SN9C102 or SN9C103 PC Camera Controllers.
+         SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers.
 
          See <file:Documentation/video4linux/sn9c102.txt> for more info.
 
index 536ad3098da43846b2e813313d005830eda5f4d2..30e3dfe537fe6813f3cee76afc87ebb1da2a7532 100644 (file)
@@ -1,5 +1,5 @@
 sn9c102-objs    := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o \
-                  sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bca.o \
+                  sn9c102_ov7630.o sn9c102_ov7660.o sn9c102_pas106b.o \
                   sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \
                   sn9c102_tas5130d1b.o
 
index 2c6ff396dafc46c87f6c1ea1568dbc96ee6b82ff..5428f34e7c5b4c69d2bcd2672ec72e666d1aede4 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
- * V4L2 driver for SN9C10x PC Camera Controllers                           *
+ * V4L2 driver for SN9C1xx PC Camera Controllers                           *
  *                                                                         *
  * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
 #include <linux/string.h>
 #include <linux/stddef.h>
 
+#include "sn9c102_config.h"
 #include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
 
-/*****************************************************************************/
-
-#define SN9C102_DEBUG
-#define SN9C102_DEBUG_LEVEL       2
-#define SN9C102_MAX_DEVICES       64
-#define SN9C102_PRESERVE_IMGSCALE 0
-#define SN9C102_FORCE_MUNMAP      0
-#define SN9C102_MAX_FRAMES        32
-#define SN9C102_URBS              2
-#define SN9C102_ISO_PACKETS       7
-#define SN9C102_ALTERNATE_SETTING 8
-#define SN9C102_URB_TIMEOUT       msecs_to_jiffies(2 * SN9C102_ISO_PACKETS)
-#define SN9C102_CTRL_TIMEOUT      300
-#define SN9C102_FRAME_TIMEOUT     2
-
-/*****************************************************************************/
-
-enum sn9c102_bridge {
-       BRIDGE_SN9C101 = 0x01,
-       BRIDGE_SN9C102 = 0x02,
-       BRIDGE_SN9C103 = 0x04,
-};
-
-SN9C102_ID_TABLE
-SN9C102_SENSOR_TABLE
 
 enum sn9c102_frame_state {
        F_UNUSED,
@@ -99,13 +76,11 @@ enum sn9c102_stream_state {
        STREAM_ON,
 };
 
-typedef char sn9c103_sof_header_t[18];
-typedef char sn9c102_sof_header_t[12];
-typedef char sn9c102_eof_header_t[4];
+typedef char sn9c102_sof_header_t[62];
 
 struct sn9c102_sysfs_attr {
        u8 reg, i2c_reg;
-       sn9c103_sof_header_t frame_header;
+       sn9c102_sof_header_t frame_header;
 };
 
 struct sn9c102_module_param {
@@ -137,8 +112,8 @@ struct sn9c102_device {
        struct v4l2_jpegcompression compression;
 
        struct sn9c102_sysfs_attr sysfs;
-       sn9c103_sof_header_t sof_header;
-       u16 reg[63];
+       sn9c102_sof_header_t sof_header;
+       u16 reg[384];
 
        struct sn9c102_module_param module_param;
 
@@ -155,10 +130,7 @@ struct sn9c102_device {
 struct sn9c102_device*
 sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id)
 {
-       if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id))
-               return cam;
-
-       return NULL;
+       return usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id) ? cam : NULL;
 }
 
 
@@ -169,6 +141,19 @@ sn9c102_attach_sensor(struct sn9c102_device* cam,
        memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor));
 }
 
+
+enum sn9c102_bridge
+sn9c102_get_bridge(struct sn9c102_device* cam)
+{
+       return cam->bridge;
+}
+
+
+struct sn9c102_sensor* sn9c102_get_sensor(struct sn9c102_device* cam)
+{
+       return &cam->sensor;
+}
+
 /*****************************************************************************/
 
 #undef DBG
diff --git a/drivers/media/video/sn9c102/sn9c102_config.h b/drivers/media/video/sn9c102/sn9c102_config.h
new file mode 100644 (file)
index 0000000..0f4e037
--- /dev/null
@@ -0,0 +1,86 @@
+/***************************************************************************
+ * Global parameters for the V4L2 driver for SN9C1xx PC Camera Controllers *
+ *                                                                         *
+ * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ *                                                                         *
+ * This program is free software; you can redistribute it and/or modify    *
+ * it under the terms of the GNU General Public License as published by    *
+ * the Free Software Foundation; either version 2 of the License, or       *
+ * (at your option) any later version.                                     *
+ *                                                                         *
+ * This program is distributed in the hope that it will be useful,         *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ * GNU General Public License for more details.                            *
+ *                                                                         *
+ * You should have received a copy of the GNU General Public License       *
+ * along with this program; if not, write to the Free Software             *
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
+ ***************************************************************************/
+
+#ifndef _SN9C102_CONFIG_H_
+#define _SN9C102_CONFIG_H_
+
+#include <linux/types.h>
+#include <linux/jiffies.h>
+
+#define SN9C102_DEBUG
+#define SN9C102_DEBUG_LEVEL       2
+#define SN9C102_MAX_DEVICES       64
+#define SN9C102_PRESERVE_IMGSCALE 0
+#define SN9C102_FORCE_MUNMAP      0
+#define SN9C102_MAX_FRAMES        32
+#define SN9C102_URBS              2
+#define SN9C102_ISO_PACKETS       7
+#define SN9C102_ALTERNATE_SETTING 8
+#define SN9C102_URB_TIMEOUT       msecs_to_jiffies(2 * SN9C102_ISO_PACKETS)
+#define SN9C102_CTRL_TIMEOUT      300
+#define SN9C102_FRAME_TIMEOUT     0
+
+/*****************************************************************************/
+
+static const u8 SN9C102_Y_QTABLE0[64] = {
+        8,   5,   5,   8,  12,  20,  25,  30,
+        6,   6,   7,   9,  13,  29,  30,  27,
+        7,   6,   8,  12,  20,  28,  34,  28,
+        7,   8,  11,  14,  25,  43,  40,  31,
+        9,  11,  18,  28,  34,  54,  51,  38,
+       12,  17,  27,  32,  40,  52,  56,  46,
+       24,  32,  39,  43,  51,  60,  60,  50,
+       36,  46,  47,  49,  56,  50,  51,  49
+};
+
+static const u8 SN9C102_UV_QTABLE0[64] = {
+        8,   9,  12,  23,  49,  49,  49,  49,
+        9,  10,  13,  33,  49,  49,  49,  49,
+       12,  13,  28,  49,  49,  49,  49,  49,
+       23,  33,  49,  49,  49,  49,  49,  49,
+       49,  49,  49,  49,  49,  49,  49,  49,
+       49,  49,  49,  49,  49,  49,  49,  49,
+       49,  49,  49,  49,  49,  49,  49,  49,
+       49,  49,  49,  49,  49,  49,  49,  49
+};
+
+static const u8 SN9C102_Y_QTABLE1[64] = {
+       16,  11,  10,  16,  24,  40,  51,  61,
+       12,  12,  14,  19,  26,  58,  60,  55,
+       14,  13,  16,  24,  40,  57,  69,  56,
+       14,  17,  22,  29,  51,  87,  80,  62,
+       18,  22,  37,  56,  68, 109, 103,  77,
+       24,  35,  55,  64,  81, 104, 113,  92,
+       49,  64,  78,  87, 103, 121, 120, 101,
+       72,  92,  95,  98, 112, 100, 103,  99
+};
+
+static const u8 SN9C102_UV_QTABLE1[64] = {
+       17,  18,  24,  47,  99,  99,  99,  99,
+       18,  21,  26,  66,  99,  99,  99,  99,
+       24,  26,  56,  99,  99,  99,  99,  99,
+       47,  66,  99,  99,  99,  99,  99,  99,
+       99,  99,  99,  99,  99,  99,  99,  99,
+       99,  99,  99,  99,  99,  99,  99,  99,
+       99,  99,  99,  99,  99,  99,  99,  99,
+       99,  99,  99,  99,  99,  99,  99,  99
+};
+
+#endif /* _SN9C102_CONFIG_H_ */
index 04d4c8f28b89a97f8f9c345b66c9a38f95cae14a..d0e2b40a77255f75f44005cb2191740c8ae5e909 100644 (file)
@@ -1,7 +1,7 @@
 /***************************************************************************
- * V4L2 driver for SN9C10x PC Camera Controllers                           *
+ * V4L2 driver for SN9C1xx PC Camera Controllers                           *
  *                                                                         *
- * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
 
 /*****************************************************************************/
 
-#define SN9C102_MODULE_NAME     "V4L2 driver for SN9C10x PC Camera Controllers"
+#define SN9C102_MODULE_NAME     "V4L2 driver for SN9C1xx PC Camera Controllers"
 #define SN9C102_MODULE_AUTHOR   "(C) 2004-2006 Luca Risolia"
 #define SN9C102_AUTHOR_EMAIL    "<luca.risolia@studio.unibo.it>"
 #define SN9C102_MODULE_LICENSE  "GPL"
-#define SN9C102_MODULE_VERSION  "1:1.27"
-#define SN9C102_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 27)
+#define SN9C102_MODULE_VERSION  "1:1.34"
+#define SN9C102_MODULE_VERSION_CODE  KERNEL_VERSION(1, 1, 34)
 
 /*****************************************************************************/
 
@@ -91,7 +91,8 @@ static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] =
                                       SN9C102_FRAME_TIMEOUT};
 module_param_array(frame_timeout, uint, NULL, 0644);
 MODULE_PARM_DESC(frame_timeout,
-                "\n<n[,...]> Timeout for a video frame in seconds."
+                "\n<0|n[,...]> Timeout for a video frame in seconds before"
+                "\nreturning an I/O error; 0 for infinity."
                 "\nThis parameter is specific for each detected camera."
                 "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"."
                 "\n");
@@ -113,32 +114,13 @@ MODULE_PARM_DESC(debug,
 
 /*****************************************************************************/
 
-static sn9c102_sof_header_t sn9c102_sof_header[] = {
-       {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x00},
-       {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x01},
-};
-
-static sn9c103_sof_header_t sn9c103_sof_header[] = {
-       {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x20},
-};
-
-static sn9c102_eof_header_t sn9c102_eof_header[] = {
-       {0x00, 0x00, 0x00, 0x00},
-       {0x40, 0x00, 0x00, 0x00},
-       {0x80, 0x00, 0x00, 0x00},
-       {0xc0, 0x00, 0x00, 0x00},
-};
-
-/*****************************************************************************/
-
 static u32
 sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
                        enum sn9c102_io_method io)
 {
        struct v4l2_pix_format* p = &(cam->sensor.pix_format);
        struct v4l2_rect* r = &(cam->sensor.cropcap.bounds);
-       const size_t imagesize = cam->module_param.force_munmap ||
-                                io == IO_READ ?
+       size_t imagesize = cam->module_param.force_munmap || io == IO_READ ?
                                 (p->width * p->height * p->priv) / 8 :
                                 (r->width * r->height * p->priv) / 8;
        void* buff = NULL;
@@ -147,9 +129,13 @@ sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
        if (count > SN9C102_MAX_FRAMES)
                count = SN9C102_MAX_FRAMES;
 
+       if (cam->bridge == BRIDGE_SN9C105 || cam->bridge == BRIDGE_SN9C120)
+               imagesize += 589 + 2; /* length of JPEG header + EOI marker */
+
        cam->nbuffers = count;
        while (cam->nbuffers > 0) {
-               if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize))))
+               if ((buff = vmalloc_32_user(cam->nbuffers *
+                                           PAGE_ALIGN(imagesize))))
                        break;
                cam->nbuffers--;
        }
@@ -322,9 +308,21 @@ static int
 sn9c102_i2c_detect_read_error(struct sn9c102_device* cam,
                              struct sn9c102_sensor* sensor)
 {
-       int r;
+       int r , err = 0;
+
        r = sn9c102_read_reg(cam, 0x08);
-       return (r < 0 || (r >= 0 && !(r & 0x08))) ? -EIO : 0;
+       if (r < 0)
+               err += r;
+
+       if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) {
+               if (!(r & 0x08))
+                       err += -1;
+       } else {
+               if (r & 0x08)
+                       err += -1;
+       }
+
+       return err ? -EIO : 0;
 }
 
 
@@ -415,7 +413,7 @@ sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
        data[4] = data3;
        data[5] = data4;
        data[6] = data5;
-       data[7] = 0x14;
+       data[7] = 0x17;
        res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
                              0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
        if (res < 0)
@@ -467,31 +465,35 @@ int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value)
 
 /*****************************************************************************/
 
-static void*
-sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
+static size_t sn9c102_sof_length(struct sn9c102_device* cam)
 {
-       size_t soflen = 0, i;
-       u8 j, n = 0;
-
        switch (cam->bridge) {
        case BRIDGE_SN9C101:
        case BRIDGE_SN9C102:
-               soflen = sizeof(sn9c102_sof_header_t);
-               n = sizeof(sn9c102_sof_header) / soflen;
-               break;
+               return 12;
        case BRIDGE_SN9C103:
-               soflen = sizeof(sn9c103_sof_header_t);
-               n = sizeof(sn9c103_sof_header) / soflen;
+               return 18;
+       case BRIDGE_SN9C105:
+       case BRIDGE_SN9C120:
+               return 62;
        }
 
+       return 0;
+}
+
+
+static void*
+sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
+{
+       char sof_header[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
+       size_t soflen = 0, i;
+
+       soflen = sn9c102_sof_length(cam);
+
        for (i = 0; (len >= soflen) && (i <= len - soflen); i++)
-               for (j = 0; j < n; j++)
-                       /* The invariable part of the header is 6 bytes long */
-                       if ((cam->bridge != BRIDGE_SN9C103 &&
-                           !memcmp(mem + i, sn9c102_sof_header[j], 6)) ||
-                           (cam->bridge == BRIDGE_SN9C103 &&
-                           !memcmp(mem + i, sn9c103_sof_header[j], 6))) {
-                               memcpy(cam->sof_header, mem + i, soflen);
+               if (!memcmp(mem + i, sof_header, sizeof(sof_header))) {
+                       memcpy(cam->sof_header, mem + i,
+                              sizeof(sn9c102_sof_header_t));
                                /* Skip the header */
                                return mem + i + soflen;
                        }
@@ -503,21 +505,123 @@ sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
 static void*
 sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len)
 {
-       size_t eoflen = sizeof(sn9c102_eof_header_t), i;
-       unsigned j, n = sizeof(sn9c102_eof_header) / eoflen;
+       char eof_header[4][4] = {
+               {0x00, 0x00, 0x00, 0x00},
+               {0x40, 0x00, 0x00, 0x00},
+               {0x80, 0x00, 0x00, 0x00},
+               {0xc0, 0x00, 0x00, 0x00},
+       };
+       size_t i, j;
 
-       if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
+       if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X ||
+           cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
                return NULL; /* EOF header does not exist in compressed data */
 
-       for (i = 0; (len >= eoflen) && (i <= len - eoflen); i++)
-               for (j = 0; j < n; j++)
-                       if (!memcmp(mem + i, sn9c102_eof_header[j], eoflen))
+       for (i = 0; (len >= 4) && (i <= len - 4); i++)
+               for (j = 0; j < ARRAY_SIZE(eof_header); j++)
+                       if (!memcmp(mem + i, eof_header[j], 4))
                                return mem + i;
 
        return NULL;
 }
 
 
+static void
+sn9c102_write_jpegheader(struct sn9c102_device* cam, struct sn9c102_frame_t* f)
+{
+       static u8 jpeg_header[589] = {
+               0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x06, 0x04, 0x05,
+               0x06, 0x05, 0x04, 0x06, 0x06, 0x05, 0x06, 0x07, 0x07, 0x06,
+               0x08, 0x0a, 0x10, 0x0a, 0x0a, 0x09, 0x09, 0x0a, 0x14, 0x0e,
+               0x0f, 0x0c, 0x10, 0x17, 0x14, 0x18, 0x18, 0x17, 0x14, 0x16,
+               0x16, 0x1a, 0x1d, 0x25, 0x1f, 0x1a, 0x1b, 0x23, 0x1c, 0x16,
+               0x16, 0x20, 0x2c, 0x20, 0x23, 0x26, 0x27, 0x29, 0x2a, 0x29,
+               0x19, 0x1f, 0x2d, 0x30, 0x2d, 0x28, 0x30, 0x25, 0x28, 0x29,
+               0x28, 0x01, 0x07, 0x07, 0x07, 0x0a, 0x08, 0x0a, 0x13, 0x0a,
+               0x0a, 0x13, 0x28, 0x1a, 0x16, 0x1a, 0x28, 0x28, 0x28, 0x28,
+               0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+               0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+               0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+               0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+               0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0xff, 0xc4, 0x01, 0xa2,
+               0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
+               0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01,
+               0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+               0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
+               0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00,
+               0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
+               0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04,
+               0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
+               0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23,
+               0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62,
+               0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25,
+               0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38,
+               0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
+               0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
+               0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
+               0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+               0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+               0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
+               0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2,
+               0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3,
+               0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3,
+               0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3,
+               0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02,
+               0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04,
+               0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
+               0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+               0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1,
+               0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1,
+               0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19,
+               0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
+               0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
+               0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
+               0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
+               0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+               0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+               0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
+               0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba,
+               0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+               0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3,
+               0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4,
+               0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xc0, 0x00, 0x11,
+               0x08, 0x01, 0xe0, 0x02, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02,
+               0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, 0x03,
+               0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
+       };
+       u8 *pos = f->bufmem;
+
+       memcpy(pos, jpeg_header, sizeof(jpeg_header));
+       *(pos + 6) = 0x00;
+       *(pos + 7 + 64) = 0x01;
+       if (cam->compression.quality == 0) {
+               memcpy(pos + 7, SN9C102_Y_QTABLE0, 64);
+               memcpy(pos + 8 + 64, SN9C102_UV_QTABLE0, 64);
+       } else if (cam->compression.quality == 1) {
+               memcpy(pos + 7, SN9C102_Y_QTABLE1, 64);
+               memcpy(pos + 8 + 64, SN9C102_UV_QTABLE1, 64);
+       }
+       *(pos + 564) = cam->sensor.pix_format.width & 0xFF;
+       *(pos + 563) = (cam->sensor.pix_format.width >> 8) & 0xFF;
+       *(pos + 562) = cam->sensor.pix_format.height & 0xFF;
+       *(pos + 561) = (cam->sensor.pix_format.height >> 8) & 0xFF;
+       *(pos + 567) = 0x21;
+
+       f->buf.bytesused += sizeof(jpeg_header);
+}
+
+
+static void
+sn9c102_write_eoimarker(struct sn9c102_device* cam, struct sn9c102_frame_t* f)
+{
+       static const u8 eoi_marker[2] = {0xff, 0xd9};
+
+       memcpy(f->bufmem + f->buf.bytesused, eoi_marker, sizeof(eoi_marker));
+       f->buf.bytesused += sizeof(eoi_marker);
+}
+
+
 static void sn9c102_urb_complete(struct urb *urb)
 {
        struct sn9c102_device* cam = urb->context;
@@ -535,7 +639,7 @@ static void sn9c102_urb_complete(struct urb *urb)
                cam->stream = STREAM_OFF;
                if ((*f))
                        (*f)->state = F_QUEUED;
-               DBG(3, "Stream interrupted");
+               DBG(3, "Stream interrupted by application");
                wake_up(&cam->wait_stream);
        }
 
@@ -557,10 +661,9 @@ static void sn9c102_urb_complete(struct urb *urb)
        imagesize = (cam->sensor.pix_format.width *
                     cam->sensor.pix_format.height *
                     cam->sensor.pix_format.priv) / 8;
-
-       soflen = (cam->bridge) == BRIDGE_SN9C103 ?
-                                 sizeof(sn9c103_sof_header_t) :
-                                 sizeof(sn9c102_sof_header_t);
+       if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
+               imagesize += 589; /* length of jpeg header */
+       soflen = sn9c102_sof_length(cam);
 
        for (i = 0; i < urb->number_of_packets; i++) {
                unsigned int img, len, status;
@@ -610,12 +713,21 @@ end_of_frame:
                                (*f)->buf.bytesused += img;
 
                                if ((*f)->buf.bytesused == imagesize ||
-                                   (cam->sensor.pix_format.pixelformat ==
-                                               V4L2_PIX_FMT_SN9C10X && eof)) {
+                                   ((cam->sensor.pix_format.pixelformat ==
+                                     V4L2_PIX_FMT_SN9C10X ||
+                                     cam->sensor.pix_format.pixelformat ==
+                                     V4L2_PIX_FMT_JPEG) && eof)) {
                                        u32 b;
+
+                                       if (cam->sensor.pix_format.pixelformat
+                                           == V4L2_PIX_FMT_JPEG)
+                                               sn9c102_write_eoimarker(cam,
+                                                                       (*f));
+
                                        b = (*f)->buf.bytesused;
                                        (*f)->state = F_DONE;
                                        (*f)->buf.sequence= ++cam->frame_count;
+
                                        spin_lock(&cam->queue_lock);
                                        list_move_tail(&(*f)->frame,
                                                       &cam->outqueue);
@@ -627,8 +739,10 @@ end_of_frame:
                                        else
                                                (*f) = NULL;
                                        spin_unlock(&cam->queue_lock);
+
                                        memcpy(cam->sysfs.frame_header,
                                               cam->sof_header, soflen);
+
                                        DBG(3, "Video frame captured: %lu "
                                               "bytes", (unsigned long)(b));
 
@@ -661,6 +775,9 @@ start_of_frame:
                        (*f)->buf.bytesused = 0;
                        len -= (sof - pos);
                        pos = sof;
+                       if (cam->sensor.pix_format.pixelformat ==
+                           V4L2_PIX_FMT_JPEG)
+                               sn9c102_write_jpegheader(cam, (*f));
                        DBG(3, "SOF detected: new video frame");
                        if (len)
                                goto redo;
@@ -671,7 +788,9 @@ start_of_frame:
                                goto end_of_frame; /* (1) */
                        else {
                                if (cam->sensor.pix_format.pixelformat ==
-                                   V4L2_PIX_FMT_SN9C10X) {
+                                   V4L2_PIX_FMT_SN9C10X ||
+                                   cam->sensor.pix_format.pixelformat ==
+                                   V4L2_PIX_FMT_JPEG) {
                                        eof = sof - soflen;
                                        goto end_of_frame;
                                } else {
@@ -701,13 +820,11 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam)
 {
        struct usb_device *udev = cam->usbdev;
        struct urb* urb;
-       const unsigned int sn9c102_wMaxPacketSize[] = {0, 128, 256, 384, 512,
-                                                      680, 800, 900, 1023};
-       const unsigned int sn9c103_wMaxPacketSize[] = {0, 128, 256, 384, 512,
-                                                      680, 800, 900, 1003};
-       const unsigned int psz = (cam->bridge == BRIDGE_SN9C103) ?
-                           sn9c103_wMaxPacketSize[SN9C102_ALTERNATE_SETTING] :
-                           sn9c102_wMaxPacketSize[SN9C102_ALTERNATE_SETTING];
+       struct usb_host_interface* altsetting = usb_altnum_to_altsetting(
+                                                   usb_ifnum_to_if(udev, 0),
+                                                   SN9C102_ALTERNATE_SETTING);
+       const unsigned int psz = le16_to_cpu(altsetting->
+                                            endpoint[0].desc.wMaxPacketSize);
        s8 i, j;
        int err = 0;
 
@@ -775,7 +892,7 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam)
        return 0;
 
 free_urbs:
-       for (i = 0; i < SN9C102_URBS; i++)
+       for (i = 0; (i < SN9C102_URBS) && cam->urb[i]; i++)
                usb_free_urb(cam->urb[i]);
 
 free_buffers:
@@ -834,29 +951,29 @@ static int sn9c102_stream_interrupt(struct sn9c102_device* cam)
 /*****************************************************************************/
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-static u8 sn9c102_strtou8(const char* buff, size_t len, ssize_t* count)
+static u16 sn9c102_strtou16(const char* buff, size_t len, ssize_t* count)
 {
-       char str[5];
+       char str[7];
        char* endp;
        unsigned long val;
 
-       if (len < 4) {
+       if (len < 6) {
                strncpy(str, buff, len);
                str[len+1] = '\0';
        } else {
                strncpy(str, buff, 4);
-               str[4] = '\0';
+               str[6] = '\0';
        }
 
        val = simple_strtoul(str, &endp, 0);
 
        *count = 0;
-       if (val <= 0xff)
+       if (val <= 0xffff)
                *count = (ssize_t)(endp - str);
        if ((*count) && (len == *count+1) && (buff[*count] == '\n'))
                *count += 1;
 
-       return (u8)val;
+       return (u16)val;
 }
 
 /*
@@ -873,7 +990,8 @@ static ssize_t sn9c102_show_reg(struct class_device* cd, char* buf)
        if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
-       cam = video_get_drvdata(to_video_device(cd));
+       cam = video_get_drvdata(container_of(cd, struct video_device,
+                                            class_dev));
        if (!cam) {
                mutex_unlock(&sn9c102_sysfs_lock);
                return -ENODEV;
@@ -891,27 +1009,28 @@ static ssize_t
 sn9c102_store_reg(struct class_device* cd, const char* buf, size_t len)
 {
        struct sn9c102_device* cam;
-       u8 index;
+       u16 index;
        ssize_t count;
 
        if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
-       cam = video_get_drvdata(to_video_device(cd));
+       cam = video_get_drvdata(container_of(cd, struct video_device,
+                                            class_dev));
        if (!cam) {
                mutex_unlock(&sn9c102_sysfs_lock);
                return -ENODEV;
        }
 
-       index = sn9c102_strtou8(buf, len, &count);
-       if (index > 0x1f || !count) {
+       index = sn9c102_strtou16(buf, len, &count);
+       if (index >= ARRAY_SIZE(cam->reg) || !count) {
                mutex_unlock(&sn9c102_sysfs_lock);
                return -EINVAL;
        }
 
        cam->sysfs.reg = index;
 
-       DBG(2, "Moved SN9C10X register index to 0x%02X", cam->sysfs.reg);
+       DBG(2, "Moved SN9C1XX register index to 0x%02X", cam->sysfs.reg);
        DBG(3, "Written bytes: %zd", count);
 
        mutex_unlock(&sn9c102_sysfs_lock);
@@ -929,7 +1048,8 @@ static ssize_t sn9c102_show_val(struct class_device* cd, char* buf)
        if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
-       cam = video_get_drvdata(to_video_device(cd));
+       cam = video_get_drvdata(container_of(cd, struct video_device,
+                                            class_dev));
        if (!cam) {
                mutex_unlock(&sn9c102_sysfs_lock);
                return -ENODEV;
@@ -954,20 +1074,21 @@ static ssize_t
 sn9c102_store_val(struct class_device* cd, const char* buf, size_t len)
 {
        struct sn9c102_device* cam;
-       u8 value;
+       u16 value;
        ssize_t count;
        int err;
 
        if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
-       cam = video_get_drvdata(to_video_device(cd));
+       cam = video_get_drvdata(container_of(cd, struct video_device,
+                                            class_dev));
        if (!cam) {
                mutex_unlock(&sn9c102_sysfs_lock);
                return -ENODEV;
        }
 
-       value = sn9c102_strtou8(buf, len, &count);
+       value = sn9c102_strtou16(buf, len, &count);
        if (!count) {
                mutex_unlock(&sn9c102_sysfs_lock);
                return -EINVAL;
@@ -979,7 +1100,7 @@ sn9c102_store_val(struct class_device* cd, const char* buf, size_t len)
                return -EIO;
        }
 
-       DBG(2, "Written SN9C10X reg. 0x%02X, val. 0x%02X",
+       DBG(2, "Written SN9C1XX reg. 0x%02X, val. 0x%02X",
            cam->sysfs.reg, value);
        DBG(3, "Written bytes: %zd", count);
 
@@ -997,7 +1118,8 @@ static ssize_t sn9c102_show_i2c_reg(struct class_device* cd, char* buf)
        if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
-       cam = video_get_drvdata(to_video_device(cd));
+       cam = video_get_drvdata(container_of(cd, struct video_device,
+                                            class_dev));
        if (!cam) {
                mutex_unlock(&sn9c102_sysfs_lock);
                return -ENODEV;
@@ -1017,19 +1139,20 @@ static ssize_t
 sn9c102_store_i2c_reg(struct class_device* cd, const char* buf, size_t len)
 {
        struct sn9c102_device* cam;
-       u8 index;
+       u16 index;
        ssize_t count;
 
        if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
-       cam = video_get_drvdata(to_video_device(cd));
+       cam = video_get_drvdata(container_of(cd, struct video_device,
+                                            class_dev));
        if (!cam) {
                mutex_unlock(&sn9c102_sysfs_lock);
                return -ENODEV;
        }
 
-       index = sn9c102_strtou8(buf, len, &count);
+       index = sn9c102_strtou16(buf, len, &count);
        if (!count) {
                mutex_unlock(&sn9c102_sysfs_lock);
                return -EINVAL;
@@ -1055,7 +1178,8 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf)
        if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
-       cam = video_get_drvdata(to_video_device(cd));
+       cam = video_get_drvdata(container_of(cd, struct video_device,
+                                            class_dev));
        if (!cam) {
                mutex_unlock(&sn9c102_sysfs_lock);
                return -ENODEV;
@@ -1085,14 +1209,15 @@ static ssize_t
 sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len)
 {
        struct sn9c102_device* cam;
-       u8 value;
+       u16 value;
        ssize_t count;
        int err;
 
        if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
-       cam = video_get_drvdata(to_video_device(cd));
+       cam = video_get_drvdata(container_of(cd, struct video_device,
+                                            class_dev));
        if (!cam) {
                mutex_unlock(&sn9c102_sysfs_lock);
                return -ENODEV;
@@ -1103,7 +1228,7 @@ sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len)
                return -ENOSYS;
        }
 
-       value = sn9c102_strtou8(buf, len, &count);
+       value = sn9c102_strtou16(buf, len, &count);
        if (!count) {
                mutex_unlock(&sn9c102_sysfs_lock);
                return -EINVAL;
@@ -1131,13 +1256,14 @@ sn9c102_store_green(struct class_device* cd, const char* buf, size_t len)
        struct sn9c102_device* cam;
        enum sn9c102_bridge bridge;
        ssize_t res = 0;
-       u8 value;
+       u16 value;
        ssize_t count;
 
        if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
-       cam = video_get_drvdata(to_video_device(cd));
+       cam = video_get_drvdata(container_of(cd, struct video_device,
+                                            class_dev));
        if (!cam) {
                mutex_unlock(&sn9c102_sysfs_lock);
                return -ENODEV;
@@ -1147,7 +1273,7 @@ sn9c102_store_green(struct class_device* cd, const char* buf, size_t len)
 
        mutex_unlock(&sn9c102_sysfs_lock);
 
-       value = sn9c102_strtou8(buf, len, &count);
+       value = sn9c102_strtou16(buf, len, &count);
        if (!count)
                return -EINVAL;
 
@@ -1160,9 +1286,11 @@ sn9c102_store_green(struct class_device* cd, const char* buf, size_t len)
                        res = sn9c102_store_val(cd, buf, len);
                break;
        case BRIDGE_SN9C103:
+       case BRIDGE_SN9C105:
+       case BRIDGE_SN9C120:
                if (value > 0x7f)
                        return -EINVAL;
-               if ((res = sn9c102_store_reg(cd, "0x04", 4)) >= 0)
+               if ((res = sn9c102_store_reg(cd, "0x07", 4)) >= 0)
                        res = sn9c102_store_val(cd, buf, len);
                break;
        }
@@ -1175,10 +1303,10 @@ static ssize_t
 sn9c102_store_blue(struct class_device* cd, const char* buf, size_t len)
 {
        ssize_t res = 0;
-       u8 value;
+       u16 value;
        ssize_t count;
 
-       value = sn9c102_strtou8(buf, len, &count);
+       value = sn9c102_strtou16(buf, len, &count);
        if (!count || value > 0x7f)
                return -EINVAL;
 
@@ -1193,10 +1321,10 @@ static ssize_t
 sn9c102_store_red(struct class_device* cd, const char* buf, size_t len)
 {
        ssize_t res = 0;
-       u8 value;
+       u16 value;
        ssize_t count;
 
-       value = sn9c102_strtou8(buf, len, &count);
+       value = sn9c102_strtou16(buf, len, &count);
        if (!count || value > 0x7f)
                return -EINVAL;
 
@@ -1212,7 +1340,8 @@ static ssize_t sn9c102_show_frame_header(struct class_device* cd, char* buf)
        struct sn9c102_device* cam;
        ssize_t count;
 
-       cam = video_get_drvdata(to_video_device(cd));
+       cam = video_get_drvdata(container_of(cd, struct video_device,
+                                            class_dev));
        if (!cam)
                return -ENODEV;
 
@@ -1243,30 +1372,36 @@ static CLASS_DEVICE_ATTR(frame_header, S_IRUGO,
 static int sn9c102_create_sysfs(struct sn9c102_device* cam)
 {
        struct video_device *v4ldev = cam->v4ldev;
-       int rc;
+       int err = 0;
 
-       rc = video_device_create_file(v4ldev, &class_device_attr_reg);
-       if (rc) goto err;
-       rc = video_device_create_file(v4ldev, &class_device_attr_val);
-       if (rc) goto err_reg;
-       rc = video_device_create_file(v4ldev, &class_device_attr_frame_header);
-       if (rc) goto err_val;
+       if ((err = video_device_create_file(v4ldev, &class_device_attr_reg)))
+               goto err_out;
+       if ((err = video_device_create_file(v4ldev, &class_device_attr_val)))
+               goto err_reg;
+       if ((err = video_device_create_file(v4ldev,
+                                           &class_device_attr_frame_header)))
+               goto err_val;
 
        if (cam->sensor.sysfs_ops) {
-               rc = video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
-               if (rc) goto err_frhead;
-               rc = video_device_create_file(v4ldev, &class_device_attr_i2c_val);
-               if (rc) goto err_i2c_reg;
+               if ((err = video_device_create_file(v4ldev,
+                                                 &class_device_attr_i2c_reg)))
+                       goto err_frame_header;
+               if ((err = video_device_create_file(v4ldev,
+                                                 &class_device_attr_i2c_val)))
+                       goto err_i2c_reg;
        }
 
        if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) {
-               rc = video_device_create_file(v4ldev, &class_device_attr_green);
-               if (rc) goto err_i2c_val;
-       } else if (cam->bridge == BRIDGE_SN9C103) {
-               rc = video_device_create_file(v4ldev, &class_device_attr_blue);
-               if (rc) goto err_i2c_val;
-               rc = video_device_create_file(v4ldev, &class_device_attr_red);
-               if (rc) goto err_blue;
+               if ((err = video_device_create_file(v4ldev,
+                                                   &class_device_attr_green)))
+                       goto err_i2c_val;
+       } else {
+               if ((err = video_device_create_file(v4ldev,
+                                                   &class_device_attr_blue)))
+                       goto err_i2c_val;
+               if ((err = video_device_create_file(v4ldev,
+                                                   &class_device_attr_red)))
+                       goto err_blue;
        }
 
        return 0;
@@ -1279,14 +1414,14 @@ err_i2c_val:
 err_i2c_reg:
        if (cam->sensor.sysfs_ops)
                video_device_remove_file(v4ldev, &class_device_attr_i2c_reg);
-err_frhead:
+err_frame_header:
        video_device_remove_file(v4ldev, &class_device_attr_frame_header);
 err_val:
        video_device_remove_file(v4ldev, &class_device_attr_val);
 err_reg:
        video_device_remove_file(v4ldev, &class_device_attr_reg);
-err:
-       return rc;
+err_out:
+       return err;
 }
 #endif /* CONFIG_VIDEO_ADV_DEBUG */
 
@@ -1297,10 +1432,36 @@ sn9c102_set_pix_format(struct sn9c102_device* cam, struct v4l2_pix_format* pix)
 {
        int err = 0;
 
-       if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
-               err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80, 0x18);
-       else
-               err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f, 0x18);
+       if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X ||
+           pix->pixelformat == V4L2_PIX_FMT_JPEG) {
+               switch (cam->bridge) {
+               case BRIDGE_SN9C101:
+               case BRIDGE_SN9C102:
+               case BRIDGE_SN9C103:
+                       err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80,
+                                                0x18);
+                       break;
+               case BRIDGE_SN9C105:
+               case BRIDGE_SN9C120:
+                       err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f,
+                                                0x18);
+                       break;
+               }
+       } else {
+               switch (cam->bridge) {
+               case BRIDGE_SN9C101:
+               case BRIDGE_SN9C102:
+               case BRIDGE_SN9C103:
+                       err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f,
+                                                0x18);
+                       break;
+               case BRIDGE_SN9C105:
+               case BRIDGE_SN9C120:
+                       err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80,
+                                                0x18);
+                       break;
+               }
+       }
 
        return err ? -EIO : 0;
 }
@@ -1310,12 +1471,46 @@ static int
 sn9c102_set_compression(struct sn9c102_device* cam,
                        struct v4l2_jpegcompression* compression)
 {
-       int err = 0;
+       int i, err = 0;
 
+       switch (cam->bridge) {
+       case BRIDGE_SN9C101:
+       case BRIDGE_SN9C102:
+       case BRIDGE_SN9C103:
        if (compression->quality == 0)
-               err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01, 0x17);
+                       err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01,
+                                                0x17);
        else if (compression->quality == 1)
-               err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe, 0x17);
+                       err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe,
+                                                0x17);
+               break;
+       case BRIDGE_SN9C105:
+       case BRIDGE_SN9C120:
+               if (compression->quality == 0) {
+                       for (i = 0; i <= 63; i++) {
+                               err += sn9c102_write_reg(cam,
+                                                        SN9C102_Y_QTABLE0[i],
+                                                        0x100 + i);
+                               err += sn9c102_write_reg(cam,
+                                                        SN9C102_UV_QTABLE0[i],
+                                                        0x140 + i);
+                       }
+                       err += sn9c102_write_reg(cam, cam->reg[0x18] & 0xbf,
+                                                0x18);
+               } else if (compression->quality == 1) {
+                       for (i = 0; i <= 63; i++) {
+                               err += sn9c102_write_reg(cam,
+                                                        SN9C102_Y_QTABLE1[i],
+                                                        0x100 + i);
+                               err += sn9c102_write_reg(cam,
+                                                        SN9C102_UV_QTABLE1[i],
+                                                        0x140 + i);
+                       }
+                       err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x40,
+                                                0x18);
+               }
+               break;
+       }
 
        return err ? -EIO : 0;
 }
@@ -1399,7 +1594,16 @@ static int sn9c102_init(struct sn9c102_device* cam)
        }
 
        if (!(cam->state & DEV_INITIALIZED))
-               cam->compression.quality =  cam->reg[0x17] & 0x01 ? 0 : 1;
+               if (cam->bridge == BRIDGE_SN9C101 ||
+                   cam->bridge == BRIDGE_SN9C102 ||
+                   cam->bridge == BRIDGE_SN9C103) {
+                       cam->compression.quality =  cam->reg[0x17] & 0x01 ?
+                                                   0 : 1;
+               } else {
+                       cam->compression.quality =  cam->reg[0x18] & 0x40 ?
+                                                   0 : 1;
+                       err += sn9c102_set_compression(cam, &cam->compression);
+               }
        else
                err += sn9c102_set_compression(cam, &cam->compression);
        err += sn9c102_set_pix_format(cam, &s->pix_format);
@@ -1408,7 +1612,8 @@ static int sn9c102_init(struct sn9c102_device* cam)
        if (err)
                return err;
 
-       if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
+       if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X ||
+           s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
                DBG(3, "Compressed video format is active, quality %d",
                    cam->compression.quality);
        else
@@ -1490,6 +1695,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp)
 
        if (cam->users) {
                DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor);
+               DBG(3, "Simultaneous opens are not supported");
                if ((filp->f_flags & O_NONBLOCK) ||
                    (filp->f_flags & O_NDELAY)) {
                        err = -EWOULDBLOCK;
@@ -1628,6 +1834,17 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
                        mutex_unlock(&cam->fileop_mutex);
                        return -EAGAIN;
                }
+               if (!cam->module_param.frame_timeout) {
+                       err = wait_event_interruptible
+                             ( cam->wait_frame,
+                               (!list_empty(&cam->outqueue)) ||
+                               (cam->state & DEV_DISCONNECTED) ||
+                               (cam->state & DEV_MISCONFIGURED) );
+                       if (err) {
+                               mutex_unlock(&cam->fileop_mutex);
+                               return err;
+                       }
+               } else {
                timeout = wait_event_interruptible_timeout
                          ( cam->wait_frame,
                            (!list_empty(&cam->outqueue)) ||
@@ -1638,12 +1855,18 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
                if (timeout < 0) {
                        mutex_unlock(&cam->fileop_mutex);
                        return timeout;
+                       } else if (timeout == 0 &&
+                                  !(cam->state & DEV_DISCONNECTED)) {
+                               DBG(1, "Video frame timeout elapsed");
+                               mutex_unlock(&cam->fileop_mutex);
+                               return -EIO;
+                       }
                }
                if (cam->state & DEV_DISCONNECTED) {
                        mutex_unlock(&cam->fileop_mutex);
                        return -ENODEV;
                }
-               if (!timeout || (cam->state & DEV_MISCONFIGURED)) {
+               if (cam->state & DEV_MISCONFIGURED) {
                        mutex_unlock(&cam->fileop_mutex);
                        return -EIO;
                }
@@ -1940,6 +2163,9 @@ exit:
        if (copy_to_user(arg, &ctrl, sizeof(ctrl)))
                return -EFAULT;
 
+       PDBGG("VIDIOC_G_CTRL: id %lu, value %lu",
+             (unsigned long)ctrl.id, (unsigned long)ctrl.value);
+
        return err;
 }
 
@@ -2126,6 +2352,45 @@ sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg)
 }
 
 
+static int
+sn9c102_vidioc_enum_framesizes(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_frmsizeenum frmsize;
+
+       if (copy_from_user(&frmsize, arg, sizeof(frmsize)))
+               return -EFAULT;
+
+       if (frmsize.index != 0)
+               return -EINVAL;
+
+       switch (cam->bridge) {
+       case BRIDGE_SN9C101:
+       case BRIDGE_SN9C102:
+       case BRIDGE_SN9C103:
+               if (frmsize.pixel_format != V4L2_PIX_FMT_SN9C10X &&
+                   frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
+                       return -EINVAL;
+       case BRIDGE_SN9C105:
+       case BRIDGE_SN9C120:
+               if (frmsize.pixel_format != V4L2_PIX_FMT_JPEG &&
+                   frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
+                       return -EINVAL;
+       }
+
+       frmsize.type = V4L2_FRMSIZE_TYPE_STEPWISE;
+       frmsize.stepwise.min_width = frmsize.stepwise.step_width = 16;
+       frmsize.stepwise.min_height = frmsize.stepwise.step_height = 16;
+       frmsize.stepwise.max_width = cam->sensor.cropcap.bounds.width;
+       frmsize.stepwise.max_height = cam->sensor.cropcap.bounds.height;
+       memset(&frmsize.reserved, 0, sizeof(frmsize.reserved));
+
+       if (copy_to_user(arg, &frmsize, sizeof(frmsize)))
+               return -EFAULT;
+
+       return 0;
+}
+
+
 static int
 sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg)
 {
@@ -2134,12 +2399,26 @@ sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg)
        if (copy_from_user(&fmtd, arg, sizeof(fmtd)))
                return -EFAULT;
 
+       if (fmtd.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
        if (fmtd.index == 0) {
                strcpy(fmtd.description, "bayer rgb");
                fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8;
        } else if (fmtd.index == 1) {
+               switch (cam->bridge) {
+               case BRIDGE_SN9C101:
+               case BRIDGE_SN9C102:
+               case BRIDGE_SN9C103:
                strcpy(fmtd.description, "compressed");
                fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X;
+                       break;
+               case BRIDGE_SN9C105:
+               case BRIDGE_SN9C120:
+                       strcpy(fmtd.description, "JPEG");
+                       fmtd.pixelformat = V4L2_PIX_FMT_JPEG;
+                       break;
+               }
                fmtd.flags = V4L2_FMT_FLAG_COMPRESSED;
        } else
                return -EINVAL;
@@ -2166,7 +2445,8 @@ sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg)
        if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
 
-       pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X)
+       pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X ||
+                             pfmt->pixelformat==V4L2_PIX_FMT_JPEG)
                             ? 0 : (pfmt->width * pfmt->priv) / 8;
        pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
        pfmt->field = V4L2_FIELD_NONE;
@@ -2237,12 +2517,25 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
        pix->width = rect.width / scale;
        pix->height = rect.height / scale;
 
+       switch (cam->bridge) {
+       case BRIDGE_SN9C101:
+       case BRIDGE_SN9C102:
+       case BRIDGE_SN9C103:
        if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X &&
            pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
                pix->pixelformat = pfmt->pixelformat;
+               break;
+       case BRIDGE_SN9C105:
+       case BRIDGE_SN9C120:
+               if (pix->pixelformat != V4L2_PIX_FMT_JPEG &&
+                   pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
+                       pix->pixelformat = pfmt->pixelformat;
+               break;
+       }
        pix->priv = pfmt->priv; /* bpp */
        pix->colorspace = pfmt->colorspace;
-       pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
+       pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X ||
+                            pix->pixelformat == V4L2_PIX_FMT_JPEG)
                            ? 0 : (pix->width * pix->priv) / 8;
        pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8);
        pix->field = V4L2_FIELD_NONE;
@@ -2315,8 +2608,7 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
 static int
 sn9c102_vidioc_g_jpegcomp(struct sn9c102_device* cam, void __user * arg)
 {
-       if (copy_to_user(arg, &cam->compression,
-                        sizeof(cam->compression)))
+       if (copy_to_user(arg, &cam->compression, sizeof(cam->compression)))
                return -EFAULT;
 
        return 0;
@@ -2471,6 +2763,7 @@ sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp,
        struct sn9c102_frame_t *f;
        unsigned long lock_flags;
        long timeout;
+       int err = 0;
 
        if (copy_from_user(&b, arg, sizeof(b)))
                return -EFAULT;
@@ -2483,6 +2776,15 @@ sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp,
                        return -EINVAL;
                if (filp->f_flags & O_NONBLOCK)
                        return -EAGAIN;
+               if (!cam->module_param.frame_timeout) {
+                       err = wait_event_interruptible
+                             ( cam->wait_frame,
+                               (!list_empty(&cam->outqueue)) ||
+                               (cam->state & DEV_DISCONNECTED) ||
+                               (cam->state & DEV_MISCONFIGURED) );
+                       if (err)
+                               return err;
+               } else {
                timeout = wait_event_interruptible_timeout
                          ( cam->wait_frame,
                            (!list_empty(&cam->outqueue)) ||
@@ -2492,9 +2794,15 @@ sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp,
                            1000 * msecs_to_jiffies(1) );
                if (timeout < 0)
                        return timeout;
+                       else if (timeout == 0 &&
+                                !(cam->state & DEV_DISCONNECTED)) {
+                               DBG(1, "Video frame timeout elapsed");
+                               return -EIO;
+                       }
+               }
                if (cam->state & DEV_DISCONNECTED)
                        return -ENODEV;
-               if (!timeout || (cam->state & DEV_MISCONFIGURED))
+               if (cam->state & DEV_MISCONFIGURED)
                        return -EIO;
        }
 
@@ -2612,6 +2920,70 @@ sn9c102_vidioc_s_parm(struct sn9c102_device* cam, void __user * arg)
 }
 
 
+static int
+sn9c102_vidioc_enumaudio(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_audio audio;
+
+       if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
+               return -EINVAL;
+
+       if (copy_from_user(&audio, arg, sizeof(audio)))
+               return -EFAULT;
+
+       if (audio.index != 0)
+               return -EINVAL;
+
+       strcpy(audio.name, "Microphone");
+       audio.capability = 0;
+       audio.mode = 0;
+
+       if (copy_to_user(arg, &audio, sizeof(audio)))
+               return -EFAULT;
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_g_audio(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_audio audio;
+
+       if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
+               return -EINVAL;
+
+       if (copy_from_user(&audio, arg, sizeof(audio)))
+               return -EFAULT;
+
+       memset(&audio, 0, sizeof(audio));
+       strcpy(audio.name, "Microphone");
+
+       if (copy_to_user(arg, &audio, sizeof(audio)))
+               return -EFAULT;
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_s_audio(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_audio audio;
+
+       if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
+               return -EINVAL;
+
+       if (copy_from_user(&audio, arg, sizeof(audio)))
+               return -EFAULT;
+
+       if (audio.index != 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+
 static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
                              unsigned int cmd, void __user * arg)
 {
@@ -2649,6 +3021,9 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
        case VIDIOC_S_CROP:
                return sn9c102_vidioc_s_crop(cam, arg);
 
+       case VIDIOC_ENUM_FRAMESIZES:
+               return sn9c102_vidioc_enum_framesizes(cam, arg);
+
        case VIDIOC_ENUM_FMT:
                return sn9c102_vidioc_enum_fmt(cam, arg);
 
@@ -2689,11 +3064,21 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
        case VIDIOC_S_PARM:
                return sn9c102_vidioc_s_parm(cam, arg);
 
+       case VIDIOC_ENUMAUDIO:
+               return sn9c102_vidioc_enumaudio(cam, arg);
+
+       case VIDIOC_G_AUDIO:
+               return sn9c102_vidioc_g_audio(cam, arg);
+
+       case VIDIOC_S_AUDIO:
+               return sn9c102_vidioc_s_audio(cam, arg);
+
        case VIDIOC_G_STD:
        case VIDIOC_S_STD:
        case VIDIOC_QUERYSTD:
        case VIDIOC_ENUMSTD:
        case VIDIOC_QUERYMENU:
+       case VIDIOC_ENUM_FRAMEINTERVALS:
                return -EINVAL;
 
        default:
@@ -2741,6 +3126,7 @@ static const struct file_operations sn9c102_fops = {
        .open =    sn9c102_open,
        .release = sn9c102_release,
        .ioctl =   sn9c102_ioctl,
+       .compat_ioctl = v4l_compat_ioctl32,
        .read =    sn9c102_read,
        .poll =    sn9c102_poll,
        .mmap =    sn9c102_mmap,
@@ -2765,7 +3151,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
        cam->usbdev = udev;
 
        if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) {
-               DBG(1, "kmalloc() failed");
+               DBG(1, "kzalloc() failed");
                err = -ENOMEM;
                goto fail;
        }
@@ -2779,24 +3165,31 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
        mutex_init(&cam->dev_mutex);
 
        r = sn9c102_read_reg(cam, 0x00);
-       if (r < 0 || r != 0x10) {
-               DBG(1, "Sorry, this is not a SN9C10x based camera "
-                      "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct);
+       if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) {
+               DBG(1, "Sorry, this is not a SN9C1xx based camera "
+                      "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
                err = -ENODEV;
                goto fail;
        }
 
-       cam->bridge = (id->idProduct & 0xffc0) == 0x6080 ?
-                     BRIDGE_SN9C103 : BRIDGE_SN9C102;
+       cam->bridge = id->driver_info;
        switch (cam->bridge) {
        case BRIDGE_SN9C101:
        case BRIDGE_SN9C102:
                DBG(2, "SN9C10[12] PC Camera Controller detected "
-                      "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct);
+                      "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
                break;
        case BRIDGE_SN9C103:
                DBG(2, "SN9C103 PC Camera Controller detected "
-                      "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct);
+                      "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+               break;
+       case BRIDGE_SN9C105:
+               DBG(2, "SN9C105 PC Camera Controller detected "
+                      "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+               break;
+       case BRIDGE_SN9C120:
+               DBG(2, "SN9C120 PC Camera Controller detected "
+                      "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
                break;
        }
 
@@ -2816,12 +3209,18 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
                goto fail;
        }
 
+       if (!(cam->bridge & cam->sensor.supported_bridge)) {
+               DBG(1, "Bridge not supported");
+               err = -ENODEV;
+               goto fail;
+       }
+
        if (sn9c102_init(cam)) {
                DBG(1, "Initialization failed. I will retry on open().");
                cam->state |= DEV_MISCONFIGURED;
        }
 
-       strcpy(cam->v4ldev->name, "SN9C10x PC Camera");
+       strcpy(cam->v4ldev->name, "SN9C1xx PC Camera");
        cam->v4ldev->owner = THIS_MODULE;
        cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
        cam->v4ldev->hardware = 0;
@@ -2838,7 +3237,10 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
                DBG(1, "V4L2 device registration failed");
                if (err == -ENFILE && video_nr[dev_nr] == -1)
                        DBG(1, "Free /dev/videoX node not found");
-               goto fail2;
+               video_nr[dev_nr] = -1;
+               dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
+               mutex_unlock(&cam->dev_mutex);
+               goto fail;
        }
 
        DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
@@ -2850,9 +3252,14 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        err = sn9c102_create_sysfs(cam);
-       if (err)
-               goto fail3;
-       DBG(2, "Optional device control through 'sysfs' interface ready");
+       if (!err)
+               DBG(2, "Optional device control through 'sysfs' "
+                      "interface ready");
+       else
+               DBG(2, "Failed to create optional 'sysfs' interface for "
+                      "device controlling. Error #%d", err);
+#else
+       DBG(2, "Optional device control through 'sysfs' interface disabled");
 #endif
 
        usb_set_intfdata(intf, cam);
@@ -2861,14 +3268,6 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
 
        return 0;
 
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-fail3:
-       video_unregister_device(cam->v4ldev);
-#endif
-fail2:
-       video_nr[dev_nr] = -1;
-       dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
-       mutex_unlock(&cam->dev_mutex);
 fail:
        if (cam) {
                kfree(cam->control_buffer);
diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h
new file mode 100644 (file)
index 0000000..3a682ec
--- /dev/null
@@ -0,0 +1,142 @@
+/***************************************************************************
+ * Table of device identifiers of the SN9C1xx PC Camera Controllers        *
+ *                                                                         *
+ * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ *                                                                         *
+ * This program is free software; you can redistribute it and/or modify    *
+ * it under the terms of the GNU General Public License as published by    *
+ * the Free Software Foundation; either version 2 of the License, or       *
+ * (at your option) any later version.                                     *
+ *                                                                         *
+ * This program is distributed in the hope that it will be useful,         *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ * GNU General Public License for more details.                            *
+ *                                                                         *
+ * You should have received a copy of the GNU General Public License       *
+ * along with this program; if not, write to the Free Software             *
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
+ ***************************************************************************/
+
+#ifndef _SN9C102_DEVTABLE_H_
+#define _SN9C102_DEVTABLE_H_
+
+#include <linux/usb.h>
+
+struct sn9c102_device;
+
+/*
+   Each SN9C1xx camera has proper PID/VID identifiers.
+   SN9C103, SN9C105, SN9C120 support multiple interfaces, but we only have to
+   handle the video class interface.
+*/
+#define SN9C102_USB_DEVICE(vend, prod, bridge)                                \
+       .match_flags = USB_DEVICE_ID_MATCH_DEVICE |                           \
+                      USB_DEVICE_ID_MATCH_INT_CLASS,                         \
+       .idVendor = (vend),                                                   \
+       .idProduct = (prod),                                                  \
+       .bInterfaceClass = 0xff,                                              \
+       .driver_info = (bridge)
+
+static const struct usb_device_id sn9c102_id_table[] = {
+       /* SN9C101 and SN9C102 */
+       { SN9C102_USB_DEVICE(0x0c45, 0x6001, BRIDGE_SN9C102), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x603f, BRIDGE_SN9C102), },
+       /* SN9C103 */
+       { SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x6082, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x6083, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x6088, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x608a, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x608b, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x608c, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x608e, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x608f, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60a0, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60a2, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60a3, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60a8, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60aa, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60ab, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60ac, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60ae, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60af, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60b0, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60b2, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60b3, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60b8, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60ba, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60bb, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), },
+       /* SN9C105 */
+       { SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), },
+       { SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60c8, BRIDGE_SN9C105), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60cc, BRIDGE_SN9C105), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60ea, BRIDGE_SN9C105), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60ec, BRIDGE_SN9C105), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60fa, BRIDGE_SN9C105), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60fb, BRIDGE_SN9C105), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), },
+       /* SN9C120 */
+       { SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), },
+       { }
+};
+
+/*
+   Probing functions: on success, you must attach the sensor to the camera
+   by calling sn9c102_attach_sensor().
+   To enable the I2C communication, you might need to perform a really basic
+   initialization of the SN9C1XX chip.
+   Functions must return 0 on success, the appropriate error otherwise.
+*/
+extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam);
+extern int sn9c102_probe_mi0343(struct sn9c102_device* cam);
+extern int sn9c102_probe_ov7630(struct sn9c102_device* cam);
+extern int sn9c102_probe_ov7660(struct sn9c102_device* cam);
+extern int sn9c102_probe_pas106b(struct sn9c102_device* cam);
+extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam);
+extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam);
+extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam);
+
+/*
+   Add the above entries to this table. Be sure to add the entry in the right
+   place, since, on failure, the next probing routine is called according to
+   the order of the list below, from top to bottom.
+*/
+static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = {
+       &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */
+       &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */
+       &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */
+       &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */
+       &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */
+       &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */
+       &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */
+       &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */
+       NULL,
+};
+
+#endif /* _SN9C102_DEVTABLE_H_ */
index c4117bf64b6996f0d7649df28c794440cb2dd3a4..7ae368f60d899d3db8945d61d72e96985fae5227 100644 (file)
@@ -1,8 +1,8 @@
 /***************************************************************************
- * Plug-in for HV7131D image sensor connected to the SN9C10x PC Camera     *
+ * Plug-in for HV7131D image sensor connected to the SN9C1xx PC Camera     *
  * Controllers                                                             *
  *                                                                         *
- * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -124,7 +124,7 @@ static int hv7131d_set_ctrl(struct sn9c102_device* cam,
 static int hv7131d_set_crop(struct sn9c102_device* cam,
                            const struct v4l2_rect* rect)
 {
-       struct sn9c102_sensor* s = &hv7131d;
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
        int err = 0;
        u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 2,
           v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2;
@@ -153,6 +153,7 @@ static int hv7131d_set_pix_format(struct sn9c102_device* cam,
 static struct sn9c102_sensor hv7131d = {
        .name = "HV7131D",
        .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+       .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
        .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
        .frequency = SN9C102_I2C_100KHZ,
        .interface = SN9C102_I2C_2WIRES,
index 4169ea4a2e20f93b673b165f979a739cf5438c4f..a33d1bc10f90e536e10f68c3f9f9392998725f69 100644 (file)
@@ -1,8 +1,8 @@
 /***************************************************************************
- * Plug-in for MI-0343 image sensor connected to the SN9C10x PC Camera     *
+ * Plug-in for MI-0343 image sensor connected to the SN9C1xx PC Camera     *
  * Controllers                                                             *
  *                                                                         *
- * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -201,7 +201,7 @@ static int mi0343_set_ctrl(struct sn9c102_device* cam,
 static int mi0343_set_crop(struct sn9c102_device* cam,
                            const struct v4l2_rect* rect)
 {
-       struct sn9c102_sensor* s = &mi0343;
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
        int err = 0;
        u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0,
           v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2;
@@ -237,6 +237,7 @@ static int mi0343_set_pix_format(struct sn9c102_device* cam,
 static struct sn9c102_sensor mi0343 = {
        .name = "MI-0343",
        .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+       .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
        .frequency = SN9C102_I2C_100KHZ,
        .interface = SN9C102_I2C_2WIRES,
        .i2c_slave_id = 0x5d,
index 3da042021787e09d4e34461503168f7fc53b74f9..7df09ff38e63408d7fd827d25f49f296cc70c4d0 100644 (file)
@@ -1,8 +1,8 @@
 /***************************************************************************
- * Plug-in for OV7630 image sensor connected to the SN9C10x PC Camera      *
+ * Plug-in for OV7630 image sensor connected to the SN9C1xx PC Camera      *
  * Controllers                                                             *
  *                                                                         *
- * Copyright (C) 2005-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -29,13 +29,17 @@ static int ov7630_init(struct sn9c102_device* cam)
 {
        int err = 0;
 
+       switch (sn9c102_get_bridge(cam)) {
+       case BRIDGE_SN9C101:
+       case BRIDGE_SN9C102:
        err += sn9c102_write_reg(cam, 0x00, 0x14);
        err += sn9c102_write_reg(cam, 0x60, 0x17);
        err += sn9c102_write_reg(cam, 0x0f, 0x18);
        err += sn9c102_write_reg(cam, 0x50, 0x19);
 
-       err += sn9c102_i2c_write(cam, 0x12, 0x80);
-       err += sn9c102_i2c_write(cam, 0x11, 0x01);
+               err += sn9c102_i2c_write(cam, 0x12, 0x8d);
+               err += sn9c102_i2c_write(cam, 0x12, 0x0d);
+               err += sn9c102_i2c_write(cam, 0x11, 0x00);
        err += sn9c102_i2c_write(cam, 0x15, 0x34);
        err += sn9c102_i2c_write(cam, 0x16, 0x03);
        err += sn9c102_i2c_write(cam, 0x17, 0x1c);
@@ -43,14 +47,72 @@ static int ov7630_init(struct sn9c102_device* cam)
        err += sn9c102_i2c_write(cam, 0x19, 0x06);
        err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
        err += sn9c102_i2c_write(cam, 0x1b, 0x04);
-       err += sn9c102_i2c_write(cam, 0x20, 0xf6);
+               err += sn9c102_i2c_write(cam, 0x20, 0x44);
+               err += sn9c102_i2c_write(cam, 0x23, 0xee);
+               err += sn9c102_i2c_write(cam, 0x26, 0xa0);
+               err += sn9c102_i2c_write(cam, 0x27, 0x9a);
+               err += sn9c102_i2c_write(cam, 0x28, 0x20);
+               err += sn9c102_i2c_write(cam, 0x29, 0x30);
+               err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
+               err += sn9c102_i2c_write(cam, 0x30, 0x24);
+               err += sn9c102_i2c_write(cam, 0x32, 0x86);
+               err += sn9c102_i2c_write(cam, 0x60, 0xa9);
+               err += sn9c102_i2c_write(cam, 0x61, 0x42);
+               err += sn9c102_i2c_write(cam, 0x65, 0x00);
+               err += sn9c102_i2c_write(cam, 0x69, 0x38);
+               err += sn9c102_i2c_write(cam, 0x6f, 0x88);
+               err += sn9c102_i2c_write(cam, 0x70, 0x0b);
+               err += sn9c102_i2c_write(cam, 0x71, 0x00);
+               err += sn9c102_i2c_write(cam, 0x74, 0x21);
+               err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
+               break;
+       case BRIDGE_SN9C103:
+               err += sn9c102_write_reg(cam, 0x00, 0x02);
+               err += sn9c102_write_reg(cam, 0x00, 0x03);
+               err += sn9c102_write_reg(cam, 0x1a, 0x04);
+               err += sn9c102_write_reg(cam, 0x20, 0x05);
+               err += sn9c102_write_reg(cam, 0x20, 0x06);
+               err += sn9c102_write_reg(cam, 0x20, 0x07);
+               err += sn9c102_write_reg(cam, 0x03, 0x10);
+               err += sn9c102_write_reg(cam, 0x0a, 0x14);
+               err += sn9c102_write_reg(cam, 0x60, 0x17);
+               err += sn9c102_write_reg(cam, 0x0f, 0x18);
+               err += sn9c102_write_reg(cam, 0x50, 0x19);
+               err += sn9c102_write_reg(cam, 0x1d, 0x1a);
+               err += sn9c102_write_reg(cam, 0x10, 0x1b);
+               err += sn9c102_write_reg(cam, 0x02, 0x1c);
+               err += sn9c102_write_reg(cam, 0x03, 0x1d);
+               err += sn9c102_write_reg(cam, 0x0f, 0x1e);
+               err += sn9c102_write_reg(cam, 0x0c, 0x1f);
+               err += sn9c102_write_reg(cam, 0x00, 0x20);
+               err += sn9c102_write_reg(cam, 0x10, 0x21);
+               err += sn9c102_write_reg(cam, 0x20, 0x22);
+               err += sn9c102_write_reg(cam, 0x30, 0x23);
+               err += sn9c102_write_reg(cam, 0x40, 0x24);
+               err += sn9c102_write_reg(cam, 0x50, 0x25);
+               err += sn9c102_write_reg(cam, 0x60, 0x26);
+               err += sn9c102_write_reg(cam, 0x70, 0x27);
+               err += sn9c102_write_reg(cam, 0x80, 0x28);
+               err += sn9c102_write_reg(cam, 0x90, 0x29);
+               err += sn9c102_write_reg(cam, 0xa0, 0x2a);
+               err += sn9c102_write_reg(cam, 0xb0, 0x2b);
+               err += sn9c102_write_reg(cam, 0xc0, 0x2c);
+               err += sn9c102_write_reg(cam, 0xd0, 0x2d);
+               err += sn9c102_write_reg(cam, 0xe0, 0x2e);
+               err += sn9c102_write_reg(cam, 0xf0, 0x2f);
+               err += sn9c102_write_reg(cam, 0xff, 0x30);
+
+               err += sn9c102_i2c_write(cam, 0x12, 0x8d);
+               err += sn9c102_i2c_write(cam, 0x12, 0x0d);
+               err += sn9c102_i2c_write(cam, 0x15, 0x34);
+               err += sn9c102_i2c_write(cam, 0x11, 0x01);
+               err += sn9c102_i2c_write(cam, 0x1b, 0x04);
+               err += sn9c102_i2c_write(cam, 0x20, 0x44);
        err += sn9c102_i2c_write(cam, 0x23, 0xee);
        err += sn9c102_i2c_write(cam, 0x26, 0xa0);
        err += sn9c102_i2c_write(cam, 0x27, 0x9a);
-       err += sn9c102_i2c_write(cam, 0x28, 0xa0);
+               err += sn9c102_i2c_write(cam, 0x28, 0x20);
        err += sn9c102_i2c_write(cam, 0x29, 0x30);
-       err += sn9c102_i2c_write(cam, 0x2a, 0xa0);
-       err += sn9c102_i2c_write(cam, 0x2b, 0x1f);
        err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
        err += sn9c102_i2c_write(cam, 0x30, 0x24);
        err += sn9c102_i2c_write(cam, 0x32, 0x86);
@@ -63,45 +125,97 @@ static int ov7630_init(struct sn9c102_device* cam)
        err += sn9c102_i2c_write(cam, 0x71, 0x00);
        err += sn9c102_i2c_write(cam, 0x74, 0x21);
        err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
+               break;
+       default:
+               break;
+       }
 
        return err;
 }
 
 
-static int ov7630_set_ctrl(struct sn9c102_device* cam,
-                          const struct v4l2_control* ctrl)
+static int ov7630_get_ctrl(struct sn9c102_device* cam,
+                          struct v4l2_control* ctrl)
 {
        int err = 0;
 
        switch (ctrl->id) {
        case V4L2_CID_EXPOSURE:
-               err += sn9c102_i2c_write(cam, 0x10, ctrl->value >> 2);
-               err += sn9c102_i2c_write(cam, 0x76, ctrl->value & 0x03);
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0)
+                       return -EIO;
                break;
        case V4L2_CID_RED_BALANCE:
-               err += sn9c102_i2c_write(cam, 0x02, ctrl->value);
+               ctrl->value = sn9c102_pread_reg(cam, 0x07);
                break;
        case V4L2_CID_BLUE_BALANCE:
-               err += sn9c102_i2c_write(cam, 0x01, ctrl->value);
+               ctrl->value = sn9c102_pread_reg(cam, 0x06);
+               break;
+       case SN9C102_V4L2_CID_GREEN_BALANCE:
+               ctrl->value = sn9c102_pread_reg(cam, 0x05);
                break;
        case V4L2_CID_GAIN:
-               err += sn9c102_i2c_write(cam, 0x00, ctrl->value);
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x3f;
+               break;
+       case V4L2_CID_DO_WHITE_BALANCE:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x3f;
+               break;
+       case V4L2_CID_WHITENESS:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x0d)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x3f;
+               break;
+       case V4L2_CID_AUTOGAIN:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x13)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x01;
+               break;
+       case V4L2_CID_VFLIP:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x75)) < 0)
+                       return -EIO;
+               ctrl->value = (ctrl->value & 0x80) ? 1 : 0;
+               break;
+       case SN9C102_V4L2_CID_GAMMA:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x14)) < 0)
+                       return -EIO;
+               ctrl->value = (ctrl->value & 0x02) ? 1 : 0;
+               break;
+       case SN9C102_V4L2_CID_BAND_FILTER:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x2d)) < 0)
+                       return -EIO;
+               ctrl->value = (ctrl->value & 0x02) ? 1 : 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return err ? -EIO : 0;
+}
+
+
+static int ov7630_set_ctrl(struct sn9c102_device* cam,
+                          const struct v4l2_control* ctrl)
+{
+       int err = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_EXPOSURE:
+               err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
                break;
-       case V4L2_CID_CONTRAST:
-               err += ctrl->value ? sn9c102_i2c_write(cam, 0x05,
-                                                      (ctrl->value-1) | 0x20)
-                                  : sn9c102_i2c_write(cam, 0x05, 0x00);
+       case V4L2_CID_RED_BALANCE:
+               err += sn9c102_write_reg(cam, ctrl->value, 0x07);
                break;
-       case V4L2_CID_BRIGHTNESS:
-               err += sn9c102_i2c_write(cam, 0x06, ctrl->value);
+       case V4L2_CID_BLUE_BALANCE:
+               err += sn9c102_write_reg(cam, ctrl->value, 0x06);
                break;
-       case V4L2_CID_SATURATION:
-               err += sn9c102_i2c_write(cam, 0x03, ctrl->value << 4);
+       case SN9C102_V4L2_CID_GREEN_BALANCE:
+               err += sn9c102_write_reg(cam, ctrl->value, 0x05);
                break;
-       case V4L2_CID_HUE:
-               err += ctrl->value ? sn9c102_i2c_write(cam, 0x04,
-                                                      (ctrl->value-1) | 0x20)
-                                  : sn9c102_i2c_write(cam, 0x04, 0x00);
+       case V4L2_CID_GAIN:
+               err += sn9c102_i2c_write(cam, 0x00, ctrl->value);
                break;
        case V4L2_CID_DO_WHITE_BALANCE:
                err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
@@ -109,23 +223,15 @@ static int ov7630_set_ctrl(struct sn9c102_device* cam,
        case V4L2_CID_WHITENESS:
                err += sn9c102_i2c_write(cam, 0x0d, ctrl->value);
                break;
-       case V4L2_CID_AUTO_WHITE_BALANCE:
-               err += sn9c102_i2c_write(cam, 0x12, (ctrl->value << 2) | 0x78);
-               break;
        case V4L2_CID_AUTOGAIN:
-               err += sn9c102_i2c_write(cam, 0x13, ctrl->value);
+               err += sn9c102_i2c_write(cam, 0x13, ctrl->value |
+                                                   (ctrl->value << 1));
                break;
        case V4L2_CID_VFLIP:
                err += sn9c102_i2c_write(cam, 0x75, 0x0e | (ctrl->value << 7));
                break;
-       case V4L2_CID_BLACK_LEVEL:
-               err += sn9c102_i2c_write(cam, 0x25, ctrl->value);
-               break;
-       case SN9C102_V4L2_CID_BRIGHT_LEVEL:
-               err += sn9c102_i2c_write(cam, 0x24, ctrl->value);
-               break;
        case SN9C102_V4L2_CID_GAMMA:
-               err += sn9c102_i2c_write(cam, 0x14, (ctrl->value << 2) | 0x80);
+               err += sn9c102_i2c_write(cam, 0x14, ctrl->value << 2);
                break;
        case SN9C102_V4L2_CID_BAND_FILTER:
                err += sn9c102_i2c_write(cam, 0x2d, ctrl->value << 2);
@@ -141,10 +247,12 @@ static int ov7630_set_ctrl(struct sn9c102_device* cam,
 static int ov7630_set_crop(struct sn9c102_device* cam,
                           const struct v4l2_rect* rect)
 {
-       struct sn9c102_sensor* s = &ov7630;
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
        int err = 0;
-       u8 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
+       u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1,
+          v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
 
+       err += sn9c102_write_reg(cam, h_start, 0x12);
        err += sn9c102_write_reg(cam, v_start, 0x13);
 
        return err;
@@ -168,7 +276,8 @@ static int ov7630_set_pix_format(struct sn9c102_device* cam,
 static struct sn9c102_sensor ov7630 = {
        .name = "OV7630",
        .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-       .sysfs_ops = SN9C102_I2C_WRITE,
+       .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
+       .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
        .frequency = SN9C102_I2C_100KHZ,
        .interface = SN9C102_I2C_2WIRES,
        .i2c_slave_id = 0x21,
@@ -184,74 +293,24 @@ static struct sn9c102_sensor ov7630 = {
                        .default_value = 0x14,
                        .flags = 0,
                },
-               {
-                       .id = V4L2_CID_HUE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "hue",
-                       .minimum = 0x00,
-                       .maximum = 0x1f+1,
-                       .step = 0x01,
-                       .default_value = 0x00,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_SATURATION,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "saturation",
-                       .minimum = 0x00,
-                       .maximum = 0x0f,
-                       .step = 0x01,
-                       .default_value = 0x08,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_CONTRAST,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "contrast",
-                       .minimum = 0x00,
-                       .maximum = 0x1f+1,
-                       .step = 0x01,
-                       .default_value = 0x00,
-                       .flags = 0,
-               },
                {
                        .id = V4L2_CID_EXPOSURE,
                        .type = V4L2_CTRL_TYPE_INTEGER,
                        .name = "exposure",
-                       .minimum = 0x000,
-                       .maximum = 0x3ff,
-                       .step = 0x001,
-                       .default_value = 0x83<<2,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_RED_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "red balance",
-                       .minimum = 0x00,
-                       .maximum = 0xff,
-                       .step = 0x01,
-                       .default_value = 0x3a,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_BLUE_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "blue balance",
                        .minimum = 0x00,
                        .maximum = 0xff,
                        .step = 0x01,
-                       .default_value = 0x77,
+                       .default_value = 0x60,
                        .flags = 0,
                },
                {
-                       .id = V4L2_CID_BRIGHTNESS,
+                       .id = V4L2_CID_WHITENESS,
                        .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "brightness",
+                       .name = "white balance background: red",
                        .minimum = 0x00,
-                       .maximum = 0xff,
+                       .maximum = 0x3f,
                        .step = 0x01,
-                       .default_value = 0xa0,
+                       .default_value = 0x20,
                        .flags = 0,
                },
                {
@@ -265,31 +324,31 @@ static struct sn9c102_sensor ov7630 = {
                        .flags = 0,
                },
                {
-                       .id = V4L2_CID_WHITENESS,
+                       .id = V4L2_CID_RED_BALANCE,
                        .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "white balance background: red",
+                       .name = "red balance",
                        .minimum = 0x00,
-                       .maximum = 0x3f,
+                       .maximum = 0x7f,
                        .step = 0x01,
                        .default_value = 0x20,
                        .flags = 0,
                },
                {
-                       .id = V4L2_CID_AUTO_WHITE_BALANCE,
-                       .type = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name = "auto white balance",
+                       .id = V4L2_CID_BLUE_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "blue balance",
                        .minimum = 0x00,
-                       .maximum = 0x01,
+                       .maximum = 0x7f,
                        .step = 0x01,
-                       .default_value = 0x01,
+                       .default_value = 0x20,
                        .flags = 0,
                },
                {
                        .id = V4L2_CID_AUTOGAIN,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "gain & exposure mode",
+                       .type = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name = "auto adjust",
                        .minimum = 0x00,
-                       .maximum = 0x03,
+                       .maximum = 0x01,
                        .step = 0x01,
                        .default_value = 0x00,
                        .flags = 0,
@@ -305,23 +364,13 @@ static struct sn9c102_sensor ov7630 = {
                        .flags = 0,
                },
                {
-                       .id = V4L2_CID_BLACK_LEVEL,
+                       .id = SN9C102_V4L2_CID_GREEN_BALANCE,
                        .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "black pixel ratio",
-                       .minimum = 0x01,
-                       .maximum = 0x9a,
-                       .step = 0x01,
-                       .default_value = 0x8a,
-                       .flags = 0,
-               },
-               {
-                       .id = SN9C102_V4L2_CID_BRIGHT_LEVEL,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "bright pixel ratio",
-                       .minimum = 0x01,
-                       .maximum = 0x9a,
+                       .name = "green balance",
+                       .minimum = 0x00,
+                       .maximum = 0x7f,
                        .step = 0x01,
-                       .default_value = 0x10,
+                       .default_value = 0x20,
                        .flags = 0,
                },
                {
@@ -345,6 +394,7 @@ static struct sn9c102_sensor ov7630 = {
                        .flags = 0,
                },
        },
+       .get_ctrl = &ov7630_get_ctrl,
        .set_ctrl = &ov7630_set_ctrl,
        .cropcap = {
                .bounds = {
@@ -364,7 +414,7 @@ static struct sn9c102_sensor ov7630 = {
        .pix_format = {
                .width = 640,
                .height = 480,
-               .pixelformat = V4L2_PIX_FMT_SBGGR8,
+               .pixelformat = V4L2_PIX_FMT_SN9C10X,
                .priv = 8,
        },
        .set_pix_format = &ov7630_set_pix_format
@@ -373,28 +423,36 @@ static struct sn9c102_sensor ov7630 = {
 
 int sn9c102_probe_ov7630(struct sn9c102_device* cam)
 {
-       const struct usb_device_id ov7630_id_table[] = {
-               { USB_DEVICE(0x0c45, 0x602c), },
-               { USB_DEVICE(0x0c45, 0x602d), },
-               { USB_DEVICE(0x0c45, 0x608f), },
-               { USB_DEVICE(0x0c45, 0x60b0), },
-               { }
-       };
-       int err = 0;
-
-       if (!sn9c102_match_id(cam, ov7630_id_table))
-               return -ENODEV;
+       int pid, ver, err = 0;
 
+       switch (sn9c102_get_bridge(cam)) {
+       case BRIDGE_SN9C101:
+       case BRIDGE_SN9C102:
        err += sn9c102_write_reg(cam, 0x01, 0x01);
        err += sn9c102_write_reg(cam, 0x00, 0x01);
        err += sn9c102_write_reg(cam, 0x28, 0x17);
-       if (err)
-               return -EIO;
+               break;
+       case BRIDGE_SN9C103: /* do _not_ change anything! */
+               err += sn9c102_write_reg(cam, 0x09, 0x01);
+               err += sn9c102_write_reg(cam, 0x42, 0x01);
+               err += sn9c102_write_reg(cam, 0x28, 0x17);
+               err += sn9c102_write_reg(cam, 0x44, 0x02);
+               pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a);
+               if (err || pid < 0) { /* try a different initialization */
+                       err = sn9c102_write_reg(cam, 0x01, 0x01);
+                       err += sn9c102_write_reg(cam, 0x00, 0x01);
+               }
+               break;
+       default:
+               break;
+       }
 
-       err += sn9c102_i2c_try_write(cam, &ov7630, 0x0b, 0);
-       if (err)
+       pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a);
+       ver = sn9c102_i2c_try_read(cam, &ov7630, 0x0b);
+       if (err || pid < 0 || ver < 0)
+               return -EIO;
+       if (pid != 0x76 || ver != 0x31)
                return -ENODEV;
-
        sn9c102_attach_sensor(cam, &ov7630);
 
        return 0;
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7660.c b/drivers/media/video/sn9c102/sn9c102_ov7660.c
new file mode 100644 (file)
index 0000000..d670c24
--- /dev/null
@@ -0,0 +1,592 @@
+/***************************************************************************
+ * Plug-in for OV7660 image sensor connected to the SN9C1xx PC Camera      *
+ * Controllers                                                             *
+ *                                                                         *
+ * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ *                                                                         *
+ * This program is free software; you can redistribute it and/or modify    *
+ * it under the terms of the GNU General Public License as published by    *
+ * the Free Software Foundation; either version 2 of the License, or       *
+ * (at your option) any later version.                                     *
+ *                                                                         *
+ * This program is distributed in the hope that it will be useful,         *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ * GNU General Public License for more details.                            *
+ *                                                                         *
+ * You should have received a copy of the GNU General Public License       *
+ * along with this program; if not, write to the Free Software             *
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
+ ***************************************************************************/
+
+#include "sn9c102_sensor.h"
+
+
+static struct sn9c102_sensor ov7660;
+
+
+static int ov7660_init(struct sn9c102_device* cam)
+{
+       int err = 0;
+
+       err += sn9c102_write_reg(cam, 0x40, 0x02);
+       err += sn9c102_write_reg(cam, 0x00, 0x03);
+       err += sn9c102_write_reg(cam, 0x1a, 0x04);
+       err += sn9c102_write_reg(cam, 0x03, 0x10);
+       err += sn9c102_write_reg(cam, 0x08, 0x14);
+       err += sn9c102_write_reg(cam, 0x20, 0x17);
+       err += sn9c102_write_reg(cam, 0x8b, 0x18);
+       err += sn9c102_write_reg(cam, 0x00, 0x19);
+       err += sn9c102_write_reg(cam, 0x1d, 0x1a);
+       err += sn9c102_write_reg(cam, 0x10, 0x1b);
+       err += sn9c102_write_reg(cam, 0x02, 0x1c);
+       err += sn9c102_write_reg(cam, 0x03, 0x1d);
+       err += sn9c102_write_reg(cam, 0x0f, 0x1e);
+       err += sn9c102_write_reg(cam, 0x0c, 0x1f);
+       err += sn9c102_write_reg(cam, 0x00, 0x20);
+       err += sn9c102_write_reg(cam, 0x29, 0x21);
+       err += sn9c102_write_reg(cam, 0x40, 0x22);
+       err += sn9c102_write_reg(cam, 0x54, 0x23);
+       err += sn9c102_write_reg(cam, 0x66, 0x24);
+       err += sn9c102_write_reg(cam, 0x76, 0x25);
+       err += sn9c102_write_reg(cam, 0x85, 0x26);
+       err += sn9c102_write_reg(cam, 0x94, 0x27);
+       err += sn9c102_write_reg(cam, 0xa1, 0x28);
+       err += sn9c102_write_reg(cam, 0xae, 0x29);
+       err += sn9c102_write_reg(cam, 0xbb, 0x2a);
+       err += sn9c102_write_reg(cam, 0xc7, 0x2b);
+       err += sn9c102_write_reg(cam, 0xd3, 0x2c);
+       err += sn9c102_write_reg(cam, 0xde, 0x2d);
+       err += sn9c102_write_reg(cam, 0xea, 0x2e);
+       err += sn9c102_write_reg(cam, 0xf4, 0x2f);
+       err += sn9c102_write_reg(cam, 0xff, 0x30);
+       err += sn9c102_write_reg(cam, 0x00, 0x3F);
+       err += sn9c102_write_reg(cam, 0xC7, 0x40);
+       err += sn9c102_write_reg(cam, 0x01, 0x41);
+       err += sn9c102_write_reg(cam, 0x44, 0x42);
+       err += sn9c102_write_reg(cam, 0x00, 0x43);
+       err += sn9c102_write_reg(cam, 0x44, 0x44);
+       err += sn9c102_write_reg(cam, 0x00, 0x45);
+       err += sn9c102_write_reg(cam, 0x44, 0x46);
+       err += sn9c102_write_reg(cam, 0x00, 0x47);
+       err += sn9c102_write_reg(cam, 0xC7, 0x48);
+       err += sn9c102_write_reg(cam, 0x01, 0x49);
+       err += sn9c102_write_reg(cam, 0xC7, 0x4A);
+       err += sn9c102_write_reg(cam, 0x01, 0x4B);
+       err += sn9c102_write_reg(cam, 0xC7, 0x4C);
+       err += sn9c102_write_reg(cam, 0x01, 0x4D);
+       err += sn9c102_write_reg(cam, 0x44, 0x4E);
+       err += sn9c102_write_reg(cam, 0x00, 0x4F);
+       err += sn9c102_write_reg(cam, 0x44, 0x50);
+       err += sn9c102_write_reg(cam, 0x00, 0x51);
+       err += sn9c102_write_reg(cam, 0x44, 0x52);
+       err += sn9c102_write_reg(cam, 0x00, 0x53);
+       err += sn9c102_write_reg(cam, 0xC7, 0x54);
+       err += sn9c102_write_reg(cam, 0x01, 0x55);
+       err += sn9c102_write_reg(cam, 0xC7, 0x56);
+       err += sn9c102_write_reg(cam, 0x01, 0x57);
+       err += sn9c102_write_reg(cam, 0xC7, 0x58);
+       err += sn9c102_write_reg(cam, 0x01, 0x59);
+       err += sn9c102_write_reg(cam, 0x44, 0x5A);
+       err += sn9c102_write_reg(cam, 0x00, 0x5B);
+       err += sn9c102_write_reg(cam, 0x44, 0x5C);
+       err += sn9c102_write_reg(cam, 0x00, 0x5D);
+       err += sn9c102_write_reg(cam, 0x44, 0x5E);
+       err += sn9c102_write_reg(cam, 0x00, 0x5F);
+       err += sn9c102_write_reg(cam, 0xC7, 0x60);
+       err += sn9c102_write_reg(cam, 0x01, 0x61);
+       err += sn9c102_write_reg(cam, 0xC7, 0x62);
+       err += sn9c102_write_reg(cam, 0x01, 0x63);
+       err += sn9c102_write_reg(cam, 0xC7, 0x64);
+       err += sn9c102_write_reg(cam, 0x01, 0x65);
+       err += sn9c102_write_reg(cam, 0x44, 0x66);
+       err += sn9c102_write_reg(cam, 0x00, 0x67);
+       err += sn9c102_write_reg(cam, 0x44, 0x68);
+       err += sn9c102_write_reg(cam, 0x00, 0x69);
+       err += sn9c102_write_reg(cam, 0x44, 0x6A);
+       err += sn9c102_write_reg(cam, 0x00, 0x6B);
+       err += sn9c102_write_reg(cam, 0xC7, 0x6C);
+       err += sn9c102_write_reg(cam, 0x01, 0x6D);
+       err += sn9c102_write_reg(cam, 0xC7, 0x6E);
+       err += sn9c102_write_reg(cam, 0x01, 0x6F);
+       err += sn9c102_write_reg(cam, 0xC7, 0x70);
+       err += sn9c102_write_reg(cam, 0x01, 0x71);
+       err += sn9c102_write_reg(cam, 0x44, 0x72);
+       err += sn9c102_write_reg(cam, 0x00, 0x73);
+       err += sn9c102_write_reg(cam, 0x44, 0x74);
+       err += sn9c102_write_reg(cam, 0x00, 0x75);
+       err += sn9c102_write_reg(cam, 0x44, 0x76);
+       err += sn9c102_write_reg(cam, 0x00, 0x77);
+       err += sn9c102_write_reg(cam, 0xC7, 0x78);
+       err += sn9c102_write_reg(cam, 0x01, 0x79);
+       err += sn9c102_write_reg(cam, 0xC7, 0x7A);
+       err += sn9c102_write_reg(cam, 0x01, 0x7B);
+       err += sn9c102_write_reg(cam, 0xC7, 0x7C);
+       err += sn9c102_write_reg(cam, 0x01, 0x7D);
+       err += sn9c102_write_reg(cam, 0x44, 0x7E);
+       err += sn9c102_write_reg(cam, 0x00, 0x7F);
+       err += sn9c102_write_reg(cam, 0x14, 0x84);
+       err += sn9c102_write_reg(cam, 0x00, 0x85);
+       err += sn9c102_write_reg(cam, 0x27, 0x86);
+       err += sn9c102_write_reg(cam, 0x00, 0x87);
+       err += sn9c102_write_reg(cam, 0x07, 0x88);
+       err += sn9c102_write_reg(cam, 0x00, 0x89);
+       err += sn9c102_write_reg(cam, 0xEC, 0x8A);
+       err += sn9c102_write_reg(cam, 0x0f, 0x8B);
+       err += sn9c102_write_reg(cam, 0xD8, 0x8C);
+       err += sn9c102_write_reg(cam, 0x0f, 0x8D);
+       err += sn9c102_write_reg(cam, 0x3D, 0x8E);
+       err += sn9c102_write_reg(cam, 0x00, 0x8F);
+       err += sn9c102_write_reg(cam, 0x3D, 0x90);
+       err += sn9c102_write_reg(cam, 0x00, 0x91);
+       err += sn9c102_write_reg(cam, 0xCD, 0x92);
+       err += sn9c102_write_reg(cam, 0x0f, 0x93);
+       err += sn9c102_write_reg(cam, 0xf7, 0x94);
+       err += sn9c102_write_reg(cam, 0x0f, 0x95);
+       err += sn9c102_write_reg(cam, 0x0C, 0x96);
+       err += sn9c102_write_reg(cam, 0x00, 0x97);
+       err += sn9c102_write_reg(cam, 0x00, 0x98);
+       err += sn9c102_write_reg(cam, 0x66, 0x99);
+       err += sn9c102_write_reg(cam, 0x05, 0x9A);
+       err += sn9c102_write_reg(cam, 0x00, 0x9B);
+       err += sn9c102_write_reg(cam, 0x04, 0x9C);
+       err += sn9c102_write_reg(cam, 0x00, 0x9D);
+       err += sn9c102_write_reg(cam, 0x08, 0x9E);
+       err += sn9c102_write_reg(cam, 0x00, 0x9F);
+       err += sn9c102_write_reg(cam, 0x2D, 0xC0);
+       err += sn9c102_write_reg(cam, 0x2D, 0xC1);
+       err += sn9c102_write_reg(cam, 0x3A, 0xC2);
+       err += sn9c102_write_reg(cam, 0x05, 0xC3);
+       err += sn9c102_write_reg(cam, 0x04, 0xC4);
+       err += sn9c102_write_reg(cam, 0x3F, 0xC5);
+       err += sn9c102_write_reg(cam, 0x00, 0xC6);
+       err += sn9c102_write_reg(cam, 0x00, 0xC7);
+       err += sn9c102_write_reg(cam, 0x50, 0xC8);
+       err += sn9c102_write_reg(cam, 0x3C, 0xC9);
+       err += sn9c102_write_reg(cam, 0x28, 0xCA);
+       err += sn9c102_write_reg(cam, 0xD8, 0xCB);
+       err += sn9c102_write_reg(cam, 0x14, 0xCC);
+       err += sn9c102_write_reg(cam, 0xEC, 0xCD);
+       err += sn9c102_write_reg(cam, 0x32, 0xCE);
+       err += sn9c102_write_reg(cam, 0xDD, 0xCF);
+       err += sn9c102_write_reg(cam, 0x32, 0xD0);
+       err += sn9c102_write_reg(cam, 0xDD, 0xD1);
+       err += sn9c102_write_reg(cam, 0x6A, 0xD2);
+       err += sn9c102_write_reg(cam, 0x50, 0xD3);
+       err += sn9c102_write_reg(cam, 0x00, 0xD4);
+       err += sn9c102_write_reg(cam, 0x00, 0xD5);
+       err += sn9c102_write_reg(cam, 0x00, 0xD6);
+
+       err += sn9c102_i2c_write(cam, 0x12, 0x80);
+       err += sn9c102_i2c_write(cam, 0x11, 0x09);
+       err += sn9c102_i2c_write(cam, 0x00, 0x0A);
+       err += sn9c102_i2c_write(cam, 0x01, 0x78);
+       err += sn9c102_i2c_write(cam, 0x02, 0x90);
+       err += sn9c102_i2c_write(cam, 0x03, 0x00);
+       err += sn9c102_i2c_write(cam, 0x04, 0x00);
+       err += sn9c102_i2c_write(cam, 0x05, 0x08);
+       err += sn9c102_i2c_write(cam, 0x06, 0x0B);
+       err += sn9c102_i2c_write(cam, 0x07, 0x00);
+       err += sn9c102_i2c_write(cam, 0x08, 0x1C);
+       err += sn9c102_i2c_write(cam, 0x09, 0x01);
+       err += sn9c102_i2c_write(cam, 0x0A, 0x76);
+       err += sn9c102_i2c_write(cam, 0x0B, 0x60);
+       err += sn9c102_i2c_write(cam, 0x0C, 0x00);
+       err += sn9c102_i2c_write(cam, 0x0D, 0x08);
+       err += sn9c102_i2c_write(cam, 0x0E, 0x04);
+       err += sn9c102_i2c_write(cam, 0x0F, 0x6F);
+       err += sn9c102_i2c_write(cam, 0x10, 0x20);
+       err += sn9c102_i2c_write(cam, 0x11, 0x03);
+       err += sn9c102_i2c_write(cam, 0x12, 0x05);
+       err += sn9c102_i2c_write(cam, 0x13, 0xF8);
+       err += sn9c102_i2c_write(cam, 0x14, 0x2C);
+       err += sn9c102_i2c_write(cam, 0x15, 0x00);
+       err += sn9c102_i2c_write(cam, 0x16, 0x02);
+       err += sn9c102_i2c_write(cam, 0x17, 0x10);
+       err += sn9c102_i2c_write(cam, 0x18, 0x60);
+       err += sn9c102_i2c_write(cam, 0x19, 0x02);
+       err += sn9c102_i2c_write(cam, 0x1A, 0x7B);
+       err += sn9c102_i2c_write(cam, 0x1B, 0x02);
+       err += sn9c102_i2c_write(cam, 0x1C, 0x7F);
+       err += sn9c102_i2c_write(cam, 0x1D, 0xA2);
+       err += sn9c102_i2c_write(cam, 0x1E, 0x01);
+       err += sn9c102_i2c_write(cam, 0x1F, 0x0E);
+       err += sn9c102_i2c_write(cam, 0x20, 0x05);
+       err += sn9c102_i2c_write(cam, 0x21, 0x05);
+       err += sn9c102_i2c_write(cam, 0x22, 0x05);
+       err += sn9c102_i2c_write(cam, 0x23, 0x05);
+       err += sn9c102_i2c_write(cam, 0x24, 0x68);
+       err += sn9c102_i2c_write(cam, 0x25, 0x58);
+       err += sn9c102_i2c_write(cam, 0x26, 0xD4);
+       err += sn9c102_i2c_write(cam, 0x27, 0x80);
+       err += sn9c102_i2c_write(cam, 0x28, 0x80);
+       err += sn9c102_i2c_write(cam, 0x29, 0x30);
+       err += sn9c102_i2c_write(cam, 0x2A, 0x00);
+       err += sn9c102_i2c_write(cam, 0x2B, 0x00);
+       err += sn9c102_i2c_write(cam, 0x2C, 0x80);
+       err += sn9c102_i2c_write(cam, 0x2D, 0x00);
+       err += sn9c102_i2c_write(cam, 0x2E, 0x00);
+       err += sn9c102_i2c_write(cam, 0x2F, 0x0E);
+       err += sn9c102_i2c_write(cam, 0x30, 0x08);
+       err += sn9c102_i2c_write(cam, 0x31, 0x30);
+       err += sn9c102_i2c_write(cam, 0x32, 0xB4);
+       err += sn9c102_i2c_write(cam, 0x33, 0x00);
+       err += sn9c102_i2c_write(cam, 0x34, 0x07);
+       err += sn9c102_i2c_write(cam, 0x35, 0x84);
+       err += sn9c102_i2c_write(cam, 0x36, 0x00);
+       err += sn9c102_i2c_write(cam, 0x37, 0x0C);
+       err += sn9c102_i2c_write(cam, 0x38, 0x02);
+       err += sn9c102_i2c_write(cam, 0x39, 0x43);
+       err += sn9c102_i2c_write(cam, 0x3A, 0x00);
+       err += sn9c102_i2c_write(cam, 0x3B, 0x02);
+       err += sn9c102_i2c_write(cam, 0x3C, 0x6C);
+       err += sn9c102_i2c_write(cam, 0x3D, 0x99);
+       err += sn9c102_i2c_write(cam, 0x3E, 0x0E);
+       err += sn9c102_i2c_write(cam, 0x3F, 0x41);
+       err += sn9c102_i2c_write(cam, 0x40, 0xC1);
+       err += sn9c102_i2c_write(cam, 0x41, 0x22);
+       err += sn9c102_i2c_write(cam, 0x42, 0x08);
+       err += sn9c102_i2c_write(cam, 0x43, 0xF0);
+       err += sn9c102_i2c_write(cam, 0x44, 0x10);
+       err += sn9c102_i2c_write(cam, 0x45, 0x78);
+       err += sn9c102_i2c_write(cam, 0x46, 0xA8);
+       err += sn9c102_i2c_write(cam, 0x47, 0x60);
+       err += sn9c102_i2c_write(cam, 0x48, 0x80);
+       err += sn9c102_i2c_write(cam, 0x49, 0x00);
+       err += sn9c102_i2c_write(cam, 0x4A, 0x00);
+       err += sn9c102_i2c_write(cam, 0x4B, 0x00);
+       err += sn9c102_i2c_write(cam, 0x4C, 0x00);
+       err += sn9c102_i2c_write(cam, 0x4D, 0x00);
+       err += sn9c102_i2c_write(cam, 0x4E, 0x00);
+       err += sn9c102_i2c_write(cam, 0x4F, 0x46);
+       err += sn9c102_i2c_write(cam, 0x50, 0x36);
+       err += sn9c102_i2c_write(cam, 0x51, 0x0F);
+       err += sn9c102_i2c_write(cam, 0x52, 0x17);
+       err += sn9c102_i2c_write(cam, 0x53, 0x7F);
+       err += sn9c102_i2c_write(cam, 0x54, 0x96);
+       err += sn9c102_i2c_write(cam, 0x55, 0x40);
+       err += sn9c102_i2c_write(cam, 0x56, 0x40);
+       err += sn9c102_i2c_write(cam, 0x57, 0x40);
+       err += sn9c102_i2c_write(cam, 0x58, 0x0F);
+       err += sn9c102_i2c_write(cam, 0x59, 0xBA);
+       err += sn9c102_i2c_write(cam, 0x5A, 0x9A);
+       err += sn9c102_i2c_write(cam, 0x5B, 0x22);
+       err += sn9c102_i2c_write(cam, 0x5C, 0xB9);
+       err += sn9c102_i2c_write(cam, 0x5D, 0x9B);
+       err += sn9c102_i2c_write(cam, 0x5E, 0x10);
+       err += sn9c102_i2c_write(cam, 0x5F, 0xF0);
+       err += sn9c102_i2c_write(cam, 0x60, 0x05);
+       err += sn9c102_i2c_write(cam, 0x61, 0x60);
+       err += sn9c102_i2c_write(cam, 0x62, 0x00);
+       err += sn9c102_i2c_write(cam, 0x63, 0x00);
+       err += sn9c102_i2c_write(cam, 0x64, 0x50);
+       err += sn9c102_i2c_write(cam, 0x65, 0x30);
+       err += sn9c102_i2c_write(cam, 0x66, 0x00);
+       err += sn9c102_i2c_write(cam, 0x67, 0x80);
+       err += sn9c102_i2c_write(cam, 0x68, 0x7A);
+       err += sn9c102_i2c_write(cam, 0x69, 0x90);
+       err += sn9c102_i2c_write(cam, 0x6A, 0x80);
+       err += sn9c102_i2c_write(cam, 0x6B, 0x0A);
+       err += sn9c102_i2c_write(cam, 0x6C, 0x30);
+       err += sn9c102_i2c_write(cam, 0x6D, 0x48);
+       err += sn9c102_i2c_write(cam, 0x6E, 0x80);
+       err += sn9c102_i2c_write(cam, 0x6F, 0x74);
+       err += sn9c102_i2c_write(cam, 0x70, 0x64);
+       err += sn9c102_i2c_write(cam, 0x71, 0x60);
+       err += sn9c102_i2c_write(cam, 0x72, 0x5C);
+       err += sn9c102_i2c_write(cam, 0x73, 0x58);
+       err += sn9c102_i2c_write(cam, 0x74, 0x54);
+       err += sn9c102_i2c_write(cam, 0x75, 0x4C);
+       err += sn9c102_i2c_write(cam, 0x76, 0x40);
+       err += sn9c102_i2c_write(cam, 0x77, 0x38);
+       err += sn9c102_i2c_write(cam, 0x78, 0x34);
+       err += sn9c102_i2c_write(cam, 0x79, 0x30);
+       err += sn9c102_i2c_write(cam, 0x7A, 0x2F);
+       err += sn9c102_i2c_write(cam, 0x7B, 0x2B);
+       err += sn9c102_i2c_write(cam, 0x7C, 0x03);
+       err += sn9c102_i2c_write(cam, 0x7D, 0x07);
+       err += sn9c102_i2c_write(cam, 0x7E, 0x17);
+       err += sn9c102_i2c_write(cam, 0x7F, 0x34);
+       err += sn9c102_i2c_write(cam, 0x80, 0x41);
+       err += sn9c102_i2c_write(cam, 0x81, 0x4D);
+       err += sn9c102_i2c_write(cam, 0x82, 0x58);
+       err += sn9c102_i2c_write(cam, 0x83, 0x63);
+       err += sn9c102_i2c_write(cam, 0x84, 0x6E);
+       err += sn9c102_i2c_write(cam, 0x85, 0x77);
+       err += sn9c102_i2c_write(cam, 0x86, 0x87);
+       err += sn9c102_i2c_write(cam, 0x87, 0x95);
+       err += sn9c102_i2c_write(cam, 0x88, 0xAF);
+       err += sn9c102_i2c_write(cam, 0x89, 0xC7);
+       err += sn9c102_i2c_write(cam, 0x8A, 0xDF);
+       err += sn9c102_i2c_write(cam, 0x8B, 0x99);
+       err += sn9c102_i2c_write(cam, 0x8C, 0x99);
+       err += sn9c102_i2c_write(cam, 0x8D, 0xCF);
+       err += sn9c102_i2c_write(cam, 0x8E, 0x20);
+       err += sn9c102_i2c_write(cam, 0x8F, 0x26);
+       err += sn9c102_i2c_write(cam, 0x90, 0x10);
+       err += sn9c102_i2c_write(cam, 0x91, 0x0C);
+       err += sn9c102_i2c_write(cam, 0x92, 0x25);
+       err += sn9c102_i2c_write(cam, 0x93, 0x00);
+       err += sn9c102_i2c_write(cam, 0x94, 0x50);
+       err += sn9c102_i2c_write(cam, 0x95, 0x50);
+       err += sn9c102_i2c_write(cam, 0x96, 0x00);
+       err += sn9c102_i2c_write(cam, 0x97, 0x01);
+       err += sn9c102_i2c_write(cam, 0x98, 0x10);
+       err += sn9c102_i2c_write(cam, 0x99, 0x40);
+       err += sn9c102_i2c_write(cam, 0x9A, 0x40);
+       err += sn9c102_i2c_write(cam, 0x9B, 0x20);
+       err += sn9c102_i2c_write(cam, 0x9C, 0x00);
+       err += sn9c102_i2c_write(cam, 0x9D, 0x99);
+       err += sn9c102_i2c_write(cam, 0x9E, 0x7F);
+       err += sn9c102_i2c_write(cam, 0x9F, 0x00);
+       err += sn9c102_i2c_write(cam, 0xA0, 0x00);
+       err += sn9c102_i2c_write(cam, 0xA1, 0x00);
+
+       return err;
+}
+
+
+static int ov7660_get_ctrl(struct sn9c102_device* cam,
+                          struct v4l2_control* ctrl)
+{
+       int err = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_EXPOSURE:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0)
+                       return -EIO;
+               break;
+       case V4L2_CID_DO_WHITE_BALANCE:
+               ctrl->value = sn9c102_pread_reg(cam, 0x02);
+               ctrl->value = (ctrl->value & 0x04) ? 1 : 0;
+               break;
+       case V4L2_CID_RED_BALANCE:
+               ctrl->value = sn9c102_pread_reg(cam, 0x05);
+               ctrl->value &= 0x7f;
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               ctrl->value = sn9c102_pread_reg(cam, 0x06);
+               ctrl->value &= 0x7f;
+               break;
+       case SN9C102_V4L2_CID_GREEN_BALANCE:
+               ctrl->value = sn9c102_pread_reg(cam, 0x07);
+               ctrl->value &= 0x7f;
+               break;
+       case V4L2_CID_GAIN:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x7f;
+               break;
+       case V4L2_CID_AUTOGAIN:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x13)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x01;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return err ? -EIO : 0;
+}
+
+
+static int ov7660_set_ctrl(struct sn9c102_device* cam,
+                          const struct v4l2_control* ctrl)
+{
+       int err = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_EXPOSURE:
+               err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
+               break;
+       case V4L2_CID_DO_WHITE_BALANCE:
+               err += sn9c102_write_reg(cam, 0x43 | (ctrl->value << 2), 0x02);
+               break;
+       case V4L2_CID_RED_BALANCE:
+               err += sn9c102_write_reg(cam, ctrl->value, 0x05);
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               err += sn9c102_write_reg(cam, ctrl->value, 0x06);
+               break;
+       case SN9C102_V4L2_CID_GREEN_BALANCE:
+               err += sn9c102_write_reg(cam, ctrl->value, 0x07);
+               break;
+       case V4L2_CID_GAIN:
+               err += sn9c102_i2c_write(cam, 0x00, ctrl->value);
+               break;
+       case V4L2_CID_AUTOGAIN:
+               err += sn9c102_i2c_write(cam, 0x13, 0xf0 | ctrl->value |
+                                                   (ctrl->value << 1));
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return err ? -EIO : 0;
+}
+
+
+static int ov7660_set_crop(struct sn9c102_device* cam,
+                          const struct v4l2_rect* rect)
+{
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+       int err = 0;
+       u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1,
+          v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
+
+       err += sn9c102_write_reg(cam, h_start, 0x12);
+       err += sn9c102_write_reg(cam, v_start, 0x13);
+
+       return err;
+}
+
+
+static int ov7660_set_pix_format(struct sn9c102_device* cam,
+                                const struct v4l2_pix_format* pix)
+{
+       int r0, err = 0;
+
+       r0 = sn9c102_pread_reg(cam, 0x01);
+
+       if (pix->pixelformat == V4L2_PIX_FMT_JPEG) {
+               err += sn9c102_write_reg(cam, r0 | 0x40, 0x01);
+               err += sn9c102_write_reg(cam, 0xa2, 0x17);
+               err += sn9c102_i2c_write(cam, 0x11, 0x00);
+       } else {
+               err += sn9c102_write_reg(cam, r0 | 0x40, 0x01);
+               err += sn9c102_write_reg(cam, 0xa2, 0x17);
+               err += sn9c102_i2c_write(cam, 0x11, 0x0d);
+       }
+
+       return err;
+}
+
+
+static struct sn9c102_sensor ov7660 = {
+       .name = "OV7660",
+       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+       .supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120,
+       .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
+       .frequency = SN9C102_I2C_100KHZ,
+       .interface = SN9C102_I2C_2WIRES,
+       .i2c_slave_id = 0x21,
+       .init = &ov7660_init,
+       .qctrl = {
+               {
+                       .id = V4L2_CID_GAIN,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "global gain",
+                       .minimum = 0x00,
+                       .maximum = 0x7f,
+                       .step = 0x01,
+                       .default_value = 0x0a,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_EXPOSURE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "exposure",
+                       .minimum = 0x00,
+                       .maximum = 0xff,
+                       .step = 0x01,
+                       .default_value = 0x50,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_DO_WHITE_BALANCE,
+                       .type = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name = "night mode",
+                       .minimum = 0x00,
+                       .maximum = 0x01,
+                       .step = 0x01,
+                       .default_value = 0x00,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_RED_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "red balance",
+                       .minimum = 0x00,
+                       .maximum = 0x7f,
+                       .step = 0x01,
+                       .default_value = 0x1f,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_BLUE_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "blue balance",
+                       .minimum = 0x00,
+                       .maximum = 0x7f,
+                       .step = 0x01,
+                       .default_value = 0x1e,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_AUTOGAIN,
+                       .type = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name = "auto adjust",
+                       .minimum = 0x00,
+                       .maximum = 0x01,
+                       .step = 0x01,
+                       .default_value = 0x00,
+                       .flags = 0,
+               },
+               {
+                       .id = SN9C102_V4L2_CID_GREEN_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "green balance",
+                       .minimum = 0x00,
+                       .maximum = 0x7f,
+                       .step = 0x01,
+                       .default_value = 0x20,
+                       .flags = 0,
+               },
+       },
+       .get_ctrl = &ov7660_get_ctrl,
+       .set_ctrl = &ov7660_set_ctrl,
+       .cropcap = {
+               .bounds = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+               .defrect = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+       },
+       .set_crop = &ov7660_set_crop,
+       .pix_format = {
+               .width = 640,
+               .height = 480,
+               .pixelformat = V4L2_PIX_FMT_JPEG,
+               .priv = 8,
+       },
+       .set_pix_format = &ov7660_set_pix_format
+};
+
+
+int sn9c102_probe_ov7660(struct sn9c102_device* cam)
+{
+       int pid, ver, err = 0;
+
+       err += sn9c102_write_reg(cam, 0x01, 0xf1);
+       err += sn9c102_write_reg(cam, 0x00, 0xf1);
+       err += sn9c102_write_reg(cam, 0x01, 0x01);
+       err += sn9c102_write_reg(cam, 0x00, 0x01);
+       err += sn9c102_write_reg(cam, 0x28, 0x17);
+
+       pid = sn9c102_i2c_try_read(cam, &ov7660, 0x0a);
+       ver = sn9c102_i2c_try_read(cam, &ov7660, 0x0b);
+       if (err || pid < 0 || ver < 0)
+               return -EIO;
+       if (pid != 0x76 || ver != 0x60)
+               return -ENODEV;
+       sn9c102_attach_sensor(cam, &ov7660);
+
+       return 0;
+}
index 9915944235e8a9ca3ae3fd76ef19ff99e866569b..8d79a5fae5ded0f6fa2b59cb9dc59edfdce14877 100644 (file)
@@ -1,8 +1,8 @@
 /***************************************************************************
- * Plug-in for PAS106B image sensor connected to the SN9C10x PC Camera     *
+ * Plug-in for PAS106B image sensor connected to the SN9C1xx PC Camera     *
  * Controllers                                                             *
  *                                                                         *
- * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -143,7 +143,7 @@ static int pas106b_set_ctrl(struct sn9c102_device* cam,
 static int pas106b_set_crop(struct sn9c102_device* cam,
                            const struct v4l2_rect* rect)
 {
-       struct sn9c102_sensor* s = &pas106b;
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
        int err = 0;
        u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4,
           v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
@@ -172,6 +172,7 @@ static int pas106b_set_pix_format(struct sn9c102_device* cam,
 static struct sn9c102_sensor pas106b = {
        .name = "PAS106B",
        .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+       .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
        .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
        .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
        .interface = SN9C102_I2C_2WIRES,
diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bca.c b/drivers/media/video/sn9c102/sn9c102_pas202bca.c
deleted file mode 100644 (file)
index c8f1ae2..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-/***************************************************************************
- * Plug-in for PAS202BCA image sensor connected to the SN9C10x PC Camera   *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
- *                                                                         *
- * This program is free software; you can redistribute it and/or modify    *
- * it under the terms of the GNU General Public License as published by    *
- * the Free Software Foundation; either version 2 of the License, or       *
- * (at your option) any later version.                                     *
- *                                                                         *
- * This program is distributed in the hope that it will be useful,         *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
- * GNU General Public License for more details.                            *
- *                                                                         *
- * You should have received a copy of the GNU General Public License       *
- * along with this program; if not, write to the Free Software             *
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
- ***************************************************************************/
-
-#include <linux/delay.h>
-#include "sn9c102_sensor.h"
-
-
-static struct sn9c102_sensor pas202bca;
-
-
-static int pas202bca_init(struct sn9c102_device* cam)
-{
-       int err = 0;
-
-       err += sn9c102_write_reg(cam, 0x00, 0x10);
-       err += sn9c102_write_reg(cam, 0x00, 0x11);
-       err += sn9c102_write_reg(cam, 0x00, 0x14);
-       err += sn9c102_write_reg(cam, 0x20, 0x17);
-       err += sn9c102_write_reg(cam, 0x30, 0x19);
-       err += sn9c102_write_reg(cam, 0x09, 0x18);
-
-       err += sn9c102_i2c_write(cam, 0x02, 0x14);
-       err += sn9c102_i2c_write(cam, 0x03, 0x40);
-       err += sn9c102_i2c_write(cam, 0x0d, 0x2c);
-       err += sn9c102_i2c_write(cam, 0x0e, 0x01);
-       err += sn9c102_i2c_write(cam, 0x0f, 0xa9);
-       err += sn9c102_i2c_write(cam, 0x10, 0x08);
-       err += sn9c102_i2c_write(cam, 0x13, 0x63);
-       err += sn9c102_i2c_write(cam, 0x15, 0x70);
-       err += sn9c102_i2c_write(cam, 0x11, 0x01);
-
-       msleep(400);
-
-       return err;
-}
-
-
-static int pas202bca_set_pix_format(struct sn9c102_device* cam,
-                                   const struct v4l2_pix_format* pix)
-{
-       int err = 0;
-
-       if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
-               err += sn9c102_write_reg(cam, 0x24, 0x17);
-       else
-               err += sn9c102_write_reg(cam, 0x20, 0x17);
-
-       return err;
-}
-
-
-static int pas202bca_set_ctrl(struct sn9c102_device* cam,
-                             const struct v4l2_control* ctrl)
-{
-       int err = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_EXPOSURE:
-               err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6);
-               err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f);
-               break;
-       case V4L2_CID_RED_BALANCE:
-               err += sn9c102_i2c_write(cam, 0x09, ctrl->value);
-               break;
-       case V4L2_CID_BLUE_BALANCE:
-               err += sn9c102_i2c_write(cam, 0x07, ctrl->value);
-               break;
-       case V4L2_CID_GAIN:
-               err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
-               break;
-       case SN9C102_V4L2_CID_GREEN_BALANCE:
-               err += sn9c102_i2c_write(cam, 0x08, ctrl->value);
-               break;
-       case SN9C102_V4L2_CID_DAC_MAGNITUDE:
-               err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
-               break;
-       default:
-               return -EINVAL;
-       }
-       err += sn9c102_i2c_write(cam, 0x11, 0x01);
-
-       return err ? -EIO : 0;
-}
-
-
-static int pas202bca_set_crop(struct sn9c102_device* cam,
-                             const struct v4l2_rect* rect)
-{
-       struct sn9c102_sensor* s = &pas202bca;
-       int err = 0;
-       u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 3,
-          v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
-
-       err += sn9c102_write_reg(cam, h_start, 0x12);
-       err += sn9c102_write_reg(cam, v_start, 0x13);
-
-       return err;
-}
-
-
-static struct sn9c102_sensor pas202bca = {
-       .name = "PAS202BCA",
-       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-       .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
-       .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
-       .interface = SN9C102_I2C_2WIRES,
-       .i2c_slave_id = 0x40,
-       .init = &pas202bca_init,
-       .qctrl = {
-               {
-                       .id = V4L2_CID_EXPOSURE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "exposure",
-                       .minimum = 0x01e5,
-                       .maximum = 0x3fff,
-                       .step = 0x0001,
-                       .default_value = 0x01e5,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_GAIN,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "global gain",
-                       .minimum = 0x00,
-                       .maximum = 0x1f,
-                       .step = 0x01,
-                       .default_value = 0x0c,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_RED_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "red balance",
-                       .minimum = 0x00,
-                       .maximum = 0x0f,
-                       .step = 0x01,
-                       .default_value = 0x01,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_BLUE_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "blue balance",
-                       .minimum = 0x00,
-                       .maximum = 0x0f,
-                       .step = 0x01,
-                       .default_value = 0x05,
-                       .flags = 0,
-               },
-               {
-                       .id = SN9C102_V4L2_CID_GREEN_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "green balance",
-                       .minimum = 0x00,
-                       .maximum = 0x0f,
-                       .step = 0x01,
-                       .default_value = 0x00,
-                       .flags = 0,
-               },
-               {
-                       .id = SN9C102_V4L2_CID_DAC_MAGNITUDE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "DAC magnitude",
-                       .minimum = 0x00,
-                       .maximum = 0xff,
-                       .step = 0x01,
-                       .default_value = 0x04,
-                       .flags = 0,
-               },
-       },
-       .set_ctrl = &pas202bca_set_ctrl,
-       .cropcap = {
-               .bounds = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 640,
-                       .height = 480,
-               },
-               .defrect = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 640,
-                       .height = 480,
-               },
-       },
-       .set_crop = &pas202bca_set_crop,
-       .pix_format = {
-               .width = 640,
-               .height = 480,
-               .pixelformat = V4L2_PIX_FMT_SBGGR8,
-               .priv = 8,
-       },
-       .set_pix_format = &pas202bca_set_pix_format
-};
-
-
-int sn9c102_probe_pas202bca(struct sn9c102_device* cam)
-{
-       const struct usb_device_id pas202bca_id_table[] = {
-               { USB_DEVICE(0x0c45, 0x60af), },
-               { }
-       };
-       int err = 0;
-
-       if (!sn9c102_match_id(cam,pas202bca_id_table))
-               return -ENODEV;
-
-       err += sn9c102_write_reg(cam, 0x01, 0x01);
-       err += sn9c102_write_reg(cam, 0x40, 0x01);
-       err += sn9c102_write_reg(cam, 0x28, 0x17);
-       if (err)
-               return -EIO;
-
-       if (sn9c102_i2c_try_write(cam, &pas202bca, 0x10, 0)) /* try to write */
-               return -ENODEV;
-
-       sn9c102_attach_sensor(cam, &pas202bca);
-
-       return 0;
-}
index e3c1178e339c7cff4148268c028f01c25f42a2aa..7894f01b56e86387efc9678f4e56b36908e516be 100644 (file)
@@ -1,13 +1,13 @@
 /***************************************************************************
- * Plug-in for PAS202BCB image sensor connected to the SN9C10x PC Camera   *
+ * Plug-in for PAS202BCB image sensor connected to the SN9C1xx PC Camera   *
  * Controllers                                                             *
  *                                                                         *
  * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio                  *
  *                       <medaglia@undl.org.br>                            *
  *                       http://cadu.homelinux.com:8080/                   *
  *                                                                         *
- * DAC Magnitude, exposure and green gain controls added by                *
- * Luca Risolia <luca.risolia@studio.unibo.it>                             *
+ * Support for SN9C103, DAC Magnitude, exposure and green gain controls    *
+ * added by Luca Risolia <luca.risolia@studio.unibo.it>                    *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -35,12 +35,54 @@ static int pas202bcb_init(struct sn9c102_device* cam)
 {
        int err = 0;
 
+       switch (sn9c102_get_bridge(cam)) {
+       case BRIDGE_SN9C101:
+       case BRIDGE_SN9C102:
        err += sn9c102_write_reg(cam, 0x00, 0x10);
        err += sn9c102_write_reg(cam, 0x00, 0x11);
        err += sn9c102_write_reg(cam, 0x00, 0x14);
        err += sn9c102_write_reg(cam, 0x20, 0x17);
        err += sn9c102_write_reg(cam, 0x30, 0x19);
        err += sn9c102_write_reg(cam, 0x09, 0x18);
+               break;
+       case BRIDGE_SN9C103:
+               err += sn9c102_write_reg(cam, 0x00, 0x02);
+               err += sn9c102_write_reg(cam, 0x00, 0x03);
+               err += sn9c102_write_reg(cam, 0x1a, 0x04);
+               err += sn9c102_write_reg(cam, 0x20, 0x05);
+               err += sn9c102_write_reg(cam, 0x20, 0x06);
+               err += sn9c102_write_reg(cam, 0x20, 0x07);
+               err += sn9c102_write_reg(cam, 0x00, 0x10);
+               err += sn9c102_write_reg(cam, 0x00, 0x11);
+               err += sn9c102_write_reg(cam, 0x00, 0x14);
+               err += sn9c102_write_reg(cam, 0x20, 0x17);
+               err += sn9c102_write_reg(cam, 0x30, 0x19);
+               err += sn9c102_write_reg(cam, 0x09, 0x18);
+               err += sn9c102_write_reg(cam, 0x02, 0x1c);
+               err += sn9c102_write_reg(cam, 0x03, 0x1d);
+               err += sn9c102_write_reg(cam, 0x0f, 0x1e);
+               err += sn9c102_write_reg(cam, 0x0c, 0x1f);
+               err += sn9c102_write_reg(cam, 0x00, 0x20);
+               err += sn9c102_write_reg(cam, 0x10, 0x21);
+               err += sn9c102_write_reg(cam, 0x20, 0x22);
+               err += sn9c102_write_reg(cam, 0x30, 0x23);
+               err += sn9c102_write_reg(cam, 0x40, 0x24);
+               err += sn9c102_write_reg(cam, 0x50, 0x25);
+               err += sn9c102_write_reg(cam, 0x60, 0x26);
+               err += sn9c102_write_reg(cam, 0x70, 0x27);
+               err += sn9c102_write_reg(cam, 0x80, 0x28);
+               err += sn9c102_write_reg(cam, 0x90, 0x29);
+               err += sn9c102_write_reg(cam, 0xa0, 0x2a);
+               err += sn9c102_write_reg(cam, 0xb0, 0x2b);
+               err += sn9c102_write_reg(cam, 0xc0, 0x2c);
+               err += sn9c102_write_reg(cam, 0xd0, 0x2d);
+               err += sn9c102_write_reg(cam, 0xe0, 0x2e);
+               err += sn9c102_write_reg(cam, 0xf0, 0x2f);
+               err += sn9c102_write_reg(cam, 0xff, 0x30);
+               break;
+       default:
+               break;
+       }
 
        err += sn9c102_i2c_write(cam, 0x02, 0x14);
        err += sn9c102_i2c_write(cam, 0x03, 0x40);
@@ -107,7 +149,7 @@ static int pas202bcb_set_pix_format(struct sn9c102_device* cam,
        int err = 0;
 
        if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
-               err += sn9c102_write_reg(cam, 0x24, 0x17);
+               err += sn9c102_write_reg(cam, 0x28, 0x17);
        else
                err += sn9c102_write_reg(cam, 0x20, 0x17);
 
@@ -152,11 +194,23 @@ static int pas202bcb_set_ctrl(struct sn9c102_device* cam,
 static int pas202bcb_set_crop(struct sn9c102_device* cam,
                              const struct v4l2_rect* rect)
 {
-       struct sn9c102_sensor* s = &pas202bcb;
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
        int err = 0;
-       u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4,
+       u8 h_start = 0,
           v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
 
+       switch (sn9c102_get_bridge(cam)) {
+       case BRIDGE_SN9C101:
+       case BRIDGE_SN9C102:
+               h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4;
+               break;
+       case BRIDGE_SN9C103:
+               h_start = (u8)(rect->left - s->cropcap.bounds.left) + 3;
+               break;
+       default:
+               break;
+       }
+
        err += sn9c102_write_reg(cam, h_start, 0x12);
        err += sn9c102_write_reg(cam, v_start, 0x13);
 
@@ -166,8 +220,8 @@ static int pas202bcb_set_crop(struct sn9c102_device* cam,
 
 static struct sn9c102_sensor pas202bcb = {
        .name = "PAS202BCB",
-       .maintainer = "Carlos Eduardo Medaglia Dyonisio "
-                     "<medaglia@undl.org.br>",
+       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+       .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
        .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
        .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
        .interface = SN9C102_I2C_2WIRES,
@@ -191,7 +245,7 @@ static struct sn9c102_sensor pas202bcb = {
                        .minimum = 0x00,
                        .maximum = 0x1f,
                        .step = 0x01,
-                       .default_value = 0x0c,
+                       .default_value = 0x0b,
                        .flags = 0,
                },
                {
@@ -201,7 +255,7 @@ static struct sn9c102_sensor pas202bcb = {
                        .minimum = 0x00,
                        .maximum = 0x0f,
                        .step = 0x01,
-                       .default_value = 0x01,
+                       .default_value = 0x00,
                        .flags = 0,
                },
                {
@@ -271,16 +325,27 @@ int sn9c102_probe_pas202bcb(struct sn9c102_device* cam)
         *  Minimal initialization to enable the I2C communication
         *  NOTE: do NOT change the values!
         */
-       err += sn9c102_write_reg(cam, 0x01, 0x01); /* sensor power down */
-       err += sn9c102_write_reg(cam, 0x40, 0x01); /* sensor power on */
-       err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 24 MHz */
-       if (err)
-               return -EIO;
+       switch (sn9c102_get_bridge(cam)) {
+       case BRIDGE_SN9C101:
+       case BRIDGE_SN9C102:
+               err += sn9c102_write_reg(cam, 0x01, 0x01); /* power down */
+               err += sn9c102_write_reg(cam, 0x40, 0x01); /* power on */
+               err += sn9c102_write_reg(cam, 0x28, 0x17); /* clock 24 MHz */
+               break;
+       case BRIDGE_SN9C103: /* do _not_ change anything! */
+               err += sn9c102_write_reg(cam, 0x09, 0x01);
+               err += sn9c102_write_reg(cam, 0x44, 0x01);
+               err += sn9c102_write_reg(cam, 0x44, 0x02);
+               err += sn9c102_write_reg(cam, 0x29, 0x17);
+               break;
+       default:
+               break;
+       }
 
        r0 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x00);
        r1 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x01);
 
-       if (r0 < 0 || r1 < 0)
+       if (err || r0 < 0 || r1 < 0)
                return -EIO;
 
        pid = (r0 << 4) | ((r1 & 0xf0) >> 4);
index 2a874ee6f9f5bb32efc9d0793bdb6a116ed6f83f..05f2942639c3be69f2819f5c1d67858da8e699a0 100644 (file)
@@ -1,7 +1,7 @@
 /***************************************************************************
- * API for image sensors connected to the SN9C10x PC Camera Controllers    *
+ * API for image sensors connected to the SN9C1xx PC Camera Controllers    *
  *                                                                         *
- * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -36,14 +36,13 @@ struct sn9c102_sensor;
 /*
    OVERVIEW.
    This is a small interface that allows you to add support for any CCD/CMOS
-   image sensors connected to the SN9C10X bridges. The entire API is documented
+   image sensors connected to the SN9C1XX bridges. The entire API is documented
    below. In the most general case, to support a sensor there are three steps
    you have to follow:
    1) define the main "sn9c102_sensor" structure by setting the basic fields;
    2) write a probing function to be called by the core module when the USB
       camera is recognized, then add both the USB ids and the name of that
-      function to the two corresponding tables SENSOR_TABLE and ID_TABLE (see
-      below);
+      function to the two corresponding tables in sn9c102_devtable.h;
    3) implement the methods that you want/need (and fill the rest of the main
       structure accordingly).
    "sn9c102_pas106b.c" is an example of all this stuff. Remember that you do
@@ -54,42 +53,21 @@ struct sn9c102_sensor;
 
 /*****************************************************************************/
 
-/*
-   Probing functions: on success, you must attach the sensor to the camera
-   by calling sn9c102_attach_sensor() provided below.
-   To enable the I2C communication, you might need to perform a really basic
-   initialization of the SN9C10X chip by using the write function declared
-   ahead.
-   Functions must return 0 on success, the appropriate error otherwise.
-*/
-extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam);
-extern int sn9c102_probe_mi0343(struct sn9c102_device* cam);
-extern int sn9c102_probe_ov7630(struct sn9c102_device* cam);
-extern int sn9c102_probe_pas106b(struct sn9c102_device* cam);
-extern int sn9c102_probe_pas202bca(struct sn9c102_device* cam);
-extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam);
-extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam);
-extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam);
-
-/*
-   Add the above entries to this table. Be sure to add the entry in the right
-   place, since, on failure, the next probing routine is called according to
-   the order of the list below, from top to bottom.
-*/
-#define SN9C102_SENSOR_TABLE                                                  \
-static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = {              \
-       &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */     \
-       &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */    \
-       &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */  \
-       &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */    \
-       &sn9c102_probe_pas202bca, /* detection mostly based on USB pid/vid */ \
-       &sn9c102_probe_ov7630, /* detection mostly based on USB pid/vid */    \
-       &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */       \
-       &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */       \
-       NULL,                                                                 \
+enum sn9c102_bridge {
+       BRIDGE_SN9C101 = 0x01,
+       BRIDGE_SN9C102 = 0x02,
+       BRIDGE_SN9C103 = 0x04,
+       BRIDGE_SN9C105 = 0x08,
+       BRIDGE_SN9C120 = 0x10,
 };
 
-/* Device identification */
+/* Return the bridge name */
+enum sn9c102_bridge sn9c102_get_bridge(struct sn9c102_device* cam);
+
+/* Return a pointer the sensor struct attached to the camera */
+struct sn9c102_sensor* sn9c102_get_sensor(struct sn9c102_device* cam);
+
+/* Identify a device */
 extern struct sn9c102_device*
 sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id);
 
@@ -98,69 +76,9 @@ extern void
 sn9c102_attach_sensor(struct sn9c102_device* cam,
                      struct sn9c102_sensor* sensor);
 
-/*
-   Each SN9C10x camera has proper PID/VID identifiers.
-   SN9C103 supports multiple interfaces, but we only handle the video class
-   interface.
-*/
-#define SN9C102_USB_DEVICE(vend, prod, intclass)                              \
-       .match_flags = USB_DEVICE_ID_MATCH_DEVICE |                           \
-                      USB_DEVICE_ID_MATCH_INT_CLASS,                         \
-       .idVendor = (vend),                                                   \
-       .idProduct = (prod),                                                  \
-       .bInterfaceClass = (intclass)
-
-#define SN9C102_ID_TABLE                                                      \
-static const struct usb_device_id sn9c102_id_table[] = {                      \
-       { USB_DEVICE(0x0c45, 0x6001), }, /* TAS5110C1B */                     \
-       { USB_DEVICE(0x0c45, 0x6005), }, /* TAS5110C1B */                     \
-       { USB_DEVICE(0x0c45, 0x6007), },                                      \
-       { USB_DEVICE(0x0c45, 0x6009), }, /* PAS106B */                        \
-       { USB_DEVICE(0x0c45, 0x600d), }, /* PAS106B */                        \
-       { USB_DEVICE(0x0c45, 0x6024), },                                      \
-       { USB_DEVICE(0x0c45, 0x6025), }, /* TAS5130D1B and TAS5110C1B */      \
-       { USB_DEVICE(0x0c45, 0x6028), }, /* PAS202BCB */                      \
-       { USB_DEVICE(0x0c45, 0x6029), }, /* PAS106B */                        \
-       { USB_DEVICE(0x0c45, 0x602a), }, /* HV7131D */                        \
-       { USB_DEVICE(0x0c45, 0x602b), }, /* MI-0343 */                        \
-       { USB_DEVICE(0x0c45, 0x602c), }, /* OV7630 */                         \
-       { USB_DEVICE(0x0c45, 0x602d), },                                      \
-       { USB_DEVICE(0x0c45, 0x602e), }, /* OV7630 */                         \
-       { USB_DEVICE(0x0c45, 0x6030), }, /* MI03x */                          \
-       { SN9C102_USB_DEVICE(0x0c45, 0x6080, 0xff), },                        \
-       { SN9C102_USB_DEVICE(0x0c45, 0x6082, 0xff), }, /* MI0343 & MI0360 */  \
-       { SN9C102_USB_DEVICE(0x0c45, 0x6083, 0xff), }, /* HV7131[D|E1] */     \
-       { SN9C102_USB_DEVICE(0x0c45, 0x6088, 0xff), },                        \
-       { SN9C102_USB_DEVICE(0x0c45, 0x608a, 0xff), },                        \
-       { SN9C102_USB_DEVICE(0x0c45, 0x608b, 0xff), },                        \
-       { SN9C102_USB_DEVICE(0x0c45, 0x608c, 0xff), }, /* HV7131/R */         \
-       { SN9C102_USB_DEVICE(0x0c45, 0x608e, 0xff), }, /* CIS-VF10 */         \
-       { SN9C102_USB_DEVICE(0x0c45, 0x608f, 0xff), }, /* OV7630 */           \
-       { SN9C102_USB_DEVICE(0x0c45, 0x60a0, 0xff), },                        \
-       { SN9C102_USB_DEVICE(0x0c45, 0x60a2, 0xff), },                        \
-       { SN9C102_USB_DEVICE(0x0c45, 0x60a3, 0xff), },                        \
-       { SN9C102_USB_DEVICE(0x0c45, 0x60a8, 0xff), }, /* PAS106B */          \
-       { SN9C102_USB_DEVICE(0x0c45, 0x60aa, 0xff), }, /* TAS5130D1B */       \
-       { SN9C102_USB_DEVICE(0x0c45, 0x60ab, 0xff), }, /* TAS5110C1B */       \
-       { SN9C102_USB_DEVICE(0x0c45, 0x60ac, 0xff), },                        \
-       { SN9C102_USB_DEVICE(0x0c45, 0x60ae, 0xff), },                        \
-       { SN9C102_USB_DEVICE(0x0c45, 0x60af, 0xff), }, /* PAS202BCB */        \
-       { SN9C102_USB_DEVICE(0x0c45, 0x60b0, 0xff), }, /* OV7630 (?) */       \
-       { SN9C102_USB_DEVICE(0x0c45, 0x60b2, 0xff), },                        \
-       { SN9C102_USB_DEVICE(0x0c45, 0x60b3, 0xff), },                        \
-       { SN9C102_USB_DEVICE(0x0c45, 0x60b8, 0xff), },                        \
-       { SN9C102_USB_DEVICE(0x0c45, 0x60ba, 0xff), },                        \
-       { SN9C102_USB_DEVICE(0x0c45, 0x60bb, 0xff), },                        \
-       { SN9C102_USB_DEVICE(0x0c45, 0x60bc, 0xff), },                        \
-       { SN9C102_USB_DEVICE(0x0c45, 0x60be, 0xff), },                        \
-       { }                                                                   \
-};
-
-/*****************************************************************************/
-
 /*
    Read/write routines: they always return -1 on error, 0 or the read value
-   otherwise. NOTE that a real read operation is not supported by the SN9C10X
+   otherwise. NOTE that a real read operation is not supported by the SN9C1XX
    chip for some of its registers. To work around this problem, a pseudo-read
    call is provided instead: it returns the last successfully written value
    on the register (0 if it has never been written), the usual -1 on error.
@@ -176,7 +94,7 @@ extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*,
    These must be used if and only if the sensor doesn't implement the standard
    I2C protocol. There are a number of good reasons why you must use the
    single-byte versions of these functions: do not abuse. The first function
-   writes n bytes, from data0 to datan, to registers 0x09 - 0x09+n of SN9C10X
+   writes n bytes, from data0 to datan, to registers 0x09 - 0x09+n of SN9C1XX
    chip. The second one programs the registers 0x09 and 0x10 with data0 and
    data1, and places the n bytes read from the sensor register table in the
    buffer pointed by 'buffer'. Both the functions return -1 on error; the write
@@ -200,16 +118,6 @@ extern int sn9c102_write_regs(struct sn9c102_device*, u8* buff, u16 index);
 extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index);
 extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index);
 
-/*
-   NOTE: there are no exported debugging functions. To uniform the output you
-   must use the dev_info()/dev_warn()/dev_err() macros defined in device.h,
-   already included here, the argument being the struct device '&usbdev->dev'
-   of the sensor structure. Do NOT use these macros before the sensor is
-   attached or the kernel will crash! However, you should not need to notify
-   the user about common errors or other messages, since this is done by the
-   master module.
-*/
-
 /*****************************************************************************/
 
 enum sn9c102_i2c_sysfs_ops {
@@ -227,17 +135,19 @@ enum sn9c102_i2c_interface {
        SN9C102_I2C_3WIRES,
 };
 
-#define SN9C102_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10
+#define SN9C102_MAX_CTRLS (V4L2_CID_LASTP1-V4L2_CID_BASE+10)
 
 struct sn9c102_sensor {
        char name[32], /* sensor name */
             maintainer[64]; /* name of the mantainer <email> */
 
+       enum sn9c102_bridge supported_bridge; /* supported SN9C1xx bridges */
+
        /* Supported operations through the 'sysfs' interface */
        enum sn9c102_i2c_sysfs_ops sysfs_ops;
 
        /*
-          These sensor capabilities must be provided if the SN9C10X controller
+          These sensor capabilities must be provided if the SN9C1XX controller
           needs to communicate through the sensor serial interface by using
           at least one of the i2c functions available.
        */
@@ -260,7 +170,7 @@ struct sn9c102_sensor {
        /*
           This function will be called after the sensor has been attached.
           It should be used to initialize the sensor only, but may also
-          configure part of the SN9C10X chip if necessary. You don't need to
+          configure part of the SN9C1XX chip if necessary. You don't need to
           setup picture settings like brightness, contrast, etc.. here, if
           the corrisponding controls are implemented (see below), since
           they are adjusted in the core driver by calling the set_ctrl()
@@ -300,7 +210,7 @@ struct sn9c102_sensor {
           It is not always true that the largest achievable active window can
           cover the whole array of pixels. The V4L2 API defines another
           area called "source rectangle", which, in turn, is a subrectangle of
-          the active window. The SN9C10X chip is always programmed to read the
+          the active window. The SN9C1XX chip is always programmed to read the
           source rectangle.
           The bounds of both the active window and the source rectangle are
           specified in the cropcap substructures 'bounds' and 'defrect'.
@@ -326,13 +236,13 @@ struct sn9c102_sensor {
                        const struct v4l2_rect* rect);
        /*
           To be called on VIDIOC_C_SETCROP. The core module always calls a
-          default routine which configures the appropriate SN9C10X regs (also
+          default routine which configures the appropriate SN9C1XX regs (also
           scaling), but you may need to override/adjust specific stuff.
           'rect' contains width and height values that are multiple of 16: in
           case you override the default function, you always have to program
           the chip to match those values; on error return the corresponding
           error code without rolling back.
-          NOTE: in case, you must program the SN9C10X chip to get rid of
+          NOTE: in case, you must program the SN9C1XX chip to get rid of
                 blank pixels or blank lines at the _start_ of each line or
                 frame after each HSYNC or VSYNC, so that the image starts with
                 real RGB data (see regs 0x12, 0x13) (having set H_SIZE and,
@@ -344,16 +254,16 @@ struct sn9c102_sensor {
        /*
           What you have to define here are: 1) initial 'width' and 'height' of
           the target rectangle 2) the initial 'pixelformat', which can be
-          either V4L2_PIX_FMT_SN9C10X (for compressed video) or
-          V4L2_PIX_FMT_SBGGR8 3) 'priv', which we'll be used to indicate the
-          number of bits per pixel for uncompressed video, 8 or 9 (despite the
-          current value of 'pixelformat').
+          either V4L2_PIX_FMT_SN9C10X, V4L2_PIX_FMT_JPEG (for ompressed video)
+          or V4L2_PIX_FMT_SBGGR8 3) 'priv', which we'll be used to indicate
+          the number of bits per pixel for uncompressed video, 8 or 9 (despite
+          the current value of 'pixelformat').
           NOTE 1: both 'width' and 'height' _must_ be either 1/1 or 1/2 or 1/4
                   of cropcap.defrect.width and cropcap.defrect.height. I
                   suggest 1/1.
           NOTE 2: The initial compression quality is defined by the first bit
                   of reg 0x17 during the initialization of the image sensor.
-          NOTE 3: as said above, you have to program the SN9C10X chip to get
+          NOTE 3: as said above, you have to program the SN9C1XX chip to get
                   rid of any blank pixels, so that the output of the sensor
                   matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR).
        */
@@ -378,12 +288,12 @@ struct sn9c102_sensor {
 /*****************************************************************************/
 
 /* Private ioctl's for control settings supported by some image sensors */
-#define SN9C102_V4L2_CID_DAC_MAGNITUDE V4L2_CID_PRIVATE_BASE
-#define SN9C102_V4L2_CID_GREEN_BALANCE V4L2_CID_PRIVATE_BASE + 1
-#define SN9C102_V4L2_CID_RESET_LEVEL V4L2_CID_PRIVATE_BASE + 2
-#define SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE V4L2_CID_PRIVATE_BASE + 3
-#define SN9C102_V4L2_CID_GAMMA V4L2_CID_PRIVATE_BASE + 4
-#define SN9C102_V4L2_CID_BAND_FILTER V4L2_CID_PRIVATE_BASE + 5
-#define SN9C102_V4L2_CID_BRIGHT_LEVEL V4L2_CID_PRIVATE_BASE + 6
+#define SN9C102_V4L2_CID_DAC_MAGNITUDE (V4L2_CID_PRIVATE_BASE + 0)
+#define SN9C102_V4L2_CID_GREEN_BALANCE (V4L2_CID_PRIVATE_BASE + 1)
+#define SN9C102_V4L2_CID_RESET_LEVEL (V4L2_CID_PRIVATE_BASE + 2)
+#define SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE (V4L2_CID_PRIVATE_BASE + 3)
+#define SN9C102_V4L2_CID_GAMMA (V4L2_CID_PRIVATE_BASE + 4)
+#define SN9C102_V4L2_CID_BAND_FILTER (V4L2_CID_PRIVATE_BASE + 5)
+#define SN9C102_V4L2_CID_BRIGHT_LEVEL (V4L2_CID_PRIVATE_BASE + 6)
 
 #endif /* _SN9C102_SENSOR_H_ */
index 294eb02fbd8873cc948e599164c728a80416b458..90023ad63adce6c8ec6788958b8a5dec2ab6105a 100644 (file)
@@ -1,8 +1,8 @@
 /***************************************************************************
- * Plug-in for TAS5110C1B image sensor connected to the SN9C10x PC Camera  *
+ * Plug-in for TAS5110C1B image sensor connected to the SN9C1xx PC Camera  *
  * Controllers                                                             *
  *                                                                         *
- * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -64,7 +64,7 @@ static int tas5110c1b_set_ctrl(struct sn9c102_device* cam,
 static int tas5110c1b_set_crop(struct sn9c102_device* cam,
                               const struct v4l2_rect* rect)
 {
-       struct sn9c102_sensor* s = &tas5110c1b;
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
        int err = 0;
        u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69,
           v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9;
@@ -98,6 +98,7 @@ static int tas5110c1b_set_pix_format(struct sn9c102_device* cam,
 static struct sn9c102_sensor tas5110c1b = {
        .name = "TAS5110C1B",
        .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+       .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
        .sysfs_ops = SN9C102_I2C_WRITE,
        .frequency = SN9C102_I2C_100KHZ,
        .interface = SN9C102_I2C_3WIRES,
@@ -145,6 +146,7 @@ int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam)
        const struct usb_device_id tas5110c1b_id_table[] = {
                { USB_DEVICE(0x0c45, 0x6001), },
                { USB_DEVICE(0x0c45, 0x6005), },
+               { USB_DEVICE(0x0c45, 0x6007), },
                { USB_DEVICE(0x0c45, 0x60ab), },
                { }
        };
index 9ecb09032b683fc0c1835c4f4c95e9bc402eb98d..cb1b318bc1ffa04fca350114cbd1a82e916ed045 100644 (file)
@@ -1,8 +1,8 @@
 /***************************************************************************
- * Plug-in for TAS5130D1B image sensor connected to the SN9C10x PC Camera  *
+ * Plug-in for TAS5130D1B image sensor connected to the SN9C1xx PC Camera  *
  * Controllers                                                             *
  *                                                                         *
- * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -65,7 +65,7 @@ static int tas5130d1b_set_ctrl(struct sn9c102_device* cam,
 static int tas5130d1b_set_crop(struct sn9c102_device* cam,
                               const struct v4l2_rect* rect)
 {
-       struct sn9c102_sensor* s = &tas5130d1b;
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
        u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 104,
           v_start = (u8)(rect->top - s->cropcap.bounds.top) + 12;
        int err = 0;
@@ -99,6 +99,7 @@ static int tas5130d1b_set_pix_format(struct sn9c102_device* cam,
 static struct sn9c102_sensor tas5130d1b = {
        .name = "TAS5130D1B",
        .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+       .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
        .sysfs_ops = SN9C102_I2C_WRITE,
        .frequency = SN9C102_I2C_100KHZ,
        .interface = SN9C102_I2C_3WIRES,
@@ -154,6 +155,7 @@ static struct sn9c102_sensor tas5130d1b = {
 int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam)
 {
        const struct usb_device_id tas5130d1b_id_table[] = {
+               { USB_DEVICE(0x0c45, 0x6024), },
                { USB_DEVICE(0x0c45, 0x6025), },
                { USB_DEVICE(0x0c45, 0x60aa), },
                { }
index 7ea9132a1965f86b28b85ef7a504db74bc2b83cd..3ae5a9cd2e28f1388f526acacdd0bb00e79cd7e5 100644 (file)
@@ -212,8 +212,7 @@ static int tvmixer_release(struct inode *inode, struct file *file)
                return -ENODEV;
        }
 
-       if (client->adapter->owner)
-               module_put(client->adapter->owner);
+       module_put(client->adapter->owner);
        return 0;
 }
 
index bc0a4fc27b24452a828e971d906e1918aeff2a27..d5ec05f56adfad470a6edca177746a134113290a 100644 (file)
@@ -950,25 +950,19 @@ static int tvp5150_command(struct i2c_client *c,
        }
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-       case VIDIOC_INT_G_REGISTER:
+       case VIDIOC_DBG_G_REGISTER:
+       case VIDIOC_DBG_S_REGISTER:
        {
                struct v4l2_register *reg = arg;
 
-               if (reg->i2c_id != I2C_DRIVERID_TVP5150)
-                       return -EINVAL;
-               reg->val = tvp5150_read(c, reg->reg & 0xff);
-               break;
-       }
-
-       case VIDIOC_INT_S_REGISTER:
-       {
-               struct v4l2_register *reg = arg;
-
-               if (reg->i2c_id != I2C_DRIVERID_TVP5150)
+               if (!v4l2_chip_match_i2c_client(c, reg->match_type, reg->match_chip))
                        return -EINVAL;
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
-               tvp5150_write(c, reg->reg & 0xff, reg->val & 0xff);
+               if (cmd == VIDIOC_DBG_G_REGISTER)
+                       reg->val = tvp5150_read(c, reg->reg & 0xff);
+               else
+                       tvp5150_write(c, reg->reg & 0xff, reg->val & 0xff);
                break;
        }
 #endif
index fc52201d607ea856da10d1584bd510dddfbe95dd..28d1133a3b7a6f770b427991a9e2441a59224dab 100644 (file)
@@ -162,27 +162,19 @@ static int upd64031a_command(struct i2c_client *client, unsigned int cmd, void *
                break;
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-       case VIDIOC_INT_G_REGISTER:
+       case VIDIOC_DBG_G_REGISTER:
+       case VIDIOC_DBG_S_REGISTER:
        {
                struct v4l2_register *reg = arg;
 
-               if (reg->i2c_id != I2C_DRIVERID_UPD64031A)
-                       return -EINVAL;
-               reg->val = upd64031a_read(client, reg->reg & 0xff);
-               break;
-       }
-
-       case VIDIOC_INT_S_REGISTER:
-       {
-               struct v4l2_register *reg = arg;
-               u8 addr = reg->reg & 0xff;
-               u8 val = reg->val & 0xff;
-
-               if (reg->i2c_id != I2C_DRIVERID_UPD64031A)
+               if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip))
                        return -EINVAL;
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
-               upd64031a_write(client, addr, val);
+               if (cmd == VIDIOC_DBG_G_REGISTER)
+                       reg->val = upd64031a_read(client, reg->reg & 0xff);
+               else
+                       upd64031a_write(client, reg->reg & 0xff, reg->val & 0xff);
                break;
        }
 #endif
index c3a7ffe5c2674365e1c3d47392678ce626d1806a..fe38224150d8ae0abd116953ec09c6f92721ee23 100644 (file)
@@ -139,27 +139,19 @@ static int upd64083_command(struct i2c_client *client, unsigned int cmd, void *a
                break;
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-       case VIDIOC_INT_G_REGISTER:
+       case VIDIOC_DBG_G_REGISTER:
+       case VIDIOC_DBG_S_REGISTER:
        {
                struct v4l2_register *reg = arg;
 
-               if (reg->i2c_id != I2C_DRIVERID_UPD64083)
-                       return -EINVAL;
-               reg->val = upd64083_read(client, reg->reg & 0xff);
-               break;
-       }
-
-       case VIDIOC_INT_S_REGISTER:
-       {
-               struct v4l2_register *reg = arg;
-               u8 addr = reg->reg & 0xff;
-               u8 val = reg->val & 0xff;
-
-               if (reg->i2c_id != I2C_DRIVERID_UPD64083)
+               if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip))
                        return -EINVAL;
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
-               upd64083_write(client, addr, val);
+               if (cmd == VIDIOC_DBG_G_REGISTER)
+                       reg->val = upd64083_read(client, reg->reg & 0xff);
+               else
+                       upd64083_write(client, reg->reg & 0xff, reg->val & 0xff);
                break;
        }
 #endif
index fc24ef05b3f31cf527b6fc850423cae317ad224b..c43a5d8990918bbffb510dbecfe47600360a392b 100644 (file)
@@ -1,6 +1,6 @@
 config VIDEO_USBVISION
        tristate "USB video devices based on Nogatech NT1003/1004/1005"
-       depends on I2C && VIDEO_V4L2
+       depends on I2C && VIDEO_V4L2 && USB
        select VIDEO_TUNER
        select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
        ---help---
index 901f664dc6db4eae563b9dbb35a6ab7971dcfa9d..f2154dc072e211d5829fe7865f6aaeea4f8e594e 100644 (file)
@@ -138,7 +138,7 @@ static void *usbvision_rvmalloc(unsigned long size)
        return mem;
 }
 
-void usbvision_rvfree(void *mem, unsigned long size)
+static void usbvision_rvfree(void *mem, unsigned long size)
 {
        unsigned long adr;
 
@@ -1852,28 +1852,33 @@ int usbvision_set_output(struct usb_usbvision *usbvision, int width,
 
 /*
  * usbvision_frames_alloc
- * allocate the maximum frames this driver can manage
+ * allocate the required frames
  */
-int usbvision_frames_alloc(struct usb_usbvision *usbvision)
+int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames)
 {
        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);
+       /*needs to be page aligned cause the buffers can be mapped individually! */
+       usbvision->max_frame_size =  PAGE_ALIGN(usbvision->curwidth *
+                                               usbvision->curheight *
+                                               usbvision->palette.bytes_per_pixel);
 
-       if(usbvision->fbuf == NULL) {
-               err("%s: unable to allocate %d bytes for fbuf ",
-                   __FUNCTION__, usbvision->fbuf_size);
-               return -ENOMEM;
+       /* Try to do my best to allocate the frames the user want in the remaining memory */
+       usbvision->num_frames = number_of_frames;
+       while (usbvision->num_frames > 0) {
+               usbvision->fbuf_size = usbvision->num_frames * usbvision->max_frame_size;
+               if((usbvision->fbuf = usbvision_rvmalloc(usbvision->fbuf_size))) {
+                       break;
+               }
+               usbvision->num_frames--;
        }
+
        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++) {
+       for (i = 0; i < usbvision->num_frames; i++) {
                usbvision->frame[i].index = i;
                usbvision->frame[i].grabstate = FrameState_Unused;
                usbvision->frame[i].data = usbvision->fbuf +
@@ -1887,7 +1892,8 @@ int usbvision_frames_alloc(struct usb_usbvision *usbvision)
                usbvision->frame[i].height = usbvision->curheight;
                usbvision->frame[i].bytes_read = 0;
        }
-       return 0;
+       PDEBUG(DBG_FUNC, "allocated %d frames (%d bytes per frame)",usbvision->num_frames,usbvision->max_frame_size);
+       return usbvision->num_frames;
 }
 
 /*
@@ -1897,9 +1903,13 @@ int usbvision_frames_alloc(struct usb_usbvision *usbvision)
 void usbvision_frames_free(struct usb_usbvision *usbvision)
 {
        /* Have to free all that memory */
+       PDEBUG(DBG_FUNC, "free %d frames",usbvision->num_frames);
+
        if (usbvision->fbuf != NULL) {
                usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size);
                usbvision->fbuf = NULL;
+
+               usbvision->num_frames = 0;
        }
 }
 /*
@@ -2351,6 +2361,32 @@ int usbvision_setup(struct usb_usbvision *usbvision,int format)
        return USBVISION_IS_OPERATIONAL(usbvision);
 }
 
+int usbvision_set_alternate(struct usb_usbvision *dev)
+{
+       int errCode, prev_alt = dev->ifaceAlt;
+       int i;
+
+       dev->ifaceAlt=0;
+       for(i=0;i< dev->num_alt; i++)
+               if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->ifaceAlt])
+                       dev->ifaceAlt=i;
+
+       if (dev->ifaceAlt != prev_alt) {
+               dev->isocPacketSize = dev->alt_max_pkt_size[dev->ifaceAlt];
+               PDEBUG(DBG_FUNC,"setting alternate %d with wMaxPacketSize=%u", dev->ifaceAlt,dev->isocPacketSize);
+               errCode = usb_set_interface(dev->dev, dev->iface, dev->ifaceAlt);
+               if (errCode < 0) {
+                       err ("cannot change alternate number to %d (error=%i)",
+                                                       dev->ifaceAlt, errCode);
+                       return errCode;
+               }
+       }
+
+       PDEBUG(DBG_ISOC, "ISO Packet Length:%d", dev->isocPacketSize);
+
+       return 0;
+}
+
 /*
  * usbvision_init_isoc()
  *
@@ -2368,15 +2404,13 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
        scratch_reset(usbvision);
 
        /* Alternate interface 1 is is the biggest frame size */
-       errCode = usb_set_interface(dev, usbvision->iface, usbvision->ifaceAltActive);
+       errCode = usbvision_set_alternate(usbvision);
        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);
@@ -2462,8 +2496,9 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision)
        if (!usbvision->remove_pending) {
 
                /* Set packet size to 0 */
+               usbvision->ifaceAlt=0;
                errCode = usb_set_interface(usbvision->dev, usbvision->iface,
-                                     usbvision->ifaceAltInactive);
+                                           usbvision->ifaceAlt);
                if (errCode < 0) {
                        err("%s: usb_set_interface() failed: error %d", __FUNCTION__, errCode);
                        usbvision->last_error = errCode;
@@ -2490,6 +2525,7 @@ int usbvision_muxsel(struct usb_usbvision *usbvision, int channel)
        RESTRICT_TO_RANGE(channel, 0, usbvision->video_inputs);
        usbvision->ctl_input = channel;
          route.input = SAA7115_COMPOSITE1;
+         route.output = 0;
          call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route);
          call_i2c_clients(usbvision, VIDIOC_S_INPUT, &usbvision->ctl_input);
 
index af33653f0db8a18b22097785b50ed7f06cdc75a8..6fc14557d623779aa3a21e93c3eeb56d422e81cf 100644 (file)
@@ -230,7 +230,7 @@ static ssize_t show_hue(struct class_device *cd, char *buf)
        ctrl.value = 0;
        if(usbvision->user)
                call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
-       return sprintf(buf, "%d\n", ctrl.value >> 8);
+       return sprintf(buf, "%d\n", ctrl.value);
 }
 static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL);
 
@@ -243,7 +243,7 @@ static ssize_t show_contrast(struct class_device *cd, char *buf)
        ctrl.value = 0;
        if(usbvision->user)
                call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
-       return sprintf(buf, "%d\n", ctrl.value >> 8);
+       return sprintf(buf, "%d\n", ctrl.value);
 }
 static CLASS_DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL);
 
@@ -256,7 +256,7 @@ static ssize_t show_brightness(struct class_device *cd, char *buf)
        ctrl.value = 0;
        if(usbvision->user)
                call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
-       return sprintf(buf, "%d\n", ctrl.value >> 8);
+       return sprintf(buf, "%d\n", ctrl.value);
 }
 static CLASS_DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL);
 
@@ -269,7 +269,7 @@ static ssize_t show_saturation(struct class_device *cd, char *buf)
        ctrl.value = 0;
        if(usbvision->user)
                call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
-       return sprintf(buf, "%d\n", ctrl.value >> 8);
+       return sprintf(buf, "%d\n", ctrl.value);
 }
 static CLASS_DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL);
 
@@ -391,19 +391,14 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file)
        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) && (isocMode==ISOC_MODE_COMPRESS)) {
-                               /* Allocate intermediate decompression buffers only if needed */
-                               errCode = usbvision_decompress_alloc(usbvision);
-                       }
+               /* Allocate memory for the scratch ring buffer */
+               errCode = usbvision_scratch_alloc(usbvision);
+               if (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_decompress_free(usbvision);
                }
@@ -476,6 +471,7 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file)
 
        usbvision_decompress_free(usbvision);
        usbvision_frames_free(usbvision);
+       usbvision_empty_framequeues(usbvision);
        usbvision_scratch_free(usbvision);
 
        usbvision->user--;
@@ -489,7 +485,7 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file)
        up(&usbvision->lock);
 
        if (usbvision->remove_pending) {
-               info("%s: Final disconnect", __FUNCTION__);
+               printk(KERN_INFO "%s: Final disconnect\n", __FUNCTION__);
                usbvision_release(usbvision);
        }
 
@@ -519,44 +515,32 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
                /* ioctls to allow direct acces to the NT100x registers */
-               case VIDIOC_INT_G_REGISTER:
+               case VIDIOC_DBG_G_REGISTER:
+               case VIDIOC_DBG_S_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)
+                       if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
                                return -EINVAL;
                        if (!capable(CAP_SYS_ADMIN))
                                return -EPERM;
-                       errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val);
+                       /* NT100x has a 8-bit register space */
+                       if (cmd == VIDIOC_DBG_G_REGISTER)
+                               errCode = usbvision_read_reg(usbvision, reg->reg&0xff);
+                       else
+                               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;
+                               err("%s: VIDIOC_DBG_%c_REGISTER failed: error %d", __FUNCTION__,
+                                   cmd == VIDIOC_DBG_G_REGISTER ? 'G' : 'S', errCode);
+                               return errCode;
                        }
+                       if (cmd == VIDIOC_DBG_S_REGISTER)
+                               reg->val = (u8)errCode;
+
+                       PDEBUG(DBG_IOCTL, "VIDIOC_DBG_%c_REGISTER reg=0x%02X, value=0x%02X",
+                              cmd == VIDIOC_DBG_G_REGISTER ? 'G' : 'S',
+                              (unsigned int)reg->reg, (unsigned int)reg->val);
                        return 0;
                }
 #endif
@@ -792,8 +776,8 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
                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);
+                       PDEBUG(DBG_IOCTL,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value);
                        return 0;
                }
                case VIDIOC_S_CTRL:
@@ -821,7 +805,9 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
                                    return ret;
                        }
 
+                       usbvision_frames_free(usbvision);
                        usbvision_empty_framequeues(usbvision);
+                       vr->count = usbvision_frames_alloc(usbvision,vr->count);
 
                        usbvision->curFrame = NULL;
 
@@ -838,7 +824,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
                        if(vb->type != V4L2_CAP_VIDEO_CAPTURE) {
                                return -EINVAL;
                        }
-                       if(vb->index>=USBVISION_NUMFRAMES)  {
+                       if(vb->index>=usbvision->num_frames)  {
                                return -EINVAL;
                        }
                        // Updating the corresponding frame state
@@ -852,7 +838,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
                                vb->flags |= V4L2_BUF_FLAG_MAPPED;
                        vb->memory = V4L2_MEMORY_MMAP;
 
-                       vb->m.offset = vb->index*usbvision->max_frame_size;
+                       vb->m.offset = vb->index*PAGE_ALIGN(usbvision->max_frame_size);
 
                        vb->memory = V4L2_MEMORY_MMAP;
                        vb->field = V4L2_FIELD_NONE;
@@ -871,7 +857,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
                        if(vb->type != V4L2_CAP_VIDEO_CAPTURE) {
                                return -EINVAL;
                        }
-                       if(vb->index>=USBVISION_NUMFRAMES)  {
+                       if(vb->index>=usbvision->num_frames)  {
                                return -EINVAL;
                        }
 
@@ -1041,6 +1027,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
                                                if ((ret = usbvision_stream_interrupt(usbvision)))
                                                        return ret;
                                        }
+                                       usbvision_frames_free(usbvision);
                                        usbvision_empty_framequeues(usbvision);
 
                                        usbvision->curFrame = NULL;
@@ -1087,12 +1074,24 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
        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);
+       /* This entry point is compatible with the mmap routines so that a user can do either
+          VIDIOC_QBUF/VIDIOC_DQBUF to get frames or call read on the device. */
+       if(!usbvision->num_frames) {
+               /* First, allocate some frames to work with if this has not been done with
+                VIDIOC_REQBUF */
+               usbvision_frames_free(usbvision);
+               usbvision_empty_framequeues(usbvision);
+               usbvision_frames_alloc(usbvision,USBVISION_NUMFRAMES);
+       }
+
+       if(usbvision->streaming != Stream_On) {
+               /* 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;i<USBVISION_NUMFRAMES;i++) {
+       /* Then, enqueue as many frames as possible (like a user of VIDIOC_QBUF would do) */
+       for(i=0;i<usbvision->num_frames;i++) {
                frame = &usbvision->frame[i];
                if(frame->grabstate == FrameState_Unused) {
                        /* Mark it as ready and enqueue frame */
@@ -1169,6 +1168,8 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
        struct video_device *dev = video_devdata(file);
        struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
 
+       PDEBUG(DBG_MMAP, "mmap");
+
        down(&usbvision->lock);
 
        if (!USBVISION_IS_OPERATIONAL(usbvision)) {
@@ -1177,16 +1178,16 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
        }
 
        if (!(vma->vm_flags & VM_WRITE) ||
-           size != PAGE_ALIGN(usbvision->curwidth*usbvision->curheight*usbvision->palette.bytes_per_pixel)) {
+           size != PAGE_ALIGN(usbvision->max_frame_size)) {
                up(&usbvision->lock);
                return -EINVAL;
        }
 
-       for (i = 0; i < USBVISION_NUMFRAMES; i++) {
-               if (((usbvision->max_frame_size*i) >> PAGE_SHIFT) == vma->vm_pgoff)
+       for (i = 0; i < usbvision->num_frames; i++) {
+               if (((PAGE_ALIGN(usbvision->max_frame_size)*i) >> PAGE_SHIFT) == vma->vm_pgoff)
                        break;
        }
-       if (i == USBVISION_NUMFRAMES) {
+       if (i == usbvision->num_frames) {
                PDEBUG(DBG_MMAP, "mmap: user supplied mapping address is out of range");
                up(&usbvision->lock);
                return -EINVAL;
@@ -1242,6 +1243,13 @@ static int usbvision_radio_open(struct inode *inode, struct file *file)
                        }
                }
 
+               /* Alternate interface 1 is is the biggest frame size */
+               errCode = usbvision_set_alternate(usbvision);
+               if (errCode < 0) {
+                       usbvision->last_error = errCode;
+                       return -EBUSY;
+               }
+
                // If so far no errors then we shall start the radio
                usbvision->radio = 1;
                call_i2c_clients(usbvision,AUDC_SET_RADIO,&usbvision->tuner_type);
@@ -1273,6 +1281,11 @@ static int usbvision_radio_close(struct inode *inode, struct file *file)
 
        down(&usbvision->lock);
 
+       /* Set packet size to 0 */
+       usbvision->ifaceAlt=0;
+       errCode = usb_set_interface(usbvision->dev, usbvision->iface,
+                                   usbvision->ifaceAlt);
+
        usbvision_audio_off(usbvision);
        usbvision->radio=0;
        usbvision->user--;
@@ -1285,7 +1298,7 @@ static int usbvision_radio_close(struct inode *inode, struct file *file)
        up(&usbvision->lock);
 
        if (usbvision->remove_pending) {
-               info("%s: Final disconnect", __FUNCTION__);
+               printk(KERN_INFO "%s: Final disconnect\n", __FUNCTION__);
                usbvision_release(usbvision);
        }
 
@@ -1611,7 +1624,7 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision)
        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);
+       printk(KERN_INFO "USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]\n", usbvision->nr,usbvision->vdev->minor & 0x1f);
 
        // Radio Device:
        if (usbvision_device_data[usbvision->DevModel].Radio) {
@@ -1623,7 +1636,7 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision)
                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);
+               printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]\n", usbvision->nr, usbvision->rdev->minor & 0x1f);
        }
        // vbi Device:
        if (usbvision_device_data[usbvision->DevModel].vbi) {
@@ -1634,7 +1647,7 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision)
                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);
+               printk(KERN_INFO "USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)\n", usbvision->nr,usbvision->vbi->minor & 0x1f);
        }
        // all done
        return 0;
@@ -1764,15 +1777,17 @@ static void usbvision_configure_video(struct usb_usbvision *usbvision)
  */
 static int __devinit usbvision_probe(struct usb_interface *intf, const struct usb_device_id *devid)
 {
-       struct usb_device *dev = interface_to_usbdev(intf);
+       struct usb_device *dev = usb_get_dev(interface_to_usbdev(intf));
+       struct usb_interface *uif;
        __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;
+       int model,i;
 
        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++) {
@@ -1783,7 +1798,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf, const struct us
                        continue;
                }
 
-               info("%s: %s found", __FUNCTION__, usbvision_device_data[model].ModelString);
+               printk(KERN_INFO "%s: %s found\n", __FUNCTION__, usbvision_device_data[model].ModelString);
                break;
        }
 
@@ -1799,7 +1814,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf, const struct us
        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);
+               err("%s: Endpoint attributes %d", __FUNCTION__, endpoint->bmAttributes);
                return -ENODEV;
        }
        if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {
@@ -1826,6 +1841,28 @@ static int __devinit usbvision_probe(struct usb_interface *intf, const struct us
 
        down(&usbvision->lock);
 
+       /* compute alternate max packet sizes */
+       uif = dev->actconfig->interface[0];
+
+       usbvision->num_alt=uif->num_altsetting;
+       PDEBUG(DBG_PROBE, "Alternate settings: %i",usbvision->num_alt);
+       usbvision->alt_max_pkt_size = kmalloc(32*
+                                             usbvision->num_alt,GFP_KERNEL);
+       if (usbvision->alt_max_pkt_size == NULL) {
+               err("usbvision: out of memory!\n");
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < usbvision->num_alt ; i++) {
+               u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc.
+                                     wMaxPacketSize);
+               usbvision->alt_max_pkt_size[i] =
+                       (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
+               PDEBUG(DBG_PROBE, "Alternate setting %i, max size= %i",i,
+                      usbvision->alt_max_pkt_size[i]);
+       }
+
+
        usbvision->nr = usbvision_nr++;
 
        usbvision->have_tuner = usbvision_device_data[model].Tuner;
@@ -1838,8 +1875,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf, const struct us
        usbvision->DevModel = model;
        usbvision->remove_pending = 0;
        usbvision->iface = ifnum;
-       usbvision->ifaceAltInactive = 0;
-       usbvision->ifaceAltActive = 1;
+       usbvision->ifaceAlt = 0;
        usbvision->video_endp = endpoint->bEndpointAddress;
        usbvision->isocPacketSize = 0;
        usbvision->usb_bandwidth = 0;
@@ -1895,7 +1931,7 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf)
        up(&usbvision->lock);
 
        if (usbvision->user) {
-               info("%s: In use, disconnect pending", __FUNCTION__);
+               printk(KERN_INFO "%s: In use, disconnect pending\n", __FUNCTION__);
                wake_up_interruptible(&usbvision->wait_frame);
                wake_up_interruptible(&usbvision->wait_stream);
        }
@@ -2061,7 +2097,7 @@ static int __init usbvision_init(void)
        errCode = usb_register(&usbvision_driver);
 
        if (errCode == 0) {
-               info(DRIVER_DESC " : " USBVISION_VERSION_STRING);
+               printk(KERN_INFO DRIVER_DESC " : " USBVISION_VERSION_STRING "\n");
                PDEBUG(DBG_PROBE, "success");
        }
        return errCode;
index e2bcaba93871d0bab0632999f38ab086a6f1d931..ad6afd3e42a423c1177692189e0356625135a49a 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <linux/list.h>
 #include <linux/usb.h>
+#include <linux/i2c.h>
 #include <media/v4l2-common.h>
 #include <media/tuner.h>
 #include <linux/videodev2.h>
@@ -396,8 +397,11 @@ struct usb_usbvision {
 
        /* Device structure */
        struct usb_device *dev;
+       /* usb transfer */
+       int num_alt;            /* Number of alternative settings */
+       unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */
        unsigned char iface;                                            /* Video interface number */
-       unsigned char ifaceAltActive, ifaceAltInactive;                 /* Alt settings */
+       unsigned char ifaceAlt;                 /* Alt settings */
        unsigned char Vin_Reg2_Preset;
        struct semaphore lock;
        struct timer_list powerOffTimer;
@@ -421,6 +425,7 @@ struct usb_usbvision {
        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
+       int num_frames;                                                 // number of frames allocated
        struct usbvision_sbuf sbuf[USBVISION_NUMSBUF];                  // S buffering
        volatile int remove_pending;                                    /* If set then about to exit */
 
@@ -486,12 +491,11 @@ 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_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);
+int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames);
 void usbvision_frames_free(struct usb_usbvision *usbvision);
 int usbvision_scratch_alloc(struct usb_usbvision *usbvision);
 void usbvision_scratch_free(struct usb_usbvision *usbvision);
@@ -502,6 +506,7 @@ 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_alternate(struct usb_usbvision *dev);
 
 int usbvision_set_audio(struct usb_usbvision *usbvision, int AudioChannel);
 int usbvision_audio_off(struct usb_usbvision *usbvision);
index 8a13e595304e59a479d3229d07f4db20a1d31b7c..d2c1ae0dbfba55f4f82f0c6911717b4a857d651b 100644 (file)
@@ -11,7 +11,7 @@
  *     as published by the Free Software Foundation; either version
  *     2 of the License, or (at your option) any later version.
  *
- * Author:     Bill Dirks <bdirks@pacbell.net>
+ * Author:     Bill Dirks <bill@thedirks.org>
  *             et al.
  *
  */
index b8ee37ded3c98c1cedf4cd5b4ee79a3f1e58dec1..54747606eae11e4d984ac3293017f539360902f2 100644 (file)
@@ -12,7 +12,7 @@
  *     as published by the Free Software Foundation; either version
  *     2 of the License, or (at your option) any later version.
  *
- * Author:     Bill Dirks <bdirks@pacbell.net>
+ * Author:     Bill Dirks <bill@thedirks.org>
  *             based on code by Alan Cox, <alan@cymru.net>
  *
  */
@@ -51,6 +51,7 @@
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/errno.h>
+#include <linux/i2c.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
@@ -271,11 +272,6 @@ char *v4l2_type_names[] = {
        [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT]  = "slicec-vbi-out",
 };
 
-static char *v4l2_memory_names[] = {
-       [V4L2_MEMORY_MMAP]    = "mmap",
-       [V4L2_MEMORY_USERPTR] = "userptr",
-       [V4L2_MEMORY_OVERLAY] = "overlay",
-};
 
 #define prt_names(a,arr) (((a)>=0)&&((a)<ARRAY_SIZE(arr)))?arr[a]:"unknown"
 
@@ -370,13 +366,21 @@ static const char *v4l2_ioctls[] = {
        [_IOC_NR(VIDIOC_ENUMAUDOUT)]       = "VIDIOC_ENUMAUDOUT",
        [_IOC_NR(VIDIOC_G_PRIORITY)]       = "VIDIOC_G_PRIORITY",
        [_IOC_NR(VIDIOC_S_PRIORITY)]       = "VIDIOC_S_PRIORITY",
-#if 1
        [_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP",
-#endif
        [_IOC_NR(VIDIOC_LOG_STATUS)]       = "VIDIOC_LOG_STATUS",
        [_IOC_NR(VIDIOC_G_EXT_CTRLS)]      = "VIDIOC_G_EXT_CTRLS",
        [_IOC_NR(VIDIOC_S_EXT_CTRLS)]      = "VIDIOC_S_EXT_CTRLS",
-       [_IOC_NR(VIDIOC_TRY_EXT_CTRLS)]    = "VIDIOC_TRY_EXT_CTRLS"
+       [_IOC_NR(VIDIOC_TRY_EXT_CTRLS)]    = "VIDIOC_TRY_EXT_CTRLS",
+#if 1
+       [_IOC_NR(VIDIOC_ENUM_FRAMESIZES)]  = "VIDIOC_ENUM_FRAMESIZES",
+       [_IOC_NR(VIDIOC_ENUM_FRAMEINTERVALS)] = "VIDIOC_ENUM_FRAMEINTERVALS",
+       [_IOC_NR(VIDIOC_G_ENC_INDEX)]      = "VIDIOC_G_ENC_INDEX",
+       [_IOC_NR(VIDIOC_ENCODER_CMD)]      = "VIDIOC_ENCODER_CMD",
+       [_IOC_NR(VIDIOC_TRY_ENCODER_CMD)]  = "VIDIOC_TRY_ENCODER_CMD",
+
+       [_IOC_NR(VIDIOC_DBG_S_REGISTER)]   = "VIDIOC_DBG_S_REGISTER",
+       [_IOC_NR(VIDIOC_DBG_G_REGISTER)]   = "VIDIOC_DBG_G_REGISTER",
+#endif
 };
 #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
 
@@ -401,8 +405,6 @@ static const char *v4l2_int_ioctls[] = {
        [_IOC_NR(TDA9887_SET_CONFIG)]          = "TDA9887_SET_CONFIG",
 
        [_IOC_NR(VIDIOC_INT_S_TUNER_MODE)]     = "VIDIOC_INT_S_TUNER_MODE",
-       [_IOC_NR(VIDIOC_INT_S_REGISTER)]       = "VIDIOC_INT_S_REGISTER",
-       [_IOC_NR(VIDIOC_INT_G_REGISTER)]       = "VIDIOC_INT_G_REGISTER",
        [_IOC_NR(VIDIOC_INT_RESET)]            = "VIDIOC_INT_RESET",
        [_IOC_NR(VIDIOC_INT_AUDIO_CLOCK_FREQ)] = "VIDIOC_INT_AUDIO_CLOCK_FREQ",
        [_IOC_NR(VIDIOC_INT_DECODE_VBI_LINE)]  = "VIDIOC_INT_DECODE_VBI_LINE",
@@ -419,14 +421,6 @@ static const char *v4l2_int_ioctls[] = {
 };
 #define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls)
 
-static void v4l_print_pix_fmt (char *s, struct v4l2_pix_format *fmt)
-{
-       printk ("%s: width=%d, height=%d, format=%d, field=%s, "
-               "bytesperline=%d sizeimage=%d, colorspace=%d\n", s,
-               fmt->width,fmt->height,fmt->pixelformat,
-               prt_names(fmt->field,v4l2_field_names),
-               fmt->bytesperline,fmt->sizeimage,fmt->colorspace);
-};
 
 /* Common ioctl debug function. This function can be used by
    external ioctl messages as well as internal V4L ioctl */
@@ -466,576 +460,6 @@ void v4l_printk_ioctl(unsigned int cmd)
        }
 }
 
-/* Common ioctl debug function. This function can be used by
-   external ioctl messages as well as internal V4L ioctl and its
-   arguments */
-void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
-{
-       printk(s);
-       printk(": ");
-       v4l_printk_ioctl(cmd);
-       switch (cmd) {
-       case VIDIOC_INT_G_CHIP_IDENT:
-       {
-               enum v4l2_chip_ident  *p=arg;
-               printk ("%s: chip ident=%d\n", s, *p);
-               break;
-       }
-       case VIDIOC_G_PRIORITY:
-       case VIDIOC_S_PRIORITY:
-       {
-               enum v4l2_priority *p=arg;
-               printk ("%s: priority=%d\n", s, *p);
-               break;
-       }
-       case VIDIOC_INT_S_TUNER_MODE:
-       {
-               enum v4l2_tuner_type *p=arg;
-               printk ("%s: tuner type=%d\n", s, *p);
-               break;
-       }
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-       case DECODER_SET_VBI_BYPASS:
-       case DECODER_ENABLE_OUTPUT:
-       case DECODER_GET_STATUS:
-       case DECODER_SET_OUTPUT:
-       case DECODER_SET_INPUT:
-       case DECODER_SET_GPIO:
-       case DECODER_SET_NORM:
-       case VIDIOCCAPTURE:
-       case VIDIOCSYNC:
-       case VIDIOCSWRITEMODE:
-#endif
-       case TUNER_SET_TYPE_ADDR:
-       case TUNER_SET_STANDBY:
-       case TDA9887_SET_CONFIG:
-#ifdef __OLD_VIDIOC_
-       case VIDIOC_OVERLAY_OLD:
-#endif
-       case VIDIOC_STREAMOFF:
-       case VIDIOC_G_OUTPUT:
-       case VIDIOC_S_OUTPUT:
-       case VIDIOC_STREAMON:
-       case VIDIOC_G_INPUT:
-       case VIDIOC_OVERLAY:
-       case VIDIOC_S_INPUT:
-       {
-               int *p=arg;
-               printk ("%s: value=%d\n", s, *p);
-               break;
-       }
-       case VIDIOC_G_AUDIO:
-       case VIDIOC_S_AUDIO:
-       case VIDIOC_ENUMAUDIO:
-#ifdef __OLD_VIDIOC_
-       case VIDIOC_G_AUDIO_OLD:
-#endif
-       {
-               struct v4l2_audio *p=arg;
-
-               printk ("%s: index=%d, name=%s, capability=%d, mode=%d\n",
-                       s,p->index, p->name,p->capability, p->mode);
-               break;
-       }
-       case VIDIOC_G_AUDOUT:
-       case VIDIOC_S_AUDOUT:
-       case VIDIOC_ENUMAUDOUT:
-#ifdef __OLD_VIDIOC_
-       case VIDIOC_G_AUDOUT_OLD:
-#endif
-       {
-               struct v4l2_audioout *p=arg;
-               printk ("%s: index=%d, name=%s, capability=%d, mode=%d\n", s,
-                               p->index, p->name, p->capability,p->mode);
-               break;
-       }
-       case VIDIOC_QBUF:
-       case VIDIOC_DQBUF:
-       case VIDIOC_QUERYBUF:
-       {
-               struct v4l2_buffer *p=arg;
-               struct v4l2_timecode *tc=&p->timecode;
-               printk ("%s: %02ld:%02d:%02d.%08ld index=%d, type=%s, "
-                       "bytesused=%d, flags=0x%08x, "
-                       "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx\n",
-                               s,
-                               (p->timestamp.tv_sec/3600),
-                               (int)(p->timestamp.tv_sec/60)%60,
-                               (int)(p->timestamp.tv_sec%60),
-                               p->timestamp.tv_usec,
-                               p->index,
-                               prt_names(p->type,v4l2_type_names),
-                               p->bytesused,p->flags,
-                               p->field,p->sequence,
-                               prt_names(p->memory,v4l2_memory_names),
-                               p->m.userptr);
-               printk ("%s: timecode= %02d:%02d:%02d type=%d, "
-                       "flags=0x%08x, frames=%d, userbits=0x%08x\n",
-                               s,tc->hours,tc->minutes,tc->seconds,
-                               tc->type, tc->flags, tc->frames, *(__u32 *) tc->userbits);
-               break;
-       }
-       case VIDIOC_QUERYCAP:
-       {
-               struct v4l2_capability *p=arg;
-               printk ("%s: driver=%s, card=%s, bus=%s, version=0x%08x, "
-                       "capabilities=0x%08x\n", s,
-                               p->driver,p->card,p->bus_info,
-                               p->version,
-                               p->capabilities);
-               break;
-       }
-       case VIDIOC_G_CTRL:
-       case VIDIOC_S_CTRL:
-#ifdef __OLD_VIDIOC_
-       case VIDIOC_S_CTRL_OLD:
-#endif
-       {
-               struct v4l2_control *p=arg;
-               printk ("%s: id=%d, value=%d\n", s, p->id, p->value);
-               break;
-       }
-       case VIDIOC_G_EXT_CTRLS:
-       case VIDIOC_S_EXT_CTRLS:
-       case VIDIOC_TRY_EXT_CTRLS:
-       {
-               struct v4l2_ext_controls *p = arg;
-               int i;
-
-               printk("%s: ctrl_class=%d, count=%d\n", s, p->ctrl_class, p->count);
-               for (i = 0; i < p->count; i++) {
-                       struct v4l2_ext_control *c = &p->controls[i];
-                       if (cmd == VIDIOC_G_EXT_CTRLS)
-                               printk("%s: id=%d\n", s, c->id);
-                       else
-                               printk("%s: id=%d, value=%d\n", s, c->id, c->value);
-               }
-               break;
-       }
-       case VIDIOC_G_CROP:
-       case VIDIOC_S_CROP:
-       {
-               struct v4l2_crop *p=arg;
-               /*FIXME: Should also show rect structs */
-               printk ("%s: type=%d\n", s, p->type);
-               break;
-       }
-       case VIDIOC_CROPCAP:
-#ifdef __OLD_VIDIOC_
-       case VIDIOC_CROPCAP_OLD:
-#endif
-       {
-               struct v4l2_cropcap *p=arg;
-               /*FIXME: Should also show rect structs */
-               printk ("%s: type=%d\n", s, p->type);
-               break;
-       }
-       case VIDIOC_INT_DECODE_VBI_LINE:
-       {
-               struct v4l2_decode_vbi_line *p=arg;
-               printk ("%s: is_second_field=%d, ptr=0x%08lx, line=%d, "
-                       "type=%d\n", s,
-                               p->is_second_field,(unsigned long)p->p,p->line,p->type);
-               break;
-       }
-       case VIDIOC_ENUM_FMT:
-       {
-               struct v4l2_fmtdesc *p=arg;
-               printk ("%s: index=%d, type=%d, flags=%d, description=%s,"
-                       " pixelformat=%d\n", s,
-                               p->index, p->type, p->flags,p->description,
-                               p->pixelformat);
-
-               break;
-       }
-       case VIDIOC_G_FMT:
-       case VIDIOC_S_FMT:
-       case VIDIOC_TRY_FMT:
-       {
-               struct v4l2_format *p=arg;
-               printk ("%s: type=%s\n", s,
-                               prt_names(p->type,v4l2_type_names));
-               switch (p->type) {
-               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-                       v4l_print_pix_fmt (s, &p->fmt.pix);
-                       break;
-               default:
-                       break;
-               }
-       }
-       case VIDIOC_G_FBUF:
-       case VIDIOC_S_FBUF:
-       {
-               struct v4l2_framebuffer *p=arg;
-               printk ("%s: capability=%d, flags=%d, base=0x%08lx\n", s,
-                               p->capability,p->flags, (unsigned long)p->base);
-               v4l_print_pix_fmt (s, &p->fmt);
-               break;
-       }
-       case VIDIOC_G_FREQUENCY:
-       case VIDIOC_S_FREQUENCY:
-       {
-               struct v4l2_frequency *p=arg;
-               printk ("%s: tuner=%d, type=%d, frequency=%d\n", s,
-                               p->tuner,p->type,p->frequency);
-               break;
-       }
-       case VIDIOC_ENUMINPUT:
-       {
-               struct v4l2_input *p=arg;
-               printk ("%s: index=%d, name=%s, type=%d, audioset=%d, "
-                       "tuner=%d, std=%Ld, status=%d\n", s,
-                               p->index,p->name,p->type,p->audioset,
-                               p->tuner,
-                               (unsigned long long)p->std,
-                               p->status);
-               break;
-       }
-       case VIDIOC_G_JPEGCOMP:
-       case VIDIOC_S_JPEGCOMP:
-       {
-               struct v4l2_jpegcompression *p=arg;
-               printk ("%s: quality=%d, APPn=%d, APP_len=%d, COM_len=%d,"
-                       " jpeg_markers=%d\n", s,
-                               p->quality,p->APPn,p->APP_len,
-                               p->COM_len,p->jpeg_markers);
-               break;
-       }
-       case VIDIOC_G_MODULATOR:
-       case VIDIOC_S_MODULATOR:
-       {
-               struct v4l2_modulator *p=arg;
-               printk ("%s: index=%d, name=%s, capability=%d, rangelow=%d,"
-                       " rangehigh=%d, txsubchans=%d\n", s,
-                               p->index, p->name,p->capability,p->rangelow,
-                               p->rangehigh,p->txsubchans);
-               break;
-       }
-       case VIDIOC_G_MPEGCOMP:
-       case VIDIOC_S_MPEGCOMP:
-       {
-               struct v4l2_mpeg_compression *p=arg;
-               /*FIXME: Several fields not shown */
-               printk ("%s: ts_pid_pmt=%d, ts_pid_audio=%d, ts_pid_video=%d, "
-                       "ts_pid_pcr=%d, ps_size=%d, au_sample_rate=%d, "
-                       "au_pesid=%c, vi_frame_rate=%d, vi_frames_per_gop=%d, "
-                       "vi_bframes_count=%d, vi_pesid=%c\n", s,
-                               p->ts_pid_pmt,p->ts_pid_audio, p->ts_pid_video,
-                               p->ts_pid_pcr, p->ps_size, p->au_sample_rate,
-                               p->au_pesid, p->vi_frame_rate,
-                               p->vi_frames_per_gop, p->vi_bframes_count,
-                               p->vi_pesid);
-               break;
-       }
-       case VIDIOC_ENUMOUTPUT:
-       {
-               struct v4l2_output *p=arg;
-               printk ("%s: index=%d, name=%s,type=%d, audioset=%d, "
-                       "modulator=%d, std=%Ld\n",
-                               s,p->index,p->name,p->type,p->audioset,
-                               p->modulator,
-                               (unsigned long long)p->std);
-               break;
-       }
-       case VIDIOC_QUERYCTRL:
-       {
-               struct v4l2_queryctrl *p=arg;
-               printk ("%s: id=%d, type=%d, name=%s, min/max=%d/%d,"
-                       " step=%d, default=%d, flags=0x%08x\n", s,
-                               p->id,p->type,p->name,p->minimum,p->maximum,
-                               p->step,p->default_value,p->flags);
-               break;
-       }
-       case VIDIOC_QUERYMENU:
-       {
-               struct v4l2_querymenu *p=arg;
-               printk ("%s: id=%d, index=%d, name=%s\n", s,
-                               p->id,p->index,p->name);
-               break;
-       }
-       case VIDIOC_INT_G_REGISTER:
-       case VIDIOC_INT_S_REGISTER:
-       {
-               struct v4l2_register *p=arg;
-               printk ("%s: i2c_id=%d, reg=%lu, val=%d\n", s,
-                               p->i2c_id,p->reg,p->val);
-
-               break;
-       }
-       case VIDIOC_REQBUFS:
-       {
-               struct v4l2_requestbuffers *p=arg;
-               printk ("%s: count=%d, type=%s, memory=%s\n", s,
-                               p->count,
-                               prt_names(p->type,v4l2_type_names),
-                               prt_names(p->memory,v4l2_memory_names));
-               break;
-       }
-       case VIDIOC_INT_S_AUDIO_ROUTING:
-       case VIDIOC_INT_S_VIDEO_ROUTING:
-       case VIDIOC_INT_G_AUDIO_ROUTING:
-       case VIDIOC_INT_G_VIDEO_ROUTING:
-       {
-               struct v4l2_routing  *p=arg;
-               printk ("%s: input=0x%x, output=0x%x\n", s, p->input, p->output);
-               break;
-       }
-       case VIDIOC_INT_S_CRYSTAL_FREQ:
-       {
-               struct v4l2_crystal_freq *p=arg;
-               printk ("%s: freq=%u, flags=0x%x\n", s, p->freq, p->flags);
-               break;
-       }
-       case VIDIOC_G_SLICED_VBI_CAP:
-       {
-               struct v4l2_sliced_vbi_cap *p=arg;
-               printk ("%s: service_set=%d\n", s,
-                               p->service_set);
-               break;
-       }
-       case VIDIOC_INT_S_VBI_DATA:
-       case VIDIOC_INT_G_VBI_DATA:
-       {
-               struct v4l2_sliced_vbi_data  *p=arg;
-               printk ("%s: id=%d, field=%d, line=%d\n", s,
-                               p->id, p->field, p->line);
-               break;
-       }
-       case VIDIOC_ENUMSTD:
-       {
-               struct v4l2_standard *p=arg;
-               printk ("%s: index=%d, id=%Ld, name=%s, fps=%d/%d, "
-                       "framelines=%d\n", s, p->index,
-                               (unsigned long long)p->id, p->name,
-                               p->frameperiod.numerator,
-                               p->frameperiod.denominator,
-                               p->framelines);
-
-               break;
-       }
-       case VIDIOC_G_PARM:
-       case VIDIOC_S_PARM:
-#ifdef __OLD_VIDIOC_
-       case VIDIOC_S_PARM_OLD:
-#endif
-       {
-               struct v4l2_streamparm *p=arg;
-               printk ("%s: type=%d\n", s, p->type);
-
-               break;
-       }
-       case VIDIOC_G_TUNER:
-       case VIDIOC_S_TUNER:
-       {
-               struct v4l2_tuner *p=arg;
-               printk ("%s: index=%d, name=%s, type=%d, capability=%d, "
-                       "rangelow=%d, rangehigh=%d, signal=%d, afc=%d, "
-                       "rxsubchans=%d, audmode=%d\n", s,
-                               p->index, p->name, p->type,
-                               p->capability, p->rangelow,p->rangehigh,
-                               p->rxsubchans, p->audmode, p->signal,
-                               p->afc);
-               break;
-       }
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-       case VIDIOCGVBIFMT:
-       case VIDIOCSVBIFMT:
-       {
-               struct vbi_format *p=arg;
-               printk ("%s: sampling_rate=%d, samples_per_line=%d, "
-                       "sample_format=%d, start=%d/%d, count=%d/%d, flags=%d\n", s,
-                               p->sampling_rate,p->samples_per_line,
-                               p->sample_format,p->start[0],p->start[1],
-                               p->count[0],p->count[1],p->flags);
-               break;
-       }
-       case VIDIOCGAUDIO:
-       case VIDIOCSAUDIO:
-       {
-               struct video_audio *p=arg;
-               printk ("%s: audio=%d, volume=%d, bass=%d, treble=%d, "
-                       "flags=%d, name=%s, mode=%d, balance=%d, step=%d\n",
-                               s,p->audio,p->volume,p->bass, p->treble,
-                               p->flags,p->name,p->mode,p->balance,p->step);
-               break;
-       }
-       case VIDIOCGFBUF:
-       case VIDIOCSFBUF:
-       {
-               struct video_buffer *p=arg;
-               printk ("%s: base=%08lx, height=%d, width=%d, depth=%d, "
-                       "bytesperline=%d\n", s,
-                               (unsigned long) p->base, p->height, p->width,
-                               p->depth,p->bytesperline);
-               break;
-       }
-       case VIDIOCGCAP:
-       {
-               struct video_capability *p=arg;
-               printk ("%s: name=%s, type=%d, channels=%d, audios=%d, "
-                       "maxwidth=%d, maxheight=%d, minwidth=%d, minheight=%d\n",
-                               s,p->name,p->type,p->channels,p->audios,
-                               p->maxwidth,p->maxheight,p->minwidth,
-                               p->minheight);
-
-               break;
-       }
-       case VIDIOCGCAPTURE:
-       case VIDIOCSCAPTURE:
-       {
-               struct video_capture *p=arg;
-               printk ("%s: x=%d, y=%d, width=%d, height=%d, decimation=%d,"
-                       " flags=%d\n", s,
-                               p->x, p->y,p->width, p->height,
-                               p->decimation,p->flags);
-               break;
-       }
-       case VIDIOCGCHAN:
-       case VIDIOCSCHAN:
-       {
-               struct video_channel *p=arg;
-               printk ("%s: channel=%d, name=%s, tuners=%d, flags=%d, "
-                       "type=%d, norm=%d\n", s,
-                               p->channel,p->name,p->tuners,
-                               p->flags,p->type,p->norm);
-
-               break;
-       }
-       case VIDIOCSMICROCODE:
-       {
-               struct video_code *p=arg;
-               printk ("%s: loadwhat=%s, datasize=%d\n", s,
-                               p->loadwhat,p->datasize);
-               break;
-       }
-       case DECODER_GET_CAPABILITIES:
-       {
-               struct video_decoder_capability *p=arg;
-               printk ("%s: flags=%d, inputs=%d, outputs=%d\n", s,
-                               p->flags,p->inputs,p->outputs);
-               break;
-       }
-       case DECODER_INIT:
-       {
-               struct video_decoder_init *p=arg;
-               printk ("%s: len=%c\n", s, p->len);
-               break;
-       }
-       case VIDIOCGPLAYINFO:
-       {
-               struct video_info *p=arg;
-               printk ("%s: frame_count=%d, h_size=%d, v_size=%d, "
-                       "smpte_timecode=%d, picture_type=%d, "
-                       "temporal_reference=%d, user_data=%s\n", s,
-                               p->frame_count, p->h_size,
-                               p->v_size, p->smpte_timecode,
-                               p->picture_type, p->temporal_reference,
-                               p->user_data);
-               break;
-       }
-       case VIDIOCKEY:
-       {
-               struct video_key *p=arg;
-               printk ("%s: key=%s, flags=%d\n", s,
-                               p->key, p->flags);
-               break;
-       }
-       case VIDIOCGMBUF:
-       {
-               struct video_mbuf *p=arg;
-               printk ("%s: size=%d, frames=%d, offsets=0x%08lx\n", s,
-                               p->size,
-                               p->frames,
-                               (unsigned long)p->offsets);
-               break;
-       }
-       case VIDIOCMCAPTURE:
-       {
-               struct video_mmap *p=arg;
-               printk ("%s: frame=%d, height=%d, width=%d, format=%d\n", s,
-                               p->frame,
-                               p->height, p->width,
-                               p->format);
-               break;
-       }
-       case VIDIOCGPICT:
-       case VIDIOCSPICT:
-       case DECODER_SET_PICTURE:
-       {
-               struct video_picture *p=arg;
-
-               printk ("%s: brightness=%d, hue=%d, colour=%d, contrast=%d,"
-                       " whiteness=%d, depth=%d, palette=%d\n", s,
-                               p->brightness, p->hue, p->colour,
-                               p->contrast, p->whiteness, p->depth,
-                               p->palette);
-               break;
-       }
-       case VIDIOCSPLAYMODE:
-       {
-               struct video_play_mode *p=arg;
-               printk ("%s: mode=%d, p1=%d, p2=%d\n", s,
-                               p->mode,p->p1,p->p2);
-               break;
-       }
-       case VIDIOCGTUNER:
-       case VIDIOCSTUNER:
-       {
-               struct video_tuner *p=arg;
-               printk ("%s: tuner=%d, name=%s, rangelow=%ld, rangehigh=%ld, "
-                       "flags=%d, mode=%d, signal=%d\n", s,
-                               p->tuner, p->name,p->rangelow, p->rangehigh,
-                               p->flags,p->mode, p->signal);
-               break;
-       }
-       case VIDIOCGUNIT:
-       {
-               struct video_unit *p=arg;
-               printk ("%s: video=%d, vbi=%d, radio=%d, audio=%d, "
-                       "teletext=%d\n", s,
-                               p->video,p->vbi,p->radio,p->audio,p->teletext);
-               break;
-       }
-       case VIDIOCGWIN:
-       case VIDIOCSWIN:
-       {
-               struct video_window *p=arg;
-               printk ("%s: x=%d, y=%d, width=%d, height=%d, chromakey=%d,"
-                       " flags=%d, clipcount=%d\n", s,
-                               p->x, p->y,p->width, p->height,
-                               p->chromakey,p->flags,
-                               p->clipcount);
-               break;
-       }
-       case VIDIOCGFREQ:
-       case VIDIOCSFREQ:
-       {
-               unsigned long *p=arg;
-               printk ("%s: value=%lu\n", s, *p);
-               break;
-       }
-#endif
-       case VIDIOC_INT_AUDIO_CLOCK_FREQ:
-       case VIDIOC_INT_I2S_CLOCK_FREQ:
-       case VIDIOC_INT_S_STANDBY:
-       case VIDIOC_INT_RESET:
-       {
-               u32 *p=arg;
-
-               printk ("%s: value=%d\n", s, *p);
-               break;
-       }
-       case VIDIOC_G_STD:
-       case VIDIOC_S_STD:
-       case VIDIOC_QUERYSTD:
-       {
-               v4l2_std_id *p=arg;
-
-               printk ("%s: value=%Lu\n", s, (unsigned long long)*p);
-               break;
-       }
-       }
-}
 
 /* ----------------------------------------------------------------- */
 
@@ -1529,6 +953,28 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id)
        return **ctrl_classes;
 }
 
+int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 match_type, u32 match_chip)
+{
+       switch (match_type) {
+       case V4L2_CHIP_MATCH_I2C_DRIVER:
+               return (c != NULL && c->driver != NULL && c->driver->id == match_chip);
+       case V4L2_CHIP_MATCH_I2C_ADDR:
+               return (c != NULL && c->addr == match_chip);
+       default:
+               return 0;
+       }
+}
+
+int v4l2_chip_match_host(u32 match_type, u32 match_chip)
+{
+       switch (match_type) {
+       case V4L2_CHIP_MATCH_HOST:
+               return match_chip == 0;
+       default:
+               return 0;
+       }
+}
+
 /* ----------------------------------------------------------------- */
 
 EXPORT_SYMBOL(v4l2_norm_to_name);
@@ -1544,7 +990,6 @@ EXPORT_SYMBOL(v4l2_prio_check);
 EXPORT_SYMBOL(v4l2_field_names);
 EXPORT_SYMBOL(v4l2_type_names);
 EXPORT_SYMBOL(v4l_printk_ioctl);
-EXPORT_SYMBOL(v4l_printk_ioctl_arg);
 
 EXPORT_SYMBOL(v4l2_ctrl_next);
 EXPORT_SYMBOL(v4l2_ctrl_check);
@@ -1553,6 +998,9 @@ EXPORT_SYMBOL(v4l2_ctrl_query_menu);
 EXPORT_SYMBOL(v4l2_ctrl_query_fill);
 EXPORT_SYMBOL(v4l2_ctrl_query_fill_std);
 
+EXPORT_SYMBOL(v4l2_chip_match_i2c_client);
+EXPORT_SYMBOL(v4l2_chip_match_host);
+
 /*
  * Local variables:
  * c-basic-offset: 8
index 6504a5866849ab73d6058304d9b7dd91b9c85db7..459786ff459a97df7bd3c56e3140a29ac0282d96 100644 (file)
@@ -148,6 +148,8 @@ int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction,
        dprintk(1,"init user [0x%lx+0x%lx => %d pages]\n",
                data,size,dma->nr_pages);
 
+       dma->varea = (void *) data;
+
        down_read(&current->mm->mmap_sem);
        err = get_user_pages(current,current->mm,
                             data & PAGE_MASK, dma->nr_pages,
@@ -285,6 +287,7 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma)
 
        vfree(dma->vmalloc);
        dma->vmalloc = NULL;
+       dma->varea = NULL;
 
        if (dma->bus_addr) {
                dma->bus_addr = 0;
index a786c1f5b9601a98474f70073cb107df1ff9e0bc..011938fb7e0e6a2c48257bd4e7adc080c23c62d3 100644 (file)
@@ -1342,6 +1342,42 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
                        ret=vfd->vidioc_s_jpegcomp(file, fh, p);
                break;
        }
+       case VIDIOC_G_ENC_INDEX:
+       {
+               struct v4l2_enc_idx *p=arg;
+
+               if (!vfd->vidioc_g_enc_index)
+                       break;
+               ret=vfd->vidioc_g_enc_index(file, fh, p);
+               if (!ret)
+                       dbgarg (cmd, "entries=%d, entries_cap=%d\n",
+                                       p->entries,p->entries_cap);
+               break;
+       }
+       case VIDIOC_ENCODER_CMD:
+       {
+               struct v4l2_encoder_cmd *p=arg;
+
+               if (!vfd->vidioc_encoder_cmd)
+                       break;
+               ret=vfd->vidioc_encoder_cmd(file, fh, p);
+               if (!ret)
+                       dbgarg (cmd, "cmd=%d, flags=%d\n",
+                                       p->cmd,p->flags);
+               break;
+       }
+       case VIDIOC_TRY_ENCODER_CMD:
+       {
+               struct v4l2_encoder_cmd *p=arg;
+
+               if (!vfd->vidioc_try_encoder_cmd)
+                       break;
+               ret=vfd->vidioc_try_encoder_cmd(file, fh, p);
+               if (!ret)
+                       dbgarg (cmd, "cmd=%d, flags=%d\n",
+                                       p->cmd,p->flags);
+               break;
+       }
        case VIDIOC_G_PARM:
        {
                struct v4l2_streamparm *p=arg;
@@ -1453,6 +1489,26 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
                ret=vfd->vidioc_log_status(file, fh);
                break;
        }
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       case VIDIOC_DBG_G_REGISTER:
+       {
+               struct v4l2_register *p=arg;
+               if (!capable(CAP_SYS_ADMIN))
+                       ret=-EPERM;
+               else if (vfd->vidioc_g_register)
+                       ret=vfd->vidioc_g_register(file, fh, p);
+               break;
+       }
+       case VIDIOC_DBG_S_REGISTER:
+       {
+               struct v4l2_register *p=arg;
+               if (!capable(CAP_SYS_ADMIN))
+                       ret=-EPERM;
+               else if (vfd->vidioc_s_register)
+                       ret=vfd->vidioc_s_register(file, fh, p);
+               break;
+       }
+#endif
        } /* switch */
 
        if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
index cfb6b1f0402c0e24885f37b9ad9adcd5a22e0bd3..f7e1d19103749edcb308ee25ff45505efc87e64d 100644 (file)
@@ -145,7 +145,9 @@ struct vivi_buffer {
 
        struct vivi_fmt        *fmt;
 
+#ifdef CONFIG_VIVI_SCATTER
        struct sg_to_addr      *to_addr;
+#endif
 };
 
 struct vivi_dmaqueue {
@@ -230,6 +232,7 @@ static u8 bars[8][3] = {
 #define TSTAMP_MAX_Y TSTAMP_MIN_Y+15
 #define TSTAMP_MIN_X 64
 
+#ifdef CONFIG_VIVI_SCATTER
 static void prep_to_addr(struct sg_to_addr to_addr[],
                         struct videobuf_buffer *vb)
 {
@@ -262,14 +265,24 @@ static int get_addr_pos(int pos, int pages, struct sg_to_addr to_addr[])
 
        return (p1);
 }
+#endif
 
+#ifdef CONFIG_VIVI_SCATTER
 static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax,
                     int hmax, int line, char *timestr)
+#else
+static void gen_line(char *basep,int inipos,int wmax,
+                    int hmax, int line, char *timestr)
+#endif
 {
-       int  w,i,j,pos=inipos,pgpos,oldpg,y;
-       char *p,*s,*basep;
-       struct page *pg;
+       int  w,i,j,pos=inipos,y;
+       char *p,*s;
        u8   chr,r,g,b,color;
+#ifdef CONFIG_VIVI_SCATTER
+       int pgpos,oldpg;
+       char *basep;
+       struct page *pg;
+
        unsigned long flags;
        spinlock_t spinlock;
 
@@ -280,6 +293,7 @@ static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax,
        pg=pfn_to_page(sg_dma_address(to_addr[oldpg].sg) >> PAGE_SHIFT);
        spin_lock_irqsave(&spinlock,flags);
        basep = kmap_atomic(pg, KM_BOUNCE_READ)+to_addr[oldpg].sg->offset;
+#endif
 
        /* We will just duplicate the second pixel at the packet */
        wmax/=2;
@@ -291,6 +305,7 @@ static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax,
                b=bars[w*7/wmax][2];
 
                for (color=0;color<4;color++) {
+#ifdef CONFIG_VIVI_SCATTER
                        pgpos=get_addr_pos(pos,pages,to_addr);
                        if (pgpos!=oldpg) {
                                pg=pfn_to_page(sg_dma_address(to_addr[pgpos].sg) >> PAGE_SHIFT);
@@ -299,6 +314,9 @@ static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax,
                                oldpg=pgpos;
                        }
                        p=basep+pos-to_addr[pgpos].pos;
+#else
+                       p=basep+pos;
+#endif
 
                        switch (color) {
                                case 0:
@@ -343,6 +361,7 @@ static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax,
 
                                pos=inipos+j*2;
                                for (color=0;color<4;color++) {
+#ifdef CONFIG_VIVI_SCATTER
                                        pgpos=get_addr_pos(pos,pages,to_addr);
                                        if (pgpos!=oldpg) {
                                                pg=pfn_to_page(sg_dma_address(
@@ -356,6 +375,9 @@ static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax,
                                                oldpg=pgpos;
                                        }
                                        p=basep+pos-to_addr[pgpos].pos;
+#else
+                                       p=basep+pos;
+#endif
 
                                        y=TO_Y(r,g,b);
 
@@ -380,19 +402,27 @@ static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax,
 
 
 end:
+#ifdef CONFIG_VIVI_SCATTER
        kunmap_atomic(basep, KM_BOUNCE_READ);
        spin_unlock_irqrestore(&spinlock,flags);
-
+#else
+       return;
+#endif
 }
 static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf)
 {
        int h,pos=0;
        int hmax  = buf->vb.height;
        int wmax  = buf->vb.width;
-       struct videobuf_buffer *vb=&buf->vb;
-       struct sg_to_addr *to_addr=buf->to_addr;
        struct timeval ts;
+#ifdef CONFIG_VIVI_SCATTER
+       struct sg_to_addr *to_addr=buf->to_addr;
+       struct videobuf_buffer *vb=&buf->vb;
+#else
+       char *tmpbuf;
+#endif
 
+#ifdef CONFIG_VIVI_SCATTER
        /* Test if DMA mapping is ready */
        if (!sg_dma_address(&vb->dma.sglist[0]))
                return;
@@ -401,9 +431,28 @@ static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf)
 
        /* Check if there is enough memory */
        BUG_ON(buf->vb.dma.nr_pages << PAGE_SHIFT < (buf->vb.width*buf->vb.height)*2);
+#else
+       if (buf->vb.dma.varea) {
+               tmpbuf=kmalloc (wmax*2, GFP_KERNEL);
+       } else {
+               tmpbuf=buf->vb.dma.vmalloc;
+       }
+
+#endif
 
        for (h=0;h<hmax;h++) {
+#ifdef CONFIG_VIVI_SCATTER
                gen_line(to_addr,pos,vb->dma.nr_pages,wmax,hmax,h,dev->timestr);
+#else
+               if (buf->vb.dma.varea) {
+                       gen_line(tmpbuf,0,wmax,hmax,h,dev->timestr);
+                       /* FIXME: replacing to __copy_to_user */
+                       if (copy_to_user(buf->vb.dma.varea+pos,tmpbuf,wmax*2)!=0)
+                               dprintk(2,"vivifill copy_to_user failed.\n");
+               } else {
+                       gen_line(tmpbuf,pos,wmax,hmax,h,dev->timestr);
+               }
+#endif
                pos += wmax*2;
        }
 
@@ -429,7 +478,7 @@ static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf)
                        dev->h,dev->m,dev->s,(dev->us+500)/1000);
 
        dprintk(2,"vivifill at %s: Buffer 0x%08lx size= %d\n",dev->timestr,
-                       (unsigned long)buf->vb.dma.vmalloc,pos);
+                       (unsigned long)buf->vb.dma.varea,pos);
 
        /* Advice that buffer was filled */
        buf->vb.state = STATE_DONE;
@@ -471,11 +520,12 @@ static void vivi_thread_tick(struct vivi_dmaqueue  *dma_q)
 
                /* Fill buffer */
                vivi_fillbuff(dev,buf);
-       }
-       if (list_empty(&dma_q->active)) {
-               del_timer(&dma_q->timeout);
-       } else {
-               mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
+
+               if (list_empty(&dma_q->active)) {
+                       del_timer(&dma_q->timeout);
+               } else {
+                       mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
+               }
        }
        if (bc != 1)
                dprintk(1,"%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc);
@@ -522,6 +572,8 @@ static int vivi_thread(void *data)
 
        dprintk(1,"thread started\n");
 
+       mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
+
        for (;;) {
                vivi_sleep(dma_q);
 
@@ -538,7 +590,6 @@ static int vivi_start_thread(struct vivi_dmaqueue  *dma_q)
        dma_q->ini_jiffies=jiffies;
 
        dprintk(1,"%s\n",__FUNCTION__);
-       init_waitqueue_head(&dma_q->wq);
 
        dma_q->kthread = kthread_run(vivi_thread, dma_q, "vivi");
 
@@ -546,6 +597,9 @@ static int vivi_start_thread(struct vivi_dmaqueue  *dma_q)
                printk(KERN_ERR "vivi: kernel_thread() failed\n");
                return PTR_ERR(dma_q->kthread);
        }
+       /* Wakes thread */
+       wake_up_interruptible(&dma_q->wq);
+
        dprintk(1,"returning from %s\n",__FUNCTION__);
        return 0;
 }
@@ -663,9 +717,11 @@ static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf)
        if (in_interrupt())
                BUG();
 
+#ifdef CONFIG_VIVI_SCATTER
        /*FIXME: Maybe a spinlock is required here */
        kfree(buf->to_addr);
        buf->to_addr=NULL;
+#endif
 
        videobuf_waiton(&buf->vb,0,0);
        videobuf_dma_unmap(vq, &buf->vb.dma);
@@ -711,11 +767,12 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
 
        buf->vb.state = STATE_PREPARED;
 
+#ifdef CONFIG_VIVI_SCATTER
        if (NULL == (buf->to_addr = kmalloc(sizeof(*buf->to_addr) * vb->dma.nr_pages,GFP_KERNEL))) {
                rc=-ENOMEM;
                goto fail;
        }
-
+#endif
        return 0;
 
 fail:
@@ -780,6 +837,7 @@ static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb
        free_buffer(vq,buf);
 }
 
+#ifdef CONFIG_VIVI_SCATTER
 static int vivi_map_sg(void *dev, struct scatterlist *sg, int nents,
                       int direction)
 {
@@ -812,6 +870,7 @@ static int vivi_dma_sync_sg(void *dev,struct scatterlist *sglist, int nr_pages,
 //     flush_write_buffers();
        return 0;
 }
+#endif
 
 static struct videobuf_queue_ops vivi_video_qops = {
        .buf_setup      = buffer_setup,
@@ -820,9 +879,9 @@ static struct videobuf_queue_ops vivi_video_qops = {
        .buf_release    = buffer_release,
 
        /* Non-pci handling routines */
-       .vb_map_sg      = vivi_map_sg,
-       .vb_dma_sync_sg = vivi_dma_sync_sg,
-       .vb_unmap_sg    = vivi_unmap_sg,
+//     .vb_map_sg      = vivi_map_sg,
+//     .vb_dma_sync_sg = vivi_dma_sync_sg,
+//     .vb_unmap_sg    = vivi_unmap_sg,
 };
 
 /* ------------------------------------------------------------------
@@ -1200,11 +1259,19 @@ static int vivi_open(struct inode *inode, struct file *file)
        sprintf(dev->timestr,"%02d:%02d:%02d:%03d",
                        dev->h,dev->m,dev->s,(dev->us+500)/1000);
 
+#ifdef CONFIG_VIVI_SCATTER
+       videobuf_queue_init(&fh->vb_vidq,VIDEOBUF_DMA_SCATTER, &vivi_video_qops,
+                       NULL, NULL,
+                       fh->type,
+                       V4L2_FIELD_INTERLACED,
+                       sizeof(struct vivi_buffer),fh);
+#else
        videobuf_queue_init(&fh->vb_vidq, &vivi_video_qops,
                        NULL, NULL,
                        fh->type,
                        V4L2_FIELD_INTERLACED,
                        sizeof(struct vivi_buffer),fh);
+#endif
 
        return 0;
 }
@@ -1352,6 +1419,7 @@ static int __init vivi_init(void)
        /* init video dma queues */
        INIT_LIST_HEAD(&dev->vidq.active);
        INIT_LIST_HEAD(&dev->vidq.queued);
+       init_waitqueue_head(&dev->vidq.wq);
 
        /* initialize locks */
        init_MUTEX(&dev->lock);
index b9c93b8c16f7f8f4949d43fcbc2da5823d9bbabb..710f12eb9126a9c2a0d4638766706368c36b78ac 100644 (file)
@@ -1,7 +1,7 @@
 /***************************************************************************
- * V4L2 driver for ZC0301 Image Processor and Control Chip                 *
+ * V4L2 driver for ZC0301[P] Image Processor and Control Chip              *
  *                                                                         *
- * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
index 8da7f15f62908a52441cb3fe464c78b1186008d0..f1120551c70c2377f434c8267bd57f380c0bc79f 100644 (file)
@@ -1,7 +1,7 @@
 /***************************************************************************
  * Video4Linux2 driver for ZC0301[P] Image Processor and Control Chip      *
  *                                                                         *
- * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * Informations about the chip internals needed to enable the I2C protocol *
  * have been taken from the documentation of the ZC030x Video4Linux1       *
@@ -52,8 +52,8 @@
 #define ZC0301_MODULE_AUTHOR  "(C) 2006 Luca Risolia"
 #define ZC0301_AUTHOR_EMAIL   "<luca.risolia@studio.unibo.it>"
 #define ZC0301_MODULE_LICENSE "GPL"
-#define ZC0301_MODULE_VERSION "1:1.05"
-#define ZC0301_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 5)
+#define ZC0301_MODULE_VERSION "1:1.07"
+#define ZC0301_MODULE_VERSION_CODE  KERNEL_VERSION(1, 1, 7)
 
 /*****************************************************************************/
 
@@ -89,7 +89,7 @@ MODULE_PARM_DESC(force_munmap,
                 "\ndetected camera."
                 "\n 0 = do not force memory unmapping"
                 "\n 1 = force memory unmapping (save memory)"
-                "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
+                "\nDefault value is "__MODULE_STRING(ZC0301_FORCE_MUNMAP)"."
                 "\n");
 
 static unsigned int frame_timeout[] = {[0 ... ZC0301_MAX_DEVICES-1] =
@@ -136,7 +136,8 @@ zc0301_request_buffers(struct zc0301_device* cam, u32 count,
 
        cam->nbuffers = count;
        while (cam->nbuffers > 0) {
-               if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize))))
+               if ((buff = vmalloc_32_user(cam->nbuffers *
+                                           PAGE_ALIGN(imagesize))))
                        break;
                cam->nbuffers--;
        }
@@ -430,7 +431,8 @@ static int zc0301_start_transfer(struct zc0301_device* cam)
        struct usb_host_interface* altsetting = usb_altnum_to_altsetting(
                                                     usb_ifnum_to_if(udev, 0),
                                                     ZC0301_ALTERNATE_SETTING);
-       const unsigned int psz = altsetting->endpoint[0].desc.wMaxPacketSize;
+       const unsigned int psz = le16_to_cpu(altsetting->
+                                            endpoint[0].desc.wMaxPacketSize);
        struct urb* urb;
        s8 i, j;
        int err = 0;
@@ -489,7 +491,7 @@ static int zc0301_start_transfer(struct zc0301_device* cam)
        return 0;
 
 free_urbs:
-       for (i = 0; i < ZC0301_URBS; i++)
+       for (i = 0; (i < ZC0301_URBS) && cam->urb[i]; i++)
                usb_free_urb(cam->urb[i]);
 
 free_buffers:
@@ -1287,6 +1289,35 @@ zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg)
 }
 
 
+static int
+zc0301_vidioc_enum_framesizes(struct zc0301_device* cam, void __user * arg)
+{
+       struct v4l2_frmsizeenum frmsize;
+
+       if (copy_from_user(&frmsize, arg, sizeof(frmsize)))
+               return -EFAULT;
+
+       if (frmsize.index != 0 && frmsize.index != 1)
+               return -EINVAL;
+
+       if (frmsize.pixel_format != V4L2_PIX_FMT_JPEG)
+               return -EINVAL;
+
+       frmsize.type = V4L2_FRMSIZE_TYPE_DISCRETE;
+
+       if (frmsize.index == 1) {
+               frmsize.discrete.width = cam->sensor.cropcap.defrect.width;
+               frmsize.discrete.height = cam->sensor.cropcap.defrect.height;
+       }
+       memset(&frmsize.reserved, 0, sizeof(frmsize.reserved));
+
+       if (copy_to_user(arg, &frmsize, sizeof(frmsize)))
+               return -EFAULT;
+
+       return 0;
+}
+
+
 static int
 zc0301_vidioc_enum_fmt(struct zc0301_device* cam, void __user * arg)
 {
@@ -1295,6 +1326,9 @@ zc0301_vidioc_enum_fmt(struct zc0301_device* cam, void __user * arg)
        if (copy_from_user(&fmtd, arg, sizeof(fmtd)))
                return -EFAULT;
 
+       if (fmtd.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
        if (fmtd.index == 0) {
                strcpy(fmtd.description, "JPEG");
                fmtd.pixelformat = V4L2_PIX_FMT_JPEG;
@@ -1795,6 +1829,9 @@ static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp,
        case VIDIOC_S_FMT:
                return zc0301_vidioc_try_s_fmt(cam, cmd, arg);
 
+       case VIDIOC_ENUM_FRAMESIZES:
+               return zc0301_vidioc_enum_framesizes(cam, arg);
+
        case VIDIOC_G_JPEGCOMP:
                return zc0301_vidioc_g_jpegcomp(cam, arg);
 
@@ -1830,6 +1867,7 @@ static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp,
        case VIDIOC_QUERYSTD:
        case VIDIOC_ENUMSTD:
        case VIDIOC_QUERYMENU:
+       case VIDIOC_ENUM_FRAMEINTERVALS:
                return -EINVAL;
 
        default:
@@ -1876,6 +1914,7 @@ static const struct file_operations zc0301_fops = {
        .open =    zc0301_open,
        .release = zc0301_release,
        .ioctl =   zc0301_ioctl,
+       .compat_ioctl = v4l_compat_ioctl32,
        .read =    zc0301_read,
        .poll =    zc0301_poll,
        .mmap =    zc0301_mmap,
@@ -1913,7 +1952,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
        mutex_init(&cam->dev_mutex);
 
        DBG(2, "ZC0301[P] Image Processor and Control Chip detected "
-              "(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct);
+              "(vid/pid 0x%04X:0x%04X)",id->idVendor, id->idProduct);
 
        for  (i = 0; zc0301_sensor_table[i]; i++) {
                err = zc0301_sensor_table[i](cam);
index ecfd39a56df18814f766a46886e95e29d06cc9c7..3efb92a0d0daec8de05728ec001fa3ee1721a9d8 100644 (file)
@@ -1,8 +1,8 @@
 /***************************************************************************
- * Plug-in for PAS202BCB image sensor connected to the ZC0301[P] Image     *
+ * Plug-in for PAS202BCB image sensor connected to the ZC0301 Image        *
  * Processor and Control Chip                                              *
  *                                                                         *
- * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * Initialization values of the ZC0301[P] have been taken from the SPCA5XX *
  * driver maintained by Michel Xhaard <mxhaard@magic.fr>                   *
index ed8542e6c50f5d361bc06c5d138e2a950fad066d..5784b1d1491c8be0d9c01d0745b3f1b26b0956d1 100644 (file)
@@ -1,8 +1,8 @@
 /***************************************************************************
- * Plug-in for PB-0330 image sensor connected to the ZC0301[P] Image       *
+ * Plug-in for PB-0330 image sensor connected to the ZC0301P Image         *
  * Processor and Control Chip                                              *
  *                                                                         *
- * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * Initialization values of the ZC0301[P] have been taken from the SPCA5XX *
  * driver maintained by Michel Xhaard <mxhaard@magic.fr>                   *
index 3daf049a288aff2f60b3ab36ac1f86d9a721de99..44e82cff9319598e1ba2e4fe7f3422f86c48af25 100644 (file)
@@ -1,8 +1,8 @@
 /***************************************************************************
- * API for image sensors connected to the ZC0301 Image Processor and       *
+ * API for image sensors connected to the ZC0301[P] Image Processor and    *
  * Control Chip                                                            *
  *                                                                         *
- * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -70,7 +70,7 @@ static const struct usb_device_id zc0301_id_table[] =  {                      \
        { ZC0301_USB_DEVICE(0x041e, 0x4036, 0xff), }, /* HV7131 */            \
        { ZC0301_USB_DEVICE(0x041e, 0x403a, 0xff), }, /* HV7131 */            \
        { ZC0301_USB_DEVICE(0x0458, 0x7007, 0xff), }, /* TAS5130 */           \
-       { ZC0301_USB_DEVICE(0x0458, 0x700C, 0xff), }, /* TAS5130 */           \
+       { ZC0301_USB_DEVICE(0x0458, 0x700c, 0xff), }, /* TAS5130 */           \
        { ZC0301_USB_DEVICE(0x0458, 0x700f, 0xff), }, /* TAS5130 */           \
        { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */            \
        { ZC0301_USB_DEVICE(0x055f, 0xd003, 0xff), }, /* TAS5130 */           \
@@ -93,9 +93,9 @@ extern int zc0301_i2c_read(struct zc0301_device*, u16 address, u8 length);
 
 /*****************************************************************************/
 
-#define ZC0301_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10
-#define ZC0301_V4L2_CID_DAC_MAGNITUDE V4L2_CID_PRIVATE_BASE
-#define ZC0301_V4L2_CID_GREEN_BALANCE V4L2_CID_PRIVATE_BASE + 1
+#define ZC0301_MAX_CTRLS (V4L2_CID_LASTP1 - V4L2_CID_BASE + 10)
+#define ZC0301_V4L2_CID_DAC_MAGNITUDE (V4L2_CID_PRIVATE_BASE + 0)
+#define ZC0301_V4L2_CID_GREEN_BALANCE (V4L2_CID_PRIVATE_BASE + 1)
 
 struct zc0301_sensor {
        char name[32];
index fc3c8854f43015ca90f2c82d18be5ef1d08d4fb6..ab6e985275b28b3ae9e4addba68732deaeea7b7a 100644 (file)
@@ -2,6 +2,20 @@
 # Multifunction miscellaneous devices
 #
 
+menu "Multifunction device drivers"
+
+config MFD_SM501
+       tristate "Support for Silicon Motion SM501"
+        ---help---
+         This is the core driver for the Silicon Motion SM501 multimedia
+         companion chip. This device is a multifunction device which may
+         provide numerous interfaces including USB host controller USB gadget,
+         Asyncronous Serial ports, Audio functions and a dual display video
+         interface. The device may be connected by PCI or local bus with
+         varying functions enabled.
+
+endmenu
+
 menu "Multimedia Capabilities Port drivers"
        depends on ARCH_SA1100
 
index adb29b5368a8deb7a75758c12df7a3577e6a0648..51432091b323f9edad3fedfa0a0fad5269a9a9f9 100644 (file)
@@ -2,6 +2,8 @@
 # Makefile for multifunction miscellaneous devices
 #
 
+obj-$(CONFIG_MFD_SM501)                += sm501.o
+
 obj-$(CONFIG_MCP)              += mcp-core.o
 obj-$(CONFIG_MCP_SA11X0)       += mcp-sa11x0.o
 obj-$(CONFIG_MCP_UCB1200)      += ucb1x00-core.o
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
new file mode 100644 (file)
index 0000000..c707c8e
--- /dev/null
@@ -0,0 +1,1148 @@
+/* linux/drivers/mfd/sm501.c
+ *
+ * Copyright (C) 2006 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *     Vincent Sanders <vince@simtec.co.uk>
+ *
+ * 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.
+ *
+ * SM501 MFD driver
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/pci.h>
+
+#include <linux/sm501.h>
+#include <linux/sm501-regs.h>
+
+#include <asm/io.h>
+
+struct sm501_device {
+       struct list_head                list;
+       struct platform_device          pdev;
+};
+
+struct sm501_devdata {
+       spinlock_t                       reg_lock;
+       struct mutex                     clock_lock;
+       struct list_head                 devices;
+
+       struct device                   *dev;
+       struct resource                 *io_res;
+       struct resource                 *mem_res;
+       struct resource                 *regs_claim;
+       struct sm501_platdata           *platdata;
+
+       int                              unit_power[20];
+       unsigned int                     pdev_id;
+       unsigned int                     irq;
+       void __iomem                    *regs;
+};
+
+#define MHZ (1000 * 1000)
+
+#ifdef DEBUG
+static const unsigned int misc_div[] = {
+       [0]             = 1,
+       [1]             = 2,
+       [2]             = 4,
+       [3]             = 8,
+       [4]             = 16,
+       [5]             = 32,
+       [6]             = 64,
+       [7]             = 128,
+       [8]             = 3,
+       [9]             = 6,
+       [10]            = 12,
+       [11]            = 24,
+       [12]            = 48,
+       [13]            = 96,
+       [14]            = 192,
+       [15]            = 384,
+};
+
+static const unsigned int px_div[] = {
+       [0]             = 1,
+       [1]             = 2,
+       [2]             = 4,
+       [3]             = 8,
+       [4]             = 16,
+       [5]             = 32,
+       [6]             = 64,
+       [7]             = 128,
+       [8]             = 3,
+       [9]             = 6,
+       [10]            = 12,
+       [11]            = 24,
+       [12]            = 48,
+       [13]            = 96,
+       [14]            = 192,
+       [15]            = 384,
+       [16]            = 5,
+       [17]            = 10,
+       [18]            = 20,
+       [19]            = 40,
+       [20]            = 80,
+       [21]            = 160,
+       [22]            = 320,
+       [23]            = 604,
+};
+
+static unsigned long decode_div(unsigned long pll2, unsigned long val,
+                               unsigned int lshft, unsigned int selbit,
+                               unsigned long mask, const unsigned int *dtab)
+{
+       if (val & selbit)
+               pll2 = 288 * MHZ;
+
+       return pll2 / dtab[(val >> lshft) & mask];
+}
+
+#define fmt_freq(x) ((x) / MHZ), ((x) % MHZ), (x)
+
+/* sm501_dump_clk
+ *
+ * Print out the current clock configuration for the device
+*/
+
+static void sm501_dump_clk(struct sm501_devdata *sm)
+{
+       unsigned long misct = readl(sm->regs + SM501_MISC_TIMING);
+       unsigned long pm0 = readl(sm->regs + SM501_POWER_MODE_0_CLOCK);
+       unsigned long pm1 = readl(sm->regs + SM501_POWER_MODE_1_CLOCK);
+       unsigned long pmc = readl(sm->regs + SM501_POWER_MODE_CONTROL);
+       unsigned long sdclk0, sdclk1;
+       unsigned long pll2 = 0;
+
+       switch (misct & 0x30) {
+       case 0x00:
+               pll2 = 336 * MHZ;
+               break;
+       case 0x10:
+               pll2 = 288 * MHZ;
+               break;
+       case 0x20:
+               pll2 = 240 * MHZ;
+               break;
+       case 0x30:
+               pll2 = 192 * MHZ;
+               break;
+       }
+
+       sdclk0 = (misct & (1<<12)) ? pll2 : 288 * MHZ;
+       sdclk0 /= misc_div[((misct >> 8) & 0xf)];
+
+       sdclk1 = (misct & (1<<20)) ? pll2 : 288 * MHZ;
+       sdclk1 /= misc_div[((misct >> 16) & 0xf)];
+
+       dev_dbg(sm->dev, "MISCT=%08lx, PM0=%08lx, PM1=%08lx\n",
+               misct, pm0, pm1);
+
+       dev_dbg(sm->dev, "PLL2 = %ld.%ld MHz (%ld), SDCLK0=%08lx, SDCLK1=%08lx\n",
+               fmt_freq(pll2), sdclk0, sdclk1);
+
+       dev_dbg(sm->dev, "SDRAM: PM0=%ld, PM1=%ld\n", sdclk0, sdclk1);
+
+       dev_dbg(sm->dev, "PM0[%c]: "
+                "P2 %ld.%ld MHz (%ld), V2 %ld.%ld (%ld), "
+x               "M %ld.%ld (%ld), MX1 %ld.%ld (%ld)\n",
+                (pmc & 3 ) == 0 ? '*' : '-',
+                fmt_freq(decode_div(pll2, pm0, 24, 1<<29, 31, px_div)),
+                fmt_freq(decode_div(pll2, pm0, 16, 1<<20, 15, misc_div)),
+                fmt_freq(decode_div(pll2, pm0, 8,  1<<12, 15, misc_div)),
+                fmt_freq(decode_div(pll2, pm0, 0,  1<<4,  15, misc_div)));
+
+       dev_dbg(sm->dev, "PM1[%c]: "
+               "P2 %ld.%ld MHz (%ld), V2 %ld.%ld (%ld), "
+               "M %ld.%ld (%ld), MX1 %ld.%ld (%ld)\n",
+               (pmc & 3 ) == 1 ? '*' : '-',
+               fmt_freq(decode_div(pll2, pm1, 24, 1<<29, 31, px_div)),
+               fmt_freq(decode_div(pll2, pm1, 16, 1<<20, 15, misc_div)),
+               fmt_freq(decode_div(pll2, pm1, 8,  1<<12, 15, misc_div)),
+               fmt_freq(decode_div(pll2, pm1, 0,  1<<4,  15, misc_div)));
+}
+#else
+static void sm501_dump_clk(struct sm501_devdata *sm)
+{
+}
+#endif
+
+/* sm501_sync_regs
+ *
+ * ensure the
+*/
+
+static void sm501_sync_regs(struct sm501_devdata *sm)
+{
+       readl(sm->regs);
+}
+
+/* sm501_misc_control
+ *
+ * alters the misceleneous control parameters
+*/
+
+int sm501_misc_control(struct device *dev,
+                      unsigned long set, unsigned long clear)
+{
+       struct sm501_devdata *sm = dev_get_drvdata(dev);
+       unsigned long misc;
+       unsigned long save;
+       unsigned long to;
+
+       spin_lock_irqsave(&sm->reg_lock, save);
+
+       misc = readl(sm->regs + SM501_MISC_CONTROL);
+       to = (misc & ~clear) | set;
+
+       if (to != misc) {
+               writel(to, sm->regs + SM501_MISC_CONTROL);
+               sm501_sync_regs(sm);
+
+               dev_dbg(sm->dev, "MISC_CONTROL %08lx\n", misc);
+       }
+
+       spin_unlock_irqrestore(&sm->reg_lock, save);
+       return to;
+}
+
+EXPORT_SYMBOL_GPL(sm501_misc_control);
+
+/* sm501_modify_reg
+ *
+ * Modify a register in the SM501 which may be shared with other
+ * drivers.
+*/
+
+unsigned long sm501_modify_reg(struct device *dev,
+                              unsigned long reg,
+                              unsigned long set,
+                              unsigned long clear)
+{
+       struct sm501_devdata *sm = dev_get_drvdata(dev);
+       unsigned long data;
+       unsigned long save;
+
+       spin_lock_irqsave(&sm->reg_lock, save);
+
+       data = readl(sm->regs + reg);
+       data |= set;
+       data &= ~clear;
+
+       writel(data, sm->regs + reg);
+       sm501_sync_regs(sm);
+
+       spin_unlock_irqrestore(&sm->reg_lock, save);
+
+       return data;
+}
+
+EXPORT_SYMBOL_GPL(sm501_modify_reg);
+
+unsigned long sm501_gpio_get(struct device *dev,
+                            unsigned long gpio)
+{
+       struct sm501_devdata *sm = dev_get_drvdata(dev);
+       unsigned long result;
+       unsigned long reg;
+
+       reg = (gpio > 32) ? SM501_GPIO_DATA_HIGH : SM501_GPIO_DATA_LOW;
+       result = readl(sm->regs + reg);
+
+       result >>= (gpio & 31);
+       return result & 1UL;
+}
+
+EXPORT_SYMBOL_GPL(sm501_gpio_get);
+
+void sm501_gpio_set(struct device *dev,
+                   unsigned long gpio,
+                   unsigned int to,
+                   unsigned int dir)
+{
+       struct sm501_devdata *sm = dev_get_drvdata(dev);
+
+       unsigned long bit = 1 << (gpio & 31);
+       unsigned long base;
+       unsigned long save;
+       unsigned long val;
+
+       base = (gpio > 32) ? SM501_GPIO_DATA_HIGH : SM501_GPIO_DATA_LOW;
+       base += SM501_GPIO;
+
+       spin_lock_irqsave(&sm->reg_lock, save);
+
+       val = readl(sm->regs + base) & ~bit;
+       if (to)
+               val |= bit;
+       writel(val, sm->regs + base);
+
+       val = readl(sm->regs + SM501_GPIO_DDR_LOW) & ~bit;
+       if (dir)
+               val |= bit;
+
+       writel(val, sm->regs + SM501_GPIO_DDR_LOW);
+       sm501_sync_regs(sm);
+
+       spin_unlock_irqrestore(&sm->reg_lock, save);
+
+}
+
+EXPORT_SYMBOL_GPL(sm501_gpio_set);
+
+
+/* sm501_unit_power
+ *
+ * alters the power active gate to set specific units on or off
+ */
+
+int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to)
+{
+       struct sm501_devdata *sm = dev_get_drvdata(dev);
+       unsigned long mode;
+       unsigned long gate;
+       unsigned long clock;
+
+       mutex_lock(&sm->clock_lock);
+
+       mode = readl(sm->regs + SM501_POWER_MODE_CONTROL);
+       gate = readl(sm->regs + SM501_CURRENT_GATE);
+       clock = readl(sm->regs + SM501_CURRENT_CLOCK);
+
+       mode &= 3;              /* get current power mode */
+
+       if (unit > ARRAY_SIZE(sm->unit_power)) {
+               dev_err(dev, "%s: bad unit %d\n", __FUNCTION__, unit);
+               goto already;
+       }
+
+       dev_dbg(sm->dev, "%s: unit %d, cur %d, to %d\n", __FUNCTION__, unit,
+               sm->unit_power[unit], to);
+
+       if (to == 0 && sm->unit_power[unit] == 0) {
+               dev_err(sm->dev, "unit %d is already shutdown\n", unit);
+               goto already;
+       }
+
+       sm->unit_power[unit] += to ? 1 : -1;
+       to = sm->unit_power[unit] ? 1 : 0;
+
+       if (to) {
+               if (gate & (1 << unit))
+                       goto already;
+               gate |= (1 << unit);
+       } else {
+               if (!(gate & (1 << unit)))
+                       goto already;
+               gate &= ~(1 << unit);
+       }
+
+       switch (mode) {
+       case 1:
+               writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
+               writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
+               mode = 0;
+               break;
+       case 2:
+       case 0:
+               writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
+               writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
+               mode = 1;
+               break;
+
+       default:
+               return -1;
+       }
+
+       writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
+       sm501_sync_regs(sm);
+
+       dev_dbg(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n",
+               gate, clock, mode);
+
+       msleep(16);
+
+ already:
+       mutex_unlock(&sm->clock_lock);
+       return gate;
+}
+
+EXPORT_SYMBOL_GPL(sm501_unit_power);
+
+
+/* Perform a rounded division. */
+static long sm501fb_round_div(long num, long denom)
+{
+        /* n / d + 1 / 2 = (2n + d) / 2d */
+        return (2 * num + denom) / (2 * denom);
+}
+
+/* clock value structure. */
+struct sm501_clock {
+       unsigned long mclk;
+       int divider;
+       int shift;
+};
+
+/* sm501_select_clock
+ *
+ * selects nearest discrete clock frequency the SM501 can achive
+ *   the maximum divisor is 3 or 5
+ */
+static unsigned long sm501_select_clock(unsigned long freq,
+                                       struct sm501_clock *clock,
+                                       int max_div)
+{
+       unsigned long mclk;
+       int divider;
+       int shift;
+       long diff;
+       long best_diff = 999999999;
+
+       /* Try 288MHz and 336MHz clocks. */
+       for (mclk = 288000000; mclk <= 336000000; mclk += 48000000) {
+               /* try dividers 1 and 3 for CRT and for panel,
+                  try divider 5 for panel only.*/
+
+               for (divider = 1; divider <= max_div; divider += 2) {
+                       /* try all 8 shift values.*/
+                       for (shift = 0; shift < 8; shift++) {
+                               /* Calculate difference to requested clock */
+                               diff = sm501fb_round_div(mclk, divider << shift) - freq;
+                               if (diff < 0)
+                                       diff = -diff;
+
+                               /* If it is less than the current, use it */
+                               if (diff < best_diff) {
+                                       best_diff = diff;
+
+                                       clock->mclk = mclk;
+                                       clock->divider = divider;
+                                       clock->shift = shift;
+                               }
+                       }
+               }
+       }
+
+       /* Return best clock. */
+       return clock->mclk / (clock->divider << clock->shift);
+}
+
+/* sm501_set_clock
+ *
+ * set one of the four clock sources to the closest available frequency to
+ *  the one specified
+*/
+
+unsigned long sm501_set_clock(struct device *dev,
+                             int clksrc,
+                             unsigned long req_freq)
+{
+       struct sm501_devdata *sm = dev_get_drvdata(dev);
+       unsigned long mode = readl(sm->regs + SM501_POWER_MODE_CONTROL);
+       unsigned long gate = readl(sm->regs + SM501_CURRENT_GATE);
+       unsigned long clock = readl(sm->regs + SM501_CURRENT_CLOCK);
+       unsigned char reg;
+       unsigned long sm501_freq; /* the actual frequency acheived */
+
+       struct sm501_clock to;
+
+       /* find achivable discrete frequency and setup register value
+        * accordingly, V2XCLK, MCLK and M1XCLK are the same P2XCLK
+        * has an extra bit for the divider */
+
+       switch (clksrc) {
+       case SM501_CLOCK_P2XCLK:
+               /* This clock is divided in half so to achive the
+                * requested frequency the value must be multiplied by
+                * 2. This clock also has an additional pre divisor */
+
+               sm501_freq = (sm501_select_clock(2 * req_freq, &to, 5) / 2);
+               reg=to.shift & 0x07;/* bottom 3 bits are shift */
+               if (to.divider == 3)
+                       reg |= 0x08; /* /3 divider required */
+               else if (to.divider == 5)
+                       reg |= 0x10; /* /5 divider required */
+               if (to.mclk != 288000000)
+                       reg |= 0x20; /* which mclk pll is source */
+               break;
+
+       case SM501_CLOCK_V2XCLK:
+               /* This clock is divided in half so to achive the
+                * requested frequency the value must be multiplied by 2. */
+
+               sm501_freq = (sm501_select_clock(2 * req_freq, &to, 3) / 2);
+               reg=to.shift & 0x07;    /* bottom 3 bits are shift */
+               if (to.divider == 3)
+                       reg |= 0x08;    /* /3 divider required */
+               if (to.mclk != 288000000)
+                       reg |= 0x10;    /* which mclk pll is source */
+               break;
+
+       case SM501_CLOCK_MCLK:
+       case SM501_CLOCK_M1XCLK:
+               /* These clocks are the same and not further divided */
+
+               sm501_freq = sm501_select_clock( req_freq, &to, 3);
+               reg=to.shift & 0x07;    /* bottom 3 bits are shift */
+               if (to.divider == 3)
+                       reg |= 0x08;    /* /3 divider required */
+               if (to.mclk != 288000000)
+                       reg |= 0x10;    /* which mclk pll is source */
+               break;
+
+       default:
+               return 0; /* this is bad */
+       }
+
+       mutex_lock(&sm->clock_lock);
+
+       mode = readl(sm->regs + SM501_POWER_MODE_CONTROL);
+       gate = readl(sm->regs + SM501_CURRENT_GATE);
+       clock = readl(sm->regs + SM501_CURRENT_CLOCK);
+
+       clock = clock & ~(0xFF << clksrc);
+       clock |= reg<<clksrc;
+
+       mode &= 3;      /* find current mode */
+
+       switch (mode) {
+       case 1:
+               writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
+               writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
+               mode = 0;
+               break;
+       case 2:
+       case 0:
+               writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
+               writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
+               mode = 1;
+               break;
+
+       default:
+               mutex_unlock(&sm->clock_lock);
+               return -1;
+       }
+
+       writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
+       sm501_sync_regs(sm);
+
+       dev_info(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n",
+                gate, clock, mode);
+
+       msleep(16);
+       mutex_unlock(&sm->clock_lock);
+
+       sm501_dump_clk(sm);
+
+       return sm501_freq;
+}
+
+EXPORT_SYMBOL_GPL(sm501_set_clock);
+
+/* sm501_find_clock
+ *
+ * finds the closest available frequency for a given clock
+*/
+
+unsigned long sm501_find_clock(int clksrc,
+                              unsigned long req_freq)
+{
+       unsigned long sm501_freq; /* the frequency achiveable by the 501 */
+       struct sm501_clock to;
+
+       switch (clksrc) {
+       case SM501_CLOCK_P2XCLK:
+               sm501_freq = (sm501_select_clock(2 * req_freq, &to, 5) / 2);
+               break;
+
+       case SM501_CLOCK_V2XCLK:
+               sm501_freq = (sm501_select_clock(2 * req_freq, &to, 3) / 2);
+               break;
+
+       case SM501_CLOCK_MCLK:
+       case SM501_CLOCK_M1XCLK:
+               sm501_freq = sm501_select_clock(req_freq, &to, 3);
+               break;
+
+       default:
+               sm501_freq = 0;         /* error */
+       }
+
+       return sm501_freq;
+}
+
+EXPORT_SYMBOL_GPL(sm501_find_clock);
+
+static struct sm501_device *to_sm_device(struct platform_device *pdev)
+{
+       return container_of(pdev, struct sm501_device, pdev);
+}
+
+/* sm501_device_release
+ *
+ * A release function for the platform devices we create to allow us to
+ * free any items we allocated
+*/
+
+static void sm501_device_release(struct device *dev)
+{
+       kfree(to_sm_device(to_platform_device(dev)));
+}
+
+/* sm501_create_subdev
+ *
+ * Create a skeleton platform device with resources for passing to a
+ * sub-driver
+*/
+
+static struct platform_device *
+sm501_create_subdev(struct sm501_devdata *sm,
+                   char *name, unsigned int res_count)
+{
+       struct sm501_device *smdev;
+
+       smdev = kzalloc(sizeof(struct sm501_device) +
+                       sizeof(struct resource) * res_count, GFP_KERNEL);
+       if (!smdev)
+               return NULL;
+
+       smdev->pdev.dev.release = sm501_device_release;
+
+       smdev->pdev.name = name;
+       smdev->pdev.id = sm->pdev_id;
+       smdev->pdev.resource = (struct resource *)(smdev+1);
+       smdev->pdev.num_resources = res_count;
+
+       smdev->pdev.dev.parent = sm->dev;
+
+       return &smdev->pdev;
+}
+
+/* sm501_register_device
+ *
+ * Register a platform device created with sm501_create_subdev()
+*/
+
+static int sm501_register_device(struct sm501_devdata *sm,
+                                struct platform_device *pdev)
+{
+       struct sm501_device *smdev = to_sm_device(pdev);
+       int ptr;
+       int ret;
+
+       for (ptr = 0; ptr < pdev->num_resources; ptr++) {
+               printk("%s[%d] flags %08lx: %08llx..%08llx\n",
+                      pdev->name, ptr,
+                      pdev->resource[ptr].flags,
+                      (unsigned long long)pdev->resource[ptr].start,
+                      (unsigned long long)pdev->resource[ptr].end);
+       }
+
+       ret = platform_device_register(pdev);
+
+       if (ret >= 0) {
+               dev_dbg(sm->dev, "registered %s\n", pdev->name);
+               list_add_tail(&smdev->list, &sm->devices);
+       } else
+               dev_err(sm->dev, "error registering %s (%d)\n",
+                       pdev->name, ret);
+
+       return ret;
+}
+
+/* sm501_create_subio
+ *
+ * Fill in an IO resource for a sub device
+*/
+
+static void sm501_create_subio(struct sm501_devdata *sm,
+                              struct resource *res,
+                              resource_size_t offs,
+                              resource_size_t size)
+{
+       res->flags = IORESOURCE_MEM;
+       res->parent = sm->io_res;
+       res->start = sm->io_res->start + offs;
+       res->end = res->start + size - 1;
+}
+
+/* sm501_create_mem
+ *
+ * Fill in an MEM resource for a sub device
+*/
+
+static void sm501_create_mem(struct sm501_devdata *sm,
+                            struct resource *res,
+                            resource_size_t *offs,
+                            resource_size_t size)
+{
+       *offs -= size;          /* adjust memory size */
+
+       res->flags = IORESOURCE_MEM;
+       res->parent = sm->mem_res;
+       res->start = sm->mem_res->start + *offs;
+       res->end = res->start + size - 1;
+}
+
+/* sm501_create_irq
+ *
+ * Fill in an IRQ resource for a sub device
+*/
+
+static void sm501_create_irq(struct sm501_devdata *sm,
+                            struct resource *res)
+{
+       res->flags = IORESOURCE_IRQ;
+       res->parent = NULL;
+       res->start = res->end = sm->irq;
+}
+
+static int sm501_register_usbhost(struct sm501_devdata *sm,
+                                 resource_size_t *mem_avail)
+{
+       struct platform_device *pdev;
+
+       pdev = sm501_create_subdev(sm, "sm501-usb", 3);
+       if (!pdev)
+               return -ENOMEM;
+
+       sm501_create_subio(sm, &pdev->resource[0], 0x40000, 0x20000);
+       sm501_create_mem(sm, &pdev->resource[1], mem_avail, 256*1024);
+       sm501_create_irq(sm, &pdev->resource[2]);
+
+       return sm501_register_device(sm, pdev);
+}
+
+static int sm501_register_display(struct sm501_devdata *sm,
+                                 resource_size_t *mem_avail)
+{
+       struct platform_device *pdev;
+
+       pdev = sm501_create_subdev(sm, "sm501-fb", 4);
+       if (!pdev)
+               return -ENOMEM;
+
+       sm501_create_subio(sm, &pdev->resource[0], 0x80000, 0x10000);
+       sm501_create_subio(sm, &pdev->resource[1], 0x100000, 0x50000);
+       sm501_create_mem(sm, &pdev->resource[2], mem_avail, *mem_avail);
+       sm501_create_irq(sm, &pdev->resource[3]);
+
+       return sm501_register_device(sm, pdev);
+}
+
+/* sm501_dbg_regs
+ *
+ * Debug attribute to attach to parent device to show core registers
+*/
+
+static ssize_t sm501_dbg_regs(struct device *dev,
+                             struct device_attribute *attr, char *buff)
+{
+       struct sm501_devdata *sm = dev_get_drvdata(dev) ;
+       unsigned int reg;
+       char *ptr = buff;
+       int ret;
+
+       for (reg = 0x00; reg < 0x70; reg += 4) {
+               ret = sprintf(ptr, "%08x = %08x\n",
+                             reg, readl(sm->regs + reg));
+               ptr += ret;
+       }
+
+       return ptr - buff;
+}
+
+
+static DEVICE_ATTR(dbg_regs, 0666, sm501_dbg_regs, NULL);
+
+/* sm501_init_reg
+ *
+ * Helper function for the init code to setup a register
+*/
+
+static inline void sm501_init_reg(struct sm501_devdata *sm,
+                                 unsigned long reg,
+                                 struct sm501_reg_init *r)
+{
+       unsigned long tmp;
+
+       tmp = readl(sm->regs + reg);
+       tmp |= r->set;
+       tmp &= ~r->mask;
+       writel(tmp, sm->regs + reg);
+}
+
+/* sm501_init_regs
+ *
+ * Setup core register values
+*/
+
+static void sm501_init_regs(struct sm501_devdata *sm,
+                           struct sm501_initdata *init)
+{
+       sm501_misc_control(sm->dev,
+                          init->misc_control.set,
+                          init->misc_control.mask);
+
+       sm501_init_reg(sm, SM501_MISC_TIMING, &init->misc_timing);
+       sm501_init_reg(sm, SM501_GPIO31_0_CONTROL, &init->gpio_low);
+       sm501_init_reg(sm, SM501_GPIO63_32_CONTROL, &init->gpio_high);
+
+       if (init->mclk) {
+               dev_info(sm->dev, "setting MCLK to %ld\n", init->mclk);
+               sm501_set_clock(sm->dev, SM501_CLOCK_MCLK, init->mclk);
+       }
+
+       if (init->m1xclk) {
+               dev_info(sm->dev, "setting M1XCLK to %ld\n", init->m1xclk);
+               sm501_set_clock(sm->dev, SM501_CLOCK_M1XCLK, init->m1xclk);
+       }
+}
+
+static unsigned int sm501_mem_local[] = {
+       [0]     = 4*1024*1024,
+       [1]     = 8*1024*1024,
+       [2]     = 16*1024*1024,
+       [3]     = 32*1024*1024,
+       [4]     = 64*1024*1024,
+       [5]     = 2*1024*1024,
+};
+
+/* sm501_init_dev
+ *
+ * Common init code for an SM501
+*/
+
+static int sm501_init_dev(struct sm501_devdata *sm)
+{
+       resource_size_t mem_avail;
+       unsigned long dramctrl;
+       int ret;
+
+       mutex_init(&sm->clock_lock);
+       spin_lock_init(&sm->reg_lock);
+
+       INIT_LIST_HEAD(&sm->devices);
+
+       dramctrl = readl(sm->regs + SM501_DRAM_CONTROL);
+
+       mem_avail = sm501_mem_local[(dramctrl >> 13) & 0x7];
+
+       dev_info(sm->dev, "SM501 At %p: Version %08x, %ld Mb, IRQ %d\n",
+                sm->regs, readl(sm->regs + SM501_DEVICEID),
+                (unsigned long)mem_avail >> 20, sm->irq);
+
+       dev_info(sm->dev, "CurrentGate      %08x\n", readl(sm->regs+0x38));
+       dev_info(sm->dev, "CurrentClock     %08x\n", readl(sm->regs+0x3c));
+       dev_info(sm->dev, "PowerModeControl %08x\n", readl(sm->regs+0x54));
+
+       ret = device_create_file(sm->dev, &dev_attr_dbg_regs);
+       if (ret)
+               dev_err(sm->dev, "failed to create debug regs file\n");
+
+       sm501_dump_clk(sm);
+
+       /* check to see if we have some device initialisation */
+
+       if (sm->platdata) {
+               struct sm501_platdata *pdata = sm->platdata;
+
+               if (pdata->init) {
+                       sm501_init_regs(sm, sm->platdata->init);
+
+                       if (pdata->init->devices & SM501_USE_USB_HOST)
+                               sm501_register_usbhost(sm, &mem_avail);
+               }
+       }
+
+       /* always create a framebuffer */
+       sm501_register_display(sm, &mem_avail);
+
+       return 0;
+}
+
+static int sm501_plat_probe(struct platform_device *dev)
+{
+       struct sm501_devdata *sm;
+       int err;
+
+       sm = kzalloc(sizeof(struct sm501_devdata), GFP_KERNEL);
+       if (sm == NULL) {
+               dev_err(&dev->dev, "no memory for device data\n");
+               err = -ENOMEM;
+               goto err1;
+       }
+
+       sm->dev = &dev->dev;
+       sm->pdev_id = dev->id;
+       sm->irq = platform_get_irq(dev, 0);
+       sm->io_res = platform_get_resource(dev, IORESOURCE_MEM, 1);
+       sm->mem_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+       sm->platdata = dev->dev.platform_data;
+
+       if (sm->irq < 0) {
+               dev_err(&dev->dev, "failed to get irq resource\n");
+               err = sm->irq;
+               goto err_res;
+       }
+
+       if (sm->io_res == NULL || sm->mem_res == NULL) {
+               dev_err(&dev->dev, "failed to get IO resource\n");
+               err = -ENOENT;
+               goto err_res;
+       }
+
+       sm->regs_claim = request_mem_region(sm->io_res->start,
+                                           0x100, "sm501");
+
+       if (sm->regs_claim == NULL) {
+               dev_err(&dev->dev, "cannot claim registers\n");
+               err= -EBUSY;
+               goto err_res;
+       }
+
+       platform_set_drvdata(dev, sm);
+
+       sm->regs = ioremap(sm->io_res->start,
+                          (sm->io_res->end - sm->io_res->start) - 1);
+
+       if (sm->regs == NULL) {
+               dev_err(&dev->dev, "cannot remap registers\n");
+               err = -EIO;
+               goto err_claim;
+       }
+
+       return sm501_init_dev(sm);
+
+ err_claim:
+       release_resource(sm->regs_claim);
+       kfree(sm->regs_claim);
+ err_res:
+       kfree(sm);
+ err1:
+       return err;
+
+}
+
+/* Initialisation data for PCI devices */
+
+static struct sm501_initdata sm501_pci_initdata = {
+       .gpio_high      = {
+               .set    = 0x3F000000,           /* 24bit panel */
+               .mask   = 0x0,
+       },
+       .misc_timing    = {
+               .set    = 0x010100,             /* SDRAM timing */
+               .mask   = 0x1F1F00,
+       },
+       .misc_control   = {
+               .set    = SM501_MISC_PNL_24BIT,
+               .mask   = 0,
+       },
+
+       .devices        = SM501_USE_ALL,
+       .mclk           = 100 * MHZ,
+       .m1xclk         = 160 * MHZ,
+};
+
+static struct sm501_platdata_fbsub sm501_pdata_fbsub = {
+       .flags          = (SM501FB_FLAG_USE_INIT_MODE |
+                          SM501FB_FLAG_USE_HWCURSOR |
+                          SM501FB_FLAG_USE_HWACCEL |
+                          SM501FB_FLAG_DISABLE_AT_EXIT),
+};
+
+static struct sm501_platdata_fb sm501_fb_pdata = {
+       .fb_route       = SM501_FB_OWN,
+       .fb_crt         = &sm501_pdata_fbsub,
+       .fb_pnl         = &sm501_pdata_fbsub,
+};
+
+static struct sm501_platdata sm501_pci_platdata = {
+       .init           = &sm501_pci_initdata,
+       .fb             = &sm501_fb_pdata,
+};
+
+static int sm501_pci_probe(struct pci_dev *dev,
+                          const struct pci_device_id *id)
+{
+       struct sm501_devdata *sm;
+       int err;
+
+       sm = kzalloc(sizeof(struct sm501_devdata), GFP_KERNEL);
+       if (sm == NULL) {
+               dev_err(&dev->dev, "no memory for device data\n");
+               err = -ENOMEM;
+               goto err1;
+       }
+
+       /* set a default set of platform data */
+       dev->dev.platform_data = sm->platdata = &sm501_pci_platdata;
+
+       /* set a hopefully unique id for our child platform devices */
+       sm->pdev_id = 32 + dev->devfn;
+
+       pci_set_drvdata(dev, sm);
+
+       err = pci_enable_device(dev);
+       if (err) {
+               dev_err(&dev->dev, "cannot enable device\n");
+               goto err2;
+       }
+
+       sm->dev = &dev->dev;
+       sm->irq = dev->irq;
+
+#ifdef __BIG_ENDIAN
+       /* if the system is big-endian, we most probably have a
+        * translation in the IO layer making the PCI bus little endian
+        * so make the framebuffer swapped pixels */
+
+       sm501_fb_pdata.flags |= SM501_FBPD_SWAP_FB_ENDIAN;
+#endif
+
+       /* check our resources */
+
+       if (!(pci_resource_flags(dev, 0) & IORESOURCE_MEM)) {
+               dev_err(&dev->dev, "region #0 is not memory?\n");
+               err = -EINVAL;
+               goto err3;
+       }
+
+       if (!(pci_resource_flags(dev, 1) & IORESOURCE_MEM)) {
+               dev_err(&dev->dev, "region #1 is not memory?\n");
+               err = -EINVAL;
+               goto err3;
+       }
+
+       /* make our resources ready for sharing */
+
+       sm->io_res = &dev->resource[1];
+       sm->mem_res = &dev->resource[0];
+
+       sm->regs_claim = request_mem_region(sm->io_res->start,
+                                           0x100, "sm501");
+       if (sm->regs_claim == NULL) {
+               dev_err(&dev->dev, "cannot claim registers\n");
+               err= -EBUSY;
+               goto err3;
+       }
+
+       sm->regs = ioremap(pci_resource_start(dev, 1),
+                          pci_resource_len(dev, 1));
+
+       if (sm->regs == NULL) {
+               dev_err(&dev->dev, "cannot remap registers\n");
+               err = -EIO;
+               goto err4;
+       }
+
+       sm501_init_dev(sm);
+       return 0;
+
+ err4:
+       release_resource(sm->regs_claim);
+       kfree(sm->regs_claim);
+ err3:
+       pci_disable_device(dev);
+ err2:
+       pci_set_drvdata(dev, NULL);
+       kfree(sm);
+ err1:
+       return err;
+}
+
+static void sm501_remove_sub(struct sm501_devdata *sm,
+                            struct sm501_device *smdev)
+{
+       list_del(&smdev->list);
+       platform_device_unregister(&smdev->pdev);
+}
+
+static void sm501_dev_remove(struct sm501_devdata *sm)
+{
+       struct sm501_device *smdev, *tmp;
+
+       list_for_each_entry_safe(smdev, tmp, &sm->devices, list)
+               sm501_remove_sub(sm, smdev);
+
+       device_remove_file(sm->dev, &dev_attr_dbg_regs);
+}
+
+static void sm501_pci_remove(struct pci_dev *dev)
+{
+       struct sm501_devdata *sm = pci_get_drvdata(dev);
+
+       sm501_dev_remove(sm);
+       iounmap(sm->regs);
+
+       release_resource(sm->regs_claim);
+       kfree(sm->regs_claim);
+
+       pci_set_drvdata(dev, NULL);
+       pci_disable_device(dev);
+}
+
+static int sm501_plat_remove(struct platform_device *dev)
+{
+       struct sm501_devdata *sm = platform_get_drvdata(dev);
+
+       sm501_dev_remove(sm);
+       iounmap(sm->regs);
+
+       release_resource(sm->regs_claim);
+       kfree(sm->regs_claim);
+
+       return 0;
+}
+
+static struct pci_device_id sm501_pci_tbl[] = {
+       { 0x126f, 0x0501, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+       { 0, },
+};
+
+MODULE_DEVICE_TABLE(pci, sm501_pci_tbl);
+
+static struct pci_driver sm501_pci_drv = {
+       .name           = "sm501",
+       .id_table       = sm501_pci_tbl,
+       .probe          = sm501_pci_probe,
+       .remove         = sm501_pci_remove,
+};
+
+static struct platform_driver sm501_plat_drv = {
+       .driver         = {
+               .name   = "sm501",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = sm501_plat_probe,
+       .remove         = sm501_plat_remove,
+};
+
+static int __init sm501_base_init(void)
+{
+       platform_driver_register(&sm501_plat_drv);
+       return pci_register_driver(&sm501_pci_drv);
+}
+
+static void __exit sm501_base_exit(void)
+{
+       platform_driver_unregister(&sm501_plat_drv);
+       pci_unregister_driver(&sm501_pci_drv);
+}
+
+module_init(sm501_base_init);
+module_exit(sm501_base_exit);
+
+MODULE_DESCRIPTION("SM501 Core Driver");
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>, Vincent Sanders");
+MODULE_LICENSE("GPL v2");
index e4e2b707a3531f0ae8371ac7f730ce27917f65ee..4b232124a1abb0dea3b9e737062250e3988b968c 100644 (file)
@@ -195,11 +195,9 @@ static struct backlight_device *asus_backlight_device;
  */
 static int read_brightness(struct backlight_device *bd);
 static int update_bl_status(struct backlight_device *bd);
-static struct backlight_properties asusbl_data = {
-       .owner = THIS_MODULE,
+static struct backlight_ops asusbl_ops = {
        .get_brightness = read_brightness,
        .update_status = update_bl_status,
-       .max_brightness = 15,
 };
 
 /* These functions actually update the LED's, and are called from a
@@ -213,7 +211,7 @@ static struct workqueue_struct *led_workqueue;
                                     enum led_brightness value);        \
        static void object##_led_update(struct work_struct *ignored);   \
        static int object##_led_wk;                                     \
-       DECLARE_WORK(object##_led_work, object##_led_update);           \
+       static DECLARE_WORK(object##_led_work, object##_led_update);    \
        static struct led_classdev object##_led = {                     \
                .name           = "asus:" ledname,                      \
                .brightness_set = object##_led_set,                     \
@@ -349,13 +347,8 @@ static void lcd_blank(int blank)
        struct backlight_device *bd = asus_backlight_device;
 
        if (bd) {
-               down(&bd->sem);
-               if (likely(bd->props)) {
-                       bd->props->power = blank;
-                       if (likely(bd->props->update_status))
-                               bd->props->update_status(bd);
-               }
-               up(&bd->sem);
+               bd->props.power = blank;
+               backlight_update_status(bd);
        }
 }
 
@@ -387,13 +380,13 @@ static int set_brightness(struct backlight_device *bd, int value)
 static int update_bl_status(struct backlight_device *bd)
 {
        int rv;
-       int value = bd->props->brightness;
+       int value = bd->props.brightness;
 
        rv = set_brightness(bd, value);
        if (rv)
                return rv;
 
-       value = (bd->props->power == FB_BLANK_UNBLANK) ? 1 : 0;
+       value = (bd->props.power == FB_BLANK_UNBLANK) ? 1 : 0;
        return set_lcd_state(value);
 }
 
@@ -1019,7 +1012,7 @@ static int asus_backlight_init(struct device *dev)
 
        if (brightness_set_handle && lcd_switch_handle) {
                bd = backlight_device_register(ASUS_HOTK_FILE, dev,
-                                              NULL, &asusbl_data);
+                                              NULL, &asusbl_ops);
                if (IS_ERR(bd)) {
                        printk(ASUS_ERR
                               "Could not register asus backlight device\n");
@@ -1029,14 +1022,10 @@ static int asus_backlight_init(struct device *dev)
 
                asus_backlight_device = bd;
 
-               down(&bd->sem);
-               if (likely(bd->props)) {
-                       bd->props->brightness = read_brightness(NULL);
-                       bd->props->power = FB_BLANK_UNBLANK;
-                       if (likely(bd->props->update_status))
-                               bd->props->update_status(bd);
-               }
-               up(&bd->sem);
+               bd->props.max_brightness = 15;
+               bd->props.brightness = read_brightness(NULL);
+               bd->props.power = FB_BLANK_UNBLANK;
+               backlight_update_status(bd);
        }
        return 0;
 }
index 8e5e07e4c1cf6b91219148ad82bf10f1469fe3e6..68c4b58525ba615b8450ff57d979099d67892a9a 100644 (file)
@@ -157,14 +157,12 @@ static int bl_get_brightness(struct backlight_device *b)
 
 static int bl_update_status(struct backlight_device *b)
 {
-       return set_lcd_level(b->props->brightness);
+       return set_lcd_level(b->props.brightness);
 }
 
-static struct backlight_properties msibl_props = {
-       .owner          = THIS_MODULE,
+static struct backlight_ops msibl_ops = {
        .get_brightness = bl_get_brightness,
        .update_status  = bl_update_status,
-       .max_brightness = MSI_LCD_LEVEL_MAX-1,
 };
 
 static struct backlight_device *msibl_device;
@@ -318,10 +316,12 @@ static int __init msi_init(void)
        /* Register backlight stuff */
 
        msibl_device = backlight_device_register("msi-laptop-bl", NULL, NULL,
-                                               &msibl_props);
+                                               &msibl_ops);
        if (IS_ERR(msibl_device))
                return PTR_ERR(msibl_device);
 
+       msibl_device->props.max_brightness = MSI_LCD_LEVEL_MAX-1,
+
        ret = platform_driver_register(&msipf_driver);
        if (ret)
                goto fail_backlight;
index cabbed0015e4eaef8369d11159afd3e44918bec1..ac708bc2f9f3ce3bf158c74cf376072d7ac8726b 100644 (file)
@@ -384,7 +384,7 @@ static void sony_snc_pf_remove(void)
 static int sony_backlight_update_status(struct backlight_device *bd)
 {
        return acpi_callsetfunc(sony_acpi_handle, "SBRT",
-                               bd->props->brightness + 1, NULL);
+                               bd->props.brightness + 1, NULL);
 }
 
 static int sony_backlight_get_brightness(struct backlight_device *bd)
@@ -398,11 +398,9 @@ static int sony_backlight_get_brightness(struct backlight_device *bd)
 }
 
 static struct backlight_device *sony_backlight_device;
-static struct backlight_properties sony_backlight_properties = {
-       .owner = THIS_MODULE,
+static struct backlight_ops sony_backlight_ops = {
        .update_status = sony_backlight_update_status,
        .get_brightness = sony_backlight_get_brightness,
-       .max_brightness = SONY_MAX_BRIGHTNESS - 1,
 };
 
 /*
@@ -455,7 +453,7 @@ static int sony_acpi_resume(struct acpi_device *device)
 static int sony_acpi_add(struct acpi_device *device)
 {
        acpi_status status;
-       int result;
+       int result = 0;
        acpi_handle handle;
 
        sony_acpi_acpi_device = device;
@@ -484,15 +482,19 @@ static int sony_acpi_add(struct acpi_device *device)
        if (ACPI_SUCCESS(acpi_get_handle(sony_acpi_handle, "GBRT", &handle))) {
                sony_backlight_device = backlight_device_register("sony", NULL,
                                                                  NULL,
-                                                                 &sony_backlight_properties);
+                                                                 &sony_backlight_ops);
 
                if (IS_ERR(sony_backlight_device)) {
                        printk(LOG_PFX "unable to register backlight device\n");
                        sony_backlight_device = NULL;
-               } else
-                       sony_backlight_properties.brightness =
+               } else {
+                       sony_backlight_device->props.brightness =
                            sony_backlight_get_brightness
                            (sony_backlight_device);
+                       sony_backlight_device->props.max_brightness = 
+                           SONY_MAX_BRIGHTNESS - 1;
+               }
+
        }
 
        if (sony_snc_pf_add())
index 5046a1661342f2e13ac8417c14ed697163368390..4a73e8b2428d8e3d61f21c1bcc990aa23ce4f976 100644 (file)
@@ -376,10 +376,11 @@ static inline void mmc_set_ios(struct mmc_host *host)
 {
        struct mmc_ios *ios = &host->ios;
 
-       pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n",
+       pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u "
+               "width %u timing %u\n",
                 mmc_hostname(host), ios->clock, ios->bus_mode,
                 ios->power_mode, ios->chip_select, ios->vdd,
-                ios->bus_width);
+                ios->bus_width, ios->timing);
 
        host->ops->set_ios(host, ios);
 }
@@ -809,6 +810,7 @@ static void mmc_power_up(struct mmc_host *host)
        host->ios.chip_select = MMC_CS_DONTCARE;
        host->ios.power_mode = MMC_POWER_UP;
        host->ios.bus_width = MMC_BUS_WIDTH_1;
+       host->ios.timing = MMC_TIMING_LEGACY;
        mmc_set_ios(host);
 
        mmc_delay(1);
@@ -828,6 +830,7 @@ static void mmc_power_off(struct mmc_host *host)
        host->ios.chip_select = MMC_CS_DONTCARE;
        host->ios.power_mode = MMC_POWER_OFF;
        host->ios.bus_width = MMC_BUS_WIDTH_1;
+       host->ios.timing = MMC_TIMING_LEGACY;
        mmc_set_ios(host);
 }
 
@@ -1112,46 +1115,50 @@ static void mmc_process_ext_csds(struct mmc_host *host)
                        continue;
                }
 
-               /* Activate highspeed support. */
-               cmd.opcode = MMC_SWITCH;
-               cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
-                         (EXT_CSD_HS_TIMING << 16) |
-                         (1 << 8) |
-                         EXT_CSD_CMD_SET_NORMAL;
-               cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
+               if (host->caps & MMC_CAP_MMC_HIGHSPEED) {
+                       /* Activate highspeed support. */
+                       cmd.opcode = MMC_SWITCH;
+                       cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+                                 (EXT_CSD_HS_TIMING << 16) |
+                                 (1 << 8) |
+                                 EXT_CSD_CMD_SET_NORMAL;
+                       cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
 
-               err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-               if (err != MMC_ERR_NONE) {
-                       printk("%s: failed to switch card to mmc v4 "
-                              "high-speed mode.\n",
-                              mmc_hostname(card->host));
-                       continue;
-               }
+                       err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+                       if (err != MMC_ERR_NONE) {
+                               printk("%s: failed to switch card to mmc v4 "
+                                      "high-speed mode.\n",
+                                      mmc_hostname(card->host));
+                               continue;
+                       }
 
-               mmc_card_set_highspeed(card);
+                       mmc_card_set_highspeed(card);
 
-               /* Check for host support for wide-bus modes. */
-               if (!(host->caps & MMC_CAP_4_BIT_DATA)) {
-                       continue;
+                       host->ios.timing = MMC_TIMING_SD_HS;
+                       mmc_set_ios(host);
                }
 
-               /* Activate 4-bit support. */
-               cmd.opcode = MMC_SWITCH;
-               cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
-                         (EXT_CSD_BUS_WIDTH << 16) |
-                         (EXT_CSD_BUS_WIDTH_4 << 8) |
-                         EXT_CSD_CMD_SET_NORMAL;
-               cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
+               /* Check for host support for wide-bus modes. */
+               if (host->caps & MMC_CAP_4_BIT_DATA) {
+                       /* Activate 4-bit support. */
+                       cmd.opcode = MMC_SWITCH;
+                       cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+                                 (EXT_CSD_BUS_WIDTH << 16) |
+                                 (EXT_CSD_BUS_WIDTH_4 << 8) |
+                                 EXT_CSD_CMD_SET_NORMAL;
+                       cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
 
-               err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-               if (err != MMC_ERR_NONE) {
-                       printk("%s: failed to switch card to "
-                              "mmc v4 4-bit bus mode.\n",
-                              mmc_hostname(card->host));
-                       continue;
-               }
+                       err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+                       if (err != MMC_ERR_NONE) {
+                               printk("%s: failed to switch card to "
+                                      "mmc v4 4-bit bus mode.\n",
+                                      mmc_hostname(card->host));
+                               continue;
+                       }
 
-               host->ios.bus_width = MMC_BUS_WIDTH_4;
+                       host->ios.bus_width = MMC_BUS_WIDTH_4;
+                       mmc_set_ios(host);
+               }
        }
 
        kfree(ext_csd);
@@ -1241,6 +1248,9 @@ static void mmc_read_switch_caps(struct mmc_host *host)
        unsigned char *status;
        struct scatterlist sg;
 
+       if (!(host->caps & MMC_CAP_SD_HIGHSPEED))
+               return;
+
        status = kmalloc(64, GFP_KERNEL);
        if (!status) {
                printk(KERN_WARNING "%s: Unable to allocate buffer for "
@@ -1332,6 +1342,9 @@ static void mmc_read_switch_caps(struct mmc_host *host)
                }
 
                mmc_card_set_highspeed(card);
+
+               host->ios.timing = MMC_TIMING_SD_HS;
+               mmc_set_ios(host);
        }
 
        kfree(status);
index 7522f76b15ec48db85c9c3091dfb4a933d2ca3ab..d749f08601b8138510d0d7e0e610e47586a1b58d 100644 (file)
@@ -606,7 +606,6 @@ static void sdhci_finish_command(struct sdhci_host *host)
 static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 {
        int div;
-       u8 ctrl;
        u16 clk;
        unsigned long timeout;
 
@@ -615,13 +614,6 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 
        writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
 
-       ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
-       if (clock > 25000000)
-               ctrl |= SDHCI_CTRL_HISPD;
-       else
-               ctrl &= ~SDHCI_CTRL_HISPD;
-       writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
-
        if (clock == 0)
                goto out;
 
@@ -761,10 +753,17 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                sdhci_set_power(host, ios->vdd);
 
        ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
+
        if (ios->bus_width == MMC_BUS_WIDTH_4)
                ctrl |= SDHCI_CTRL_4BITBUS;
        else
                ctrl &= ~SDHCI_CTRL_4BITBUS;
+
+       if (ios->timing == MMC_TIMING_SD_HS)
+               ctrl |= SDHCI_CTRL_HISPD;
+       else
+               ctrl &= ~SDHCI_CTRL_HISPD;
+
        writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
 
        mmiowb();
@@ -994,7 +993,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
 
        intmask = readl(host->ioaddr + SDHCI_INT_STATUS);
 
-       if (!intmask) {
+       if (!intmask || intmask == 0xffffffff) {
                result = IRQ_NONE;
                goto out;
        }
@@ -1080,6 +1079,13 @@ static int sdhci_suspend (struct pci_dev *pdev, pm_message_t state)
 
        pci_save_state(pdev);
        pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
+
+       for (i = 0;i < chip->num_slots;i++) {
+               if (!chip->hosts[i])
+                       continue;
+               free_irq(chip->hosts[i]->irq, chip->hosts[i]);
+       }
+
        pci_disable_device(pdev);
        pci_set_power_state(pdev, pci_choose_state(pdev, state));
 
@@ -1108,6 +1114,11 @@ static int sdhci_resume (struct pci_dev *pdev)
                        continue;
                if (chip->hosts[i]->flags & SDHCI_USE_DMA)
                        pci_set_master(pdev);
+               ret = request_irq(chip->hosts[i]->irq, sdhci_irq,
+                       IRQF_SHARED, chip->hosts[i]->slot_descr,
+                       chip->hosts[i]);
+               if (ret)
+                       return ret;
                sdhci_init(chip->hosts[i]);
                mmiowb();
                ret = mmc_resume_host(chip->hosts[i]->mmc);
@@ -1274,6 +1285,9 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
        mmc->f_max = host->max_clk;
        mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK;
 
+       if (caps & SDHCI_CAN_DO_HISPD)
+               mmc->caps |= MMC_CAP_SD_HIGHSPEED;
+
        mmc->ocr_avail = 0;
        if (caps & SDHCI_CAN_VDD_330)
                mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34;
@@ -1282,13 +1296,6 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
        if (caps & SDHCI_CAN_VDD_180)
                mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19;
 
-       if ((host->max_clk > 25000000) && !(caps & SDHCI_CAN_DO_HISPD)) {
-               printk(KERN_ERR "%s: Controller reports > 25 MHz base clock,"
-                       " but no high speed support.\n",
-                       host->slot_descr);
-               mmc->f_max = 25000000;
-       }
-
        if (mmc->ocr_avail == 0) {
                printk(KERN_ERR "%s: Hardware doesn't report any "
                        "support voltages.\n", host->slot_descr);
index e3acd398fb37910c539dfb22fb0a8921748522ff..1f6445840461a844b51b869473001171105ba8d3 100644 (file)
@@ -359,6 +359,8 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
                cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
                cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
                cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
+               cfi->chips[i].ref_point_counter = 0;
+               init_waitqueue_head(&(cfi->chips[i].wq));
        }
 
        map->fldrv = &cfi_amdstd_chipdrv;
index 69d49e0250a9a3a532ff95f9ac7ce261862e314d..b344ff858b2d7a6c220216050b6124b99e603e2f 100644 (file)
@@ -158,6 +158,8 @@ struct mtd_info *cfi_cmdset_0020(struct map_info *map, int primary)
                cfi->chips[i].word_write_time = 128;
                cfi->chips[i].buffer_write_time = 128;
                cfi->chips[i].erase_time = 1024;
+               cfi->chips[i].ref_point_counter = 0;
+               init_waitqueue_head(&(cfi->chips[i].wq));
        }
 
        return cfi_staa_setup(map);
index b1104fe1f20723a4dfaca7400efc6d0e85bdab0b..1c3b34ad732511f56c5138a0ac92d9fad2b95263 100644 (file)
@@ -402,8 +402,8 @@ static int __init init_dnpc(void)
                        ++higlvl_partition_info[i].name;
        }
 
-       printk(KERN_NOTICE "DIL/Net %s flash: 0x%lx at 0x%lx\n",
-               is_dnp ? "DNPC" : "ADNP", dnpc_map.size, dnpc_map.phys);
+       printk(KERN_NOTICE "DIL/Net %s flash: 0x%lx at 0x%llx\n",
+               is_dnp ? "DNPC" : "ADNP", dnpc_map.size, (unsigned long long)dnpc_map.phys);
 
        dnpc_map.virt = ioremap_nocache(dnpc_map.phys, dnpc_map.size);
 
index 0bc013fd66a3f08570be112bca66454bff67da9b..aa64a475278134eb3eafea4bb5cb7db40459b8da 100644 (file)
@@ -30,7 +30,7 @@
 
 #define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */
 
-#define BIOS_CNTL      0xDC
+#define BIOS_CNTL              0xDC
 #define BIOS_LOCK_ENABLE       0x02
 #define BIOS_WRITE_ENABLE      0x01
 
@@ -145,7 +145,7 @@ static void esb2rom_cleanup(struct esb2rom_window *window)
 }
 
 static int __devinit esb2rom_init_one(struct pci_dev *pdev,
-                               const struct pci_device_id *ent)
+                                     const struct pci_device_id *ent)
 {
        static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
        struct esb2rom_window *window = &esb2rom_window;
@@ -185,7 +185,7 @@ static int __devinit esb2rom_init_one(struct pci_dev *pdev,
        /* Find a region continuous to the end of the ROM window  */
        window->phys = 0;
        pci_read_config_word(pdev, FWH_DEC_EN1, &word);
-       printk(KERN_DEBUG "pci_read_config_byte : %x\n", word);
+       printk(KERN_DEBUG "pci_read_config_word : %x\n", word);
 
        if ((word & FWH_8MiB) == FWH_8MiB)
                window->phys = 0xff400000;
@@ -212,6 +212,11 @@ static int __devinit esb2rom_init_one(struct pci_dev *pdev,
        else if ((word & FWH_0_5MiB) == FWH_0_5MiB)
                window->phys = 0xfff80000;
 
+       if (window->phys == 0) {
+               printk(KERN_ERR MOD_NAME ": Rom window is closed\n");
+               goto out;
+       }
+
        /* reserved  0x0020 and 0x0010 */
        window->phys -= 0x400000UL;
        window->size = (0xffffffffUL - window->phys) + 1UL;
index 880580c44e0134186d9a3df3fd1b81731359aa2b..41844ea02462486a3e3b4eedb978debbc6f7eb62 100644 (file)
@@ -727,6 +727,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[],       /* subdevices to c
        concat->mtd.erasesize = subdev[0]->erasesize;
        concat->mtd.writesize = subdev[0]->writesize;
        concat->mtd.oobsize = subdev[0]->oobsize;
+       concat->mtd.oobavail = subdev[0]->oobavail;
        if (subdev[0]->writev)
                concat->mtd.writev = concat_writev;
        if (subdev[0]->read_oob)
index 633def3fb0875daf3a38bda7dea4cfb5d8adee77..1af989023c6644ca89c8e4107c21fcde8137904d 100644 (file)
@@ -200,6 +200,11 @@ static int part_erase (struct mtd_info *mtd, struct erase_info *instr)
                return -EINVAL;
        instr->addr += part->offset;
        ret = part->master->erase(part->master, instr);
+       if (ret) {
+               if (instr->fail_addr != 0xffffffff)
+                       instr->fail_addr -= part->offset;
+               instr->addr -= part->offset;
+       }
        return ret;
 }
 
@@ -338,6 +343,7 @@ int add_mtd_partitions(struct mtd_info *master,
                slave->mtd.size = parts[i].size;
                slave->mtd.writesize = master->writesize;
                slave->mtd.oobsize = master->oobsize;
+               slave->mtd.oobavail = master->oobavail;
                slave->mtd.subpage_sft = master->subpage_sft;
 
                slave->mtd.name = parts[i].name;
@@ -559,4 +565,3 @@ EXPORT_SYMBOL_GPL(deregister_mtd_parser);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Nicolas Pitre <nico@cam.org>");
 MODULE_DESCRIPTION("Generic support for partitioning of MTD devices");
-
index fd6bb3ed40dfb73936abf9481527915038d002a7..c328a7514510d836e843b6657e4bf1f71340389b 100644 (file)
@@ -530,7 +530,6 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
 {
        struct mtd_info *mtd;
        struct cafe_priv *cafe;
-       uint32_t timing1, timing2, timing3;
        uint32_t ctrl;
        int err = 0;
 
@@ -587,21 +586,19 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
        }
 
        if (numtimings == 3) {
-               timing1 = timing[0];
-               timing2 = timing[1];
-               timing3 = timing[2];
                cafe_dev_dbg(&cafe->pdev->dev, "Using provided timings (%08x %08x %08x)\n",
-                            timing1, timing2, timing3);
+                            timing[0], timing[1], timing[2]);
        } else {
-               timing1 = cafe_readl(cafe, NAND_TIMING1);
-               timing2 = cafe_readl(cafe, NAND_TIMING2);
-               timing3 = cafe_readl(cafe, NAND_TIMING3);
+               timing[0] = cafe_readl(cafe, NAND_TIMING1);
+               timing[1] = cafe_readl(cafe, NAND_TIMING2);
+               timing[2] = cafe_readl(cafe, NAND_TIMING3);
 
-               if (timing1 | timing2 | timing3) {
-                       cafe_dev_dbg(&cafe->pdev->dev, "Timing registers already set (%08x %08x %08x)\n", timing1, timing2, timing3);
+               if (timing[0] | timing[1] | timing[2]) {
+                       cafe_dev_dbg(&cafe->pdev->dev, "Timing registers already set (%08x %08x %08x)\n",
+                                    timing[0], timing[1], timing[2]);
                } else {
                        dev_warn(&cafe->pdev->dev, "Timing registers unset; using most conservative defaults\n");
-                       timing1 = timing2 = timing3 = 0xffffffff;
+                       timing[0] = timing[1] = timing[2] = 0xffffffff;
                }
        }
 
@@ -609,9 +606,9 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
        cafe_writel(cafe, 1, NAND_RESET);
        cafe_writel(cafe, 0, NAND_RESET);
 
-       cafe_writel(cafe, timing1, NAND_TIMING1);
-       cafe_writel(cafe, timing2, NAND_TIMING2);
-       cafe_writel(cafe, timing3, NAND_TIMING3);
+       cafe_writel(cafe, timing[0], NAND_TIMING1);
+       cafe_writel(cafe, timing[1], NAND_TIMING2);
+       cafe_writel(cafe, timing[2], NAND_TIMING3);
 
        cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
        err = request_irq(pdev->irq, &cafe_nand_interrupt, IRQF_SHARED,
index 12608c13cce5b2365c3aaf5e77f2481ec9bef241..595208f965a55cdd31f5359cd704d283785a3d34 100644 (file)
@@ -114,7 +114,7 @@ module_param(no_autopart, int, 0);
 static int show_firmware_partition = 0;
 module_param(show_firmware_partition, int, 0);
 
-#ifdef MTD_NAND_DISKONCHIP_BBTWRITE
+#ifdef CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE
 static int inftl_bbt_write = 1;
 #else
 static int inftl_bbt_write = 0;
index acaf97bc80d18f89696987db2c0370fd8cac0b76..6af37b8cff65a039d7216203e2b5b9b7750d2bf1 100644 (file)
@@ -2524,6 +2524,7 @@ int nand_scan_tail(struct mtd_info *mtd)
        for (i = 0; chip->ecc.layout->oobfree[i].length; i++)
                chip->ecc.layout->oobavail +=
                        chip->ecc.layout->oobfree[i].length;
+       mtd->oobavail = chip->ecc.layout->oobavail;
 
        /*
         * Set the number of read / write steps for one page depending on ECC
index 0ddfd6de75c52e75864c6cb6ab7d7550e45089dd..5fac4c421a20be16cad4397a08d3f0e48a84ce91 100644 (file)
@@ -473,7 +473,7 @@ static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u
        ecc_code[1] = ecc >> 8;
        ecc_code[2] = ecc >> 16;
 
-       pr_debug("%s: returning ecc %06x\n", __func__, ecc);
+       pr_debug("%s: returning ecc %06lx\n", __func__, ecc);
 
        return 0;
 }
index 7f1cb6e5dccb5b8463554cbf48e5227b66b1597d..9e14a26ca4e82ba07b4b328811f2f5f661eb1a60 100644 (file)
@@ -4,6 +4,11 @@
  *  Copyright (C) 2005-2007 Samsung Electronics
  *  Kyungmin Park <kyungmin.park@samsung.com>
  *
+ *  Credits:
+ *     Adrian Hunter <ext-adrian.hunter@nokia.com>:
+ *     auto-placement support, read-while load support, various fixes
+ *     Copyright (C) Nokia Corporation, 2007
+ *
  * 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.
@@ -831,7 +836,7 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf, int col
        int readcol = column;
        int readend = column + thislen;
        int lastgap = 0;
-       uint8_t *oob_buf = this->page_buf + mtd->writesize;
+       uint8_t *oob_buf = this->oob_buf;
 
        for (free = this->ecclayout->oobfree; free->length; ++free) {
                if (readcol >= lastgap)
@@ -849,7 +854,8 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf, int col
                        int n = ed - st;
                        memcpy(buf, oob_buf + st, n);
                        buf += n;
-               }
+               } else
+                       break;
        }
        return 0;
 }
@@ -947,9 +953,9 @@ static int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
 
 /**
  * onenand_read_oob - [MTD Interface] NAND write data and/or out-of-band
- * @mtd:       MTD device structure
- * @from:      offset to read from
- * @ops:       oob operation description structure
+ * @param mtd:         MTD device structure
+ * @param from:                offset to read from
+ * @param ops:         oob operation description structure
  */
 static int onenand_read_oob(struct mtd_info *mtd, loff_t from,
                            struct mtd_oob_ops *ops)
@@ -1017,7 +1023,7 @@ static int onenand_bbt_wait(struct mtd_info *mtd, int state)
  * onenand_bbt_read_oob - [MTD Interface] OneNAND read out-of-band for bbt scan
  * @param mtd          MTD device structure
  * @param from         offset to read from
- * @param @ops         oob operation description structure
+ * @param ops          oob operation description structure
  *
  * OneNAND read out-of-band data from the spare area for bbt scan
  */
@@ -1093,7 +1099,7 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
 static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to)
 {
        struct onenand_chip *this = mtd->priv;
-       char *readp = this->page_buf + mtd->writesize;
+       char oobbuf[64];
        int status, i;
 
        this->command(mtd, ONENAND_CMD_READOOB, to, mtd->oobsize);
@@ -1102,9 +1108,9 @@ static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to
        if (status)
                return status;
 
-       this->read_bufferram(mtd, ONENAND_SPARERAM, readp, 0, mtd->oobsize);
-       for(i = 0; i < mtd->oobsize; i++)
-               if (buf[i] != 0xFF && buf[i] != readp[i])
+       this->read_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize);
+       for (i = 0; i < mtd->oobsize; i++)
+               if (buf[i] != 0xFF && buf[i] != oobbuf[i])
                        return -EBADMSG;
 
        return 0;
@@ -1290,7 +1296,8 @@ static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf,
                        int n = ed - st;
                        memcpy(oob_buf + st, buf, n);
                        buf += n;
-               }
+               } else
+                       break;
        }
        return 0;
 }
@@ -1312,6 +1319,7 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
        struct onenand_chip *this = mtd->priv;
        int column, ret = 0, oobsize;
        int written = 0;
+       u_char *oobbuf;
 
        DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
 
@@ -1331,7 +1339,7 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
        }
 
        /* For compatibility with NAND: Do not allow write past end of page */
-       if (column + len > oobsize) {
+       if (unlikely(column + len > oobsize)) {
                printk(KERN_ERR "onenand_write_oob: "
                      "Attempt to write past end of page\n");
                return -EINVAL;
@@ -1348,6 +1356,8 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
        /* Grab the lock and see if the device is available */
        onenand_get_device(mtd, FL_WRITING);
 
+       oobbuf = this->oob_buf;
+
        /* Loop until all data write */
        while (written < len) {
                int thislen = min_t(int, oobsize, len - written);
@@ -1358,12 +1368,12 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
 
                /* We send data to spare ram with oobsize
                 * to prevent byte access */
-               memset(this->page_buf, 0xff, mtd->oobsize);
+               memset(oobbuf, 0xff, mtd->oobsize);
                if (mode == MTD_OOB_AUTO)
-                       onenand_fill_auto_oob(mtd, this->page_buf, buf, column, thislen);
+                       onenand_fill_auto_oob(mtd, oobbuf, buf, column, thislen);
                else
-                       memcpy(this->page_buf + column, buf, thislen);
-               this->write_bufferram(mtd, ONENAND_SPARERAM, this->page_buf, 0, mtd->oobsize);
+                       memcpy(oobbuf + column, buf, thislen);
+               this->write_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize);
 
                this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize);
 
@@ -1375,7 +1385,7 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
                        break;
                }
 
-               ret = onenand_verify_oob(mtd, this->page_buf, to);
+               ret = onenand_verify_oob(mtd, oobbuf, to);
                if (ret) {
                        printk(KERN_ERR "onenand_write_oob: verify failed %d\n", ret);
                        break;
@@ -1400,9 +1410,9 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
 
 /**
  * onenand_write_oob - [MTD Interface] NAND write data and/or out-of-band
- * @mtd:       MTD device structure
- * @from:      offset to read from
- * @ops:       oob operation description structure
+ * @param mtd:         MTD device structure
+ * @param to:          offset to write
+ * @param ops:         oob operation description structure
  */
 static int onenand_write_oob(struct mtd_info *mtd, loff_t to,
                             struct mtd_oob_ops *ops)
@@ -1616,6 +1626,7 @@ static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs)
  * @param mtd          MTD device structure
  * @param ofs          offset relative to mtd start
  * @param len          number of bytes to lock or unlock
+ * @param cmd          lock or unlock command
  *
  * Lock or unlock one or more blocks
  */
@@ -2117,10 +2128,11 @@ static void onenand_check_features(struct mtd_info *mtd)
 }
 
 /**
- * onenand_print_device_info - Print device ID
+ * onenand_print_device_info - Print device & version ID
  * @param device        device ID
+ * @param version      version ID
  *
- * Print device ID
+ * Print device & version ID
  */
 static void onenand_print_device_info(int device, int version)
 {
@@ -2320,15 +2332,25 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
 
        /* Allocate buffers, if necessary */
        if (!this->page_buf) {
-               size_t len;
-               len = mtd->writesize + mtd->oobsize;
-               this->page_buf = kmalloc(len, GFP_KERNEL);
+               this->page_buf = kzalloc(mtd->writesize, GFP_KERNEL);
                if (!this->page_buf) {
                        printk(KERN_ERR "onenand_scan(): Can't allocate page_buf\n");
                        return -ENOMEM;
                }
                this->options |= ONENAND_PAGEBUF_ALLOC;
        }
+       if (!this->oob_buf) {
+               this->oob_buf = kzalloc(mtd->oobsize, GFP_KERNEL);
+               if (!this->oob_buf) {
+                       printk(KERN_ERR "onenand_scan(): Can't allocate oob_buf\n");
+                       if (this->options & ONENAND_PAGEBUF_ALLOC) {
+                               this->options &= ~ONENAND_PAGEBUF_ALLOC;
+                               kfree(this->page_buf);
+                       }
+                       return -ENOMEM;
+               }
+               this->options |= ONENAND_OOBBUF_ALLOC;
+       }
 
        this->state = FL_READY;
        init_waitqueue_head(&this->wq);
@@ -2367,6 +2389,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
        for (i = 0; this->ecclayout->oobfree[i].length; i++)
                this->ecclayout->oobavail +=
                        this->ecclayout->oobfree[i].length;
+       mtd->oobavail = this->ecclayout->oobavail;
 
        mtd->ecclayout = this->ecclayout;
 
@@ -2424,9 +2447,11 @@ void onenand_release(struct mtd_info *mtd)
                kfree(bbm->bbt);
                kfree(this->bbm);
        }
-       /* Buffer allocated by onenand_scan */
+       /* Buffers allocated by onenand_scan */
        if (this->options & ONENAND_PAGEBUF_ALLOC)
                kfree(this->page_buf);
+       if (this->options & ONENAND_OOBBUF_ALLOC)
+               kfree(this->oob_buf);
 }
 
 EXPORT_SYMBOL_GPL(onenand_scan);
index 716a47210aa326676df0c2945e5cf9d5e072ae29..b406ecfa7268910d9c6c124bbf08b2e124c0df5a 100644 (file)
@@ -822,11 +822,17 @@ static int vortex_resume(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct vortex_private *vp = netdev_priv(dev);
+       int err;
 
        if (dev && vp) {
                pci_set_power_state(pdev, PCI_D0);
                pci_restore_state(pdev);
-               pci_enable_device(pdev);
+               err = pci_enable_device(pdev);
+               if (err) {
+                       printk(KERN_WARNING "%s: Could not enable device \n",
+                               dev->name);
+                       return err;
+               }
                pci_set_master(pdev);
                if (request_irq(dev->irq, vp->full_bus_master_rx ?
                                &boomerang_interrupt : &vortex_interrupt, IRQF_SHARED, dev->name, dev)) {
@@ -852,19 +858,7 @@ static struct eisa_device_id vortex_eisa_ids[] = {
 };
 MODULE_DEVICE_TABLE(eisa, vortex_eisa_ids);
 
-static int vortex_eisa_probe(struct device *device);
-static int vortex_eisa_remove(struct device *device);
-
-static struct eisa_driver vortex_eisa_driver = {
-       .id_table = vortex_eisa_ids,
-       .driver   = {
-               .name    = "3c59x",
-               .probe   = vortex_eisa_probe,
-               .remove  = vortex_eisa_remove
-       }
-};
-
-static int vortex_eisa_probe(struct device *device)
+static int __init vortex_eisa_probe(struct device *device)
 {
        void __iomem *ioaddr;
        struct eisa_device *edev;
@@ -887,7 +881,7 @@ static int vortex_eisa_probe(struct device *device)
        return 0;
 }
 
-static int vortex_eisa_remove(struct device *device)
+static int __devexit vortex_eisa_remove(struct device *device)
 {
        struct eisa_device *edev;
        struct net_device *dev;
@@ -912,7 +906,17 @@ static int vortex_eisa_remove(struct device *device)
        free_netdev(dev);
        return 0;
 }
-#endif
+
+static struct eisa_driver vortex_eisa_driver = {
+       .id_table = vortex_eisa_ids,
+       .driver   = {
+               .name    = "3c59x",
+               .probe   = vortex_eisa_probe,
+               .remove  = __devexit_p(vortex_eisa_remove)
+       }
+};
+
+#endif /* CONFIG_EISA */
 
 /* returns count found (>= 0), or negative on error */
 static int __init vortex_eisa_init(void)
index 6f93a765e56479ec9f0b598faf517468d3cd6ca0..12c8453f44bce3e337dc3a3f8d440153ee02061c 100644 (file)
@@ -448,8 +448,7 @@ static void cp_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
        spin_lock_irqsave(&cp->lock, flags);
        cp->cpcmd &= ~RxVlanOn;
        cpw16(CpCmd, cp->cpcmd);
-       if (cp->vlgrp)
-               cp->vlgrp->vlan_devices[vid] = NULL;
+       vlan_group_set_device(cp->vlgrp, vid, NULL);
        spin_unlock_irqrestore(&cp->lock, flags);
 }
 #endif /* CP_VLAN_TAG_USED */
index 35ad5cff18e65936862c20276de4468189a12568..99304b2aa86e3d70d40520a9332e9a57930d4350 100644 (file)
@@ -1109,6 +1109,8 @@ static void __devexit rtl8139_remove_one (struct pci_dev *pdev)
 
        assert (dev != NULL);
 
+       flush_scheduled_work();
+
        unregister_netdev (dev);
 
        __rtl8139_cleanup_dev (dev);
@@ -1603,18 +1605,21 @@ static void rtl8139_thread (struct work_struct *work)
        struct net_device *dev = tp->mii.dev;
        unsigned long thr_delay = next_tick;
 
+       rtnl_lock();
+
+       if (!netif_running(dev))
+               goto out_unlock;
+
        if (tp->watchdog_fired) {
                tp->watchdog_fired = 0;
                rtl8139_tx_timeout_task(work);
-       } else if (rtnl_trylock()) {
-               rtl8139_thread_iter (dev, tp, tp->mmio_addr);
-               rtnl_unlock ();
-       } else {
-               /* unlikely race.  mitigate with fast poll. */
-               thr_delay = HZ / 2;
-       }
+       } else
+               rtl8139_thread_iter(dev, tp, tp->mmio_addr);
 
-       schedule_delayed_work(&tp->thread, thr_delay);
+       if (tp->have_thread)
+               schedule_delayed_work(&tp->thread, thr_delay);
+out_unlock:
+       rtnl_unlock ();
 }
 
 static void rtl8139_start_thread(struct rtl8139_private *tp)
@@ -1626,19 +1631,11 @@ static void rtl8139_start_thread(struct rtl8139_private *tp)
                return;
 
        tp->have_thread = 1;
+       tp->watchdog_fired = 0;
 
        schedule_delayed_work(&tp->thread, next_tick);
 }
 
-static void rtl8139_stop_thread(struct rtl8139_private *tp)
-{
-       if (tp->have_thread) {
-               cancel_rearming_delayed_work(&tp->thread);
-               tp->have_thread = 0;
-       } else
-               flush_scheduled_work();
-}
-
 static inline void rtl8139_tx_clear (struct rtl8139_private *tp)
 {
        tp->cur_tx = 0;
@@ -1696,12 +1693,11 @@ static void rtl8139_tx_timeout (struct net_device *dev)
 {
        struct rtl8139_private *tp = netdev_priv(dev);
 
+       tp->watchdog_fired = 1;
        if (!tp->have_thread) {
-               INIT_DELAYED_WORK(&tp->thread, rtl8139_tx_timeout_task);
+               INIT_DELAYED_WORK(&tp->thread, rtl8139_thread);
                schedule_delayed_work(&tp->thread, next_tick);
-       } else
-               tp->watchdog_fired = 1;
-
+       }
 }
 
 static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
@@ -2233,8 +2229,6 @@ static int rtl8139_close (struct net_device *dev)
 
        netif_stop_queue (dev);
 
-       rtl8139_stop_thread(tp);
-
        if (netif_msg_ifdown(tp))
                printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n",
                        dev->name, RTL_R16 (IntrStatus));
index d9400ef87195d9ba7a114726436d21d26f9e16c7..5ff0922e628cc1a392e229e9ae8807a62d6ea4b8 100644 (file)
@@ -430,10 +430,10 @@ config HPLANCE
 
 config LASI_82596
        tristate "Lasi ethernet"
-       depends on NET_ETHERNET && PARISC && GSC_LASI
+       depends on NET_ETHERNET && GSC
        help
-         Say Y here to support the on-board Intel 82596 ethernet controller
-         built into Hewlett-Packard PA-RISC machines.
+         Say Y here to support the builtin Intel 82596 ethernet controller
+         found in Hewlett-Packard PA-RISC machines with 10Mbit ethernet.
 
 config MIPS_JAZZ_SONIC
        tristate "MIPS JAZZ onboard SONIC Ethernet support"
@@ -2245,7 +2245,7 @@ config BNX2
 
 config SPIDER_NET
        tristate "Spider Gigabit Ethernet driver"
-       depends on PCI && PPC_IBM_CELL_BLADE
+       depends on PCI && (PPC_IBM_CELL_BLADE || PPC_CELLEB)
        select FW_LOADER
        help
          This driver supports the Gigabit Ethernet chips present on the
@@ -2307,27 +2307,6 @@ config MV643XX_ETH
          chipset which is used in the Momenco Ocelot C and Jaguar ATX and
          Pegasos II, amongst other PPC and MIPS boards.
 
-config MV643XX_ETH_0
-       bool "MV-643XX Port 0"
-       depends on MV643XX_ETH
-       help
-         This enables support for Port 0 of the Marvell MV643XX Gigabit
-         Ethernet.
-
-config MV643XX_ETH_1
-       bool "MV-643XX Port 1"
-       depends on MV643XX_ETH
-       help
-         This enables support for Port 1 of the Marvell MV643XX Gigabit
-         Ethernet.
-
-config MV643XX_ETH_2
-       bool "MV-643XX Port 2"
-       depends on MV643XX_ETH
-       help
-         This enables support for Port 2 of the Marvell MV643XX Gigabit
-         Ethernet.
-
 config QLA3XXX
        tristate "QLogic QLA3XXX Network Driver Support"
        depends on PCI
index 33c6645455ae73f684a6cdfe33f8b0a1a6a6a5af..7138e0e025bca734e3d7a289e384e620fb50f659 100644 (file)
@@ -2293,10 +2293,7 @@ static void ace_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 
        local_irq_save(flags);
        ace_mask_irq(dev);
-
-       if (ap->vlgrp)
-               ap->vlgrp->vlan_devices[vid] = NULL;
-
+       vlan_group_set_device(ap->vlgrp, vid, NULL);
        ace_unmask_irq(dev);
        local_irq_restore(flags);
 }
index 9c399aaefbdd1b6b045c97fab94e28dfaef3b990..962c954c2d566e1645c6a4f9e76a96061412c38c 100644 (file)
@@ -1737,8 +1737,7 @@ static void amd8111e_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid
 {
        struct amd8111e_priv *lp = netdev_priv(dev);
        spin_lock_irq(&lp->lock);
-       if (lp->vlgrp)
-               lp->vlgrp->vlan_devices[vid] = NULL;
+       vlan_group_set_device(lp->vlgrp, vid, NULL);
        spin_unlock_irq(&lp->lock);
 }
 #endif
index 65673485bb6b35c1f1e457261a14a7740d5b9389..88d4f70035bb3c106180adf2159137691745bc9d 100644 (file)
@@ -1252,8 +1252,7 @@ static void atl1_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
 
        spin_lock_irqsave(&adapter->lock, flags);
        /* atl1_irq_disable(adapter); */
-       if (adapter->vlgrp)
-               adapter->vlgrp->vlan_devices[vid] = NULL;
+       vlan_group_set_device(adapter->vlgrp, vid, NULL);
        /* atl1_irq_enable(adapter); */
        spin_unlock_irqrestore(&adapter->lock, flags);
        /* We don't do Vlan filtering */
@@ -1266,7 +1265,7 @@ static void atl1_restore_vlan(struct atl1_adapter *adapter)
        if (adapter->vlgrp) {
                u16 vid;
                for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
-                       if (!adapter->vlgrp->vlan_devices[vid])
+                       if (!vlan_group_get_device(adapter->vlgrp, vid))
                                continue;
                        atl1_vlan_rx_add_vid(adapter->netdev, vid);
                }
index 5a96d7611af1f4dc0f573d6c12b07e5bc79787fc..c12e5ea6181967a4f80a876ed3f6f82dbb988777 100644 (file)
@@ -4467,9 +4467,7 @@ bnx2_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
        struct bnx2 *bp = netdev_priv(dev);
 
        bnx2_netif_stop(bp);
-
-       if (bp->vlgrp)
-               bp->vlgrp->vlan_devices[vid] = NULL;
+       vlan_group_set_device(bp->vlgrp, vid, NULL);
        bnx2_set_rx_mode(dev);
 
        bnx2_netif_start(bp);
index a7c8f98a890c12bae0f8e8ac1e47a9037476f01f..e4724d874e7c5cb5ee90acd72b6ebca2000bcbc3 100644 (file)
@@ -60,6 +60,7 @@
 #include <linux/errno.h>
 #include <linux/netdevice.h>
 #include <linux/inetdevice.h>
+#include <linux/igmp.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
@@ -488,9 +489,9 @@ static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid)
                        /* Save and then restore vlan_dev in the grp array,
                         * since the slave's driver might clear it.
                         */
-                       vlan_dev = bond->vlgrp->vlan_devices[vid];
+                       vlan_dev = vlan_group_get_device(bond->vlgrp, vid);
                        slave_dev->vlan_rx_kill_vid(slave_dev, vid);
-                       bond->vlgrp->vlan_devices[vid] = vlan_dev;
+                       vlan_group_set_device(bond->vlgrp, vid, vlan_dev);
                }
        }
 
@@ -550,9 +551,9 @@ static void bond_del_vlans_from_slave(struct bonding *bond, struct net_device *s
                /* Save and then restore vlan_dev in the grp array,
                 * since the slave's driver might clear it.
                 */
-               vlan_dev = bond->vlgrp->vlan_devices[vlan->vlan_id];
+               vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id);
                slave_dev->vlan_rx_kill_vid(slave_dev, vlan->vlan_id);
-               bond->vlgrp->vlan_devices[vlan->vlan_id] = vlan_dev;
+               vlan_group_set_device(bond->vlgrp, vlan->vlan_id, vlan_dev);
        }
 
 unreg:
@@ -861,6 +862,28 @@ static void bond_mc_delete(struct bonding *bond, void *addr, int alen)
        }
 }
 
+
+/*
+ * Retrieve the list of registered multicast addresses for the bonding
+ * device and retransmit an IGMP JOIN request to the current active
+ * slave.
+ */
+static void bond_resend_igmp_join_requests(struct bonding *bond)
+{
+       struct in_device *in_dev;
+       struct ip_mc_list *im;
+
+       rcu_read_lock();
+       in_dev = __in_dev_get_rcu(bond->dev);
+       if (in_dev) {
+               for (im = in_dev->mc_list; im; im = im->next) {
+                       ip_mc_rejoin_group(im);
+               }
+       }
+
+       rcu_read_unlock();
+}
+
 /*
  * Totally destroys the mc_list in bond
  */
@@ -874,6 +897,7 @@ static void bond_mc_list_destroy(struct bonding *bond)
                kfree(dmi);
                dmi = bond->mc_list;
        }
+        bond->mc_list = NULL;
 }
 
 /*
@@ -967,6 +991,7 @@ static void bond_mc_swap(struct bonding *bond, struct slave *new_active, struct
                for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next) {
                        dev_mc_add(new_active->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
                }
+               bond_resend_igmp_join_requests(bond);
        }
 }
 
@@ -2397,7 +2422,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
                vlan_id = 0;
                list_for_each_entry_safe(vlan, vlan_next, &bond->vlan_list,
                                         vlan_list) {
-                       vlan_dev = bond->vlgrp->vlan_devices[vlan->vlan_id];
+                       vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id);
                        if (vlan_dev == rt->u.dst.dev) {
                                vlan_id = vlan->vlan_id;
                                dprintk("basa: vlan match on %s %d\n",
@@ -2444,7 +2469,7 @@ static void bond_send_gratuitous_arp(struct bonding *bond)
        }
 
        list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
-               vlan_dev = bond->vlgrp->vlan_devices[vlan->vlan_id];
+               vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id);
                if (vlan->vlan_ip) {
                        bond_arp_send(slave->dev, ARPOP_REPLY, vlan->vlan_ip,
                                      vlan->vlan_ip, vlan->vlan_id);
@@ -3371,7 +3396,7 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event,
 
                list_for_each_entry_safe(vlan, vlan_next, &bond->vlan_list,
                                         vlan_list) {
-                       vlan_dev = bond->vlgrp->vlan_devices[vlan->vlan_id];
+                       vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id);
                        if (vlan_dev == event_dev) {
                                switch (event) {
                                case NETDEV_UP:
@@ -3423,15 +3448,21 @@ void bond_register_arp(struct bonding *bond)
 {
        struct packet_type *pt = &bond->arp_mon_pt;
 
+       if (pt->type)
+               return;
+
        pt->type = htons(ETH_P_ARP);
-       pt->dev = NULL; /*bond->dev;XXX*/
+       pt->dev = bond->dev;
        pt->func = bond_arp_rcv;
        dev_add_pack(pt);
 }
 
 void bond_unregister_arp(struct bonding *bond)
 {
-       dev_remove_pack(&bond->arp_mon_pt);
+       struct packet_type *pt = &bond->arp_mon_pt;
+
+       dev_remove_pack(pt);
+       pt->type = 0;
 }
 
 /*---------------------------- Hashing Policies -----------------------------*/
@@ -4011,42 +4042,6 @@ out:
        return 0;
 }
 
-static void bond_activebackup_xmit_copy(struct sk_buff *skb,
-                                        struct bonding *bond,
-                                        struct slave *slave)
-{
-       struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
-       struct ethhdr *eth_data;
-       u8 *hwaddr;
-       int res;
-
-       if (!skb2) {
-               printk(KERN_ERR DRV_NAME ": Error: "
-                      "bond_activebackup_xmit_copy(): skb_copy() failed\n");
-               return;
-       }
-
-       skb2->mac.raw = (unsigned char *)skb2->data;
-       eth_data = eth_hdr(skb2);
-
-       /* Pick an appropriate source MAC address
-        *      -- use slave's perm MAC addr, unless used by bond
-        *      -- otherwise, borrow active slave's perm MAC addr
-        *         since that will not be used
-        */
-       hwaddr = slave->perm_hwaddr;
-       if (!memcmp(eth_data->h_source, hwaddr, ETH_ALEN))
-               hwaddr = bond->curr_active_slave->perm_hwaddr;
-
-       /* Set source MAC address appropriately */
-       memcpy(eth_data->h_source, hwaddr, ETH_ALEN);
-
-       res = bond_dev_queue_xmit(bond, skb2, slave->dev);
-       if (res)
-               dev_kfree_skb(skb2);
-
-       return;
-}
 
 /*
  * in active-backup mode, we know that bond->curr_active_slave is always valid if
@@ -4067,21 +4062,6 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d
        if (!bond->curr_active_slave)
                goto out;
 
-       /* Xmit IGMP frames on all slaves to ensure rapid fail-over
-          for multicast traffic on snooping switches */
-       if (skb->protocol == __constant_htons(ETH_P_IP) &&
-           skb->nh.iph->protocol == IPPROTO_IGMP) {
-               struct slave *slave, *active_slave;
-               int i;
-
-               active_slave = bond->curr_active_slave;
-               bond_for_each_slave_from_to(bond, slave, i, active_slave->next,
-                                           active_slave->prev)
-                       if (IS_UP(slave->dev) &&
-                           (slave->link == BOND_LINK_UP))
-                               bond_activebackup_xmit_copy(skb, bond, slave);
-       }
-
        res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev);
 
 out:
index 7d0f24f697770c734701bb7c8f7a835a5d559a0b..125c9b10586920bb244970606c85cfe21025277f 100644 (file)
@@ -889,8 +889,7 @@ static void vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
        struct adapter *adapter = dev->priv;
 
        spin_lock_irq(&adapter->async_lock);
-       if (adapter->vlan_grp)
-               adapter->vlan_grp->vlan_devices[vid] = NULL;
+       vlan_group_set_device(adapter->vlan_grp, vid, NULL);
        spin_unlock_irq(&adapter->async_lock);
 }
 #endif
index 89a682702fa90a57201a7b4fe463ffa2a6287efe..326d4a6651232ea66e796e7fa083ff5979fe03e6 100644 (file)
@@ -1696,6 +1696,7 @@ irqreturn_t t1_interrupt(int irq, void *cookie)
 {
        int work_done;
        struct adapter *adapter = cookie;
+       struct respQ *Q = &adapter->sge->respQ;
 
        spin_lock(&adapter->async_lock);
 
index 5c97a64451ce3fa187fb0f4edcf5b8a8d851be00..80c3d8f268a7091edce2bd01f05174b1fc065afc 100644 (file)
@@ -74,6 +74,11 @@ enum {                               /* adapter flags */
 struct rx_desc;
 struct rx_sw_desc;
 
+struct sge_fl_page {
+       struct skb_frag_struct frag;
+       unsigned char *va;
+};
+
 struct sge_fl {                        /* SGE per free-buffer list state */
        unsigned int buf_size;  /* size of each Rx buffer */
        unsigned int credits;   /* # of available Rx buffers */
@@ -81,11 +86,13 @@ struct sge_fl {                     /* SGE per free-buffer list state */
        unsigned int cidx;      /* consumer index */
        unsigned int pidx;      /* producer index */
        unsigned int gen;       /* free list generation */
+       unsigned int cntxt_id;  /* SGE context id for the free list */
+       struct sge_fl_page page;
        struct rx_desc *desc;   /* address of HW Rx descriptor ring */
        struct rx_sw_desc *sdesc;       /* address of SW Rx descriptor ring */
        dma_addr_t phys_addr;   /* physical address of HW ring start */
-       unsigned int cntxt_id;  /* SGE context id for the free list */
        unsigned long empty;    /* # of times queue ran out of buffers */
+       unsigned long alloc_failed; /* # of times buffer allocation failed */
 };
 
 /*
@@ -121,6 +128,8 @@ struct sge_rspq {           /* state for an SGE response queue */
        unsigned long empty;    /* # of times queue ran out of credits */
        unsigned long nomem;    /* # of responses deferred due to no mem */
        unsigned long unhandled_irqs;   /* # of spurious intrs */
+       unsigned long starved;
+       unsigned long restarted;
 };
 
 struct tx_desc;
index a94281861a663dcb12f06f372b54c725aff99e16..0a82fcddf2d8a9d49b014b21a3662349464fa484 100644 (file)
  * Ioctl commands specific to this driver.
  */
 enum {
-       CHELSIO_SETREG = 1024,
-       CHELSIO_GETREG,
-       CHELSIO_SETTPI,
-       CHELSIO_GETTPI,
-       CHELSIO_GETMTUTAB,
-       CHELSIO_SETMTUTAB,
-       CHELSIO_GETMTU,
-       CHELSIO_SET_PM,
-       CHELSIO_GET_PM,
-       CHELSIO_GET_TCAM,
-       CHELSIO_SET_TCAM,
-       CHELSIO_GET_TCB,
-       CHELSIO_GET_MEM,
-       CHELSIO_LOAD_FW,
-       CHELSIO_GET_PROTO,
-       CHELSIO_SET_PROTO,
-       CHELSIO_SET_TRACE_FILTER,
-       CHELSIO_SET_QSET_PARAMS,
-       CHELSIO_GET_QSET_PARAMS,
-       CHELSIO_SET_QSET_NUM,
-       CHELSIO_GET_QSET_NUM,
-       CHELSIO_SET_PKTSCHED,
+       CHELSIO_GETMTUTAB               = 1029,
+       CHELSIO_SETMTUTAB               = 1030,
+       CHELSIO_SET_PM                  = 1032,
+       CHELSIO_GET_PM                  = 1033,
+       CHELSIO_GET_MEM                 = 1038,
+       CHELSIO_LOAD_FW                 = 1041,
+       CHELSIO_SET_TRACE_FILTER        = 1044,
+       CHELSIO_SET_QSET_PARAMS         = 1045,
+       CHELSIO_GET_QSET_PARAMS         = 1046,
+       CHELSIO_SET_QSET_NUM            = 1047,
+       CHELSIO_GET_QSET_NUM            = 1048,
 };
 
 struct ch_reg {
index 43583ed655ab8a3171b5dc9be25c26078a10a79d..7ff834e45d6bf9d035288c88829831b899591019 100644 (file)
@@ -434,27 +434,25 @@ static int setup_sge_qsets(struct adapter *adap)
 
 static ssize_t attr_show(struct device *d, struct device_attribute *attr,
                         char *buf,
-                        ssize_t(*format) (struct adapter *, char *))
+                        ssize_t(*format) (struct net_device *, char *))
 {
        ssize_t len;
-       struct adapter *adap = to_net_dev(d)->priv;
 
        /* Synchronize with ioctls that may shut down the device */
        rtnl_lock();
-       len = (*format) (adap, buf);
+       len = (*format) (to_net_dev(d), buf);
        rtnl_unlock();
        return len;
 }
 
 static ssize_t attr_store(struct device *d, struct device_attribute *attr,
                          const char *buf, size_t len,
-                         ssize_t(*set) (struct adapter *, unsigned int),
+                         ssize_t(*set) (struct net_device *, unsigned int),
                          unsigned int min_val, unsigned int max_val)
 {
        char *endp;
        ssize_t ret;
        unsigned int val;
-       struct adapter *adap = to_net_dev(d)->priv;
 
        if (!capable(CAP_NET_ADMIN))
                return -EPERM;
@@ -464,7 +462,7 @@ static ssize_t attr_store(struct device *d, struct device_attribute *attr,
                return -EINVAL;
 
        rtnl_lock();
-       ret = (*set) (adap, val);
+       ret = (*set) (to_net_dev(d), val);
        if (!ret)
                ret = len;
        rtnl_unlock();
@@ -472,8 +470,9 @@ static ssize_t attr_store(struct device *d, struct device_attribute *attr,
 }
 
 #define CXGB3_SHOW(name, val_expr) \
-static ssize_t format_##name(struct adapter *adap, char *buf) \
+static ssize_t format_##name(struct net_device *dev, char *buf) \
 { \
+       struct adapter *adap = dev->priv; \
        return sprintf(buf, "%u\n", val_expr); \
 } \
 static ssize_t show_##name(struct device *d, struct device_attribute *attr, \
@@ -482,8 +481,10 @@ static ssize_t show_##name(struct device *d, struct device_attribute *attr, \
        return attr_show(d, attr, buf, format_##name); \
 }
 
-static ssize_t set_nfilters(struct adapter *adap, unsigned int val)
+static ssize_t set_nfilters(struct net_device *dev, unsigned int val)
 {
+       struct adapter *adap = dev->priv;
+
        if (adap->flags & FULL_INIT_DONE)
                return -EBUSY;
        if (val && adap->params.rev == 0)
@@ -500,8 +501,10 @@ static ssize_t store_nfilters(struct device *d, struct device_attribute *attr,
        return attr_store(d, attr, buf, len, set_nfilters, 0, ~0);
 }
 
-static ssize_t set_nservers(struct adapter *adap, unsigned int val)
+static ssize_t set_nservers(struct net_device *dev, unsigned int val)
 {
+       struct adapter *adap = dev->priv;
+
        if (adap->flags & FULL_INIT_DONE)
                return -EBUSY;
        if (val > t3_mc5_size(&adap->mc5) - adap->params.mc5.nfilters)
@@ -1549,32 +1552,6 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
                return -EFAULT;
 
        switch (cmd) {
-       case CHELSIO_SETREG:{
-               struct ch_reg edata;
-
-               if (!capable(CAP_NET_ADMIN))
-                       return -EPERM;
-               if (copy_from_user(&edata, useraddr, sizeof(edata)))
-                       return -EFAULT;
-               if ((edata.addr & 3) != 0
-                       || edata.addr >= adapter->mmio_len)
-                       return -EINVAL;
-               writel(edata.val, adapter->regs + edata.addr);
-               break;
-       }
-       case CHELSIO_GETREG:{
-               struct ch_reg edata;
-
-               if (copy_from_user(&edata, useraddr, sizeof(edata)))
-                       return -EFAULT;
-               if ((edata.addr & 3) != 0
-                       || edata.addr >= adapter->mmio_len)
-                       return -EINVAL;
-               edata.val = readl(adapter->regs + edata.addr);
-               if (copy_to_user(useraddr, &edata, sizeof(edata)))
-                       return -EFAULT;
-               break;
-       }
        case CHELSIO_SET_QSET_PARAMS:{
                int i;
                struct qset_params *q;
@@ -1838,10 +1815,10 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
                        return -EINVAL;
 
                /*
-                       * Version scheme:
-                       * bits 0..9: chip version
-                       * bits 10..15: chip revision
-                       */
+                * Version scheme:
+                * bits 0..9: chip version
+                * bits 10..15: chip revision
+                */
                t.version = 3 | (adapter->params.rev << 10);
                if (copy_to_user(useraddr, &t, sizeof(t)))
                        return -EFAULT;
@@ -1890,20 +1867,6 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
                                                t.trace_rx);
                break;
        }
-       case CHELSIO_SET_PKTSCHED:{
-               struct ch_pktsched_params p;
-
-               if (!capable(CAP_NET_ADMIN))
-                               return -EPERM;
-               if (!adapter->open_device_map)
-                               return -EAGAIN; /* uP and SGE must be running */
-               if (copy_from_user(&p, useraddr, sizeof(p)))
-                               return -EFAULT;
-               send_pktsched_cmd(adapter, p.sched, p.idx, p.min, p.max,
-                                 p.binding);
-               break;
-                       
-       }
        default:
                return -EOPNOTSUPP;
        }
index b2cf5f6feb4a4ada3b8ab4bacd48943efdb4d9af..f6ed033efb56519cb924b790a225d642b7b8cb6d 100644 (file)
@@ -160,14 +160,16 @@ static struct net_device *get_iff_from_mac(struct adapter *adapter,
        int i;
 
        for_each_port(adapter, i) {
-               const struct vlan_group *grp;
+               struct vlan_group *grp;
                struct net_device *dev = adapter->port[i];
                const struct port_info *p = netdev_priv(dev);
 
                if (!memcmp(dev->dev_addr, mac, ETH_ALEN)) {
                        if (vlan && vlan != VLAN_VID_MASK) {
                                grp = p->vlan_grp;
-                               dev = grp ? grp->vlan_devices[vlan] : NULL;
+                               dev = NULL;
+                               if (grp)
+                                       dev = vlan_group_get_device(grp, vlan);
                        } else
                                while (dev->master)
                                        dev = dev->master;
index 3f2cf8a07c613a78ffe951a68b48571aec921820..c23783432e51d07180069c9445157b6e566b60b5 100644 (file)
 #define USE_GTS 0
 
 #define SGE_RX_SM_BUF_SIZE 1536
+
+/*
+ * If USE_RX_PAGE is defined, the small freelist populated with (partial)
+ * pages instead of skbs. Pages are carved up into RX_PAGE_SIZE chunks (must
+ * be a multiple of the host page size).
+ */
+#define USE_RX_PAGE
+#define RX_PAGE_SIZE 2048
+
+/*
+ * skb freelist packets are copied into a new skb (and the freelist one is 
+ * reused) if their len is <= 
+ */
 #define SGE_RX_COPY_THRES  256
 
-# define SGE_RX_DROP_THRES 16
+/*
+ * Minimum number of freelist entries before we start dropping TUNNEL frames.
+ */
+#define SGE_RX_DROP_THRES 16
 
 /*
  * Period of the Tx buffer reclaim timer.  This timer does not need to run
@@ -85,7 +101,10 @@ struct tx_sw_desc {         /* SW state per Tx descriptor */
 };
 
 struct rx_sw_desc {            /* SW state per Rx descriptor */
-       struct sk_buff *skb;
+       union {
+               struct sk_buff *skb;
+               struct sge_fl_page page;
+       } t;
         DECLARE_PCI_UNMAP_ADDR(dma_addr);
 };
 
@@ -104,6 +123,15 @@ struct unmap_info {                /* packet unmapping info, overlays skb->cb */
        u32 len;                /* mapped length of skb main body */
 };
 
+/*
+ * Holds unmapping information for Tx packets that need deferred unmapping.
+ * This structure lives at skb->head and must be allocated by callers.
+ */
+struct deferred_unmap_info {
+       struct pci_dev *pdev;
+       dma_addr_t addr[MAX_SKB_FRAGS + 1];
+};
+
 /*
  * Maps a number of flits to the number of Tx descriptors that can hold them.
  * The formula is
@@ -252,10 +280,13 @@ static void free_tx_desc(struct adapter *adapter, struct sge_txq *q,
        struct pci_dev *pdev = adapter->pdev;
        unsigned int cidx = q->cidx;
 
+       const int need_unmap = need_skb_unmap() &&
+                              q->cntxt_id >= FW_TUNNEL_SGEEC_START;
+
        d = &q->sdesc[cidx];
        while (n--) {
                if (d->skb) {   /* an SGL is present */
-                       if (need_skb_unmap())
+                       if (need_unmap)
                                unmap_skb(d->skb, q, cidx, pdev);
                        if (d->skb->priority == cidx)
                                kfree_skb(d->skb);
@@ -320,16 +351,27 @@ static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q)
 
                pci_unmap_single(pdev, pci_unmap_addr(d, dma_addr),
                                 q->buf_size, PCI_DMA_FROMDEVICE);
-               kfree_skb(d->skb);
-               d->skb = NULL;
+
+               if (q->buf_size != RX_PAGE_SIZE) {
+                       kfree_skb(d->t.skb);
+                       d->t.skb = NULL;
+               } else {
+                       if (d->t.page.frag.page)
+                               put_page(d->t.page.frag.page);
+                       d->t.page.frag.page = NULL;
+               }
                if (++cidx == q->size)
                        cidx = 0;
        }
+
+       if (q->page.frag.page)
+               put_page(q->page.frag.page);
+       q->page.frag.page = NULL;
 }
 
 /**
  *     add_one_rx_buf - add a packet buffer to a free-buffer list
- *     @skb: the buffer to add
+ *     @va: va of the buffer to add
  *     @len: the buffer length
  *     @d: the HW Rx descriptor to write
  *     @sd: the SW Rx descriptor to write
@@ -339,14 +381,13 @@ static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q)
  *     Add a buffer of the given length to the supplied HW and SW Rx
  *     descriptors.
  */
-static inline void add_one_rx_buf(struct sk_buff *skb, unsigned int len,
+static inline void add_one_rx_buf(unsigned char *va, unsigned int len,
                                  struct rx_desc *d, struct rx_sw_desc *sd,
                                  unsigned int gen, struct pci_dev *pdev)
 {
        dma_addr_t mapping;
 
-       sd->skb = skb;
-       mapping = pci_map_single(pdev, skb->data, len, PCI_DMA_FROMDEVICE);
+       mapping = pci_map_single(pdev, va, len, PCI_DMA_FROMDEVICE);
        pci_unmap_addr_set(sd, dma_addr, mapping);
 
        d->addr_lo = cpu_to_be32(mapping);
@@ -371,14 +412,47 @@ static void refill_fl(struct adapter *adap, struct sge_fl *q, int n, gfp_t gfp)
 {
        struct rx_sw_desc *sd = &q->sdesc[q->pidx];
        struct rx_desc *d = &q->desc[q->pidx];
+       struct sge_fl_page *p = &q->page;
 
        while (n--) {
-               struct sk_buff *skb = alloc_skb(q->buf_size, gfp);
+               unsigned char *va;
 
-               if (!skb)
-                       break;
+               if (unlikely(q->buf_size != RX_PAGE_SIZE)) {
+                       struct sk_buff *skb = alloc_skb(q->buf_size, gfp);
+
+                       if (!skb) {
+                               q->alloc_failed++;
+                               break;
+                       }
+                       va = skb->data;
+                       sd->t.skb = skb;
+               } else {
+                       if (!p->frag.page) {
+                               p->frag.page = alloc_pages(gfp, 0);
+                               if (unlikely(!p->frag.page)) {
+                                       q->alloc_failed++;
+                                       break;
+                               } else {
+                                       p->frag.size = RX_PAGE_SIZE;
+                                       p->frag.page_offset = 0;
+                                       p->va = page_address(p->frag.page);
+                               }
+                       }
+
+                       memcpy(&sd->t, p, sizeof(*p));
+                       va = p->va;
+
+                       p->frag.page_offset += RX_PAGE_SIZE;
+                       BUG_ON(p->frag.page_offset > PAGE_SIZE);
+                       p->va += RX_PAGE_SIZE;
+                       if (p->frag.page_offset == PAGE_SIZE)
+                               p->frag.page = NULL;
+                       else
+                               get_page(p->frag.page);
+               }
+
+               add_one_rx_buf(va, q->buf_size, d, sd, q->gen, adap->pdev);
 
-               add_one_rx_buf(skb, q->buf_size, d, sd, q->gen, adap->pdev);
                d++;
                sd++;
                if (++q->pidx == q->size) {
@@ -413,7 +487,7 @@ static void recycle_rx_buf(struct adapter *adap, struct sge_fl *q,
        struct rx_desc *from = &q->desc[idx];
        struct rx_desc *to = &q->desc[q->pidx];
 
-       q->sdesc[q->pidx] = q->sdesc[idx];
+       memcpy(&q->sdesc[q->pidx], &q->sdesc[idx], sizeof(struct rx_sw_desc));
        to->addr_lo = from->addr_lo;    /* already big endian */
        to->addr_hi = from->addr_hi;    /* likewise */
        wmb();
@@ -446,7 +520,7 @@ static void recycle_rx_buf(struct adapter *adap, struct sge_fl *q,
  *     of the SW ring.
  */
 static void *alloc_ring(struct pci_dev *pdev, size_t nelem, size_t elem_size,
-                       size_t sw_size, dma_addr_t *phys, void *metadata)
+                       size_t sw_size, dma_addr_t * phys, void *metadata)
 {
        size_t len = nelem * elem_size;
        void *s = NULL;
@@ -575,61 +649,6 @@ static inline unsigned int flits_to_desc(unsigned int n)
        return flit_desc_map[n];
 }
 
-/**
- *     get_packet - return the next ingress packet buffer from a free list
- *     @adap: the adapter that received the packet
- *     @fl: the SGE free list holding the packet
- *     @len: the packet length including any SGE padding
- *     @drop_thres: # of remaining buffers before we start dropping packets
- *
- *     Get the next packet from a free list and complete setup of the
- *     sk_buff.  If the packet is small we make a copy and recycle the
- *     original buffer, otherwise we use the original buffer itself.  If a
- *     positive drop threshold is supplied packets are dropped and their
- *     buffers recycled if (a) the number of remaining buffers is under the
- *     threshold and the packet is too big to copy, or (b) the packet should
- *     be copied but there is no memory for the copy.
- */
-static struct sk_buff *get_packet(struct adapter *adap, struct sge_fl *fl,
-                                 unsigned int len, unsigned int drop_thres)
-{
-       struct sk_buff *skb = NULL;
-       struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
-
-       prefetch(sd->skb->data);
-
-       if (len <= SGE_RX_COPY_THRES) {
-               skb = alloc_skb(len, GFP_ATOMIC);
-               if (likely(skb != NULL)) {
-                       __skb_put(skb, len);
-                       pci_dma_sync_single_for_cpu(adap->pdev,
-                                                   pci_unmap_addr(sd,
-                                                                  dma_addr),
-                                                   len, PCI_DMA_FROMDEVICE);
-                       memcpy(skb->data, sd->skb->data, len);
-                       pci_dma_sync_single_for_device(adap->pdev,
-                                                      pci_unmap_addr(sd,
-                                                                     dma_addr),
-                                                      len, PCI_DMA_FROMDEVICE);
-               } else if (!drop_thres)
-                       goto use_orig_buf;
-             recycle:
-               recycle_rx_buf(adap, fl, fl->cidx);
-               return skb;
-       }
-
-       if (unlikely(fl->credits < drop_thres))
-               goto recycle;
-
-      use_orig_buf:
-       pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr),
-                        fl->buf_size, PCI_DMA_FROMDEVICE);
-       skb = sd->skb;
-       skb_put(skb, len);
-       __refill_fl(adap, fl);
-       return skb;
-}
-
 /**
  *     get_imm_packet - return the next ingress packet buffer from a response
  *     @resp: the response descriptor containing the packet data
@@ -1226,6 +1245,50 @@ int t3_mgmt_tx(struct adapter *adap, struct sk_buff *skb)
        return ctrl_xmit(adap, &adap->sge.qs[0].txq[TXQ_CTRL], skb);
 }
 
+/**
+ *     deferred_unmap_destructor - unmap a packet when it is freed
+ *     @skb: the packet
+ *
+ *     This is the packet destructor used for Tx packets that need to remain
+ *     mapped until they are freed rather than until their Tx descriptors are
+ *     freed.
+ */
+static void deferred_unmap_destructor(struct sk_buff *skb)
+{
+       int i;
+       const dma_addr_t *p;
+       const struct skb_shared_info *si;
+       const struct deferred_unmap_info *dui;
+       const struct unmap_info *ui = (struct unmap_info *)skb->cb;
+
+       dui = (struct deferred_unmap_info *)skb->head;
+       p = dui->addr;
+
+       if (ui->len)
+               pci_unmap_single(dui->pdev, *p++, ui->len, PCI_DMA_TODEVICE);
+
+       si = skb_shinfo(skb);
+       for (i = 0; i < si->nr_frags; i++)
+               pci_unmap_page(dui->pdev, *p++, si->frags[i].size,
+                              PCI_DMA_TODEVICE);
+}
+
+static void setup_deferred_unmapping(struct sk_buff *skb, struct pci_dev *pdev,
+                                    const struct sg_ent *sgl, int sgl_flits)
+{
+       dma_addr_t *p;
+       struct deferred_unmap_info *dui;
+
+       dui = (struct deferred_unmap_info *)skb->head;
+       dui->pdev = pdev;
+       for (p = dui->addr; sgl_flits >= 3; sgl++, sgl_flits -= 3) {
+               *p++ = be64_to_cpu(sgl->addr[0]);
+               *p++ = be64_to_cpu(sgl->addr[1]);
+       }
+       if (sgl_flits)
+               *p = be64_to_cpu(sgl->addr[0]);
+}
+
 /**
  *     write_ofld_wr - write an offload work request
  *     @adap: the adapter
@@ -1262,8 +1325,11 @@ static void write_ofld_wr(struct adapter *adap, struct sk_buff *skb,
        sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl;
        sgl_flits = make_sgl(skb, sgp, skb->h.raw, skb->tail - skb->h.raw,
                             adap->pdev);
-       if (need_skb_unmap())
+       if (need_skb_unmap()) {
+               setup_deferred_unmapping(skb, adap->pdev, sgp, sgl_flits);
+               skb->destructor = deferred_unmap_destructor;
                ((struct unmap_info *)skb->cb)->len = skb->tail - skb->h.raw;
+       }
 
        write_wr_hdr_sgl(ndesc, skb, d, pidx, q, sgl, flits, sgl_flits,
                         gen, from->wr_hi, from->wr_lo);
@@ -1617,7 +1683,6 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
        struct cpl_rx_pkt *p = (struct cpl_rx_pkt *)(skb->data + pad);
        struct port_info *pi;
 
-       rq->eth_pkts++;
        skb_pull(skb, sizeof(*p) + pad);
        skb->dev = adap->port[p->iff];
        skb->dev->last_rx = jiffies;
@@ -1645,6 +1710,85 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
                netif_rx(skb);
 }
 
+#define SKB_DATA_SIZE 128
+
+static void skb_data_init(struct sk_buff *skb, struct sge_fl_page *p,
+                         unsigned int len)
+{
+       skb->len = len;
+       if (len <= SKB_DATA_SIZE) {
+               memcpy(skb->data, p->va, len);
+               skb->tail += len;
+               put_page(p->frag.page);
+       } else {
+               memcpy(skb->data, p->va, SKB_DATA_SIZE);
+               skb_shinfo(skb)->frags[0].page = p->frag.page;
+               skb_shinfo(skb)->frags[0].page_offset =
+                   p->frag.page_offset + SKB_DATA_SIZE;
+               skb_shinfo(skb)->frags[0].size = len - SKB_DATA_SIZE;
+               skb_shinfo(skb)->nr_frags = 1;
+               skb->data_len = len - SKB_DATA_SIZE;
+               skb->tail += SKB_DATA_SIZE;
+               skb->truesize += skb->data_len;
+       }
+}
+
+/**
+*      get_packet - return the next ingress packet buffer from a free list
+*      @adap: the adapter that received the packet
+*      @fl: the SGE free list holding the packet
+*      @len: the packet length including any SGE padding
+*      @drop_thres: # of remaining buffers before we start dropping packets
+*
+*      Get the next packet from a free list and complete setup of the
+*      sk_buff.  If the packet is small we make a copy and recycle the
+*      original buffer, otherwise we use the original buffer itself.  If a
+*      positive drop threshold is supplied packets are dropped and their
+*      buffers recycled if (a) the number of remaining buffers is under the
+*      threshold and the packet is too big to copy, or (b) the packet should
+*      be copied but there is no memory for the copy.
+*/
+static struct sk_buff *get_packet(struct adapter *adap, struct sge_fl *fl,
+                                 unsigned int len, unsigned int drop_thres)
+{
+       struct sk_buff *skb = NULL;
+       struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
+
+       prefetch(sd->t.skb->data);
+
+       if (len <= SGE_RX_COPY_THRES) {
+               skb = alloc_skb(len, GFP_ATOMIC);
+               if (likely(skb != NULL)) {
+                       struct rx_desc *d = &fl->desc[fl->cidx];
+                       dma_addr_t mapping =
+                           (dma_addr_t)((u64) be32_to_cpu(d->addr_hi) << 32 |
+                                        be32_to_cpu(d->addr_lo));
+
+                       __skb_put(skb, len);
+                       pci_dma_sync_single_for_cpu(adap->pdev, mapping, len,
+                                                   PCI_DMA_FROMDEVICE);
+                       memcpy(skb->data, sd->t.skb->data, len);
+                       pci_dma_sync_single_for_device(adap->pdev, mapping, len,
+                                                      PCI_DMA_FROMDEVICE);
+               } else if (!drop_thres)
+                       goto use_orig_buf;
+recycle:
+               recycle_rx_buf(adap, fl, fl->cidx);
+               return skb;
+       }
+
+       if (unlikely(fl->credits < drop_thres))
+               goto recycle;
+
+use_orig_buf:
+       pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr),
+                        fl->buf_size, PCI_DMA_FROMDEVICE);
+       skb = sd->t.skb;
+       skb_put(skb, len);
+       __refill_fl(adap, fl);
+       return skb;
+}
+
 /**
  *     handle_rsp_cntrl_info - handles control information in a response
  *     @qs: the queue set corresponding to the response
@@ -1767,7 +1911,7 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs,
        q->next_holdoff = q->holdoff_tmr;
 
        while (likely(budget_left && is_new_response(r, q))) {
-               int eth, ethpad = 0;
+               int eth, ethpad = 2;
                struct sk_buff *skb = NULL;
                u32 len, flags = ntohl(r->flags);
                u32 rss_hi = *(const u32 *)r, rss_lo = r->rss_hdr.rss_hash_val;
@@ -1794,18 +1938,56 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs,
                                break;
                        }
                        q->imm_data++;
+                       ethpad = 0;
                } else if ((len = ntohl(r->len_cq)) != 0) {
-                       struct sge_fl *fl;
+                       struct sge_fl *fl =
+                           (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0];
+
+                       if (fl->buf_size == RX_PAGE_SIZE) {
+                               struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
+                               struct sge_fl_page *p = &sd->t.page;
+
+                               prefetch(p->va);
+                               prefetch(p->va + L1_CACHE_BYTES);
+
+                               __refill_fl(adap, fl);
+
+                               pci_unmap_single(adap->pdev,
+                                                pci_unmap_addr(sd, dma_addr),
+                                                fl->buf_size,
+                                                PCI_DMA_FROMDEVICE);
+
+                               if (eth) {
+                                       if (unlikely(fl->credits <
+                                                    SGE_RX_DROP_THRES))
+                                               goto eth_recycle;
+
+                                       skb = alloc_skb(SKB_DATA_SIZE,
+                                                       GFP_ATOMIC);
+                                       if (unlikely(!skb)) {
+eth_recycle:
+                                               q->rx_drops++;
+                                               recycle_rx_buf(adap, fl,
+                                                              fl->cidx);
+                                               goto eth_done;
+                                       }
+                               } else {
+                                       skb = alloc_skb(SKB_DATA_SIZE,
+                                                       GFP_ATOMIC);
+                                       if (unlikely(!skb))
+                                               goto no_mem;
+                               }
+
+                               skb_data_init(skb, p, G_RSPD_LEN(len));
+eth_done:
+                               fl->credits--;
+                               q->eth_pkts++;
+                       } else {
+                               fl->credits--;
+                               skb = get_packet(adap, fl, G_RSPD_LEN(len),
+                                                eth ? SGE_RX_DROP_THRES : 0);
+                       }
 
-                       fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0];
-                       fl->credits--;
-                       skb = get_packet(adap, fl, G_RSPD_LEN(len),
-                                        eth ? SGE_RX_DROP_THRES : 0);
-                       if (!skb)
-                               q->rx_drops++;
-                       else if (r->rss_hdr.opcode == CPL_TRACE_PKT)
-                               __skb_pull(skb, 2);
-                       ethpad = 2;
                        if (++fl->cidx == fl->size)
                                fl->cidx = 0;
                } else
@@ -1829,18 +2011,23 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs,
                        q->credits = 0;
                }
 
-               if (likely(skb != NULL)) {
+               if (skb) {
+                       /* Preserve the RSS info in csum & priority */
+                       skb->csum = rss_hi;
+                       skb->priority = rss_lo;
+
                        if (eth)
                                rx_eth(adap, q, skb, ethpad);
                        else {
-                               /* Preserve the RSS info in csum & priority */
-                               skb->csum = rss_hi;
-                               skb->priority = rss_lo;
-                               ngathered = rx_offload(&adap->tdev, q, skb,
-                                                      offload_skbs, ngathered);
+                               if (unlikely(r->rss_hdr.opcode ==
+                                            CPL_TRACE_PKT))
+                                       __skb_pull(skb, ethpad);
+
+                               ngathered = rx_offload(&adap->tdev, q,
+                                                      skb, offload_skbs,
+                                                      ngathered);
                        }
                }
-
                --budget_left;
        }
 
@@ -2320,10 +2507,23 @@ static void sge_timer_cb(unsigned long data)
            &adap->sge.qs[0].rspq.lock;
        if (spin_trylock_irq(lock)) {
                if (!napi_is_scheduled(qs->netdev)) {
+                       u32 status = t3_read_reg(adap, A_SG_RSPQ_FL_STATUS);
+
                        if (qs->fl[0].credits < qs->fl[0].size)
                                __refill_fl(adap, &qs->fl[0]);
                        if (qs->fl[1].credits < qs->fl[1].size)
                                __refill_fl(adap, &qs->fl[1]);
+
+                       if (status & (1 << qs->rspq.cntxt_id)) {
+                               qs->rspq.starved++;
+                               if (qs->rspq.credits) {
+                                       refill_rspq(adap, &qs->rspq, 1);
+                                       qs->rspq.credits--;
+                                       qs->rspq.restarted++;
+                                       t3_write_reg(adap, A_SG_RSPQ_FL_STATUS,
+                                                    1 << qs->rspq.cntxt_id);
+                               }
+                       }
                }
                spin_unlock_irq(lock);
        }
@@ -2432,13 +2632,21 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
            flits_to_desc(sgl_len(MAX_SKB_FRAGS + 1) + 3);
 
        if (ntxq == 1) {
+#ifdef USE_RX_PAGE
+               q->fl[0].buf_size = RX_PAGE_SIZE;
+#else
                q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + 2 +
                    sizeof(struct cpl_rx_pkt);
+#endif
                q->fl[1].buf_size = MAX_FRAME_SIZE + 2 +
                    sizeof(struct cpl_rx_pkt);
        } else {
+#ifdef USE_RX_PAGE
+               q->fl[0].buf_size = RX_PAGE_SIZE;
+#else
                q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE +
                    sizeof(struct cpl_rx_data);
+#endif
                q->fl[1].buf_size = (16 * 1024) -
                    SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
        }
@@ -2632,7 +2840,7 @@ void __devinit t3_sge_prep(struct adapter *adap, struct sge_params *p)
                q->polling = adap->params.rev > 0;
                q->coalesce_usecs = 5;
                q->rspq_size = 1024;
-               q->fl_size = 4096;
+               q->fl_size = 1024;
                q->jumbo_size = 512;
                q->txq_size[TXQ_ETH] = 1024;
                q->txq_size[TXQ_OFLD] = 1024;
index 365a7f5b1f94441c670c9c8c599d9199edb23eb7..eaa7a2e89a30df876e3182bed3df133df21d65ee 100644 (file)
@@ -884,11 +884,13 @@ int t3_check_fw_version(struct adapter *adapter)
        major = G_FW_VERSION_MAJOR(vers);
        minor = G_FW_VERSION_MINOR(vers);
 
-       if (type == FW_VERSION_T3 && major == 3 && minor == 1)
+       if (type == FW_VERSION_T3 && major == FW_VERSION_MAJOR &&
+           minor == FW_VERSION_MINOR)
                return 0;
 
        CH_ERR(adapter, "found wrong FW version(%u.%u), "
-              "driver needs version 3.1\n", major, minor);
+              "driver needs version %u.%u\n", major, minor,
+              FW_VERSION_MAJOR, FW_VERSION_MINOR);
        return -EINVAL;
 }
 
index 2b67dd523cc174261deb19bc1f13c62996baab83..82278f8502594a416f5313eacb978f7673e0d959 100644 (file)
@@ -35,5 +35,7 @@
 #define DRV_DESC "Chelsio T3 Network Driver"
 #define DRV_NAME "cxgb3"
 /* Driver version */
-#define DRV_VERSION "1.0"
+#define DRV_VERSION "1.0-ko"
+#define FW_VERSION_MAJOR 3
+#define FW_VERSION_MINOR 2
 #endif                         /* __CHELSIO_VERSION_H */
index 8396e411f1ce7b59088e2b8f5667ca5d01a789c4..e547ce14eefe354913112455e34ebfe91b6e8fdc 100644 (file)
@@ -38,12 +38,6 @@ static const char version[] = "de600.c: $Revision: 1.41-2.5 $,  Bjorn Ekwall (bj
 /* Add more time here if your adapter won't work OK: */
 #define DE600_SLOW_DOWN        udelay(delay_time)
 
- /*
- * If you still have trouble reading/writing to the adapter,
- * modify the following "#define": (see <asm/io.h> for more info)
-#define REALLY_SLOW_IO
- */
-
 /* use 0 for production, 1 for verification, >2 for debug */
 #ifdef DE600_DEBUG
 #define PRINTK(x) if (de600_debug >= 2) printk x
index a71023741c3af8b3acb1c61ecd90bab11b3faaab..1d08e937af825421009ba1071190ac1dc5049a9c 100644 (file)
@@ -376,7 +376,7 @@ e1000_update_mng_vlan(struct e1000_adapter *adapter)
        uint16_t vid = adapter->hw.mng_cookie.vlan_id;
        uint16_t old_vid = adapter->mng_vlan_id;
        if (adapter->vlgrp) {
-               if (!adapter->vlgrp->vlan_devices[vid]) {
+               if (!vlan_group_get_device(adapter->vlgrp, vid)) {
                        if (adapter->hw.mng_cookie.status &
                                E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) {
                                e1000_vlan_rx_add_vid(netdev, vid);
@@ -386,7 +386,7 @@ e1000_update_mng_vlan(struct e1000_adapter *adapter)
 
                        if ((old_vid != (uint16_t)E1000_MNG_VLAN_NONE) &&
                                        (vid != old_vid) &&
-                                       !adapter->vlgrp->vlan_devices[old_vid])
+                           !vlan_group_get_device(adapter->vlgrp, old_vid))
                                e1000_vlan_rx_kill_vid(netdev, old_vid);
                } else
                        adapter->mng_vlan_id = vid;
@@ -1417,6 +1417,10 @@ e1000_open(struct net_device *netdev)
        if ((err = e1000_setup_all_rx_resources(adapter)))
                goto err_setup_rx;
 
+       err = e1000_request_irq(adapter);
+       if (err)
+               goto err_req_irq;
+
        e1000_power_up_phy(adapter);
 
        if ((err = e1000_up(adapter)))
@@ -1427,10 +1431,6 @@ e1000_open(struct net_device *netdev)
                e1000_update_mng_vlan(adapter);
        }
 
-       err = e1000_request_irq(adapter);
-       if (err)
-               goto err_req_irq;
-
        /* If AMT is enabled, let the firmware know that the network
         * interface is now open */
        if (adapter->hw.mac_type == e1000_82573 &&
@@ -1439,10 +1439,10 @@ e1000_open(struct net_device *netdev)
 
        return E1000_SUCCESS;
 
-err_req_irq:
-       e1000_down(adapter);
 err_up:
        e1000_power_down_phy(adapter);
+       e1000_free_irq(adapter);
+err_req_irq:
        e1000_free_all_rx_resources(adapter);
 err_setup_rx:
        e1000_free_all_tx_resources(adapter);
@@ -1482,7 +1482,7 @@ e1000_close(struct net_device *netdev)
        if ((adapter->hw.mng_cookie.status &
                          E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
             !(adapter->vlgrp &&
-                         adapter->vlgrp->vlan_devices[adapter->mng_vlan_id])) {
+              vlan_group_get_device(adapter->vlgrp, adapter->mng_vlan_id))) {
                e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
        }
 
@@ -4998,10 +4998,7 @@ e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
        uint32_t vfta, index;
 
        e1000_irq_disable(adapter);
-
-       if (adapter->vlgrp)
-               adapter->vlgrp->vlan_devices[vid] = NULL;
-
+       vlan_group_set_device(adapter->vlgrp, vid, NULL);
        e1000_irq_enable(adapter);
 
        if ((adapter->hw.mng_cookie.status &
@@ -5027,7 +5024,7 @@ e1000_restore_vlan(struct e1000_adapter *adapter)
        if (adapter->vlgrp) {
                uint16_t vid;
                for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
-                       if (!adapter->vlgrp->vlan_devices[vid])
+                       if (!vlan_group_get_device(adapter->vlgrp, vid))
                                continue;
                        e1000_vlan_rx_add_vid(adapter->netdev, vid);
                }
index 88ad1c8bcee49d2a34f1d00aac8a0292a17deaab..0e4042bc0a48e44c570b54b7e205ff3a8a8e58eb 100644 (file)
@@ -1939,8 +1939,7 @@ static void ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
        int index;
        u64 hret;
 
-       if (port->vgrp)
-               port->vgrp->vlan_devices[vid] = NULL;
+       vlan_group_set_device(port->vgrp, vid, NULL);
 
        cb1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
        if (!cb1) {
index a363148d019850d16b843a1a0cb0f4743f25f32a..46e1697d9cfd01638d9e5616027641a0ed639656 100644 (file)
@@ -839,7 +839,7 @@ enum {
        NV_MSIX_INT_DISABLED,
        NV_MSIX_INT_ENABLED
 };
-static int msix = NV_MSIX_INT_ENABLED;
+static int msix = NV_MSIX_INT_DISABLED;
 
 /*
  * DMA 64bit
@@ -3104,13 +3104,17 @@ static int nv_napi_poll(struct net_device *dev, int *budget)
        struct fe_priv *np = netdev_priv(dev);
        u8 __iomem *base = get_hwbase(dev);
        unsigned long flags;
+       int retcode;
 
-       if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+       if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
                pkts = nv_rx_process(dev, limit);
-       else
+               retcode = nv_alloc_rx(dev);
+       } else {
                pkts = nv_rx_process_optimized(dev, limit);
+               retcode = nv_alloc_rx_optimized(dev);
+       }
 
-       if (nv_alloc_rx(dev)) {
+       if (retcode) {
                spin_lock_irqsave(&np->lock, flags);
                if (!np->in_shutdown)
                        mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
@@ -5370,19 +5374,19 @@ static struct pci_device_id pci_tbl[] = {
        },
        {       /* MCP65 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_20),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
        },
        {       /* MCP65 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_21),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
        },
        {       /* MCP65 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_22),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
        },
        {       /* MCP65 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
        },
        {       /* MCP67 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_24),
index 1f83988a6a640c3b40f882e48fef8e11669d32e1..d981d4c41dd3b1ef6faa49fcdcf21bc4bc88c9c0 100644 (file)
@@ -1132,8 +1132,7 @@ static void gfar_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
 
        spin_lock_irqsave(&priv->rxlock, flags);
 
-       if (priv->vlgrp)
-               priv->vlgrp->vlan_devices[vid] = NULL;
+       vlan_group_set_device(priv->vlgrp, vid, NULL);
 
        spin_unlock_irqrestore(&priv->rxlock, flags);
 }
index 153b6dc80af4c38bebcca28a4cf8afc6a4209124..84aa2117c0ee52b0f296f265317afbae773860d4 100644 (file)
@@ -52,6 +52,7 @@
 #include <linux/hdlcdrv.h>
 #include <linux/baycom.h>
 #include <linux/jiffies.h>
+#include <linux/random.h>
 #include <net/ax25.h> 
 #include <asm/uaccess.h>
 
@@ -433,16 +434,6 @@ static void encode_hdlc(struct baycom_state *bc)
 
 /* ---------------------------------------------------------------------- */
 
-static unsigned short random_seed;
-
-static inline unsigned short random_num(void)
-{
-       random_seed = 28629 * random_seed + 157;
-       return random_seed;
-}
-
-/* ---------------------------------------------------------------------- */
-
 static int transmit(struct baycom_state *bc, int cnt, unsigned char stat)
 {
        struct parport *pp = bc->pdev->port;
@@ -464,7 +455,7 @@ static int transmit(struct baycom_state *bc, int cnt, unsigned char stat)
                        if ((--bc->hdlctx.slotcnt) > 0)
                                return 0;
                        bc->hdlctx.slotcnt = bc->ch_params.slottime;
-                       if ((random_num() % 256) > bc->ch_params.ppersist)
+                       if ((random32() % 256) > bc->ch_params.ppersist)
                                return 0;
                }
        }
index 452873e7c68f5d358c2bac2c6274e58f7a868a03..f5a17ad9d3d66850abd57373d0b36f51845dfe04 100644 (file)
@@ -56,6 +56,7 @@
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <linux/hdlcdrv.h>
+#include <linux/random.h>
 #include <net/ax25.h> 
 #include <asm/uaccess.h>
 
@@ -371,16 +372,6 @@ static void start_tx(struct net_device *dev, struct hdlcdrv_state *s)
 
 /* ---------------------------------------------------------------------- */
 
-static unsigned short random_seed;
-
-static inline unsigned short random_num(void)
-{
-       random_seed = 28629 * random_seed + 157;
-       return random_seed;
-}
-
-/* ---------------------------------------------------------------------- */
-
 void hdlcdrv_arbitrate(struct net_device *dev, struct hdlcdrv_state *s)
 {
        if (!s || s->magic != HDLCDRV_MAGIC || s->hdlctx.ptt || !s->skb) 
@@ -396,7 +387,7 @@ void hdlcdrv_arbitrate(struct net_device *dev, struct hdlcdrv_state *s)
        if ((--s->hdlctx.slotcnt) > 0)
                return;
        s->hdlctx.slotcnt = s->ch_params.slottime;
-       if ((random_num() % 256) > s->ch_params.ppersist)
+       if ((random32() % 256) > s->ch_params.ppersist)
                return;
        start_tx(dev, s);
 }
index 08f27119a8076fbff08caddb35780fdb89b3becb..ee3ea4fa729f370a79567dbb3432f2d5b3d37b10 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/bitops.h>
+#include <linux/random.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <linux/interrupt.h>
@@ -566,14 +567,6 @@ static void yam_start_tx(struct net_device *dev, struct yam_port *yp)
        ptt_on(dev);
 }
 
-static unsigned short random_seed;
-
-static inline unsigned short random_num(void)
-{
-       random_seed = 28629 * random_seed + 157;
-       return random_seed;
-}
-
 static void yam_arbitrate(struct net_device *dev)
 {
        struct yam_port *yp = netdev_priv(dev);
@@ -600,7 +593,7 @@ static void yam_arbitrate(struct net_device *dev)
        yp->slotcnt = yp->slot / 10;
 
        /* is random > persist ? */
-       if ((random_num() % 256) > yp->pers)
+       if ((random32() % 256) > yp->pers)
                return;
 
        yam_start_tx(dev, yp);
index 0c36828893446dec2849c1f192081fc346b15871..afc2ec72529ee4ac22b76546dab7f3630d11aade 100644 (file)
@@ -2213,8 +2213,7 @@ ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
 
        ixgb_irq_disable(adapter);
 
-       if(adapter->vlgrp)
-               adapter->vlgrp->vlan_devices[vid] = NULL;
+       vlan_group_set_device(adapter->vlgrp, vid, NULL);
 
        ixgb_irq_enable(adapter);
 
@@ -2234,7 +2233,7 @@ ixgb_restore_vlan(struct ixgb_adapter *adapter)
        if(adapter->vlgrp) {
                uint16_t vid;
                for(vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
-                       if(!adapter->vlgrp->vlan_devices[vid])
+                       if(!vlan_group_get_device(adapter->vlgrp, vid))
                                continue;
                        ixgb_vlan_rx_add_vid(adapter->netdev, vid);
                }
index ea392f2a5aa26aeb9c9f7670fbb6303e2c9c1672..452863d5d498a5aa9f9d08c0e9f4b817d13a3584 100644 (file)
@@ -384,7 +384,7 @@ struct i596_private {
        struct device *dev;
 };
 
-static char init_setup[] =
+static const char init_setup[] =
 {
        0x8E,                   /* length, prefetch on */
        0xC8,                   /* fifo to 8, monitor off */
@@ -683,7 +683,7 @@ static int init_i596_mem(struct net_device *dev)
        enable_irq(dev->irq);   /* enable IRQs from LAN */
 
        DEB(DEB_INIT, printk("%s: queuing CmdConfigure\n", dev->name));
-       memcpy(lp->cf_cmd.i596_config, init_setup, 14);
+       memcpy(lp->cf_cmd.i596_config, init_setup, sizeof(init_setup));
        lp->cf_cmd.cmd.command = CmdConfigure;
        CHECK_WBACK(lp, &(lp->cf_cmd), sizeof(struct cf_cmd));
        i596_add_cmd(dev, &lp->cf_cmd.cmd);
@@ -1156,32 +1156,12 @@ static int __devinit i82596_probe(struct net_device *dev,
        dma_addr_t dma_addr;
 
        /* This lot is ensure things have been cache line aligned. */
-       if (sizeof(struct i596_rfd) != 32) {
-           printk("82596: sizeof(struct i596_rfd) = %d\n",
-                           (int)sizeof(struct i596_rfd));
-           return -ENODEV;
-       }
-       if ((sizeof(struct i596_rbd) % 32) != 0) {
-           printk("82596: sizeof(struct i596_rbd) = %d\n",
-                           (int)sizeof(struct i596_rbd));
-           return -ENODEV;
-       }
-       if ((sizeof(struct tx_cmd) % 32) != 0) {
-           printk("82596: sizeof(struct tx_cmd) = %d\n",
-                           (int)sizeof(struct tx_cmd));
-           return -ENODEV;
-       }
-       if (sizeof(struct i596_tbd) != 32) {
-           printk("82596: sizeof(struct i596_tbd) = %d\n",
-                           (int)sizeof(struct i596_tbd));
-           return -ENODEV;
-       }
+       BUILD_BUG_ON(sizeof(struct i596_rfd) != 32);
+       BUILD_BUG_ON(sizeof(struct i596_rbd) &  31);
+       BUILD_BUG_ON(sizeof(struct tx_cmd)   &  31);
+       BUILD_BUG_ON(sizeof(struct i596_tbd) != 32);
 #ifndef __LP64__
-       if (sizeof(struct i596_private) > 4096) {
-           printk("82596: sizeof(struct i596_private) = %d\n",
-                           (int)sizeof(struct i596_private));
-           return -ENODEV;
-       }
+       BUILD_BUG_ON(sizeof(struct i596_private) > 4096);
 #endif
 
        if (!dev->base_addr || !dev->irq)
index d98e53efa2ef56158a8d0ea63fbcbda2dba08096..1ee27c360a4b845f0631824d9ea585729aa70bf4 100644 (file)
@@ -147,13 +147,13 @@ static void mv643xx_eth_rx_refill_descs(struct net_device *dev)
        int unaligned;
 
        while (mp->rx_desc_count < mp->rx_ring_size) {
-               skb = dev_alloc_skb(ETH_RX_SKB_SIZE + ETH_DMA_ALIGN);
+               skb = dev_alloc_skb(ETH_RX_SKB_SIZE + dma_get_cache_alignment());
                if (!skb)
                        break;
                mp->rx_desc_count++;
-               unaligned = (u32)skb->data & (ETH_DMA_ALIGN - 1);
+               unaligned = (u32)skb->data & (dma_get_cache_alignment() - 1);
                if (unaligned)
-                       skb_reserve(skb, ETH_DMA_ALIGN - unaligned);
+                       skb_reserve(skb, dma_get_cache_alignment() - unaligned);
                pkt_info.cmd_sts = ETH_RX_ENABLE_INTERRUPT;
                pkt_info.byte_cnt = ETH_RX_SKB_SIZE;
                pkt_info.buf_ptr = dma_map_single(NULL, skb->data,
@@ -787,6 +787,12 @@ static int mv643xx_eth_open(struct net_device *dev)
        unsigned int size;
        int err;
 
+       /* Clear any pending ethernet port interrupts */
+       mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
+       mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+       /* wait for previous write to complete */
+       mv_read (MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num));
+
        err = request_irq(dev->irq, mv643xx_eth_int_handler,
                        IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, dev);
        if (err) {
@@ -875,10 +881,6 @@ static int mv643xx_eth_open(struct net_device *dev)
 
        mv643xx_eth_rx_refill_descs(dev);       /* Fill RX ring with skb's */
 
-       /* Clear any pending ethernet port interrupts */
-       mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
-       mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
-
        eth_port_start(dev);
 
        /* Interrupt Coalescing */
@@ -1309,7 +1311,7 @@ static void mv643xx_init_ethtool_cmd(struct net_device *dev, int phy_address,
 static int mv643xx_eth_probe(struct platform_device *pdev)
 {
        struct mv643xx_eth_platform_data *pd;
-       int port_num = pdev->id;
+       int port_num;
        struct mv643xx_private *mp;
        struct net_device *dev;
        u8 *p;
@@ -1319,6 +1321,12 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
        int duplex = DUPLEX_HALF;
        int speed = 0;                  /* default to auto-negotiation */
 
+       pd = pdev->dev.platform_data;
+       if (pd == NULL) {
+               printk(KERN_ERR "No mv643xx_eth_platform_data\n");
+               return -ENODEV;
+       }
+
        dev = alloc_etherdev(sizeof(struct mv643xx_private));
        if (!dev)
                return -ENOMEM;
@@ -1331,8 +1339,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
        BUG_ON(!res);
        dev->irq = res->start;
 
-       mp->port_num = port_num;
-
        dev->open = mv643xx_eth_open;
        dev->stop = mv643xx_eth_stop;
        dev->hard_start_xmit = mv643xx_eth_start_xmit;
@@ -1373,39 +1379,40 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
 
        spin_lock_init(&mp->lock);
 
+       port_num = pd->port_number;
+
        /* set default config values */
        eth_port_uc_addr_get(dev, dev->dev_addr);
        mp->rx_ring_size = MV643XX_ETH_PORT_DEFAULT_RECEIVE_QUEUE_SIZE;
        mp->tx_ring_size = MV643XX_ETH_PORT_DEFAULT_TRANSMIT_QUEUE_SIZE;
 
-       pd = pdev->dev.platform_data;
-       if (pd) {
-               if (pd->mac_addr)
-                       memcpy(dev->dev_addr, pd->mac_addr, 6);
-
-               if (pd->phy_addr || pd->force_phy_addr)
-                       ethernet_phy_set(port_num, pd->phy_addr);
+       if (is_valid_ether_addr(pd->mac_addr))
+               memcpy(dev->dev_addr, pd->mac_addr, 6);
 
-               if (pd->rx_queue_size)
-                       mp->rx_ring_size = pd->rx_queue_size;
+       if (pd->phy_addr || pd->force_phy_addr)
+               ethernet_phy_set(port_num, pd->phy_addr);
 
-               if (pd->tx_queue_size)
-                       mp->tx_ring_size = pd->tx_queue_size;
+       if (pd->rx_queue_size)
+               mp->rx_ring_size = pd->rx_queue_size;
 
-               if (pd->tx_sram_size) {
-                       mp->tx_sram_size = pd->tx_sram_size;
-                       mp->tx_sram_addr = pd->tx_sram_addr;
-               }
+       if (pd->tx_queue_size)
+               mp->tx_ring_size = pd->tx_queue_size;
 
-               if (pd->rx_sram_size) {
-                       mp->rx_sram_size = pd->rx_sram_size;
-                       mp->rx_sram_addr = pd->rx_sram_addr;
-               }
+       if (pd->tx_sram_size) {
+               mp->tx_sram_size = pd->tx_sram_size;
+               mp->tx_sram_addr = pd->tx_sram_addr;
+       }
 
-               duplex = pd->duplex;
-               speed = pd->speed;
+       if (pd->rx_sram_size) {
+               mp->rx_sram_size = pd->rx_sram_size;
+               mp->rx_sram_addr = pd->rx_sram_addr;
        }
 
+       duplex = pd->duplex;
+       speed = pd->speed;
+
+       mp->port_num = port_num;
+
        /* Hook up MII support for ethtool */
        mp->mii.dev = dev;
        mp->mii.mdio_read = mv643xx_mdio_read;
index 33c5fafdbbd3f2cfae431b9fa03d15f172df0a9b..7d4e90cf49e8704f797c7f142570693a370a4826 100644 (file)
@@ -9,6 +9,8 @@
 
 #include <linux/mv643xx.h>
 
+#include <asm/dma-mapping.h>
+
 /* Checksum offload for Tx works for most packets, but
  * fails if previous packet sent did not use hw csum
  */
 #define MAX_DESCS_PER_SKB      1
 #endif
 
-/*
- * The MV643XX HW requires 8-byte alignment.  However, when I/O
- * is non-cache-coherent, we need to ensure that the I/O buffers
- * we use don't share cache lines with other data.
- */
-#if defined(CONFIG_DMA_NONCOHERENT) || defined(CONFIG_NOT_COHERENT_CACHE)
-#define ETH_DMA_ALIGN          L1_CACHE_BYTES
-#else
-#define ETH_DMA_ALIGN          8
-#endif
-
 #define ETH_VLAN_HLEN          4
 #define ETH_FCS_LEN            4
 #define ETH_HW_IP_ALIGN                2               /* hw aligns IP header */
 #define ETH_WRAPPER_LEN                (ETH_HW_IP_ALIGN + ETH_HLEN + \
                                        ETH_VLAN_HLEN + ETH_FCS_LEN)
-#define ETH_RX_SKB_SIZE                (dev->mtu + ETH_WRAPPER_LEN + ETH_DMA_ALIGN)
+#define ETH_RX_SKB_SIZE                (dev->mtu + ETH_WRAPPER_LEN + dma_get_cache_alignment())
 
 #define ETH_RX_QUEUES_ENABLED  (1 << 0)        /* use only Q0 for receive */
 #define ETH_TX_QUEUES_ENABLED  (1 << 0)        /* use only Q0 for transmit */
index 030924fb1ab3544545ea5770c9d265010bd9f315..ac02b3b60f926e40f175aed8c1f2ac27adc090f4 100644 (file)
@@ -1,7 +1,7 @@
 /*************************************************************************
  * myri10ge.c: Myricom Myri-10G Ethernet driver.
  *
- * Copyright (C) 2005, 2006 Myricom, Inc.
+ * Copyright (C) 2005 - 2007 Myricom, Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS 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.
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 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.
  *
  *
  * If the eeprom on your board is not recent enough, you will need to get a
@@ -181,6 +181,7 @@ struct myri10ge_priv {
        int intr_coal_delay;
        __be32 __iomem *intr_coal_delay_ptr;
        int mtrr;
+       int wc_enabled;
        int wake_queue;
        int stop_queue;
        int down_cnt;
@@ -195,6 +196,10 @@ struct myri10ge_priv {
        char *fw_name;
        char eeprom_strings[MYRI10GE_EEPROM_STRINGS_SIZE];
        char fw_version[128];
+       int fw_ver_major;
+       int fw_ver_minor;
+       int fw_ver_tiny;
+       int adopted_rx_filter_bug;
        u8 mac_addr[6];         /* eeprom mac address */
        unsigned long serial_number;
        int vendor_specific_offset;
@@ -447,7 +452,6 @@ myri10ge_validate_firmware(struct myri10ge_priv *mgp,
                           struct mcp_gen_header *hdr)
 {
        struct device *dev = &mgp->pdev->dev;
-       int major, minor;
 
        /* check firmware type */
        if (ntohl(hdr->mcp_type) != MCP_TYPE_ETH) {
@@ -458,9 +462,11 @@ myri10ge_validate_firmware(struct myri10ge_priv *mgp,
        /* save firmware version for ethtool */
        strncpy(mgp->fw_version, hdr->version, sizeof(mgp->fw_version));
 
-       sscanf(mgp->fw_version, "%d.%d", &major, &minor);
+       sscanf(mgp->fw_version, "%d.%d.%d", &mgp->fw_ver_major,
+              &mgp->fw_ver_minor, &mgp->fw_ver_tiny);
 
-       if (!(major == MXGEFW_VERSION_MAJOR && minor == MXGEFW_VERSION_MINOR)) {
+       if (!(mgp->fw_ver_major == MXGEFW_VERSION_MAJOR
+             && mgp->fw_ver_minor == MXGEFW_VERSION_MINOR)) {
                dev_err(dev, "Found firmware version %s\n", mgp->fw_version);
                dev_err(dev, "Driver needs %d.%d\n", MXGEFW_VERSION_MAJOR,
                        MXGEFW_VERSION_MINOR);
@@ -561,6 +567,18 @@ static int myri10ge_adopt_running_firmware(struct myri10ge_priv *mgp)
        memcpy_fromio(hdr, mgp->sram + hdr_offset, bytes);
        status = myri10ge_validate_firmware(mgp, hdr);
        kfree(hdr);
+
+       /* check to see if adopted firmware has bug where adopting
+        * it will cause broadcasts to be filtered unless the NIC
+        * is kept in ALLMULTI mode */
+       if (mgp->fw_ver_major == 1 && mgp->fw_ver_minor == 4 &&
+           mgp->fw_ver_tiny >= 4 && mgp->fw_ver_tiny <= 11) {
+               mgp->adopted_rx_filter_bug = 1;
+               dev_warn(dev, "Adopting fw %d.%d.%d: "
+                        "working around rx filter bug\n",
+                        mgp->fw_ver_major, mgp->fw_ver_minor,
+                        mgp->fw_ver_tiny);
+       }
        return status;
 }
 
@@ -700,6 +718,8 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
        int status;
        size_t bytes;
        u32 len;
+       struct page *dmatest_page;
+       dma_addr_t dmatest_bus;
 
        /* try to send a reset command to the card to see if it
         * is alive */
@@ -709,6 +729,11 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
                dev_err(&mgp->pdev->dev, "failed reset\n");
                return -ENXIO;
        }
+       dmatest_page = alloc_page(GFP_KERNEL);
+       if (!dmatest_page)
+               return -ENOMEM;
+       dmatest_bus = pci_map_page(mgp->pdev, dmatest_page, 0, PAGE_SIZE,
+                                  DMA_BIDIRECTIONAL);
 
        /* Now exchange information about interrupts  */
 
@@ -747,8 +772,8 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
 
        len = mgp->tx.boundary;
 
-       cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus);
-       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus);
+       cmd.data0 = MYRI10GE_LOWPART_TO_U32(dmatest_bus);
+       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(dmatest_bus);
        cmd.data2 = len * 0x10000;
        status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0);
        if (status == 0)
@@ -757,8 +782,8 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
        else
                dev_warn(&mgp->pdev->dev, "DMA read benchmark failed: %d\n",
                         status);
-       cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus);
-       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus);
+       cmd.data0 = MYRI10GE_LOWPART_TO_U32(dmatest_bus);
+       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(dmatest_bus);
        cmd.data2 = len * 0x1;
        status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0);
        if (status == 0)
@@ -768,8 +793,8 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
                dev_warn(&mgp->pdev->dev, "DMA write benchmark failed: %d\n",
                         status);
 
-       cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus);
-       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus);
+       cmd.data0 = MYRI10GE_LOWPART_TO_U32(dmatest_bus);
+       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(dmatest_bus);
        cmd.data2 = len * 0x10001;
        status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0);
        if (status == 0)
@@ -779,6 +804,9 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
                dev_warn(&mgp->pdev->dev,
                         "DMA read/write benchmark failed: %d\n", status);
 
+       pci_unmap_page(mgp->pdev, dmatest_bus, PAGE_SIZE, DMA_BIDIRECTIONAL);
+       put_page(dmatest_page);
+
        memset(mgp->rx_done.entry, 0, bytes);
 
        /* reset mcp/driver shared state back to 0 */
@@ -794,6 +822,8 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
        status = myri10ge_update_mac_address(mgp, mgp->dev->dev_addr);
        myri10ge_change_promisc(mgp, 0, 0);
        myri10ge_change_pause(mgp, mgp->pause);
+       if (mgp->adopted_rx_filter_bug)
+               (void)myri10ge_send_cmd(mgp, MXGEFW_ENABLE_ALLMULTI, &cmd, 1);
        return status;
 }
 
@@ -1356,7 +1386,7 @@ myri10ge_get_ethtool_stats(struct net_device *netdev,
                data[i] = ((unsigned long *)&mgp->stats)[i];
 
        data[i++] = (unsigned int)mgp->tx.boundary;
-       data[i++] = (unsigned int)(mgp->mtrr >= 0);
+       data[i++] = (unsigned int)mgp->wc_enabled;
        data[i++] = (unsigned int)mgp->pdev->irq;
        data[i++] = (unsigned int)mgp->msi_enabled;
        data[i++] = (unsigned int)mgp->read_dma;
@@ -1437,6 +1467,8 @@ static int myri10ge_allocate_rings(struct net_device *dev)
        status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_RING_SIZE, &cmd, 0);
        tx_ring_size = cmd.data0;
        status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_RX_RING_SIZE, &cmd, 0);
+       if (status != 0)
+               return status;
        rx_ring_size = cmd.data0;
 
        tx_ring_entries = tx_ring_size / sizeof(struct mcp_kreq_ether_send);
@@ -1444,6 +1476,8 @@ static int myri10ge_allocate_rings(struct net_device *dev)
        mgp->tx.mask = tx_ring_entries - 1;
        mgp->rx_small.mask = mgp->rx_big.mask = rx_ring_entries - 1;
 
+       status = -ENOMEM;
+
        /* allocate the host shadow rings */
 
        bytes = 8 + (MYRI10GE_MAX_SEND_DESC_TSO + 4)
@@ -1716,7 +1750,7 @@ static int myri10ge_open(struct net_device *dev)
                goto abort_with_irq;
        }
 
-       if (myri10ge_wcfifo && mgp->mtrr >= 0) {
+       if (myri10ge_wcfifo && mgp->wc_enabled) {
                mgp->tx.wc_fifo = (u8 __iomem *) mgp->sram + MXGEFW_ETH_SEND_4;
                mgp->rx_small.wc_fifo =
                    (u8 __iomem *) mgp->sram + MXGEFW_ETH_RECV_SMALL;
@@ -2239,7 +2273,7 @@ static void myri10ge_set_multicast_list(struct net_device *dev)
        myri10ge_change_promisc(mgp, dev->flags & IFF_PROMISC, 1);
 
        /* This firmware is known to not support multicast */
-       if (!mgp->fw_multicast_support)
+       if (!mgp->fw_multicast_support || mgp->adopted_rx_filter_bug)
                return;
 
        /* Disable multicast filtering */
@@ -2491,6 +2525,12 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
                                 bridge->vendor, bridge->device);
                        mgp->tx.boundary = 4096;
                        mgp->fw_name = myri10ge_fw_aligned;
+               } else if (bridge &&
+                          bridge->vendor == PCI_VENDOR_ID_SGI &&
+                          bridge->device == 0x4002 /* TIOCE pcie-port */ ) {
+                       /* this pcie bridge does not support 4K rdma request */
+                       mgp->tx.boundary = 2048;
+                       mgp->fw_name = myri10ge_fw_aligned;
                }
        } else {
                if (myri10ge_force_firmware == 1) {
@@ -2811,9 +2851,12 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        mgp->board_span = pci_resource_len(pdev, 0);
        mgp->iomem_base = pci_resource_start(pdev, 0);
        mgp->mtrr = -1;
+       mgp->wc_enabled = 0;
 #ifdef CONFIG_MTRR
        mgp->mtrr = mtrr_add(mgp->iomem_base, mgp->board_span,
                             MTRR_TYPE_WRCOMB, 1);
+       if (mgp->mtrr >= 0)
+               mgp->wc_enabled = 1;
 #endif
        /* Hack.  need to get rid of these magic numbers */
        mgp->sram_size =
@@ -2908,7 +2951,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        dev_info(dev, "%s IRQ %d, tx bndry %d, fw %s, WC %s\n",
                 (mgp->msi_enabled ? "MSI" : "xPIC"),
                 netdev->irq, mgp->tx.boundary, mgp->fw_name,
-                (mgp->mtrr >= 0 ? "Enabled" : "Disabled"));
+                (mgp->wc_enabled ? "Enabled" : "Disabled"));
 
        return 0;
 
index ffa0afd2eddcd372c614a6724be4cb3444e85f28..c6172a77a6d793de039fee2db63b374551f6d980 100644 (file)
@@ -244,6 +244,9 @@ enum {
        MII_EN_SCRM     = 0x0004,       /* enable scrambler (tp) */
 };
 
+enum {
+       NATSEMI_FLAG_IGNORE_PHY         = 0x1,
+};
 
 /* array of board data directly indexed by pci_tbl[x].driver_data */
 static const struct {
@@ -251,11 +254,13 @@ static const struct {
        unsigned long flags;
        unsigned int eeprom_size;
 } natsemi_pci_info[] __devinitdata = {
+       { "Aculab E1/T1 PMXc cPCI carrier card", NATSEMI_FLAG_IGNORE_PHY, 128 },
        { "NatSemi DP8381[56]", 0, 24 },
 };
 
 static const struct pci_device_id natsemi_pci_tbl[] __devinitdata = {
-       { PCI_VENDOR_ID_NS, 0x0020, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+       { PCI_VENDOR_ID_NS, 0x0020, 0x12d9,     0x000c,     0, 0, 0 },
+       { PCI_VENDOR_ID_NS, 0x0020, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
        { }     /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, natsemi_pci_tbl);
@@ -568,6 +573,8 @@ struct netdev_private {
        u32 intr_status;
        /* Do not touch the nic registers */
        int hands_off;
+       /* Don't pay attention to the reported link state. */
+       int ignore_phy;
        /* external phy that is used: only valid if dev->if_port != PORT_TP */
        int mii;
        int phy_addr_external;
@@ -696,7 +703,10 @@ static void __devinit natsemi_init_media (struct net_device *dev)
        struct netdev_private *np = netdev_priv(dev);
        u32 tmp;
 
-       netif_carrier_off(dev);
+       if (np->ignore_phy)
+               netif_carrier_on(dev);
+       else
+               netif_carrier_off(dev);
 
        /* get the initial settings from hardware */
        tmp            = mdio_read(dev, MII_BMCR);
@@ -806,8 +816,13 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
        np->hands_off = 0;
        np->intr_status = 0;
        np->eeprom_size = natsemi_pci_info[chip_idx].eeprom_size;
+       if (natsemi_pci_info[chip_idx].flags & NATSEMI_FLAG_IGNORE_PHY)
+               np->ignore_phy = 1;
+       else
+               np->ignore_phy = 0;
 
        /* Initial port:
+        * - If configured to ignore the PHY set up for external.
         * - If the nic was configured to use an external phy and if find_mii
         *   finds a phy: use external port, first phy that replies.
         * - Otherwise: internal port.
@@ -815,7 +830,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
         * The address would be used to access a phy over the mii bus, but
         * the internal phy is accessed through mapped registers.
         */
-       if (readl(ioaddr + ChipConfig) & CfgExtPhy)
+       if (np->ignore_phy || readl(ioaddr + ChipConfig) & CfgExtPhy)
                dev->if_port = PORT_MII;
        else
                dev->if_port = PORT_TP;
@@ -825,7 +840,9 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
 
        if (dev->if_port != PORT_TP) {
                np->phy_addr_external = find_mii(dev);
-               if (np->phy_addr_external == PHY_ADDR_NONE) {
+               /* If we're ignoring the PHY it doesn't matter if we can't
+                * find one. */
+               if (!np->ignore_phy && np->phy_addr_external == PHY_ADDR_NONE) {
                        dev->if_port = PORT_TP;
                        np->phy_addr_external = PHY_ADDR_INTERNAL;
                }
@@ -891,6 +908,8 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
                printk("%02x, IRQ %d", dev->dev_addr[i], irq);
                if (dev->if_port == PORT_TP)
                        printk(", port TP.\n");
+               else if (np->ignore_phy)
+                       printk(", port MII, ignoring PHY\n");
                else
                        printk(", port MII, phy ad %d.\n", np->phy_addr_external);
        }
@@ -1571,9 +1590,13 @@ static void check_link(struct net_device *dev)
 {
        struct netdev_private *np = netdev_priv(dev);
        void __iomem * ioaddr = ns_ioaddr(dev);
-       int duplex;
+       int duplex = np->duplex;
        u16 bmsr;
 
+       /* If we are ignoring the PHY then don't try reading it. */
+       if (np->ignore_phy)
+               goto propagate_state;
+
        /* The link status field is latched: it remains low after a temporary
         * link failure until it's read. We need the current link status,
         * thus read twice.
@@ -1585,7 +1608,7 @@ static void check_link(struct net_device *dev)
                if (netif_carrier_ok(dev)) {
                        if (netif_msg_link(np))
                                printk(KERN_NOTICE "%s: link down.\n",
-                                       dev->name);
+                                      dev->name);
                        netif_carrier_off(dev);
                        undo_cable_magic(dev);
                }
@@ -1609,6 +1632,7 @@ static void check_link(struct net_device *dev)
                        duplex = 1;
        }
 
+propagate_state:
        /* if duplex is set then bit 28 must be set, too */
        if (duplex ^ !!(np->rx_config & RxAcceptTx)) {
                if (netif_msg_link(np))
@@ -2000,6 +2024,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
        struct netdev_private *np = netdev_priv(dev);
        void __iomem * ioaddr = ns_ioaddr(dev);
        unsigned entry;
+       unsigned long flags;
 
        /* Note: Ordering is important here, set the field with the
           "ownership" bit last, and only then increment cur_tx. */
@@ -2013,7 +2038,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
 
        np->tx_ring[entry].addr = cpu_to_le32(np->tx_dma[entry]);
 
-       spin_lock_irq(&np->lock);
+       spin_lock_irqsave(&np->lock, flags);
 
        if (!np->hands_off) {
                np->tx_ring[entry].cmd_status = cpu_to_le32(DescOwn | skb->len);
@@ -2032,7 +2057,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
                dev_kfree_skb_irq(skb);
                np->stats.tx_dropped++;
        }
-       spin_unlock_irq(&np->lock);
+       spin_unlock_irqrestore(&np->lock, flags);
 
        dev->trans_start = jiffies;
 
@@ -2198,6 +2223,8 @@ static void netdev_rx(struct net_device *dev, int *work_done, int work_to_do)
                pkt_len = (desc_status & DescSizeMask) - 4;
                if ((desc_status&(DescMore|DescPktOK|DescRxLong)) != DescPktOK){
                        if (desc_status & DescMore) {
+                               unsigned long flags;
+
                                if (netif_msg_rx_err(np))
                                        printk(KERN_WARNING
                                                "%s: Oversized(?) Ethernet "
@@ -2212,12 +2239,12 @@ static void netdev_rx(struct net_device *dev, int *work_done, int work_to_do)
                                 * reset procedure documented in
                                 * AN-1287. */
 
-                               spin_lock_irq(&np->lock);
+                               spin_lock_irqsave(&np->lock, flags);
                                reset_rx(dev);
                                reinit_rx(dev);
                                writel(np->ring_dma, ioaddr + RxRingPtr);
                                check_link(dev);
-                               spin_unlock_irq(&np->lock);
+                               spin_unlock_irqrestore(&np->lock, flags);
 
                                /* We'll enable RX on exit from this
                                 * function. */
@@ -2372,8 +2399,19 @@ static struct net_device_stats *get_stats(struct net_device *dev)
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void natsemi_poll_controller(struct net_device *dev)
 {
+       struct netdev_private *np = netdev_priv(dev);
+
        disable_irq(dev->irq);
-       intr_handler(dev->irq, dev);
+
+       /*
+        * A real interrupt might have already reached us at this point
+        * but NAPI might still haven't called us back.  As the interrupt
+        * status register is cleared by reading, we should prevent an
+        * interrupt loss in this case...
+        */
+       if (!np->intr_status)
+               intr_handler(dev->irq, dev);
+
        enable_irq(dev->irq);
 }
 #endif
@@ -2818,6 +2856,15 @@ static int netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
                return -EINVAL;
        }
 
+       /*
+        * If we're ignoring the PHY then autoneg and the internal
+        * transciever are really not going to work so don't let the
+        * user select them.
+        */
+       if (np->ignore_phy && (ecmd->autoneg == AUTONEG_ENABLE ||
+                              ecmd->port == PORT_TP))
+               return -EINVAL;
+
        /*
         * maxtxpkt, maxrxpkt: ignored for now.
         *
index 2807ef400fb583ecdb5c248e8cc05b2330ec3fff..81742e4e5610e7b037c40eab93d13e855c60fd2b 100644 (file)
@@ -72,6 +72,8 @@
 #define FLASH_SECTOR_SIZE (64 * 1024)
 #define FLASH_TOTAL_SIZE  (NUM_FLASH_SECTORS * FLASH_SECTOR_SIZE)
 
+#define PHAN_VENDOR_ID 0x4040
+
 #define RCV_DESC_RINGSIZE      \
        (sizeof(struct rcv_desc) * adapter->max_rx_desc_count)
 #define STATUS_DESC_RINGSIZE   \
@@ -82,7 +84,7 @@
        (sizeof(struct netxen_cmd_buffer) * adapter->max_tx_desc_count)
 #define RCV_BUFFSIZE   \
        (sizeof(struct netxen_rx_buffer) * rcv_desc->max_rx_desc_count)
-#define find_diff_among(a,b,range) ((a)<(b)?((b)-(a)):((b)+(range)-(a)))
+#define find_diff_among(a,b,range) ((a)<=(b)?((b)-(a)):((b)+(range)-(a)))
 
 #define NETXEN_NETDEV_STATUS           0x1
 #define NETXEN_RCV_PRODUCER_OFFSET     0
index 6252e9a8727854719cf2323fe5f5f61a867ea54f..986ef98db229bc7e9a7e829f6282c547c96bd9de 100644 (file)
@@ -82,8 +82,7 @@ static const struct netxen_nic_stats netxen_nic_gstrings_stats[] = {
 #define NETXEN_NIC_STATS_LEN   ARRAY_SIZE(netxen_nic_gstrings_stats)
 
 static const char netxen_nic_gstrings_test[][ETH_GSTRING_LEN] = {
-       "Register_Test_offline", "EEPROM_Test_offline",
-       "Interrupt_Test_offline", "Loopback_Test_offline",
+       "Register_Test_on_offline",
        "Link_Test_on_offline"
 };
 
@@ -394,19 +393,12 @@ netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
        }
 }
 
-static void
-netxen_nic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
-{
-       wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
-       /* options can be added depending upon the mode */
-       wol->wolopts = 0;
-}
-
 static u32 netxen_nic_test_link(struct net_device *dev)
 {
        struct netxen_port *port = netdev_priv(dev);
        struct netxen_adapter *adapter = port->adapter;
        __u32 status;
+       int val;
 
        /* read which mode */
        if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
@@ -415,11 +407,13 @@ static u32 netxen_nic_test_link(struct net_device *dev)
                                         NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
                                         &status) != 0)
                        return -EIO;
-               else
-                       return (netxen_get_phy_link(status));
+               else {
+                       val = netxen_get_phy_link(status);
+                       return !val;
+               }
        } else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
-               int val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE));
-               return val == XG_LINK_UP;
+               val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE));
+               return (val == XG_LINK_UP) ? 0 : 1;
        }
        return -EIO;
 }
@@ -606,100 +600,21 @@ netxen_nic_set_pauseparam(struct net_device *dev,
 
 static int netxen_nic_reg_test(struct net_device *dev)
 {
-       struct netxen_port *port = netdev_priv(dev);
-       struct netxen_adapter *adapter = port->adapter;
-       u32 data_read, data_written, save;
-       __u32 mode;
-
-       /* 
-        * first test the "Read Only" registers by writing which mode
-        */
-       netxen_nic_read_w0(adapter, NETXEN_NIU_MODE, &mode);
-       if (netxen_get_niu_enable_ge(mode)) {   /* GB Mode */
-               netxen_nic_read_w0(adapter,
-                                  NETXEN_NIU_GB_MII_MGMT_STATUS(port->portnum),
-                                  &data_read);
-
-               save = data_read;
-               if (data_read)
-                       data_written = data_read & NETXEN_NIC_INVALID_DATA;
-               else
-                       data_written = NETXEN_NIC_INVALID_DATA;
-               netxen_nic_write_w0(adapter,
-                                   NETXEN_NIU_GB_MII_MGMT_STATUS(port->
-                                                                 portnum),
-                                   data_written);
-               netxen_nic_read_w0(adapter,
-                                  NETXEN_NIU_GB_MII_MGMT_STATUS(port->portnum),
-                                  &data_read);
-
-               if (data_written == data_read) {
-                       netxen_nic_write_w0(adapter,
-                                           NETXEN_NIU_GB_MII_MGMT_STATUS(port->
-                                                                         portnum),
-                                           save);
-
-                       return 0;
-               }
-
-               /* netxen_niu_gb_mii_mgmt_indicators is read only */
-               netxen_nic_read_w0(adapter,
-                                  NETXEN_NIU_GB_MII_MGMT_INDICATE(port->
-                                                                  portnum),
-                                  &data_read);
-
-               save = data_read;
-               if (data_read)
-                       data_written = data_read & NETXEN_NIC_INVALID_DATA;
-               else
-                       data_written = NETXEN_NIC_INVALID_DATA;
-               netxen_nic_write_w0(adapter,
-                                   NETXEN_NIU_GB_MII_MGMT_INDICATE(port->
-                                                                   portnum),
-                                   data_written);
-
-               netxen_nic_read_w0(adapter,
-                                  NETXEN_NIU_GB_MII_MGMT_INDICATE(port->
-                                                                  portnum),
-                                  &data_read);
-
-               if (data_written == data_read) {
-                       netxen_nic_write_w0(adapter,
-                                           NETXEN_NIU_GB_MII_MGMT_INDICATE
-                                           (port->portnum), save);
-                       return 0;
-               }
+       struct netxen_adapter *adapter = netdev_priv(dev);
+       u32 data_read, data_written;
 
-               /* netxen_niu_gb_interface_status is read only */
-               netxen_nic_read_w0(adapter,
-                                  NETXEN_NIU_GB_INTERFACE_STATUS(port->
-                                                                 portnum),
-                                  &data_read);
+       netxen_nic_read_w0(adapter, NETXEN_PCIX_PH_REG(0), &data_read);
+       if ((data_read & 0xffff) != PHAN_VENDOR_ID)
+       return 1;
 
-               save = data_read;
-               if (data_read)
-                       data_written = data_read & NETXEN_NIC_INVALID_DATA;
-               else
-                       data_written = NETXEN_NIC_INVALID_DATA;
-               netxen_nic_write_w0(adapter,
-                                   NETXEN_NIU_GB_INTERFACE_STATUS(port->
-                                                                  portnum),
-                                   data_written);
+       data_written = (u32)0xa5a5a5a5;
 
-               netxen_nic_read_w0(adapter,
-                                  NETXEN_NIU_GB_INTERFACE_STATUS(port->
-                                                                 portnum),
-                                  &data_read);
+       netxen_nic_reg_write(adapter, CRB_SCRATCHPAD_TEST, data_written);
+       data_read = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_SCRATCHPAD_TEST));
+       if (data_written != data_read)
+               return 1;
 
-               if (data_written == data_read) {
-                       netxen_nic_write_w0(adapter,
-                                           NETXEN_NIU_GB_INTERFACE_STATUS
-                                           (port->portnum), save);
-
-                       return 0;
-               }
-       }                       /* GB Mode */
-       return 1;
+       return 0;
 }
 
 static int netxen_nic_diag_test_count(struct net_device *dev)
@@ -713,26 +628,20 @@ netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
 {
        if (eth_test->flags == ETH_TEST_FL_OFFLINE) {   /* offline tests */
                /* link test */
-               if (!(data[4] = (u64) netxen_nic_test_link(dev)))
+               if ((data[1] = (u64) netxen_nic_test_link(dev)))
                        eth_test->flags |= ETH_TEST_FL_FAILED;
 
-               if (netif_running(dev))
-                       dev->stop(dev);
-
                /* register tests */
-               if (!(data[0] = netxen_nic_reg_test(dev)))
+               if ((data[0] = netxen_nic_reg_test(dev)))
                        eth_test->flags |= ETH_TEST_FL_FAILED;
-               /* other tests pass as of now */
-               data[1] = data[2] = data[3] = 1;
-               if (netif_running(dev))
-                       dev->open(dev);
        } else {                /* online tests */
-               /* link test */
-               if (!(data[4] = (u64) netxen_nic_test_link(dev)))
+               /* register tests */
+               if((data[0] = netxen_nic_reg_test(dev)))
                        eth_test->flags |= ETH_TEST_FL_FAILED;
 
-               /* other tests pass by default */
-               data[0] = data[1] = data[2] = data[3] = 1;
+               /* link test */
+               if ((data[1] = (u64) netxen_nic_test_link(dev)))
+                       eth_test->flags |= ETH_TEST_FL_FAILED;
        }
 }
 
@@ -783,7 +692,6 @@ struct ethtool_ops netxen_nic_ethtool_ops = {
        .get_drvinfo = netxen_nic_get_drvinfo,
        .get_regs_len = netxen_nic_get_regs_len,
        .get_regs = netxen_nic_get_regs,
-       .get_wol = netxen_nic_get_wol,
        .get_link = ethtool_op_get_link,
        .get_eeprom_len = netxen_nic_get_eeprom_len,
        .get_eeprom = netxen_nic_get_eeprom,
index 7195af3e8f3ddb1182d5b81d1debe33adc44be1c..1be55702557dc33e914fe8673a4b39f6827e0cdc 100644 (file)
@@ -228,7 +228,7 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
                            &adapter->ctx_desc_pdev);
 
        printk("ctx_desc_phys_addr: 0x%llx\n",
-              (u64) adapter->ctx_desc_phys_addr);
+              (unsigned long long) adapter->ctx_desc_phys_addr);
        if (addr == NULL) {
                DPRINTK(ERR, "bad return from pci_alloc_consistent\n");
                err = -ENOMEM;
@@ -242,11 +242,13 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
        adapter->cmd_consumer = (uint32_t *) (((char *)addr) +
                                              sizeof(struct netxen_ring_ctx));
 
-       addr = pci_alloc_consistent(adapter->ahw.pdev,
-                                   sizeof(struct cmd_desc_type0) *
-                                   adapter->max_tx_desc_count,
-                                   (dma_addr_t *) & hw->cmd_desc_phys_addr);
-       printk("cmd_desc_phys_addr: 0x%llx\n", (u64) hw->cmd_desc_phys_addr);
+       addr = netxen_alloc(adapter->ahw.pdev,
+                           sizeof(struct cmd_desc_type0) *
+                           adapter->max_tx_desc_count,
+                           (dma_addr_t *) & hw->cmd_desc_phys_addr,
+                           &adapter->ahw.cmd_desc_pdev);
+       printk("cmd_desc_phys_addr: 0x%llx\n",
+              (unsigned long long) hw->cmd_desc_phys_addr);
 
        if (addr == NULL) {
                DPRINTK(ERR, "bad return from pci_alloc_consistent\n");
@@ -507,8 +509,8 @@ void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw)
 void netxen_load_firmware(struct netxen_adapter *adapter)
 {
        int i;
-       long data, size = 0;
-       long flashaddr = NETXEN_FLASH_BASE, memaddr = NETXEN_PHANTOM_MEM_BASE;
+       u32 data, size = 0;
+       u32 flashaddr = NETXEN_FLASH_BASE, memaddr = NETXEN_PHANTOM_MEM_BASE;
        u64 off;
        void __iomem *addr;
 
@@ -950,6 +952,7 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
                                       netxen_nic_driver_name);
                                return;
                        }
+                       *ptr32 = le32_to_cpu(*ptr32);
                        ptr32++;
                        addr += sizeof(u32);
                }
index 2f324366784d9e9a3509dddb56bb1864d423e6ba..586d32b676af3fe4b485cb5f66b7c99415277691 100644 (file)
 #include "netxen_nic_phan_reg.h"
 
 struct crb_addr_pair {
-       long addr;
-       long data;
+       u32 addr;
+       u32 data;
 };
 
 #define NETXEN_MAX_CRB_XFORM 60
 static unsigned int crb_addr_xform[NETXEN_MAX_CRB_XFORM];
-#define NETXEN_ADDR_ERROR ((unsigned long ) 0xffffffff )
+#define NETXEN_ADDR_ERROR (0xffffffff)
 
 #define crb_addr_transform(name) \
        crb_addr_xform[NETXEN_HW_PX_MAP_CRB_##name] = \
@@ -252,10 +252,10 @@ void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
  * netxen_decode_crb_addr(0 - utility to translate from internal Phantom CRB
  * address to external PCI CRB address.
  */
-unsigned long netxen_decode_crb_addr(unsigned long addr)
+u32 netxen_decode_crb_addr(u32 addr)
 {
        int i;
-       unsigned long base_addr, offset, pci_base;
+       u32 base_addr, offset, pci_base;
 
        crb_addr_transform_setup();
 
@@ -499,7 +499,10 @@ static inline int do_rom_fast_write_words(struct netxen_adapter *adapter,
                while(1) {
                        int data1;
 
-                       do_rom_fast_read(adapter, addridx, &data1);
+                       ret = do_rom_fast_read(adapter, addridx, &data1);
+                       if (ret < 0)
+                               return ret;
+
                        if (data1 == data)
                                break;
 
@@ -753,7 +756,7 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
        int n, i;
        int init_delay = 0;
        struct crb_addr_pair *buf;
-       unsigned long off;
+       u32 off;
 
        /* resetall */
        status = netxen_nic_get_board_info(adapter);
@@ -810,14 +813,13 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
                        if (verbose)
                                printk("%s: PCI:     0x%08x == 0x%08x\n",
                                       netxen_nic_driver_name, (unsigned int)
-                                      netxen_decode_crb_addr((unsigned long)
-                                                             addr), val);
+                                      netxen_decode_crb_addr(addr), val);
                }
                for (i = 0; i < n; i++) {
 
-                       off = netxen_decode_crb_addr((unsigned long)buf[i].addr);
+                       off = netxen_decode_crb_addr(buf[i].addr);
                        if (off == NETXEN_ADDR_ERROR) {
-                               printk(KERN_ERR"CRB init value out of range %lx\n",
+                               printk(KERN_ERR"CRB init value out of range %x\n",
                                        buf[i].addr);
                                continue;
                        }
@@ -924,6 +926,10 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter)
 void netxen_free_adapter_offload(struct netxen_adapter *adapter)
 {
        if (adapter->dummy_dma.addr) {
+               writel(0, NETXEN_CRB_NORMALIZE(adapter,
+                       CRB_HOST_DUMMY_BUF_ADDR_HI));
+               writel(0, NETXEN_CRB_NORMALIZE(adapter,
+                       CRB_HOST_DUMMY_BUF_ADDR_LO));
                pci_free_consistent(adapter->ahw.pdev,
                                    NETXEN_HOST_DUMMY_DMA_SIZE,
                                    adapter->dummy_dma.addr,
index 225ff55527c447f1e0955eac185cec895e951548..7d2525e76abbedcbc6cf1584c3207239b40c8944 100644 (file)
@@ -42,8 +42,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/vmalloc.h>
 
-#define PHAN_VENDOR_ID 0x4040
-
 MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID);
@@ -379,6 +377,8 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                netdev->tx_timeout = netxen_tx_timeout;
                netdev->watchdog_timeo = HZ;
 
+               netxen_nic_change_mtu(netdev, netdev->mtu);
+
                SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops);
                netdev->poll = netxen_nic_poll;
                netdev->weight = NETXEN_NETDEV_WEIGHT;
@@ -434,13 +434,11 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                adapter->port_count++;
                adapter->port[i] = port;
        }
-#ifndef CONFIG_PPC64
        writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
        netxen_pinit_from_rom(adapter, 0);
        udelay(500);
        netxen_load_firmware(adapter);
        netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
-#endif
        /*
         * delay a while to ensure that the Pegs are up & running.
         * Otherwise, we might see some flaky behaviour.
@@ -525,14 +523,17 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
        if (adapter == NULL)
                return;
 
+       if (adapter->irq)
+               free_irq(adapter->irq, adapter);
        netxen_nic_stop_all_ports(adapter);
        /* leave the hw in the same state as reboot */
-       netxen_pinit_from_rom(adapter, 0);
        writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+       netxen_pinit_from_rom(adapter, 0);
+       udelay(500);
        netxen_load_firmware(adapter);
        netxen_free_adapter_offload(adapter);
 
-       udelay(500);            /* Delay for a while to drain the DMA engines */
+       mdelay(1000);           /* Delay for a while to drain the DMA engines */
        for (i = 0; i < adapter->port_count; i++) {
                port = adapter->port[i];
                if ((port) && (port->netdev)) {
@@ -543,7 +544,6 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
 
        if ((adapter->flags & NETXEN_NIC_MSI_ENABLED))
                pci_disable_msi(pdev);
-       pci_set_drvdata(pdev, NULL);
        if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC)
                netxen_free_hw_resources(adapter);
 
@@ -554,6 +554,7 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
 
        pci_release_regions(pdev);
        pci_disable_device(pdev);
+       pci_set_drvdata(pdev, NULL);
 
        for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) {
                recv_ctx = &adapter->recv_ctx[ctxid];
@@ -672,8 +673,6 @@ static int netxen_nic_close(struct net_device *netdev)
 
        if (!adapter->active_ports) {
                netxen_nic_disable_int(adapter);
-               if (adapter->irq)
-                       free_irq(adapter->irq, adapter);
                cmd_buff = adapter->cmd_buf_arr;
                for (i = 0; i < adapter->max_tx_desc_count; i++) {
                        buffrag = cmd_buff->frag_array;
@@ -1155,8 +1154,8 @@ static void __exit netxen_exit_module(void)
        /*
         * Wait for some time to allow the dma to drain, if any.
         */
-       destroy_workqueue(netxen_workq);
        pci_unregister_driver(&netxen_driver);
+       destroy_workqueue(netxen_workq);
 }
 
 module_exit(netxen_exit_module);
index 7879f855af0b27786414d0b06a914a6cb9c3011a..0c7c94328b7f6749489fc5746cac526e3bd9c1b5 100644 (file)
 #define CRB_CMD_CONSUMER_OFFSET_1   NETXEN_NIC_REG(0x1b0)
 #define CRB_TEMP_STATE              NETXEN_NIC_REG(0x1b4)
 
+/* used for ethtool tests */
+#define CRB_SCRATCHPAD_TEST        NETXEN_NIC_REG(0x280)
+
 /*
  * CrbPortPhanCntrHi/Lo is used to pass the address of HostPhantomIndex address
  * which can be read by the Phantom host to get producer/consumer indexes from
index 196993a29b09d2f020d6606eb72f0a4aa8bb5263..a6f4b24b017660a1811c9ccf68a5c56b963af4ce 100644 (file)
@@ -104,8 +104,6 @@ static int automatic_resume; /* experimental .. better should be zero */
 static int rfdadd;     /* rfdadd=1 may be better for 8K MEM cards */
 static int fifo=0x8;   /* don't change */
 
-/* #define REALLY_SLOW_IO */
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
index 568daeb3e9d8f56ac0e4b37249c5d2b9507dc66f..9ec6e9e54f47781b99d8c4402bc6930bd0807f6c 100644 (file)
@@ -514,8 +514,7 @@ static void ns83820_vlan_rx_kill_vid(struct net_device *ndev, unsigned short vid
 
        spin_lock_irq(&dev->misc_lock);
        spin_lock(&dev->tx_lock);
-       if (dev->vlgrp)
-               dev->vlgrp->vlan_devices[vid] = NULL;
+       vlan_group_set_device(dev->vlgrp, vid, NULL);
        spin_unlock(&dev->tx_lock);
        spin_unlock_irq(&dev->misc_lock);
 }
index 36f9d988278f76771292c45a365a41ddd4ad478e..4d94ba7899bfaf181ea972cb670b0555b575d38a 100644 (file)
@@ -1234,14 +1234,14 @@ static void pcnet32_rx_entry(struct net_device *dev,
                skb_put(skb, pkt_len);  /* Make room */
                pci_dma_sync_single_for_cpu(lp->pci_dev,
                                            lp->rx_dma_addr[entry],
-                                           PKT_BUF_SZ - 2,
+                                           pkt_len,
                                            PCI_DMA_FROMDEVICE);
                eth_copy_and_sum(skb,
                                 (unsigned char *)(lp->rx_skbuff[entry]->data),
                                 pkt_len, 0);
                pci_dma_sync_single_for_device(lp->pci_dev,
                                               lp->rx_dma_addr[entry],
-                                              PKT_BUF_SZ - 2,
+                                              pkt_len,
                                               PCI_DMA_FROMDEVICE);
        }
        lp->stats.rx_bytes += skb->len;
index 860bb0f60f688892e27e2cdb76837a421f08066b..ebfa2967cd68213a4ac8069b1807205631d58910 100644 (file)
@@ -7,6 +7,12 @@
  *
  * Version:    0.7.0
  *
+ * 070228 :    Fix to allow multiple sessions with same remote MAC and same
+ *             session id by including the local device ifindex in the
+ *             tuple identifying a session. This also ensures packets can't
+ *             be injected into a session from interfaces other than the one
+ *             specified by userspace. Florian Zumbiehl <florz@florz.de>
+ *             (Oh, BTW, this one is YYMMDD, in case you were wondering ...)
  * 220102 :    Fix module use count on failure in pppoe_create, pppox_sk -acme
  * 030700 :    Fixed connect logic to allow for disconnect.
  * 270700 :    Fixed potential SMP problems; we must protect against
@@ -127,14 +133,14 @@ static struct pppox_sock *item_hash_table[PPPOE_HASH_SIZE];
  *  Set/get/delete/rehash items  (internal versions)
  *
  **********************************************************************/
-static struct pppox_sock *__get_item(unsigned long sid, unsigned char *addr)
+static struct pppox_sock *__get_item(unsigned long sid, unsigned char *addr, int ifindex)
 {
        int hash = hash_item(sid, addr);
        struct pppox_sock *ret;
 
        ret = item_hash_table[hash];
 
-       while (ret && !cmp_addr(&ret->pppoe_pa, sid, addr))
+       while (ret && !(cmp_addr(&ret->pppoe_pa, sid, addr) && ret->pppoe_ifindex == ifindex))
                ret = ret->next;
 
        return ret;
@@ -147,21 +153,19 @@ static int __set_item(struct pppox_sock *po)
 
        ret = item_hash_table[hash];
        while (ret) {
-               if (cmp_2_addr(&ret->pppoe_pa, &po->pppoe_pa))
+               if (cmp_2_addr(&ret->pppoe_pa, &po->pppoe_pa) && ret->pppoe_ifindex == po->pppoe_ifindex)
                        return -EALREADY;
 
                ret = ret->next;
        }
 
-       if (!ret) {
-               po->next = item_hash_table[hash];
-               item_hash_table[hash] = po;
-       }
+       po->next = item_hash_table[hash];
+       item_hash_table[hash] = po;
 
        return 0;
 }
 
-static struct pppox_sock *__delete_item(unsigned long sid, char *addr)
+static struct pppox_sock *__delete_item(unsigned long sid, char *addr, int ifindex)
 {
        int hash = hash_item(sid, addr);
        struct pppox_sock *ret, **src;
@@ -170,7 +174,7 @@ static struct pppox_sock *__delete_item(unsigned long sid, char *addr)
        src = &item_hash_table[hash];
 
        while (ret) {
-               if (cmp_addr(&ret->pppoe_pa, sid, addr)) {
+               if (cmp_addr(&ret->pppoe_pa, sid, addr) && ret->pppoe_ifindex == ifindex) {
                        *src = ret->next;
                        break;
                }
@@ -188,12 +192,12 @@ static struct pppox_sock *__delete_item(unsigned long sid, char *addr)
  *
  **********************************************************************/
 static inline struct pppox_sock *get_item(unsigned long sid,
-                                        unsigned char *addr)
+                                        unsigned char *addr, int ifindex)
 {
        struct pppox_sock *po;
 
        read_lock_bh(&pppoe_hash_lock);
-       po = __get_item(sid, addr);
+       po = __get_item(sid, addr, ifindex);
        if (po)
                sock_hold(sk_pppox(po));
        read_unlock_bh(&pppoe_hash_lock);
@@ -203,7 +207,15 @@ static inline struct pppox_sock *get_item(unsigned long sid,
 
 static inline struct pppox_sock *get_item_by_addr(struct sockaddr_pppox *sp)
 {
-       return get_item(sp->sa_addr.pppoe.sid, sp->sa_addr.pppoe.remote);
+       struct net_device *dev = NULL;
+       int ifindex;
+
+       dev = dev_get_by_name(sp->sa_addr.pppoe.dev);
+       if(!dev)
+               return NULL;
+       ifindex = dev->ifindex;
+       dev_put(dev);
+       return get_item(sp->sa_addr.pppoe.sid, sp->sa_addr.pppoe.remote, ifindex);
 }
 
 static inline int set_item(struct pppox_sock *po)
@@ -220,12 +232,12 @@ static inline int set_item(struct pppox_sock *po)
        return i;
 }
 
-static inline struct pppox_sock *delete_item(unsigned long sid, char *addr)
+static inline struct pppox_sock *delete_item(unsigned long sid, char *addr, int ifindex)
 {
        struct pppox_sock *ret;
 
        write_lock_bh(&pppoe_hash_lock);
-       ret = __delete_item(sid, addr);
+       ret = __delete_item(sid, addr, ifindex);
        write_unlock_bh(&pppoe_hash_lock);
 
        return ret;
@@ -391,7 +403,7 @@ static int pppoe_rcv(struct sk_buff *skb,
 
        ph = (struct pppoe_hdr *) skb->nh.raw;
 
-       po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source);
+       po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source, dev->ifindex);
        if (po != NULL)
                return sk_receive_skb(sk_pppox(po), skb, 0);
 drop:
@@ -425,7 +437,7 @@ static int pppoe_disc_rcv(struct sk_buff *skb,
        if (ph->code != PADT_CODE)
                goto abort;
 
-       po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source);
+       po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source, dev->ifindex);
        if (po) {
                struct sock *sk = sk_pppox(po);
 
@@ -517,7 +529,7 @@ static int pppoe_release(struct socket *sock)
 
        po = pppox_sk(sk);
        if (po->pppoe_pa.sid) {
-               delete_item(po->pppoe_pa.sid, po->pppoe_pa.remote);
+               delete_item(po->pppoe_pa.sid, po->pppoe_pa.remote, po->pppoe_ifindex);
        }
 
        if (po->pppoe_dev)
@@ -539,7 +551,7 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
                  int sockaddr_len, int flags)
 {
        struct sock *sk = sock->sk;
-       struct net_device *dev = NULL;
+       struct net_device *dev;
        struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr;
        struct pppox_sock *po = pppox_sk(sk);
        int error;
@@ -565,7 +577,7 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
                pppox_unbind_sock(sk);
 
                /* Delete the old binding */
-               delete_item(po->pppoe_pa.sid,po->pppoe_pa.remote);
+               delete_item(po->pppoe_pa.sid,po->pppoe_pa.remote,po->pppoe_ifindex);
 
                if(po->pppoe_dev)
                        dev_put(po->pppoe_dev);
@@ -585,6 +597,7 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
                        goto end;
 
                po->pppoe_dev = dev;
+               po->pppoe_ifindex = dev->ifindex;
 
                if (!(dev->flags & IFF_UP))
                        goto err_put;
@@ -705,7 +718,7 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd,
                        break;
 
                /* PPPoE address from the user specifies an outbound
-                  PPPoE address to which frames are forwarded to */
+                  PPPoE address which frames are forwarded to */
                err = -EFAULT;
                if (copy_from_user(&po->pppoe_relay,
                                   (void __user *)arg,
index a142cdfd947b961f0420ce74a0339de272c5b8b0..d3f65dab306c88568b0ce0900a651bfe5874a070 100755 (executable)
@@ -39,7 +39,7 @@
 
 #define DRV_NAME       "qla3xxx"
 #define DRV_STRING     "QLogic ISP3XXX Network Driver"
-#define DRV_VERSION    "v2.02.00-k36"
+#define DRV_VERSION    "v2.03.00-k3"
 #define PFX            DRV_NAME " "
 
 static const char ql3xxx_driver_name[] = DRV_NAME;
@@ -276,7 +276,8 @@ static void ql_enable_interrupts(struct ql3_adapter *qdev)
 static void ql_release_to_lrg_buf_free_list(struct ql3_adapter *qdev,
                                            struct ql_rcv_buf_cb *lrg_buf_cb)
 {
-       u64 map;
+       dma_addr_t map;
+       int err;
        lrg_buf_cb->next = NULL;
 
        if (qdev->lrg_buf_free_tail == NULL) {  /* The list is empty  */
@@ -287,9 +288,10 @@ static void ql_release_to_lrg_buf_free_list(struct ql3_adapter *qdev,
        }
 
        if (!lrg_buf_cb->skb) {
-               lrg_buf_cb->skb = dev_alloc_skb(qdev->lrg_buffer_len);
+               lrg_buf_cb->skb = netdev_alloc_skb(qdev->ndev,
+                                                  qdev->lrg_buffer_len);
                if (unlikely(!lrg_buf_cb->skb)) {
-                       printk(KERN_ERR PFX "%s: failed dev_alloc_skb().\n",
+                       printk(KERN_ERR PFX "%s: failed netdev_alloc_skb().\n",
                               qdev->ndev->name);
                        qdev->lrg_buf_skb_check++;
                } else {
@@ -303,6 +305,17 @@ static void ql_release_to_lrg_buf_free_list(struct ql3_adapter *qdev,
                                             qdev->lrg_buffer_len -
                                             QL_HEADER_SPACE,
                                             PCI_DMA_FROMDEVICE);
+                       err = pci_dma_mapping_error(map);
+                       if(err) {
+                               printk(KERN_ERR "%s: PCI mapping failed with error: %d\n", 
+                                      qdev->ndev->name, err);
+                               dev_kfree_skb(lrg_buf_cb->skb);
+                               lrg_buf_cb->skb = NULL;
+
+                               qdev->lrg_buf_skb_check++;
+                               return;
+                       }
+
                        lrg_buf_cb->buf_phy_addr_low =
                            cpu_to_le32(LS_64BITS(map));
                        lrg_buf_cb->buf_phy_addr_high =
@@ -1387,6 +1400,8 @@ static void ql_link_state_machine(struct ql3_adapter *qdev)
                        printk(KERN_INFO PFX
                               "%s: Reset in progress, skip processing link "
                               "state.\n", qdev->ndev->name);
+
+               spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);               
                return;
        }
 
@@ -1518,8 +1533,10 @@ static int ql_get_auto_cfg_status(struct ql3_adapter *qdev)
        spin_lock_irqsave(&qdev->hw_lock, hw_flags);
        if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK,
                (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
-                        2) << 7))
+                        2) << 7)) {
+               spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
                return 0;
+       }
        status = ql_is_auto_cfg(qdev);
        ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK);
        spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
@@ -1533,8 +1550,10 @@ static u32 ql_get_speed(struct ql3_adapter *qdev)
        spin_lock_irqsave(&qdev->hw_lock, hw_flags);
        if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK,
                (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
-                        2) << 7))
+                        2) << 7)) {
+               spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
                return 0;
+       }
        status = ql_get_link_speed(qdev);
        ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK);
        spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
@@ -1548,8 +1567,10 @@ static int ql_get_full_dup(struct ql3_adapter *qdev)
        spin_lock_irqsave(&qdev->hw_lock, hw_flags);
        if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK,
                (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
-                        2) << 7))
+                        2) << 7)) {
+               spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
                return 0;
+       }
        status = ql_is_link_full_dup(qdev);
        ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK);
        spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
@@ -1615,14 +1636,16 @@ static const struct ethtool_ops ql3xxx_ethtool_ops = {
 static int ql_populate_free_queue(struct ql3_adapter *qdev)
 {
        struct ql_rcv_buf_cb *lrg_buf_cb = qdev->lrg_buf_free_head;
-       u64 map;
+       dma_addr_t map;
+       int err;
 
        while (lrg_buf_cb) {
                if (!lrg_buf_cb->skb) {
-                       lrg_buf_cb->skb = dev_alloc_skb(qdev->lrg_buffer_len);
+                       lrg_buf_cb->skb = netdev_alloc_skb(qdev->ndev,
+                                                          qdev->lrg_buffer_len);
                        if (unlikely(!lrg_buf_cb->skb)) {
                                printk(KERN_DEBUG PFX
-                                      "%s: Failed dev_alloc_skb().\n",
+                                      "%s: Failed netdev_alloc_skb().\n",
                                       qdev->ndev->name);
                                break;
                        } else {
@@ -1636,6 +1659,17 @@ static int ql_populate_free_queue(struct ql3_adapter *qdev)
                                                     qdev->lrg_buffer_len -
                                                     QL_HEADER_SPACE,
                                                     PCI_DMA_FROMDEVICE);
+
+                               err = pci_dma_mapping_error(map);
+                               if(err) {
+                                       printk(KERN_ERR "%s: PCI mapping failed with error: %d\n", 
+                                              qdev->ndev->name, err);
+                                       dev_kfree_skb(lrg_buf_cb->skb);
+                                       lrg_buf_cb->skb = NULL;
+                                       break;
+                               }
+
+
                                lrg_buf_cb->buf_phy_addr_low =
                                    cpu_to_le32(LS_64BITS(map));
                                lrg_buf_cb->buf_phy_addr_high =
@@ -1690,11 +1724,11 @@ static void ql_update_lrg_bufq_prod_index(struct ql3_adapter *qdev)
 
                        qdev->lrg_buf_q_producer_index++;
 
-                       if (qdev->lrg_buf_q_producer_index == NUM_LBUFQ_ENTRIES)
+                       if (qdev->lrg_buf_q_producer_index == qdev->num_lbufq_entries)
                                qdev->lrg_buf_q_producer_index = 0;
 
                        if (qdev->lrg_buf_q_producer_index ==
-                           (NUM_LBUFQ_ENTRIES - 1)) {
+                           (qdev->num_lbufq_entries - 1)) {
                                lrg_buf_q_ele = qdev->lrg_buf_q_virt_addr;
                        }
                }
@@ -1713,8 +1747,31 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
 {
        struct ql_tx_buf_cb *tx_cb;
        int i;
+       int retval = 0;
 
+       if(mac_rsp->flags & OB_MAC_IOCB_RSP_S) {
+               printk(KERN_WARNING "Frame short but, frame was padded and sent.\n");
+       }
+       
        tx_cb = &qdev->tx_buf[mac_rsp->transaction_id];
+
+       /*  Check the transmit response flags for any errors */
+       if(mac_rsp->flags & OB_MAC_IOCB_RSP_S) {
+               printk(KERN_ERR "Frame too short to be legal, frame not sent.\n");
+
+               qdev->stats.tx_errors++;
+               retval = -EIO;
+               goto frame_not_sent;
+       }
+
+       if(tx_cb->seg_count == 0) {
+               printk(KERN_ERR "tx_cb->seg_count == 0: %d\n", mac_rsp->transaction_id);
+
+               qdev->stats.tx_errors++;
+               retval = -EIO;
+               goto invalid_seg_count;
+       }
+
        pci_unmap_single(qdev->pdev,
                         pci_unmap_addr(&tx_cb->map[0], mapaddr),
                         pci_unmap_len(&tx_cb->map[0], maplen),
@@ -1731,11 +1788,32 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
        }
        qdev->stats.tx_packets++;
        qdev->stats.tx_bytes += tx_cb->skb->len;
+
+frame_not_sent:
        dev_kfree_skb_irq(tx_cb->skb);
        tx_cb->skb = NULL;
+
+invalid_seg_count:
        atomic_inc(&qdev->tx_count);
 }
 
+void ql_get_sbuf(struct ql3_adapter *qdev)
+{
+       if (++qdev->small_buf_index == NUM_SMALL_BUFFERS)
+               qdev->small_buf_index = 0;
+       qdev->small_buf_release_cnt++;
+}
+
+struct ql_rcv_buf_cb *ql_get_lbuf(struct ql3_adapter *qdev)
+{
+       struct ql_rcv_buf_cb *lrg_buf_cb = NULL;
+       lrg_buf_cb = &qdev->lrg_buf[qdev->lrg_buf_index];
+       qdev->lrg_buf_release_cnt++;
+       if (++qdev->lrg_buf_index == qdev->num_large_buffers)
+               qdev->lrg_buf_index = 0;
+       return(lrg_buf_cb);
+}
+
 /*
  * The difference between 3022 and 3032 for inbound completions:
  * 3022 uses two buffers per completion.  The first buffer contains 
@@ -1751,47 +1829,21 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
 static void ql_process_mac_rx_intr(struct ql3_adapter *qdev,
                                   struct ib_mac_iocb_rsp *ib_mac_rsp_ptr)
 {
-       long int offset;
-       u32 lrg_buf_phy_addr_low = 0;
        struct ql_rcv_buf_cb *lrg_buf_cb1 = NULL;
        struct ql_rcv_buf_cb *lrg_buf_cb2 = NULL;
-       u32 *curr_ial_ptr;
        struct sk_buff *skb;
        u16 length = le16_to_cpu(ib_mac_rsp_ptr->length);
 
        /*
         * Get the inbound address list (small buffer).
         */
-       offset = qdev->small_buf_index * QL_SMALL_BUFFER_SIZE;
-       if (++qdev->small_buf_index == NUM_SMALL_BUFFERS)
-               qdev->small_buf_index = 0;
+       ql_get_sbuf(qdev);
 
-       curr_ial_ptr = (u32 *) (qdev->small_buf_virt_addr + offset);
-       qdev->last_rsp_offset = qdev->small_buf_phy_addr_low + offset;
-       qdev->small_buf_release_cnt++;
-
-       if (qdev->device_id == QL3022_DEVICE_ID) {
-               /* start of first buffer (3022 only) */
-               lrg_buf_phy_addr_low = le32_to_cpu(*curr_ial_ptr);
-               lrg_buf_cb1 = &qdev->lrg_buf[qdev->lrg_buf_index];
-               qdev->lrg_buf_release_cnt++;
-               if (++qdev->lrg_buf_index == NUM_LARGE_BUFFERS) {
-                       qdev->lrg_buf_index = 0;
-               }
-               curr_ial_ptr++; /* 64-bit pointers require two incs. */
-               curr_ial_ptr++;
-       }
+       if (qdev->device_id == QL3022_DEVICE_ID)
+               lrg_buf_cb1 = ql_get_lbuf(qdev);
 
        /* start of second buffer */
-       lrg_buf_phy_addr_low = le32_to_cpu(*curr_ial_ptr);
-       lrg_buf_cb2 = &qdev->lrg_buf[qdev->lrg_buf_index];
-
-       /*
-        * Second buffer gets sent up the stack.
-        */
-       qdev->lrg_buf_release_cnt++;
-       if (++qdev->lrg_buf_index == NUM_LARGE_BUFFERS)
-               qdev->lrg_buf_index = 0;
+       lrg_buf_cb2 = ql_get_lbuf(qdev);
        skb = lrg_buf_cb2->skb;
 
        qdev->stats.rx_packets++;
@@ -1819,11 +1871,8 @@ static void ql_process_mac_rx_intr(struct ql3_adapter *qdev,
 static void ql_process_macip_rx_intr(struct ql3_adapter *qdev,
                                     struct ib_ip_iocb_rsp *ib_ip_rsp_ptr)
 {
-       long int offset;
-       u32 lrg_buf_phy_addr_low = 0;
        struct ql_rcv_buf_cb *lrg_buf_cb1 = NULL;
        struct ql_rcv_buf_cb *lrg_buf_cb2 = NULL;
-       u32 *curr_ial_ptr;
        struct sk_buff *skb1 = NULL, *skb2;
        struct net_device *ndev = qdev->ndev;
        u16 length = le16_to_cpu(ib_ip_rsp_ptr->length);
@@ -1833,35 +1882,20 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev,
         * Get the inbound address list (small buffer).
         */
 
-       offset = qdev->small_buf_index * QL_SMALL_BUFFER_SIZE;
-       if (++qdev->small_buf_index == NUM_SMALL_BUFFERS)
-               qdev->small_buf_index = 0;
-       curr_ial_ptr = (u32 *) (qdev->small_buf_virt_addr + offset);
-       qdev->last_rsp_offset = qdev->small_buf_phy_addr_low + offset;
-       qdev->small_buf_release_cnt++;
+       ql_get_sbuf(qdev);
 
        if (qdev->device_id == QL3022_DEVICE_ID) {
                /* start of first buffer on 3022 */
-               lrg_buf_phy_addr_low = le32_to_cpu(*curr_ial_ptr);
-               lrg_buf_cb1 = &qdev->lrg_buf[qdev->lrg_buf_index];
-               qdev->lrg_buf_release_cnt++;
-               if (++qdev->lrg_buf_index == NUM_LARGE_BUFFERS)
-                       qdev->lrg_buf_index = 0;
+               lrg_buf_cb1 = ql_get_lbuf(qdev);
                skb1 = lrg_buf_cb1->skb;
-               curr_ial_ptr++; /* 64-bit pointers require two incs. */
-               curr_ial_ptr++;
                size = ETH_HLEN;
                if (*((u16 *) skb1->data) != 0xFFFF)
                        size += VLAN_ETH_HLEN - ETH_HLEN;
        }
 
        /* start of second buffer */
-       lrg_buf_phy_addr_low = le32_to_cpu(*curr_ial_ptr);
-       lrg_buf_cb2 = &qdev->lrg_buf[qdev->lrg_buf_index];
+       lrg_buf_cb2 = ql_get_lbuf(qdev);
        skb2 = lrg_buf_cb2->skb;
-       qdev->lrg_buf_release_cnt++;
-       if (++qdev->lrg_buf_index == NUM_LARGE_BUFFERS)
-               qdev->lrg_buf_index = 0;
 
        skb_put(skb2, length);  /* Just the second buffer length here. */
        pci_unmap_single(qdev->pdev,
@@ -1914,10 +1948,13 @@ static int ql_tx_rx_clean(struct ql3_adapter *qdev,
        struct net_rsp_iocb *net_rsp;
        struct net_device *ndev = qdev->ndev;
        unsigned long hw_flags;
+       int work_done = 0;
+
+       u32 rsp_producer_index = le32_to_cpu(*(qdev->prsp_producer_index));
 
        /* While there are entries in the completion queue. */
-       while ((cpu_to_le32(*(qdev->prsp_producer_index)) !=
-               qdev->rsp_consumer_index) && (*rx_cleaned < work_to_do)) {
+       while ((rsp_producer_index !=
+               qdev->rsp_consumer_index) && (work_done < work_to_do)) {
 
                net_rsp = qdev->rsp_current;
                switch (net_rsp->opcode) {
@@ -1968,37 +2005,34 @@ static int ql_tx_rx_clean(struct ql3_adapter *qdev,
                } else {
                        qdev->rsp_current++;
                }
+
+               work_done = *tx_cleaned + *rx_cleaned;
        }
 
-       spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+       if(work_done) {
+               spin_lock_irqsave(&qdev->hw_lock, hw_flags);
 
-       ql_update_lrg_bufq_prod_index(qdev);
+               ql_update_lrg_bufq_prod_index(qdev);
 
-       if (qdev->small_buf_release_cnt >= 16) {
-               while (qdev->small_buf_release_cnt >= 16) {
-                       qdev->small_buf_q_producer_index++;
+               if (qdev->small_buf_release_cnt >= 16) {
+                       while (qdev->small_buf_release_cnt >= 16) {
+                               qdev->small_buf_q_producer_index++;
 
-                       if (qdev->small_buf_q_producer_index ==
-                           NUM_SBUFQ_ENTRIES)
-                               qdev->small_buf_q_producer_index = 0;
-                       qdev->small_buf_release_cnt -= 8;
-               }
+                               if (qdev->small_buf_q_producer_index ==
+                                   NUM_SBUFQ_ENTRIES)
+                                       qdev->small_buf_q_producer_index = 0;
+                               qdev->small_buf_release_cnt -= 8;
+                       }
 
-               ql_write_common_reg(qdev,
-                                   &port_regs->CommonRegs.
-                                   rxSmallQProducerIndex,
-                                   qdev->small_buf_q_producer_index);
-       }
+                       wmb();
+                       ql_write_common_reg(qdev,
+                                           &port_regs->CommonRegs.
+                                           rxSmallQProducerIndex,
+                                           qdev->small_buf_q_producer_index);
 
-       ql_write_common_reg(qdev,
-                           &port_regs->CommonRegs.rspQConsumerIndex,
-                           qdev->rsp_consumer_index);
-       spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+               }
 
-       if (unlikely(netif_queue_stopped(qdev->ndev))) {
-               if (netif_queue_stopped(qdev->ndev) &&
-                   (atomic_read(&qdev->tx_count) > (NUM_REQ_Q_ENTRIES / 4)))
-                       netif_wake_queue(qdev->ndev);
+               spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
        }
 
        return *tx_cleaned + *rx_cleaned;
@@ -2009,6 +2043,8 @@ static int ql_poll(struct net_device *ndev, int *budget)
        struct ql3_adapter *qdev = netdev_priv(ndev);
        int work_to_do = min(*budget, ndev->quota);
        int rx_cleaned = 0, tx_cleaned = 0;
+       unsigned long hw_flags;
+       struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
 
        if (!netif_carrier_ok(ndev))
                goto quit_polling;
@@ -2017,9 +2053,17 @@ static int ql_poll(struct net_device *ndev, int *budget)
        *budget -= rx_cleaned;
        ndev->quota -= rx_cleaned;
 
-       if ((!tx_cleaned && !rx_cleaned) || !netif_running(ndev)) {
+       if( tx_cleaned + rx_cleaned != work_to_do ||
+           !netif_running(ndev)) {
 quit_polling:
                netif_rx_complete(ndev);
+
+               spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+               ql_write_common_reg(qdev,
+                                   &port_regs->CommonRegs.rspQConsumerIndex,
+                                   qdev->rsp_consumer_index);
+               spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+
                ql_enable_interrupts(qdev);
                return 0;
        }
@@ -2073,10 +2117,9 @@ static irqreturn_t ql3xxx_isr(int irq, void *dev_id)
                spin_unlock(&qdev->adapter_lock);
        } else if (value & ISP_IMR_DISABLE_CMPL_INT) {
                ql_disable_interrupts(qdev);
-               if (likely(netif_rx_schedule_prep(ndev)))
+               if (likely(netif_rx_schedule_prep(ndev))) {
                        __netif_rx_schedule(ndev);
-               else
-                       ql_enable_interrupts(qdev);
+               }
        } else {
                return IRQ_NONE;
        }
@@ -2093,8 +2136,12 @@ static irqreturn_t ql3xxx_isr(int irq, void *dev_id)
  * the next AOL if more frags are coming.  
  * That is why the frags:segment count  ratio is not linear.
  */
-static int ql_get_seg_count(unsigned short frags)
+static int ql_get_seg_count(struct ql3_adapter *qdev,
+                           unsigned short frags)
 {
+       if (qdev->device_id == QL3022_DEVICE_ID)
+               return 1;
+
        switch(frags) {
        case 0: return 1;       /* just the skb->data seg */
        case 1: return 2;       /* skb->data + 1 frag */
@@ -2139,11 +2186,13 @@ static void ql_hw_csum_setup(struct sk_buff *skb,
 
        if (ip) {
                if (ip->protocol == IPPROTO_TCP) {
-                       mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_TC;
+                       mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_TC | 
+                       OB_3032MAC_IOCB_REQ_IC;
                        mac_iocb_ptr->ip_hdr_off = offset;
                        mac_iocb_ptr->ip_hdr_len = ip->ihl;
                } else if (ip->protocol == IPPROTO_UDP) {
-                       mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_UC;
+                       mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_UC | 
+                       OB_3032MAC_IOCB_REQ_IC;
                        mac_iocb_ptr->ip_hdr_off = offset;
                        mac_iocb_ptr->ip_hdr_len = ip->ihl;
                }
@@ -2151,53 +2200,42 @@ static void ql_hw_csum_setup(struct sk_buff *skb,
 }
 
 /*
- * The difference between 3022 and 3032 sends:
- * 3022 only supports a simple single segment transmission.
- * 3032 supports checksumming and scatter/gather lists (fragments).
- * The 3032 supports sglists by using the 3 addr/len pairs (ALP) 
- * in the IOCB plus a chain of outbound address lists (OAL) that 
- * each contain 5 ALPs.  The last ALP of the IOCB (3rd) or OAL (5th) 
- * will used to point to an OAL when more ALP entries are required.  
- * The IOCB is always the top of the chain followed by one or more 
- * OALs (when necessary).
+ * Map the buffers for this transmit.  This will return
+ * NETDEV_TX_BUSY or NETDEV_TX_OK based on success.
  */
-static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev)
+static int ql_send_map(struct ql3_adapter *qdev,
+                               struct ob_mac_iocb_req *mac_iocb_ptr,
+                               struct ql_tx_buf_cb *tx_cb,
+                               struct sk_buff *skb)
 {
-       struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev);
-       struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
-       struct ql_tx_buf_cb *tx_cb;
-       u32 tot_len = skb->len;
        struct oal *oal;
        struct oal_entry *oal_entry;
-       int len;
-       struct ob_mac_iocb_req *mac_iocb_ptr;
-       u64 map;
+       int len = skb_headlen(skb);
+       dma_addr_t map;
+       int err;
+       int completed_segs, i;
        int seg_cnt, seg = 0;
        int frag_cnt = (int)skb_shinfo(skb)->nr_frags;
 
-       if (unlikely(atomic_read(&qdev->tx_count) < 2)) {
-               if (!netif_queue_stopped(ndev))
-                       netif_stop_queue(ndev);
-               return NETDEV_TX_BUSY;
-       }
-       tx_cb = &qdev->tx_buf[qdev->req_producer_index] ;
-       seg_cnt = tx_cb->seg_count = ql_get_seg_count((skb_shinfo(skb)->nr_frags));
+       seg_cnt = tx_cb->seg_count = ql_get_seg_count(qdev,
+                                                     (skb_shinfo(skb)->nr_frags));
        if(seg_cnt == -1) {
                printk(KERN_ERR PFX"%s: invalid segment count!\n",__func__);
-               return NETDEV_TX_OK;
-
+               return NETDEV_TX_BUSY;
        }
-       mac_iocb_ptr = tx_cb->queue_entry;
-       memset((void *)mac_iocb_ptr, 0, sizeof(struct ob_mac_iocb_req));
-       mac_iocb_ptr->opcode = qdev->mac_ob_opcode;
-       mac_iocb_ptr->flags |= qdev->mb_bit_mask;
-       mac_iocb_ptr->transaction_id = qdev->req_producer_index;
-       mac_iocb_ptr->data_len = cpu_to_le16((u16) tot_len);
-       tx_cb->skb = skb;
-       if (skb->ip_summed == CHECKSUM_PARTIAL)
-               ql_hw_csum_setup(skb, mac_iocb_ptr);
-       len = skb_headlen(skb);
+       /*
+        * Map the skb buffer first.
+        */
        map = pci_map_single(qdev->pdev, skb->data, len, PCI_DMA_TODEVICE);
+
+       err = pci_dma_mapping_error(map);
+       if(err) {
+               printk(KERN_ERR "%s: PCI mapping failed with error: %d\n", 
+                      qdev->ndev->name, err);
+
+               return NETDEV_TX_BUSY;
+       }
+       
        oal_entry = (struct oal_entry *)&mac_iocb_ptr->buf_addr0_low;
        oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map));
        oal_entry->dma_hi = cpu_to_le32(MS_64BITS(map));
@@ -2206,15 +2244,14 @@ static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev)
        pci_unmap_len_set(&tx_cb->map[seg], maplen, len);
        seg++;
 
-       if (!skb_shinfo(skb)->nr_frags) {
+       if (seg_cnt == 1) {
                /* Terminate the last segment. */
                oal_entry->len =
                    cpu_to_le32(le32_to_cpu(oal_entry->len) | OAL_LAST_ENTRY);
        } else {
-               int i;
                oal = tx_cb->oal;
-               for (i=0; i<frag_cnt; i++,seg++) {
-                       skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+               for (completed_segs=0; completed_segs<frag_cnt; completed_segs++,seg++) {
+                       skb_frag_t *frag = &skb_shinfo(skb)->frags[completed_segs];
                        oal_entry++;
                        if ((seg == 2 && seg_cnt > 3) ||        /* Check for continuation */
                            (seg == 7 && seg_cnt > 8) ||        /* requirements. It's strange */
@@ -2224,6 +2261,15 @@ static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev)
                                map = pci_map_single(qdev->pdev, oal,
                                                     sizeof(struct oal),
                                                     PCI_DMA_TODEVICE);
+
+                               err = pci_dma_mapping_error(map);
+                               if(err) {
+
+                                       printk(KERN_ERR "%s: PCI mapping outbound address list with error: %d\n", 
+                                              qdev->ndev->name, err);
+                                       goto map_error;
+                               }
+
                                oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map));
                                oal_entry->dma_hi = cpu_to_le32(MS_64BITS(map));
                                oal_entry->len =
@@ -2242,6 +2288,14 @@ static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev)
                            pci_map_page(qdev->pdev, frag->page,
                                         frag->page_offset, frag->size,
                                         PCI_DMA_TODEVICE);
+
+                       err = pci_dma_mapping_error(map);
+                       if(err) {
+                               printk(KERN_ERR "%s: PCI mapping frags failed with error: %d\n", 
+                                      qdev->ndev->name, err);
+                               goto map_error;
+                       }
+
                        oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map));
                        oal_entry->dma_hi = cpu_to_le32(MS_64BITS(map));
                        oal_entry->len = cpu_to_le32(frag->size);
@@ -2253,6 +2307,94 @@ static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev)
                oal_entry->len =
                    cpu_to_le32(le32_to_cpu(oal_entry->len) | OAL_LAST_ENTRY);
        }
+
+       return NETDEV_TX_OK;
+
+map_error:
+       /* A PCI mapping failed and now we will need to back out
+        * We need to traverse through the oal's and associated pages which 
+        * have been mapped and now we must unmap them to clean up properly
+        */
+       
+       seg = 1;
+       oal_entry = (struct oal_entry *)&mac_iocb_ptr->buf_addr0_low;
+       oal = tx_cb->oal;
+       for (i=0; i<completed_segs; i++,seg++) {
+               oal_entry++;
+
+               if((seg == 2 && seg_cnt > 3) ||        /* Check for continuation */
+                  (seg == 7 && seg_cnt > 8) ||        /* requirements. It's strange */
+                  (seg == 12 && seg_cnt > 13) ||      /* but necessary. */
+                  (seg == 17 && seg_cnt > 18)) {
+                       pci_unmap_single(qdev->pdev,
+                               pci_unmap_addr(&tx_cb->map[seg], mapaddr),
+                               pci_unmap_len(&tx_cb->map[seg], maplen),
+                                PCI_DMA_TODEVICE);
+                       oal++;
+                       seg++;
+               }
+
+               pci_unmap_page(qdev->pdev,
+                              pci_unmap_addr(&tx_cb->map[seg], mapaddr),
+                              pci_unmap_len(&tx_cb->map[seg], maplen),
+                              PCI_DMA_TODEVICE);
+       }
+
+       pci_unmap_single(qdev->pdev,
+                        pci_unmap_addr(&tx_cb->map[0], mapaddr),
+                        pci_unmap_addr(&tx_cb->map[0], maplen),
+                        PCI_DMA_TODEVICE);
+
+       return NETDEV_TX_BUSY;
+
+}
+
+/*
+ * The difference between 3022 and 3032 sends:
+ * 3022 only supports a simple single segment transmission.
+ * 3032 supports checksumming and scatter/gather lists (fragments).
+ * The 3032 supports sglists by using the 3 addr/len pairs (ALP) 
+ * in the IOCB plus a chain of outbound address lists (OAL) that 
+ * each contain 5 ALPs.  The last ALP of the IOCB (3rd) or OAL (5th) 
+ * will used to point to an OAL when more ALP entries are required.  
+ * The IOCB is always the top of the chain followed by one or more 
+ * OALs (when necessary).
+ */
+static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev)
+{
+       struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev);
+       struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+       struct ql_tx_buf_cb *tx_cb;
+       u32 tot_len = skb->len;
+       struct ob_mac_iocb_req *mac_iocb_ptr;
+
+       if (unlikely(atomic_read(&qdev->tx_count) < 2)) {
+               return NETDEV_TX_BUSY;
+       }
+       
+       tx_cb = &qdev->tx_buf[qdev->req_producer_index] ;
+       if((tx_cb->seg_count = ql_get_seg_count(qdev,
+                                               (skb_shinfo(skb)->nr_frags))) == -1) {
+               printk(KERN_ERR PFX"%s: invalid segment count!\n",__func__);
+               return NETDEV_TX_OK;
+       }
+       
+       mac_iocb_ptr = tx_cb->queue_entry;
+       mac_iocb_ptr->opcode = qdev->mac_ob_opcode;
+       mac_iocb_ptr->flags = OB_MAC_IOCB_REQ_X;
+       mac_iocb_ptr->flags |= qdev->mb_bit_mask;
+       mac_iocb_ptr->transaction_id = qdev->req_producer_index;
+       mac_iocb_ptr->data_len = cpu_to_le16((u16) tot_len);
+       tx_cb->skb = skb;
+       if (qdev->device_id == QL3032_DEVICE_ID &&
+           skb->ip_summed == CHECKSUM_PARTIAL)
+               ql_hw_csum_setup(skb, mac_iocb_ptr);
+       
+       if(ql_send_map(qdev,mac_iocb_ptr,tx_cb,skb) != NETDEV_TX_OK) {
+               printk(KERN_ERR PFX"%s: Could not map the segments!\n",__func__);
+               return NETDEV_TX_BUSY;
+       }
+       
        wmb();
        qdev->req_producer_index++;
        if (qdev->req_producer_index == NUM_REQ_Q_ENTRIES)
@@ -2338,12 +2480,19 @@ static int ql_alloc_buffer_queues(struct ql3_adapter *qdev)
 {
        /* Create Large Buffer Queue */
        qdev->lrg_buf_q_size =
-           NUM_LBUFQ_ENTRIES * sizeof(struct lrg_buf_q_entry);
+           qdev->num_lbufq_entries * sizeof(struct lrg_buf_q_entry);
        if (qdev->lrg_buf_q_size < PAGE_SIZE)
                qdev->lrg_buf_q_alloc_size = PAGE_SIZE;
        else
                qdev->lrg_buf_q_alloc_size = qdev->lrg_buf_q_size * 2;
 
+       qdev->lrg_buf = kmalloc(qdev->num_large_buffers * sizeof(struct ql_rcv_buf_cb),GFP_KERNEL);
+       if (qdev->lrg_buf == NULL) {
+               printk(KERN_ERR PFX
+                      "%s: qdev->lrg_buf alloc failed.\n", qdev->ndev->name);
+               return -ENOMEM;
+       }
+       
        qdev->lrg_buf_q_alloc_virt_addr =
            pci_alloc_consistent(qdev->pdev,
                                 qdev->lrg_buf_q_alloc_size,
@@ -2393,7 +2542,7 @@ static void ql_free_buffer_queues(struct ql3_adapter *qdev)
                       "%s: Already done.\n", qdev->ndev->name);
                return;
        }
-
+       if(qdev->lrg_buf) kfree(qdev->lrg_buf);
        pci_free_consistent(qdev->pdev,
                            qdev->lrg_buf_q_alloc_size,
                            qdev->lrg_buf_q_alloc_virt_addr,
@@ -2438,8 +2587,6 @@ static int ql_alloc_small_buffers(struct ql3_adapter *qdev)
 
        small_buf_q_entry = qdev->small_buf_q_virt_addr;
 
-       qdev->last_rsp_offset = qdev->small_buf_phy_addr_low;
-
        /* Initialize the small buffer queue. */
        for (i = 0; i < (QL_ADDR_ELE_PER_BUFQ_ENTRY * NUM_SBUFQ_ENTRIES); i++) {
                small_buf_q_entry->addr_high =
@@ -2476,7 +2623,7 @@ static void ql_free_large_buffers(struct ql3_adapter *qdev)
        int i = 0;
        struct ql_rcv_buf_cb *lrg_buf_cb;
 
-       for (i = 0; i < NUM_LARGE_BUFFERS; i++) {
+       for (i = 0; i < qdev->num_large_buffers; i++) {
                lrg_buf_cb = &qdev->lrg_buf[i];
                if (lrg_buf_cb->skb) {
                        dev_kfree_skb(lrg_buf_cb->skb);
@@ -2497,7 +2644,7 @@ static void ql_init_large_buffers(struct ql3_adapter *qdev)
        struct ql_rcv_buf_cb *lrg_buf_cb;
        struct bufq_addr_element *buf_addr_ele = qdev->lrg_buf_q_virt_addr;
 
-       for (i = 0; i < NUM_LARGE_BUFFERS; i++) {
+       for (i = 0; i < qdev->num_large_buffers; i++) {
                lrg_buf_cb = &qdev->lrg_buf[i];
                buf_addr_ele->addr_high = lrg_buf_cb->buf_phy_addr_high;
                buf_addr_ele->addr_low = lrg_buf_cb->buf_phy_addr_low;
@@ -2512,10 +2659,12 @@ static int ql_alloc_large_buffers(struct ql3_adapter *qdev)
        int i;
        struct ql_rcv_buf_cb *lrg_buf_cb;
        struct sk_buff *skb;
-       u64 map;
+       dma_addr_t map;
+       int err;
 
-       for (i = 0; i < NUM_LARGE_BUFFERS; i++) {
-               skb = dev_alloc_skb(qdev->lrg_buffer_len);
+       for (i = 0; i < qdev->num_large_buffers; i++) {
+               skb = netdev_alloc_skb(qdev->ndev,
+                                      qdev->lrg_buffer_len);
                if (unlikely(!skb)) {
                        /* Better luck next round */
                        printk(KERN_ERR PFX
@@ -2541,6 +2690,15 @@ static int ql_alloc_large_buffers(struct ql3_adapter *qdev)
                                             qdev->lrg_buffer_len -
                                             QL_HEADER_SPACE,
                                             PCI_DMA_FROMDEVICE);
+
+                       err = pci_dma_mapping_error(map);
+                       if(err) {
+                               printk(KERN_ERR "%s: PCI mapping failed with error: %d\n",
+                                      qdev->ndev->name, err);
+                               ql_free_large_buffers(qdev);
+                               return -ENOMEM;
+                       }
+
                        pci_unmap_addr_set(lrg_buf_cb, mapaddr, map);
                        pci_unmap_len_set(lrg_buf_cb, maplen,
                                          qdev->lrg_buffer_len -
@@ -2592,9 +2750,15 @@ static int ql_create_send_free_list(struct ql3_adapter *qdev)
 
 static int ql_alloc_mem_resources(struct ql3_adapter *qdev)
 {
-       if (qdev->ndev->mtu == NORMAL_MTU_SIZE)
+       if (qdev->ndev->mtu == NORMAL_MTU_SIZE) {
+               qdev->num_lbufq_entries = NUM_LBUFQ_ENTRIES;
                qdev->lrg_buffer_len = NORMAL_MTU_SIZE;
+       }
        else if (qdev->ndev->mtu == JUMBO_MTU_SIZE) {
+               /*
+                * Bigger buffers, so less of them.
+                */
+               qdev->num_lbufq_entries = JUMBO_NUM_LBUFQ_ENTRIES;
                qdev->lrg_buffer_len = JUMBO_MTU_SIZE;
        } else {
                printk(KERN_ERR PFX
@@ -2602,6 +2766,7 @@ static int ql_alloc_mem_resources(struct ql3_adapter *qdev)
                       qdev->ndev->name);
                return -ENOMEM;
        }
+       qdev->num_large_buffers = qdev->num_lbufq_entries * QL_ADDR_ELE_PER_BUFQ_ENTRY;
        qdev->lrg_buffer_len += VLAN_ETH_HLEN + VLAN_ID_LEN + QL_HEADER_SPACE;
        qdev->max_frame_size =
            (qdev->lrg_buffer_len - QL_HEADER_SPACE) + ETHERNET_CRC_SIZE;
@@ -2834,7 +2999,7 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev)
                           &hmem_regs->rxLargeQBaseAddrLow,
                           LS_64BITS(qdev->lrg_buf_q_phy_addr));
 
-       ql_write_page1_reg(qdev, &hmem_regs->rxLargeQLength, NUM_LBUFQ_ENTRIES);
+       ql_write_page1_reg(qdev, &hmem_regs->rxLargeQLength, qdev->num_lbufq_entries);
 
        ql_write_page1_reg(qdev,
                           &hmem_regs->rxLargeBufferLength,
@@ -2856,7 +3021,7 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev)
 
        qdev->small_buf_q_producer_index = NUM_SBUFQ_ENTRIES - 1;
        qdev->small_buf_release_cnt = 8;
-       qdev->lrg_buf_q_producer_index = NUM_LBUFQ_ENTRIES - 1;
+       qdev->lrg_buf_q_producer_index = qdev->num_lbufq_entries - 1;
        qdev->lrg_buf_release_cnt = 8;
        qdev->lrg_buf_next_free =
            (struct bufq_addr_element *)qdev->lrg_buf_q_virt_addr;
@@ -3292,6 +3457,7 @@ static int ql_adapter_up(struct ql3_adapter *qdev)
 err_init:
        ql_sem_unlock(qdev, QL_DRVR_SEM_MASK);
 err_lock:
+       spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
        free_irq(qdev->pdev->irq, ndev);
 err_irq:
        if (qdev->msi && test_bit(QL_MSI_ENABLED,&qdev->flags)) {
@@ -3343,27 +3509,6 @@ static struct net_device_stats *ql3xxx_get_stats(struct net_device *dev)
        return &qdev->stats;
 }
 
-static int ql3xxx_change_mtu(struct net_device *ndev, int new_mtu)
-{
-       struct ql3_adapter *qdev = netdev_priv(ndev);
-       printk(KERN_ERR PFX "%s:  new mtu size = %d.\n", ndev->name, new_mtu);
-       if (new_mtu != NORMAL_MTU_SIZE && new_mtu != JUMBO_MTU_SIZE) {
-               printk(KERN_ERR PFX
-                      "%s: mtu size of %d is not valid.  Use exactly %d or "
-                      "%d.\n", ndev->name, new_mtu, NORMAL_MTU_SIZE,
-                      JUMBO_MTU_SIZE);
-               return -EINVAL;
-       }
-
-       if (!netif_running(ndev)) {
-               ndev->mtu = new_mtu;
-               return 0;
-       }
-
-       ndev->mtu = new_mtu;
-       return ql_cycle_adapter(qdev,QL_DO_RESET);
-}
-
 static void ql3xxx_set_multicast_list(struct net_device *ndev)
 {
        /*
@@ -3609,8 +3754,12 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev,
        }
 
        ndev = alloc_etherdev(sizeof(struct ql3_adapter));
-       if (!ndev)
+       if (!ndev) {
+               printk(KERN_ERR PFX "%s could not alloc etherdev\n",
+                      pci_name(pdev));
+               err = -ENOMEM;
                goto err_out_free_regions;
+       }
 
        SET_MODULE_OWNER(ndev);
        SET_NETDEV_DEV(ndev, &pdev->dev);
@@ -3639,6 +3788,7 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev,
        if (!qdev->mem_map_registers) {
                printk(KERN_ERR PFX "%s: cannot map device registers\n",
                       pci_name(pdev));
+               err = -EIO;
                goto err_out_free_ndev;
        }
 
@@ -3650,7 +3800,6 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev,
        ndev->hard_start_xmit = ql3xxx_send;
        ndev->stop = ql3xxx_close;
        ndev->get_stats = ql3xxx_get_stats;
-       ndev->change_mtu = ql3xxx_change_mtu;
        ndev->set_multicast_list = ql3xxx_set_multicast_list;
        SET_ETHTOOL_OPS(ndev, &ql3xxx_ethtool_ops);
        ndev->set_mac_address = ql3xxx_set_mac_address;
@@ -3667,6 +3816,7 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev,
                printk(KERN_ALERT PFX
                       "ql3xxx_probe: Adapter #%d, Invalid NVRAM parameters.\n",
                       qdev->index);
+               err = -EIO;
                goto err_out_iounmap;
        }
 
@@ -3674,9 +3824,11 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev,
 
        /* Validate and set parameters */
        if (qdev->mac_index) {
+               ndev->mtu = qdev->nvram_data.macCfg_port1.etherMtu_mac ;
                memcpy(ndev->dev_addr, &qdev->nvram_data.funcCfg_fn2.macAddress,
                       ETH_ALEN);
        } else {
+               ndev->mtu = qdev->nvram_data.macCfg_port0.etherMtu_mac ;
                memcpy(ndev->dev_addr, &qdev->nvram_data.funcCfg_fn0.macAddress,
                       ETH_ALEN);
        }
index b2d76ea68827a4a7dafc4b262be1d62dc381ea01..34cd6580fd07cbfadd80230e8890c370c72fcfe8 100755 (executable)
@@ -1014,13 +1014,15 @@ struct eeprom_data {
 
 /* Transmit and Receive Buffers */
 #define NUM_LBUFQ_ENTRIES      128
+#define JUMBO_NUM_LBUFQ_ENTRIES        \
+(NUM_LBUFQ_ENTRIES/(JUMBO_MTU_SIZE/NORMAL_MTU_SIZE))
 #define NUM_SBUFQ_ENTRIES      64
 #define QL_SMALL_BUFFER_SIZE    32
 #define QL_ADDR_ELE_PER_BUFQ_ENTRY \
 (sizeof(struct lrg_buf_q_entry) / sizeof(struct bufq_addr_element))
     /* Each send has at least control block.  This is how many we keep. */
 #define NUM_SMALL_BUFFERS      NUM_SBUFQ_ENTRIES * QL_ADDR_ELE_PER_BUFQ_ENTRY
-#define NUM_LARGE_BUFFERS      NUM_LBUFQ_ENTRIES * QL_ADDR_ELE_PER_BUFQ_ENTRY
+
 #define QL_HEADER_SPACE 32     /* make header space at top of skb. */
 /*
  * Large & Small Buffers for Receives
@@ -1092,7 +1094,6 @@ struct oal_entry {
        u32 len;
 #define OAL_LAST_ENTRY   0x80000000    /* Last valid buffer in list. */
 #define OAL_CONT_ENTRY   0x40000000    /* points to an OAL. (continuation) */
-       u32 reserved;
 };
 
 struct oal {
@@ -1193,7 +1194,7 @@ struct ql3_adapter {
        struct net_rsp_iocb *rsp_current;
        u16 rsp_consumer_index;
        u16 reserved_06;
-       u32 *prsp_producer_index;
+       volatile u32 *prsp_producer_index;
        u32 rsp_producer_index_phy_addr_high;
        u32 rsp_producer_index_phy_addr_low;
 
@@ -1207,9 +1208,11 @@ struct ql3_adapter {
        u32 lrg_buf_q_producer_index;
        u32 lrg_buf_release_cnt;
        struct bufq_addr_element *lrg_buf_next_free;
+       u32 num_large_buffers;
+       u32 num_lbufq_entries;
 
        /* Large (Receive) Buffers */
-       struct ql_rcv_buf_cb lrg_buf[NUM_LARGE_BUFFERS];
+       struct ql_rcv_buf_cb *lrg_buf;
        struct ql_rcv_buf_cb *lrg_buf_free_head;
        struct ql_rcv_buf_cb *lrg_buf_free_tail;
        u32 lrg_buf_free_count;
index 5598d86380b430a3853fe613b9a36cda9e022dd2..521b5f0618a4a904a4d736d2263a6573eb9dbd5e 100644 (file)
@@ -572,8 +572,8 @@ static void rtl8169_xmii_reset_enable(void __iomem *ioaddr)
 {
        unsigned int val;
 
-       mdio_write(ioaddr, MII_BMCR, BMCR_RESET);
-       val = mdio_read(ioaddr, MII_BMCR);
+       val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET;
+       mdio_write(ioaddr, MII_BMCR, val & 0xffff);
 }
 
 static void rtl8169_check_link_status(struct net_device *dev,
@@ -890,8 +890,7 @@ static void rtl8169_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
        unsigned long flags;
 
        spin_lock_irqsave(&tp->lock, flags);
-       if (tp->vlgrp)
-               tp->vlgrp->vlan_devices[vid] = NULL;
+       vlan_group_set_device(tp->vlgrp, vid, NULL);
        spin_unlock_irqrestore(&tp->lock, flags);
 }
 
@@ -1369,11 +1368,7 @@ static inline void rtl8169_request_timer(struct net_device *dev)
            (tp->phy_version >= RTL_GIGA_PHY_VER_H))
                return;
 
-       init_timer(timer);
-       timer->expires = jiffies + RTL8169_PHY_TIMEOUT;
-       timer->data = (unsigned long)(dev);
-       timer->function = rtl8169_phy_timer;
-       add_timer(timer);
+       mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1686,6 +1681,10 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        tp->mmio_addr = ioaddr;
        tp->align = rtl_cfg_info[ent->driver_data].align;
 
+       init_timer(&tp->timer);
+       tp->timer.data = (unsigned long) dev;
+       tp->timer.function = rtl8169_phy_timer;
+
        spin_lock_init(&tp->lock);
 
        rc = register_netdev(dev);
@@ -1733,6 +1732,8 @@ rtl8169_remove_one(struct pci_dev *pdev)
        assert(dev != NULL);
        assert(tp != NULL);
 
+       flush_scheduled_work();
+
        unregister_netdev(dev);
        rtl8169_release_board(pdev, dev, tp->mmio_addr);
        pci_set_drvdata(pdev, NULL);
@@ -2161,10 +2162,13 @@ static void rtl8169_reinit_task(struct work_struct *work)
        struct net_device *dev = tp->dev;
        int ret;
 
-       if (netif_running(dev)) {
-               rtl8169_wait_for_quiescence(dev);
-               rtl8169_close(dev);
-       }
+       rtnl_lock();
+
+       if (!netif_running(dev))
+               goto out_unlock;
+
+       rtl8169_wait_for_quiescence(dev);
+       rtl8169_close(dev);
 
        ret = rtl8169_open(dev);
        if (unlikely(ret < 0)) {
@@ -2179,6 +2183,9 @@ static void rtl8169_reinit_task(struct work_struct *work)
                }
                rtl8169_schedule_work(dev, rtl8169_reinit_task);
        }
+
+out_unlock:
+       rtnl_unlock();
 }
 
 static void rtl8169_reset_task(struct work_struct *work)
@@ -2187,8 +2194,10 @@ static void rtl8169_reset_task(struct work_struct *work)
                container_of(work, struct rtl8169_private, task.work);
        struct net_device *dev = tp->dev;
 
+       rtnl_lock();
+
        if (!netif_running(dev))
-               return;
+               goto out_unlock;
 
        rtl8169_wait_for_quiescence(dev);
 
@@ -2210,6 +2219,9 @@ static void rtl8169_reset_task(struct work_struct *work)
                }
                rtl8169_schedule_work(dev, rtl8169_reset_task);
        }
+
+out_unlock:
+       rtnl_unlock();
 }
 
 static void rtl8169_tx_timeout(struct net_device *dev)
@@ -2722,8 +2734,6 @@ static void rtl8169_down(struct net_device *dev)
 
        netif_stop_queue(dev);
 
-       flush_scheduled_work();
-
 core_down:
        spin_lock_irq(&tp->lock);
 
index 0e345cbc2bf918a2f0a55fd0c360ae36905f07e8..33fb7f3b7041800e87b73f0d63c782551ab1f478 100644 (file)
@@ -430,6 +430,7 @@ struct XENA_dev_config {
 #define TX_PA_CFG_IGNORE_SNAP_OUI          BIT(2)
 #define TX_PA_CFG_IGNORE_LLC_CTRL          BIT(3)
 #define        TX_PA_CFG_IGNORE_L2_ERR                    BIT(6)
+#define RX_PA_CFG_STRIP_VLAN_TAG               BIT(15)
 
 /* Recent add, used only debug purposes. */
        u64 pcc_enable;
index e8e0d94e9bddfa9c1935b7752f8daa303e5387d7..46ebf141ee5a15b62d0c16eeb77b86dc939a31a9 100644 (file)
  *     Possible values '1' for enable '0' for disable. Default is '0'
  * lro_max_pkts: This parameter defines maximum number of packets can be
  *     aggregated as a single large packet
+ * napi: This parameter used to enable/disable NAPI (polling Rx)
+ *     Possible values '1' for enable and '0' for disable. Default is '1'
+ * ufo: This parameter used to enable/disable UDP Fragmentation Offload(UFO)
+ *      Possible values '1' for enable and '0' for disable. Default is '0'
+ * vlan_tag_strip: This can be used to enable or disable vlan stripping.
+ *                 Possible values '1' for enable , '0' for disable.
+ *                 Default is '2' - which means disable in promisc mode
+ *                 and enable in non-promiscuous mode.
  ************************************************************************/
 
 #include <linux/module.h>
@@ -76,7 +84,7 @@
 #include "s2io.h"
 #include "s2io-regs.h"
 
-#define DRV_VERSION "2.0.16.1"
+#define DRV_VERSION "2.0.17.1"
 
 /* S2io Driver name & version. */
 static char s2io_driver_name[] = "Neterion";
@@ -131,7 +139,7 @@ static char s2io_gstrings[][ETH_GSTRING_LEN] = {
        "BIST Test\t(offline)"
 };
 
-static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {
+static char ethtool_xena_stats_keys[][ETH_GSTRING_LEN] = {
        {"tmac_frms"},
        {"tmac_data_octets"},
        {"tmac_drop_frms"},
@@ -225,7 +233,10 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {
        {"rxd_rd_cnt"},
        {"rxd_wr_cnt"},
        {"txf_rd_cnt"},
-       {"rxf_wr_cnt"},
+       {"rxf_wr_cnt"}
+};
+
+static char ethtool_enhanced_stats_keys[][ETH_GSTRING_LEN] = {
        {"rmac_ttl_1519_4095_frms"},
        {"rmac_ttl_4096_8191_frms"},
        {"rmac_ttl_8192_max_frms"},
@@ -241,7 +252,10 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {
        {"rmac_red_discard"},
        {"rmac_rts_discard"},
        {"rmac_ingm_full_discard"},
-       {"link_fault_cnt"},
+       {"link_fault_cnt"}
+};
+
+static char ethtool_driver_stats_keys[][ETH_GSTRING_LEN] = {
        {"\n DRIVER STATISTICS"},
        {"single_bit_ecc_errs"},
        {"double_bit_ecc_errs"},
@@ -269,8 +283,16 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {
        ("lro_avg_aggr_pkts"),
 };
 
-#define S2IO_STAT_LEN sizeof(ethtool_stats_keys)/ ETH_GSTRING_LEN
-#define S2IO_STAT_STRINGS_LEN S2IO_STAT_LEN * ETH_GSTRING_LEN
+#define S2IO_XENA_STAT_LEN sizeof(ethtool_xena_stats_keys)/ ETH_GSTRING_LEN
+#define S2IO_ENHANCED_STAT_LEN sizeof(ethtool_enhanced_stats_keys)/ \
+                                       ETH_GSTRING_LEN
+#define S2IO_DRIVER_STAT_LEN sizeof(ethtool_driver_stats_keys)/ ETH_GSTRING_LEN
+
+#define XFRAME_I_STAT_LEN (S2IO_XENA_STAT_LEN + S2IO_DRIVER_STAT_LEN )
+#define XFRAME_II_STAT_LEN (XFRAME_I_STAT_LEN + S2IO_ENHANCED_STAT_LEN )
+
+#define XFRAME_I_STAT_STRINGS_LEN ( XFRAME_I_STAT_LEN * ETH_GSTRING_LEN )
+#define XFRAME_II_STAT_STRINGS_LEN ( XFRAME_II_STAT_LEN * ETH_GSTRING_LEN )
 
 #define S2IO_TEST_LEN  sizeof(s2io_gstrings) / ETH_GSTRING_LEN
 #define S2IO_STRINGS_LEN       S2IO_TEST_LEN * ETH_GSTRING_LEN
@@ -293,6 +315,9 @@ static void s2io_vlan_rx_register(struct net_device *dev,
        spin_unlock_irqrestore(&nic->tx_lock, flags);
 }
 
+/* A flag indicating whether 'RX_PA_CFG_STRIP_VLAN_TAG' bit is set or not */
+int vlan_strip_flag;
+
 /* Unregister the vlan */
 static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid)
 {
@@ -300,8 +325,7 @@ static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid)
        unsigned long flags;
 
        spin_lock_irqsave(&nic->tx_lock, flags);
-       if (nic->vlgrp)
-               nic->vlgrp->vlan_devices[vid] = NULL;
+       vlan_group_set_device(nic->vlgrp, vid, NULL);
        spin_unlock_irqrestore(&nic->tx_lock, flags);
 }
 
@@ -404,6 +428,7 @@ S2IO_PARM_INT(indicate_max_pkts, 0);
 
 S2IO_PARM_INT(napi, 1);
 S2IO_PARM_INT(ufo, 0);
+S2IO_PARM_INT(vlan_tag_strip, NO_STRIP_IN_PROMISC);
 
 static unsigned int tx_fifo_len[MAX_TX_FIFOS] =
     {DEFAULT_FIFO_0_LEN, [1 ...(MAX_TX_FIFOS - 1)] = DEFAULT_FIFO_1_7_LEN};
@@ -1371,6 +1396,16 @@ static int init_nic(struct s2io_nic *nic)
                                &bar0->rts_frm_len_n[i]);
                }
        }
+       
+       /* Disable differentiated services steering logic */
+       for (i = 0; i < 64; i++) {
+               if (rts_ds_steer(nic, i, 0) == FAILURE) {
+                       DBG_PRINT(ERR_DBG, "%s: failed rts ds steering",
+                               dev->name);
+                       DBG_PRINT(ERR_DBG, "set on codepoint %d\n", i);
+                       return FAILURE;
+               }
+       }
 
        /* Program statistics memory */
        writeq(mac_control->stats_mem_phy, &bar0->stat_addr);
@@ -1943,6 +1978,13 @@ static int start_nic(struct s2io_nic *nic)
                writeq(val64, &bar0->rx_pa_cfg);
        }
 
+       if (vlan_tag_strip == 0) {
+               val64 = readq(&bar0->rx_pa_cfg);
+               val64 &= ~RX_PA_CFG_STRIP_VLAN_TAG;
+               writeq(val64, &bar0->rx_pa_cfg);
+               vlan_strip_flag = 0;
+       }
+
        /*
         * Enabling MC-RLDRAM. After enabling the device, we timeout
         * for around 100ms, which is approximately the time required
@@ -3195,26 +3237,37 @@ static void alarm_intr_handler(struct s2io_nic *nic)
  *   SUCCESS on success and FAILURE on failure.
  */
 
-static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit)
+static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit,
+                               int bit_state)
 {
-       int ret = FAILURE, cnt = 0;
+       int ret = FAILURE, cnt = 0, delay = 1;
        u64 val64;
 
-       while (TRUE) {
+       if ((bit_state != S2IO_BIT_RESET) && (bit_state != S2IO_BIT_SET))
+               return FAILURE;
+
+       do {
                val64 = readq(addr);
-               if (!(val64 & busy_bit)) {
-                       ret = SUCCESS;
-                       break;
+               if (bit_state == S2IO_BIT_RESET) {
+                       if (!(val64 & busy_bit)) {
+                               ret = SUCCESS;
+                               break;
+                       }
+               } else {
+                       if (!(val64 & busy_bit)) {
+                               ret = SUCCESS;
+                               break;
+                       }
                }
 
                if(in_interrupt())
-                       mdelay(50);
+                       mdelay(delay);
                else
-                       msleep(50);
+                       msleep(delay);
 
-               if (cnt++ > 10)
-                       break;
-       }
+               if (++cnt >= 10)
+                       delay = 50;
+       } while (cnt < 20);
        return ret;
 }
 /*
@@ -3340,6 +3393,9 @@ new_way:
                writeq(val64, &bar0->pcc_err_reg);
        }
 
+       /* restore the previously assigned mac address */
+       s2io_set_mac_addr(sp->dev, (u8 *)&sp->def_mac_addr[0].mac_addr);
+
        sp->device_enabled_once = FALSE;
 }
 
@@ -3758,7 +3814,6 @@ static int s2io_close(struct net_device *dev)
 {
        struct s2io_nic *sp = dev->priv;
 
-       flush_scheduled_work();
        netif_stop_queue(dev);
        /* Reset card, kill tasklet and free Tx and Rx buffers. */
        s2io_card_down(sp);
@@ -4088,6 +4143,11 @@ static void s2io_txpic_intr_handle(struct s2io_nic *sp)
                        val64 &= ~GPIO_INT_MASK_LINK_UP;
                        val64 |= GPIO_INT_MASK_LINK_DOWN;
                        writeq(val64, &bar0->gpio_int_mask);
+
+                       /* turn off LED */
+                       val64 = readq(&bar0->adapter_control);
+                       val64 = val64 &(~ADAPTER_LED_ON);
+                       writeq(val64, &bar0->adapter_control);
                }
        }
        val64 = readq(&bar0->gpio_int_mask);
@@ -4297,7 +4357,8 @@ static void s2io_set_multicast(struct net_device *dev)
                writeq(val64, &bar0->rmac_addr_cmd_mem);
                /* Wait till command completes */
                wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
-                                     RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING);
+                                       RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
+                                       S2IO_BIT_RESET);
 
                sp->m_cast_flg = 1;
                sp->all_multi_pos = MAC_MC_ALL_MC_ADDR_OFFSET;
@@ -4313,7 +4374,8 @@ static void s2io_set_multicast(struct net_device *dev)
                writeq(val64, &bar0->rmac_addr_cmd_mem);
                /* Wait till command completes */
                wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
-                                     RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING);
+                                       RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
+                                       S2IO_BIT_RESET);
 
                sp->m_cast_flg = 0;
                sp->all_multi_pos = 0;
@@ -4330,6 +4392,13 @@ static void s2io_set_multicast(struct net_device *dev)
                writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
                writel((u32) (val64 >> 32), (add + 4));
 
+               if (vlan_tag_strip != 1) {
+                       val64 = readq(&bar0->rx_pa_cfg);
+                       val64 &= ~RX_PA_CFG_STRIP_VLAN_TAG;
+                       writeq(val64, &bar0->rx_pa_cfg);
+                       vlan_strip_flag = 0;
+               }
+
                val64 = readq(&bar0->mac_cfg);
                sp->promisc_flg = 1;
                DBG_PRINT(INFO_DBG, "%s: entered promiscuous mode\n",
@@ -4345,6 +4414,13 @@ static void s2io_set_multicast(struct net_device *dev)
                writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
                writel((u32) (val64 >> 32), (add + 4));
 
+               if (vlan_tag_strip != 0) {
+                       val64 = readq(&bar0->rx_pa_cfg);
+                       val64 |= RX_PA_CFG_STRIP_VLAN_TAG;
+                       writeq(val64, &bar0->rx_pa_cfg);
+                       vlan_strip_flag = 1;
+               }
+
                val64 = readq(&bar0->mac_cfg);
                sp->promisc_flg = 0;
                DBG_PRINT(INFO_DBG, "%s: left promiscuous mode\n",
@@ -4379,7 +4455,8 @@ static void s2io_set_multicast(struct net_device *dev)
 
                        /* Wait for command completes */
                        if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
-                                     RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) {
+                                       RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
+                                       S2IO_BIT_RESET)) {
                                DBG_PRINT(ERR_DBG, "%s: Adding ",
                                          dev->name);
                                DBG_PRINT(ERR_DBG, "Multicasts failed\n");
@@ -4410,7 +4487,8 @@ static void s2io_set_multicast(struct net_device *dev)
 
                        /* Wait for command completes */
                        if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
-                                     RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) {
+                                       RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
+                                       S2IO_BIT_RESET)) {
                                DBG_PRINT(ERR_DBG, "%s: Adding ",
                                          dev->name);
                                DBG_PRINT(ERR_DBG, "Multicasts failed\n");
@@ -4436,6 +4514,7 @@ static int s2io_set_mac_addr(struct net_device *dev, u8 * addr)
        struct XENA_dev_config __iomem *bar0 = sp->bar0;
        register u64 val64, mac_addr = 0;
        int i;
+       u64 old_mac_addr = 0;
 
        /*
         * Set the new MAC address as the new unicast filter and reflect this
@@ -4445,6 +4524,22 @@ static int s2io_set_mac_addr(struct net_device *dev, u8 * addr)
        for (i = 0; i < ETH_ALEN; i++) {
                mac_addr <<= 8;
                mac_addr |= addr[i];
+               old_mac_addr <<= 8;
+               old_mac_addr |= sp->def_mac_addr[0].mac_addr[i];
+       }
+
+       if(0 == mac_addr)
+               return SUCCESS;
+
+       /* Update the internal structure with this new mac address */
+       if(mac_addr != old_mac_addr) {
+               memset(sp->def_mac_addr[0].mac_addr, 0, sizeof(ETH_ALEN));
+               sp->def_mac_addr[0].mac_addr[5] = (u8) (mac_addr);
+               sp->def_mac_addr[0].mac_addr[4] = (u8) (mac_addr >> 8);
+               sp->def_mac_addr[0].mac_addr[3] = (u8) (mac_addr >> 16);
+               sp->def_mac_addr[0].mac_addr[2] = (u8) (mac_addr >> 24);
+               sp->def_mac_addr[0].mac_addr[1] = (u8) (mac_addr >> 32);
+               sp->def_mac_addr[0].mac_addr[0] = (u8) (mac_addr >> 40);
        }
 
        writeq(RMAC_ADDR_DATA0_MEM_ADDR(mac_addr),
@@ -4456,7 +4551,7 @@ static int s2io_set_mac_addr(struct net_device *dev, u8 * addr)
        writeq(val64, &bar0->rmac_addr_cmd_mem);
        /* Wait till command completes */
        if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
-                     RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) {
+                     RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, S2IO_BIT_RESET)) {
                DBG_PRINT(ERR_DBG, "%s: set_mac_addr failed\n", dev->name);
                return FAILURE;
        }
@@ -4547,7 +4642,11 @@ static void s2io_ethtool_gdrvinfo(struct net_device *dev,
        info->regdump_len = XENA_REG_SPACE;
        info->eedump_len = XENA_EEPROM_SPACE;
        info->testinfo_len = S2IO_TEST_LEN;
-       info->n_stats = S2IO_STAT_LEN;
+
+       if (sp->device_type == XFRAME_I_DEVICE)
+               info->n_stats = XFRAME_I_STAT_LEN;
+       else
+               info->n_stats = XFRAME_II_STAT_LEN;
 }
 
 /**
@@ -5569,22 +5668,30 @@ static void s2io_get_ethtool_stats(struct net_device *dev,
        tmp_stats[i++] = le32_to_cpu(stat_info->rxd_wr_cnt);
        tmp_stats[i++] = le32_to_cpu(stat_info->txf_rd_cnt);
        tmp_stats[i++] = le32_to_cpu(stat_info->rxf_wr_cnt);
-       tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_1519_4095_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_4096_8191_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_8192_max_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_gt_max_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_osized_alt_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_jabber_alt_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_gt_max_alt_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_vlan_frms);
-        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_len_discard);
-        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_fcs_discard);
-        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_pf_discard);
-        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_da_discard);
-        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_red_discard);
-        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_rts_discard);
-        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_ingm_full_discard);
-        tmp_stats[i++] = le32_to_cpu(stat_info->link_fault_cnt);
+
+       /* Enhanced statistics exist only for Hercules */
+       if(sp->device_type == XFRAME_II_DEVICE) {
+               tmp_stats[i++] =
+                               le64_to_cpu(stat_info->rmac_ttl_1519_4095_frms);
+               tmp_stats[i++] =
+                               le64_to_cpu(stat_info->rmac_ttl_4096_8191_frms);
+               tmp_stats[i++] =
+                               le64_to_cpu(stat_info->rmac_ttl_8192_max_frms);
+               tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_gt_max_frms);
+               tmp_stats[i++] = le64_to_cpu(stat_info->rmac_osized_alt_frms);
+               tmp_stats[i++] = le64_to_cpu(stat_info->rmac_jabber_alt_frms);
+               tmp_stats[i++] = le64_to_cpu(stat_info->rmac_gt_max_alt_frms);
+               tmp_stats[i++] = le64_to_cpu(stat_info->rmac_vlan_frms);
+               tmp_stats[i++] = le32_to_cpu(stat_info->rmac_len_discard);
+               tmp_stats[i++] = le32_to_cpu(stat_info->rmac_fcs_discard);
+               tmp_stats[i++] = le32_to_cpu(stat_info->rmac_pf_discard);
+               tmp_stats[i++] = le32_to_cpu(stat_info->rmac_da_discard);
+               tmp_stats[i++] = le32_to_cpu(stat_info->rmac_red_discard);
+               tmp_stats[i++] = le32_to_cpu(stat_info->rmac_rts_discard);
+               tmp_stats[i++] = le32_to_cpu(stat_info->rmac_ingm_full_discard);
+               tmp_stats[i++] = le32_to_cpu(stat_info->link_fault_cnt);
+       }
+
        tmp_stats[i++] = 0;
        tmp_stats[i++] = stat_info->sw_stat.single_ecc_errs;
        tmp_stats[i++] = stat_info->sw_stat.double_ecc_errs;
@@ -5664,18 +5771,42 @@ static int s2io_ethtool_self_test_count(struct net_device *dev)
 static void s2io_ethtool_get_strings(struct net_device *dev,
                                     u32 stringset, u8 * data)
 {
+       int stat_size = 0;
+       struct s2io_nic *sp = dev->priv;
+
        switch (stringset) {
        case ETH_SS_TEST:
                memcpy(data, s2io_gstrings, S2IO_STRINGS_LEN);
                break;
        case ETH_SS_STATS:
-               memcpy(data, &ethtool_stats_keys,
-                      sizeof(ethtool_stats_keys));
+               stat_size = sizeof(ethtool_xena_stats_keys);
+               memcpy(data, &ethtool_xena_stats_keys,stat_size);
+               if(sp->device_type == XFRAME_II_DEVICE) {
+                       memcpy(data + stat_size,
+                               &ethtool_enhanced_stats_keys,
+                               sizeof(ethtool_enhanced_stats_keys));
+                       stat_size += sizeof(ethtool_enhanced_stats_keys);
+               }
+
+               memcpy(data + stat_size, &ethtool_driver_stats_keys,
+                       sizeof(ethtool_driver_stats_keys));
        }
 }
 static int s2io_ethtool_get_stats_count(struct net_device *dev)
 {
-       return (S2IO_STAT_LEN);
+       struct s2io_nic *sp = dev->priv;
+       int stat_count = 0;
+       switch(sp->device_type) {
+       case XFRAME_I_DEVICE:
+               stat_count = XFRAME_I_STAT_LEN;
+       break;
+
+       case XFRAME_II_DEVICE:
+               stat_count = XFRAME_II_STAT_LEN;
+       break;
+       }
+
+       return stat_count;
 }
 
 static int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
@@ -5847,9 +5978,14 @@ static void s2io_set_link(struct work_struct *work)
        register u64 val64;
        u16 subid;
 
+       rtnl_lock();
+
+       if (!netif_running(dev))
+               goto out_unlock;
+
        if (test_and_set_bit(0, &(nic->link_state))) {
                /* The card is being reset, no point doing anything */
-               return;
+               goto out_unlock;
        }
 
        subid = nic->pdev->subsystem_device;
@@ -5903,6 +6039,9 @@ static void s2io_set_link(struct work_struct *work)
                s2io_link(nic, LINK_DOWN);
        }
        clear_bit(0, &(nic->link_state));
+
+out_unlock:
+       rtnl_unlock();
 }
 
 static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp,
@@ -6059,10 +6198,13 @@ static  int rxd_owner_bit_reset(struct s2io_nic *sp)
                                        rx_blocks[j].rxds[k].virt_addr;
                                if(sp->rxd_mode >= RXD_MODE_3A)
                                        ba = &mac_control->rings[i].ba[j][k];
-                               set_rxd_buffer_pointer(sp, rxdp, ba,
+                               if (set_rxd_buffer_pointer(sp, rxdp, ba,
                                                       &skb,(u64 *)&temp0_64,
                                                       (u64 *)&temp1_64,
-                                                      (u64 *)&temp2_64, size);
+                                                      (u64 *)&temp2_64,
+                                                       size) == ENOMEM) {
+                                       return 0;
+                               }
 
                                set_rxd_buffer_size(sp, rxdp, size);
                                wmb();
@@ -6105,7 +6247,7 @@ static int s2io_add_isr(struct s2io_nic * sp)
                }
        }
        if (sp->intr_type == MSI_X) {
-               int i;
+               int i, msix_tx_cnt=0,msix_rx_cnt=0;
 
                for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) {
                        if (sp->s2io_entries[i].type == MSIX_FIFO_TYPE) {
@@ -6114,16 +6256,36 @@ static int s2io_add_isr(struct s2io_nic * sp)
                                err = request_irq(sp->entries[i].vector,
                                          s2io_msix_fifo_handle, 0, sp->desc[i],
                                                  sp->s2io_entries[i].arg);
-                               DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc[i],
-                               (unsigned long long)sp->msix_info[i].addr);
+                               /* If either data or addr is zero print it */
+                               if(!(sp->msix_info[i].addr &&
+                                       sp->msix_info[i].data)) {
+                                       DBG_PRINT(ERR_DBG, "%s @ Addr:0x%llx"
+                                               "Data:0x%lx\n",sp->desc[i],
+                                               (unsigned long long)
+                                               sp->msix_info[i].addr,
+                                               (unsigned long)
+                                               ntohl(sp->msix_info[i].data));
+                               } else {
+                                       msix_tx_cnt++;
+                               }
                        } else {
                                sprintf(sp->desc[i], "%s:MSI-X-%d-RX",
                                        dev->name, i);
                                err = request_irq(sp->entries[i].vector,
                                          s2io_msix_ring_handle, 0, sp->desc[i],
                                                  sp->s2io_entries[i].arg);
-                               DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc[i],
-                               (unsigned long long)sp->msix_info[i].addr);
+                               /* If either data or addr is zero print it */
+                               if(!(sp->msix_info[i].addr &&
+                                       sp->msix_info[i].data)) {
+                                       DBG_PRINT(ERR_DBG, "%s @ Addr:0x%llx"
+                                               "Data:0x%lx\n",sp->desc[i],
+                                               (unsigned long long)
+                                               sp->msix_info[i].addr,
+                                               (unsigned long)
+                                               ntohl(sp->msix_info[i].data));
+                               } else {
+                                       msix_rx_cnt++;
+                               }
                        }
                        if (err) {
                                DBG_PRINT(ERR_DBG,"%s:MSI-X-%d registration "
@@ -6133,6 +6295,8 @@ static int s2io_add_isr(struct s2io_nic * sp)
                        }
                        sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS;
                }
+               printk("MSI-X-TX %d entries enabled\n",msix_tx_cnt);
+               printk("MSI-X-RX %d entries enabled\n",msix_rx_cnt);
        }
        if (sp->intr_type == INTA) {
                err = request_irq((int) sp->pdev->irq, s2io_isr, IRQF_SHARED,
@@ -6356,6 +6520,11 @@ static void s2io_restart_nic(struct work_struct *work)
        struct s2io_nic *sp = container_of(work, struct s2io_nic, rst_timer_task);
        struct net_device *dev = sp->dev;
 
+       rtnl_lock();
+
+       if (!netif_running(dev))
+               goto out_unlock;
+
        s2io_card_down(sp);
        if (s2io_card_up(sp)) {
                DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
@@ -6364,7 +6533,8 @@ static void s2io_restart_nic(struct work_struct *work)
        netif_wake_queue(dev);
        DBG_PRINT(ERR_DBG, "%s: was reset by Tx watchdog timer\n",
                  dev->name);
-
+out_unlock:
+       rtnl_unlock();
 }
 
 /**
@@ -6554,7 +6724,8 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
 
        if (!sp->lro) {
                skb->protocol = eth_type_trans(skb, dev);
-               if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) {
+               if ((sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2) &&
+                       vlan_strip_flag)) {
                        /* Queueing the vlan frame to the upper layer */
                        if (napi)
                                vlan_hwaccel_receive_skb(skb, sp->vlgrp,
@@ -6691,8 +6862,7 @@ static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type)
                                        "Defaulting to INTA\n");
                *dev_intr_type = INTA;
        }
-       if ( (rx_ring_num > 1) && (*dev_intr_type != INTA) )
-               napi = 0;
+
        if (rx_ring_mode > 3) {
                DBG_PRINT(ERR_DBG, "s2io: Requested ring mode not supported\n");
                DBG_PRINT(ERR_DBG, "s2io: Defaulting to 3-buffer mode\n");
@@ -6701,6 +6871,37 @@ static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type)
        return SUCCESS;
 }
 
+/**
+ * rts_ds_steer - Receive traffic steering based on IPv4 or IPv6 TOS
+ * or Traffic class respectively.
+ * @nic: device peivate variable
+ * Description: The function configures the receive steering to
+ * desired receive ring.
+ * Return Value:  SUCCESS on success and
+ * '-1' on failure (endian settings incorrect).
+ */
+static int rts_ds_steer(struct s2io_nic *nic, u8 ds_codepoint, u8 ring)
+{
+       struct XENA_dev_config __iomem *bar0 = nic->bar0;
+       register u64 val64 = 0;
+
+       if (ds_codepoint > 63)
+               return FAILURE;
+
+       val64 = RTS_DS_MEM_DATA(ring);
+       writeq(val64, &bar0->rts_ds_mem_data);
+
+       val64 = RTS_DS_MEM_CTRL_WE |
+               RTS_DS_MEM_CTRL_STROBE_NEW_CMD |
+               RTS_DS_MEM_CTRL_OFFSET(ds_codepoint);
+
+       writeq(val64, &bar0->rts_ds_mem_ctrl);
+
+       return wait_for_cmd_complete(&bar0->rts_ds_mem_ctrl,
+                               RTS_DS_MEM_CTRL_STROBE_CMD_BEING_EXECUTED,
+                               S2IO_BIT_RESET);
+}
+
 /**
  *  s2io_init_nic - Initialization of the adapter .
  *  @pdev : structure containing the PCI related information of the device.
@@ -6995,13 +7196,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
            RMAC_ADDR_CMD_MEM_OFFSET(0 + MAC_MAC_ADDR_START_OFFSET);
        writeq(val64, &bar0->rmac_addr_cmd_mem);
        wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
-                     RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING);
+                     RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, S2IO_BIT_RESET);
        tmp64 = readq(&bar0->rmac_addr_data0_mem);
        mac_down = (u32) tmp64;
        mac_up = (u32) (tmp64 >> 32);
 
-       memset(sp->def_mac_addr[0].mac_addr, 0, sizeof(ETH_ALEN));
-
        sp->def_mac_addr[0].mac_addr[3] = (u8) (mac_up);
        sp->def_mac_addr[0].mac_addr[2] = (u8) (mac_up >> 8);
        sp->def_mac_addr[0].mac_addr[1] = (u8) (mac_up >> 16);
@@ -7173,6 +7372,8 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev)
                return;
        }
 
+       flush_scheduled_work();
+
        sp = dev->priv;
        unregister_netdev(dev);
 
index 0de0c65f945aba87f90760557adca24bb49173ed..803137ca4b6c52f254b050d893cb9b42fe458a52 100644 (file)
@@ -32,7 +32,8 @@
 #define FAILURE -1
 #define S2IO_MINUS_ONE 0xFFFFFFFFFFFFFFFFULL
 #define S2IO_MAX_PCI_CONFIG_SPACE_REINIT 100
-
+#define S2IO_BIT_RESET 1
+#define S2IO_BIT_SET 2
 #define CHECKBIT(value, nbit) (value & (1 << nbit))
 
 /* Maximum time to flicker LED when asked to identify NIC using ethtool */
@@ -296,6 +297,9 @@ struct stat_block {
        struct xpakStat xpak_stat;
 };
 
+/* Default value for 'vlan_strip_tag' configuration parameter */
+#define NO_STRIP_IN_PROMISC 2
+
 /*
  * Structures representing different init time configuration
  * parameters of the NIC.
@@ -1005,7 +1009,8 @@ static int s2io_set_swapper(struct s2io_nic * sp);
 static void s2io_card_down(struct s2io_nic *nic);
 static int s2io_card_up(struct s2io_nic *nic);
 static int get_xena_rev_id(struct pci_dev *pdev);
-static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit);
+static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit,
+                                       int bit_state);
 static int s2io_add_isr(struct s2io_nic * sp);
 static void s2io_rem_isr(struct s2io_nic * sp);
 
@@ -1019,6 +1024,7 @@ static void queue_rx_frame(struct sk_buff *skb);
 static void update_L3L4_header(struct s2io_nic *sp, struct lro *lro);
 static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro,
                           struct sk_buff *skb, u32 tcp_len);
+static int rts_ds_steer(struct s2io_nic *nic, u8 ds_codepoint, u8 ring);
 
 #define s2io_tcp_mss(skb) skb_shinfo(skb)->gso_size
 #define s2io_udp_mss(skb) skb_shinfo(skb)->gso_size
index a833e7f9757f4b12757f9229e8aa127b9527172d..52ed522a234c15163f116fc299d159fdc2717560 100644 (file)
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/route.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
-#include <linux/bitops.h>
 
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
 #include <asm/sgi/hpc3.h>
 #include <asm/sgi/ip22.h>
-#include <asm/sgialib.h>
 
 #include "sgiseeq.h"
 
index 45d91b1591001f67d0135b31765811345c69f396..b08508b358339131da79709561cd2a339746482e 100644 (file)
@@ -909,6 +909,9 @@ static void sis190_phy_task(struct work_struct *work)
 
        rtnl_lock();
 
+       if (!netif_running(dev))
+               goto out_unlock;
+
        val = mdio_read(ioaddr, phy_id, MII_BMCR);
        if (val & BMCR_RESET) {
                // FIXME: needlessly high ?  -- FR 02/07/2005
@@ -981,6 +984,7 @@ static void sis190_phy_task(struct work_struct *work)
                netif_carrier_on(dev);
        }
 
+out_unlock:
        rtnl_unlock();
 }
 
@@ -1102,8 +1106,6 @@ static void sis190_down(struct net_device *dev)
 
        netif_stop_queue(dev);
 
-       flush_scheduled_work();
-
        do {
                spin_lock_irq(&tp->lock);
 
@@ -1857,6 +1859,7 @@ static void __devexit sis190_remove_one(struct pci_dev *pdev)
        struct net_device *dev = pci_get_drvdata(pdev);
 
        sis190_mii_remove(dev);
+       flush_scheduled_work();
        unregister_netdev(dev);
        sis190_release_board(pdev);
        pci_set_drvdata(pdev, NULL);
index fb2b530516358684939212d47be8a8b0e6b25453..b3750f28427926d29e101b5a0bbd5f58a619e3e6 100644 (file)
@@ -968,10 +968,10 @@ static void mdio_write(struct net_device *net_dev, int phy_id, int location,
 
 static u16 sis900_reset_phy(struct net_device *net_dev, int phy_addr)
 {
-       int i = 0;
+       int i;
        u16 status;
 
-       while (i++ < 2)
+       for (i = 0; i < 2; i++)
                status = mdio_read(net_dev, phy_addr, MII_STATUS);
 
        mdio_write( net_dev, phy_addr, MII_CONTROL, MII_CNTL_RESET );
@@ -1430,7 +1430,7 @@ static void sis900_auto_negotiate(struct net_device *net_dev, int phy_addr)
        int i = 0;
        u32 status;
 
-       while (i++ < 2)
+       for (i = 0; i < 2; i++)
                status = mdio_read(net_dev, phy_addr, MII_STATUS);
 
        if (!(status & MII_STAT_LINK)){
@@ -1466,9 +1466,9 @@ static void sis900_read_mode(struct net_device *net_dev, int *speed, int *duplex
        int phy_addr = sis_priv->cur_phy;
        u32 status;
        u16 autoadv, autorec;
-       int i = 0;
+       int i;
 
-       while (i++ < 2)
+       for (i = 0; i < 2; i++)
                status = mdio_read(net_dev, phy_addr, MII_STATUS);
 
        if (!(status & MII_STAT_LINK))
index 4c8aaa7623338b56ba32b6c51877941d30df3bdf..5310d39b5737492da4aed57fc29f563750810d1e 100644 (file)
@@ -73,7 +73,7 @@ static const char * const cfm_events[] = {
 /*
  * map from state to downstream port type
  */
-static const u_char cf_to_ptype[] = {
+static const unsigned char cf_to_ptype[] = {
        TNONE,TNONE,TNONE,TNONE,TNONE,
        TNONE,TB,TB,TS,
        TA,TB,TS,TB
index e482e7fcbb2be36117ee646d4699fb87d49c141d..eea75a401b0c8887ef08c430e7ce5e27c42adab6 100644 (file)
@@ -77,13 +77,13 @@ static const struct pci_device_id skge_id_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940B) },
        { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) },
        { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU) },
-       { PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T), },
+       { PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T) },
        { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) },    /* DGE-530T */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) },
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */
        { PCI_DEVICE(PCI_VENDOR_ID_CNET, PCI_DEVICE_ID_CNET_GIGACARD) },
        { PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1064) },
-       { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, },
+       { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015 },
        { 0 }
 };
 MODULE_DEVICE_TABLE(pci, skge_id_table);
@@ -1419,7 +1419,8 @@ static void xm_link_timer(struct work_struct *work)
        mutex_unlock(&hw->phy_mutex);
 
 nochange:
-       schedule_delayed_work(&skge->link_thread, LINK_HZ);
+       if (netif_running(dev))
+               schedule_delayed_work(&skge->link_thread, LINK_HZ);
 }
 
 static void genesis_mac_init(struct skge_hw *hw, int port)
@@ -2530,7 +2531,7 @@ static int skge_down(struct net_device *dev)
 
        netif_stop_queue(dev);
        if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC)
-               cancel_rearming_delayed_work(&skge->link_thread);
+               cancel_delayed_work(&skge->link_thread);
 
        skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
        if (hw->chip_id == CHIP_ID_GENESIS)
@@ -2766,6 +2767,17 @@ static int skge_change_mtu(struct net_device *dev, int new_mtu)
        return err;
 }
 
+static const u8 pause_mc_addr[ETH_ALEN] = { 0x1, 0x80, 0xc2, 0x0, 0x0, 0x1 };
+
+static void genesis_add_filter(u8 filter[8], const u8 *addr)
+{
+       u32 crc, bit;
+
+       crc = ether_crc_le(ETH_ALEN, addr);
+       bit = ~crc & 0x3f;
+       filter[bit/8] |= 1 << (bit%8);
+}
+
 static void genesis_set_multicast(struct net_device *dev)
 {
        struct skge_port *skge = netdev_priv(dev);
@@ -2787,24 +2799,33 @@ static void genesis_set_multicast(struct net_device *dev)
                memset(filter, 0xff, sizeof(filter));
        else {
                memset(filter, 0, sizeof(filter));
-               for (i = 0; list && i < count; i++, list = list->next) {
-                       u32 crc, bit;
-                       crc = ether_crc_le(ETH_ALEN, list->dmi_addr);
-                       bit = ~crc & 0x3f;
-                       filter[bit/8] |= 1 << (bit%8);
-               }
+
+               if (skge->flow_status == FLOW_STAT_REM_SEND
+                   || skge->flow_status == FLOW_STAT_SYMMETRIC)
+                       genesis_add_filter(filter, pause_mc_addr);
+
+               for (i = 0; list && i < count; i++, list = list->next)
+                       genesis_add_filter(filter, list->dmi_addr);
        }
 
        xm_write32(hw, port, XM_MODE, mode);
        xm_outhash(hw, port, XM_HSM, filter);
 }
 
+static void yukon_add_filter(u8 filter[8], const u8 *addr)
+{
+        u32 bit = ether_crc(ETH_ALEN, addr) & 0x3f;
+        filter[bit/8] |= 1 << (bit%8);
+}
+
 static void yukon_set_multicast(struct net_device *dev)
 {
        struct skge_port *skge = netdev_priv(dev);
        struct skge_hw *hw = skge->hw;
        int port = skge->port;
        struct dev_mc_list *list = dev->mc_list;
+       int rx_pause = (skge->flow_status == FLOW_STAT_REM_SEND
+                       || skge->flow_status == FLOW_STAT_SYMMETRIC);
        u16 reg;
        u8 filter[8];
 
@@ -2817,16 +2838,17 @@ static void yukon_set_multicast(struct net_device *dev)
                reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
        else if (dev->flags & IFF_ALLMULTI)     /* all multicast */
                memset(filter, 0xff, sizeof(filter));
-       else if (dev->mc_count == 0)            /* no multicast */
+       else if (dev->mc_count == 0 && !rx_pause)/* no multicast */
                reg &= ~GM_RXCR_MCF_ENA;
        else {
                int i;
                reg |= GM_RXCR_MCF_ENA;
 
-               for (i = 0; list && i < dev->mc_count; i++, list = list->next) {
-                       u32 bit = ether_crc(ETH_ALEN, list->dmi_addr) & 0x3f;
-                       filter[bit/8] |= 1 << (bit%8);
-               }
+               if (rx_pause)
+                       yukon_add_filter(filter, pause_mc_addr);
+
+               for (i = 0; list && i < dev->mc_count; i++, list = list->next)
+                       yukon_add_filter(filter, list->dmi_addr);
        }
 
 
@@ -3690,6 +3712,8 @@ static void __devexit skge_remove(struct pci_dev *pdev)
        if (!hw)
                return;
 
+       flush_scheduled_work();
+
        if ((dev1 = hw->dev[1]))
                unregister_netdev(dev1);
        dev0 = hw->dev[0];
@@ -3704,8 +3728,6 @@ static void __devexit skge_remove(struct pci_dev *pdev)
        skge_write16(hw, B0_LED, LED_STAT_OFF);
        skge_write8(hw, B0_CTST, CS_RST_SET);
 
-       flush_scheduled_work();
-
        free_irq(pdev->irq, hw);
        pci_release_regions(pdev);
        pci_disable_device(pdev);
index 17b1b479dff575a03943b232e6d29849e0a78e51..e9354dfa7e9af0ee0b2ad78f5c9604627ee96dd8 100644 (file)
@@ -1849,8 +1849,7 @@ enum {
                          GMR_FS_JABBER,
 /* Rx GMAC FIFO Flush Mask (default) */
        RX_FF_FL_DEF_MSK = GMR_FS_CRC_ERR | GMR_FS_RX_FF_OV |GMR_FS_MII_ERR |
-                          GMR_FS_BAD_FC | GMR_FS_GOOD_FC | GMR_FS_UN_SIZE |
-                          GMR_FS_JABBER,
+                          GMR_FS_BAD_FC |  GMR_FS_UN_SIZE | GMR_FS_JABBER,
 };
 
 /*     RX_GMF_CTRL_T   32 bit  Rx GMAC FIFO Control/Test */
index 52edbd7ac17e6a134e2af1ca4fe3abd9e42c46ac..ab0ab92583fe427a0568cbb87c5571b918909998 100644 (file)
@@ -1053,8 +1053,7 @@ static void sky2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 
        sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_OFF);
        sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_OFF);
-       if (sky2->vlgrp)
-               sky2->vlgrp->vlan_devices[vid] = NULL;
+       vlan_group_set_device(sky2->vlgrp, vid, NULL);
 
        netif_tx_unlock_bh(dev);
 }
@@ -2166,9 +2165,27 @@ force_update:
                        /* fall through */
 #endif
                case OP_RXCHKS:
-                       skb = sky2->rx_ring[sky2->rx_next].skb;
-                       skb->ip_summed = CHECKSUM_COMPLETE;
-                       skb->csum = status & 0xffff;
+                       if (!sky2->rx_csum)
+                               break;
+
+                       /* Both checksum counters are programmed to start at
+                        * the same offset, so unless there is a problem they
+                        * should match. This failure is an early indication that
+                        * hardware receive checksumming won't work.
+                        */
+                       if (likely(status >> 16 == (status & 0xffff))) {
+                               skb = sky2->rx_ring[sky2->rx_next].skb;
+                               skb->ip_summed = CHECKSUM_COMPLETE;
+                               skb->csum = status & 0xffff;
+                       } else {
+                               printk(KERN_NOTICE PFX "%s: hardware receive "
+                                      "checksum problem (status = %#x)\n",
+                                      dev->name, status);
+                               sky2->rx_csum = 0;
+                               sky2_write32(sky2->hw,
+                                            Q_ADDR(rxqaddr[le->link], Q_CSR),
+                                            BMU_DIS_RX_CHKSUM);
+                       }
                        break;
 
                case OP_TXINDEXLE:
index 64ed8ff5b03ac6038e4d54fecee1dea85529bf22..3b91af89e4c72b0781f7c52214f7970b79fb76c7 100644 (file)
@@ -1,7 +1,8 @@
 /*
- * Network device driver for Cell Processor-Based Blade
+ * Network device driver for Cell Processor-Based Blade and Celleb platform
  *
  * (C) Copyright IBM Corp. 2005
+ * (C) Copyright 2006 TOSHIBA CORPORATION
  *
  * Authors : Utz Bacher <utz.bacher@de.ibm.com>
  *           Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
@@ -165,6 +166,41 @@ spider_net_read_phy(struct net_device *netdev, int mii_id, int reg)
        return readvalue;
 }
 
+/**
+ * spider_net_setup_aneg - initial auto-negotiation setup
+ * @card: device structure
+ **/
+static void
+spider_net_setup_aneg(struct spider_net_card *card)
+{
+       struct mii_phy *phy = &card->phy;
+       u32 advertise = 0;
+       u16 bmcr, bmsr, stat1000, estat;
+
+       bmcr     = spider_net_read_phy(card->netdev, phy->mii_id, MII_BMCR);
+       bmsr     = spider_net_read_phy(card->netdev, phy->mii_id, MII_BMSR);
+       stat1000 = spider_net_read_phy(card->netdev, phy->mii_id, MII_STAT1000);
+       estat    = spider_net_read_phy(card->netdev, phy->mii_id, MII_ESTATUS);
+
+       if (bmsr & BMSR_10HALF)
+               advertise |= ADVERTISED_10baseT_Half;
+       if (bmsr & BMSR_10FULL)
+               advertise |= ADVERTISED_10baseT_Full;
+       if (bmsr & BMSR_100HALF)
+               advertise |= ADVERTISED_100baseT_Half;
+       if (bmsr & BMSR_100FULL)
+               advertise |= ADVERTISED_100baseT_Full;
+
+       if ((bmsr & BMSR_ESTATEN) && (estat & ESTATUS_1000_TFULL))
+               advertise |= SUPPORTED_1000baseT_Full;
+       if ((bmsr & BMSR_ESTATEN) && (estat & ESTATUS_1000_THALF))
+               advertise |= SUPPORTED_1000baseT_Half;
+
+       mii_phy_probe(phy, phy->mii_id);
+       phy->def->ops->setup_aneg(phy, advertise);
+
+}
+
 /**
  * spider_net_rx_irq_off - switch off rx irq on this spider card
  * @card: device structure
@@ -263,9 +299,9 @@ spider_net_get_mac_address(struct net_device *netdev)
  * returns the status as in the dmac_cmd_status field of the descriptor
  */
 static inline int
-spider_net_get_descr_status(struct spider_net_descr *descr)
+spider_net_get_descr_status(struct spider_net_hw_descr *hwdescr)
 {
-       return descr->dmac_cmd_status & SPIDER_NET_DESCR_IND_PROC_MASK;
+       return hwdescr->dmac_cmd_status & SPIDER_NET_DESCR_IND_PROC_MASK;
 }
 
 /**
@@ -283,12 +319,12 @@ spider_net_free_chain(struct spider_net_card *card,
        descr = chain->ring;
        do {
                descr->bus_addr = 0;
-               descr->next_descr_addr = 0;
+               descr->hwdescr->next_descr_addr = 0;
                descr = descr->next;
        } while (descr != chain->ring);
 
        dma_free_coherent(&card->pdev->dev, chain->num_desc,
-           chain->ring, chain->dma_addr);
+           chain->hwring, chain->dma_addr);
 }
 
 /**
@@ -307,31 +343,34 @@ spider_net_init_chain(struct spider_net_card *card,
 {
        int i;
        struct spider_net_descr *descr;
+       struct spider_net_hw_descr *hwdescr;
        dma_addr_t buf;
        size_t alloc_size;
 
-       alloc_size = chain->num_desc * sizeof (struct spider_net_descr);
+       alloc_size = chain->num_desc * sizeof(struct spider_net_hw_descr);
 
-       chain->ring = dma_alloc_coherent(&card->pdev->dev, alloc_size,
+       chain->hwring = dma_alloc_coherent(&card->pdev->dev, alloc_size,
                &chain->dma_addr, GFP_KERNEL);
 
-       if (!chain->ring)
+       if (!chain->hwring)
                return -ENOMEM;
 
-       descr = chain->ring;
-       memset(descr, 0, alloc_size);
+       memset(chain->ring, 0, chain->num_desc * sizeof(struct spider_net_descr));
 
        /* Set up the hardware pointers in each descriptor */
+       descr = chain->ring;
+       hwdescr = chain->hwring;
        buf = chain->dma_addr;
-       for (i=0; i < chain->num_desc; i++, descr++) {
-               descr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
+       for (i=0; i < chain->num_desc; i++, descr++, hwdescr++) {
+               hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
+               hwdescr->next_descr_addr = 0;
 
+               descr->hwdescr = hwdescr;
                descr->bus_addr = buf;
-               descr->next_descr_addr = 0;
                descr->next = descr + 1;
                descr->prev = descr - 1;
 
-               buf += sizeof(struct spider_net_descr);
+               buf += sizeof(struct spider_net_hw_descr);
        }
        /* do actual circular list */
        (descr-1)->next = chain->ring;
@@ -357,10 +396,11 @@ spider_net_free_rx_chain_contents(struct spider_net_card *card)
        descr = card->rx_chain.head;
        do {
                if (descr->skb) {
-                       dev_kfree_skb(descr->skb);
-                       pci_unmap_single(card->pdev, descr->buf_addr,
+                       pci_unmap_single(card->pdev, descr->hwdescr->buf_addr,
                                         SPIDER_NET_MAX_FRAME,
                                         PCI_DMA_BIDIRECTIONAL);
+                       dev_kfree_skb(descr->skb);
+                       descr->skb = NULL;
                }
                descr = descr->next;
        } while (descr != card->rx_chain.head);
@@ -380,6 +420,7 @@ static int
 spider_net_prepare_rx_descr(struct spider_net_card *card,
                            struct spider_net_descr *descr)
 {
+       struct spider_net_hw_descr *hwdescr = descr->hwdescr;
        dma_addr_t buf;
        int offset;
        int bufsize;
@@ -398,11 +439,11 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
                card->spider_stats.alloc_rx_skb_error++;
                return -ENOMEM;
        }
-       descr->buf_size = bufsize;
-       descr->result_size = 0;
-       descr->valid_size = 0;
-       descr->data_status = 0;
-       descr->data_error = 0;
+       hwdescr->buf_size = bufsize;
+       hwdescr->result_size = 0;
+       hwdescr->valid_size = 0;
+       hwdescr->data_status = 0;
+       hwdescr->data_error = 0;
 
        offset = ((unsigned long)descr->skb->data) &
                (SPIDER_NET_RXBUF_ALIGN - 1);
@@ -411,21 +452,22 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
        /* iommu-map the skb */
        buf = pci_map_single(card->pdev, descr->skb->data,
                        SPIDER_NET_MAX_FRAME, PCI_DMA_FROMDEVICE);
-       descr->buf_addr = buf;
        if (pci_dma_mapping_error(buf)) {
                dev_kfree_skb_any(descr->skb);
+               descr->skb = NULL;
                if (netif_msg_rx_err(card) && net_ratelimit())
                        pr_err("Could not iommu-map rx buffer\n");
                card->spider_stats.rx_iommu_map_error++;
-               descr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
+               hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
        } else {
-               descr->next_descr_addr = 0;
+               hwdescr->buf_addr = buf;
+               hwdescr->next_descr_addr = 0;
                wmb();
-               descr->dmac_cmd_status = SPIDER_NET_DESCR_CARDOWNED |
+               hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_CARDOWNED |
                                         SPIDER_NET_DMAC_NOINTR_COMPLETE;
 
                wmb();
-               descr->prev->next_descr_addr = descr->bus_addr;
+               descr->prev->hwdescr->next_descr_addr = descr->bus_addr;
        }
 
        return 0;
@@ -481,7 +523,7 @@ spider_net_refill_rx_chain(struct spider_net_card *card)
        if (!spin_trylock_irqsave(&chain->lock, flags))
                return;
 
-       while (spider_net_get_descr_status(chain->head) ==
+       while (spider_net_get_descr_status(chain->head->hwdescr) ==
                        SPIDER_NET_DESCR_NOT_IN_USE) {
                if (spider_net_prepare_rx_descr(card, chain->head))
                        break;
@@ -642,7 +684,9 @@ static int
 spider_net_prepare_tx_descr(struct spider_net_card *card,
                            struct sk_buff *skb)
 {
+       struct spider_net_descr_chain *chain = &card->tx_chain;
        struct spider_net_descr *descr;
+       struct spider_net_hw_descr *hwdescr;
        dma_addr_t buf;
        unsigned long flags;
 
@@ -655,32 +699,39 @@ spider_net_prepare_tx_descr(struct spider_net_card *card,
                return -ENOMEM;
        }
 
-       spin_lock_irqsave(&card->tx_chain.lock, flags);
+       spin_lock_irqsave(&chain->lock, flags);
        descr = card->tx_chain.head;
-       card->tx_chain.head = descr->next;
+       if (descr->next == chain->tail->prev) {
+               spin_unlock_irqrestore(&chain->lock, flags);
+               pci_unmap_single(card->pdev, buf, skb->len, PCI_DMA_TODEVICE);
+               return -ENOMEM;
+       }
+       hwdescr = descr->hwdescr;
+       chain->head = descr->next;
 
-       descr->buf_addr = buf;
-       descr->buf_size = skb->len;
-       descr->next_descr_addr = 0;
        descr->skb = skb;
-       descr->data_status = 0;
+       hwdescr->buf_addr = buf;
+       hwdescr->buf_size = skb->len;
+       hwdescr->next_descr_addr = 0;
+       hwdescr->data_status = 0;
 
-       descr->dmac_cmd_status =
+       hwdescr->dmac_cmd_status =
                        SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_NOCS;
-       spin_unlock_irqrestore(&card->tx_chain.lock, flags);
+       spin_unlock_irqrestore(&chain->lock, flags);
 
        if (skb->protocol == htons(ETH_P_IP))
                switch (skb->nh.iph->protocol) {
                case IPPROTO_TCP:
-                       descr->dmac_cmd_status |= SPIDER_NET_DMAC_TCP;
+                       hwdescr->dmac_cmd_status |= SPIDER_NET_DMAC_TCP;
                        break;
                case IPPROTO_UDP:
-                       descr->dmac_cmd_status |= SPIDER_NET_DMAC_UDP;
+                       hwdescr->dmac_cmd_status |= SPIDER_NET_DMAC_UDP;
                        break;
                }
 
        /* Chain the bus address, so that the DMA engine finds this descr. */
-       descr->prev->next_descr_addr = descr->bus_addr;
+       wmb();
+       descr->prev->hwdescr->next_descr_addr = descr->bus_addr;
 
        card->netdev->trans_start = jiffies; /* set netdev watchdog timer */
        return 0;
@@ -689,16 +740,17 @@ spider_net_prepare_tx_descr(struct spider_net_card *card,
 static int
 spider_net_set_low_watermark(struct spider_net_card *card)
 {
+       struct spider_net_descr *descr = card->tx_chain.tail;
+       struct spider_net_hw_descr *hwdescr;
        unsigned long flags;
        int status;
        int cnt=0;
        int i;
-       struct spider_net_descr *descr = card->tx_chain.tail;
 
        /* Measure the length of the queue. Measurement does not
         * need to be precise -- does not need a lock. */
        while (descr != card->tx_chain.head) {
-               status = descr->dmac_cmd_status & SPIDER_NET_DESCR_NOT_IN_USE;
+               status = descr->hwdescr->dmac_cmd_status & SPIDER_NET_DESCR_NOT_IN_USE;
                if (status == SPIDER_NET_DESCR_NOT_IN_USE)
                        break;
                descr = descr->next;
@@ -717,10 +769,12 @@ spider_net_set_low_watermark(struct spider_net_card *card)
 
        /* Set the new watermark, clear the old watermark */
        spin_lock_irqsave(&card->tx_chain.lock, flags);
-       descr->dmac_cmd_status |= SPIDER_NET_DESCR_TXDESFLG;
-       if (card->low_watermark && card->low_watermark != descr)
-               card->low_watermark->dmac_cmd_status =
-                    card->low_watermark->dmac_cmd_status & ~SPIDER_NET_DESCR_TXDESFLG;
+       descr->hwdescr->dmac_cmd_status |= SPIDER_NET_DESCR_TXDESFLG;
+       if (card->low_watermark && card->low_watermark != descr) {
+               hwdescr = card->low_watermark->hwdescr;
+               hwdescr->dmac_cmd_status =
+                    hwdescr->dmac_cmd_status & ~SPIDER_NET_DESCR_TXDESFLG;
+       }
        card->low_watermark = descr;
        spin_unlock_irqrestore(&card->tx_chain.lock, flags);
        return cnt;
@@ -743,16 +797,22 @@ spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
 {
        struct spider_net_descr_chain *chain = &card->tx_chain;
        struct spider_net_descr *descr;
+       struct spider_net_hw_descr *hwdescr;
        struct sk_buff *skb;
        u32 buf_addr;
        unsigned long flags;
        int status;
 
-       while (chain->tail != chain->head) {
+       while (1) {
                spin_lock_irqsave(&chain->lock, flags);
+               if (chain->tail == chain->head) {
+                       spin_unlock_irqrestore(&chain->lock, flags);
+                       return 0;
+               }
                descr = chain->tail;
+               hwdescr = descr->hwdescr;
 
-               status = spider_net_get_descr_status(descr);
+               status = spider_net_get_descr_status(hwdescr);
                switch (status) {
                case SPIDER_NET_DESCR_COMPLETE:
                        card->netdev_stats.tx_packets++;
@@ -788,9 +848,10 @@ spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
                }
 
                chain->tail = descr->next;
-               descr->dmac_cmd_status |= SPIDER_NET_DESCR_NOT_IN_USE;
+               hwdescr->dmac_cmd_status |= SPIDER_NET_DESCR_NOT_IN_USE;
                skb = descr->skb;
-               buf_addr = descr->buf_addr;
+               descr->skb = NULL;
+               buf_addr = hwdescr->buf_addr;
                spin_unlock_irqrestore(&chain->lock, flags);
 
                /* unmap the skb */
@@ -826,7 +887,7 @@ spider_net_kick_tx_dma(struct spider_net_card *card)
 
        descr = card->tx_chain.tail;
        for (;;) {
-               if (spider_net_get_descr_status(descr) ==
+               if (spider_net_get_descr_status(descr->hwdescr) ==
                                SPIDER_NET_DESCR_CARDOWNED) {
                        spider_net_write_reg(card, SPIDER_NET_GDTDCHA,
                                        descr->bus_addr);
@@ -855,13 +916,10 @@ spider_net_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
        int cnt;
        struct spider_net_card *card = netdev_priv(netdev);
-       struct spider_net_descr_chain *chain = &card->tx_chain;
 
        spider_net_release_tx_chain(card, 0);
 
-       if ((chain->head->next == chain->tail->prev) ||
-          (spider_net_prepare_tx_descr(card, skb) != 0)) {
-
+       if (spider_net_prepare_tx_descr(card, skb) != 0) {
                card->netdev_stats.tx_dropped++;
                netif_stop_queue(netdev);
                return NETDEV_TX_BUSY;
@@ -922,17 +980,18 @@ static void
 spider_net_pass_skb_up(struct spider_net_descr *descr,
                       struct spider_net_card *card)
 {
+       struct spider_net_hw_descr *hwdescr= descr->hwdescr;
        struct sk_buff *skb;
        struct net_device *netdev;
        u32 data_status, data_error;
 
-       data_status = descr->data_status;
-       data_error = descr->data_error;
+       data_status = hwdescr->data_status;
+       data_error = hwdescr->data_error;
        netdev = card->netdev;
 
        skb = descr->skb;
        skb->dev = netdev;
-       skb_put(skb, descr->valid_size);
+       skb_put(skb, hwdescr->valid_size);
 
        /* the card seems to add 2 bytes of junk in front
         * of the ethernet frame */
@@ -994,23 +1053,25 @@ static void show_rx_chain(struct spider_net_card *card)
 #endif
 
 /**
- * spider_net_decode_one_descr - processes an rx descriptor
+ * spider_net_decode_one_descr - processes an RX descriptor
  * @card: card structure
  *
- * Returns 1 if a packet has been sent to the stack, otherwise 0
+ * Returns 1 if a packet has been sent to the stack, otherwise 0.
  *
- * Processes an rx descriptor by iommu-unmapping the data buffer and passing
- * the packet up to the stack. This function is called in softirq
- * context, e.g. either bottom half from interrupt or NAPI polling context
+ * Processes an RX descriptor by iommu-unmapping the data buffer
+ * and passing the packet up to the stack. This function is called
+ * in softirq context, e.g. either bottom half from interrupt or
+ * NAPI polling context.
  */
 static int
 spider_net_decode_one_descr(struct spider_net_card *card)
 {
        struct spider_net_descr_chain *chain = &card->rx_chain;
        struct spider_net_descr *descr = chain->tail;
+       struct spider_net_hw_descr *hwdescr = descr->hwdescr;
        int status;
 
-       status = spider_net_get_descr_status(descr);
+       status = spider_net_get_descr_status(hwdescr);
 
        /* Nothing in the descriptor, or ring must be empty */
        if ((status == SPIDER_NET_DESCR_CARDOWNED) ||
@@ -1021,7 +1082,7 @@ spider_net_decode_one_descr(struct spider_net_card *card)
        chain->tail = descr->next;
 
        /* unmap descriptor */
-       pci_unmap_single(card->pdev, descr->buf_addr,
+       pci_unmap_single(card->pdev, hwdescr->buf_addr,
                        SPIDER_NET_MAX_FRAME, PCI_DMA_FROMDEVICE);
 
        if ( (status == SPIDER_NET_DESCR_RESPONSE_ERROR) ||
@@ -1037,34 +1098,33 @@ spider_net_decode_one_descr(struct spider_net_card *card)
        if ( (status != SPIDER_NET_DESCR_COMPLETE) &&
             (status != SPIDER_NET_DESCR_FRAME_END) ) {
                if (netif_msg_rx_err(card))
-                       pr_err("%s: RX descriptor with unkown state %d\n",
+                       pr_err("%s: RX descriptor with unknown state %d\n",
                               card->netdev->name, status);
                card->spider_stats.rx_desc_unk_state++;
                goto bad_desc;
        }
 
        /* The cases we'll throw away the packet immediately */
-       if (descr->data_error & SPIDER_NET_DESTROY_RX_FLAGS) {
+       if (hwdescr->data_error & SPIDER_NET_DESTROY_RX_FLAGS) {
                if (netif_msg_rx_err(card))
                        pr_err("%s: error in received descriptor found, "
                               "data_status=x%08x, data_error=x%08x\n",
                               card->netdev->name,
-                              descr->data_status, descr->data_error);
+                              hwdescr->data_status, hwdescr->data_error);
                goto bad_desc;
        }
 
-       if (descr->dmac_cmd_status & 0xfefe) {
+       if (hwdescr->dmac_cmd_status & 0xfefe) {
                pr_err("%s: bad status, cmd_status=x%08x\n",
                               card->netdev->name,
-                              descr->dmac_cmd_status);
-               pr_err("buf_addr=x%08x\n", descr->buf_addr);
-               pr_err("buf_size=x%08x\n", descr->buf_size);
-               pr_err("next_descr_addr=x%08x\n", descr->next_descr_addr);
-               pr_err("result_size=x%08x\n", descr->result_size);
-               pr_err("valid_size=x%08x\n", descr->valid_size);
-               pr_err("data_status=x%08x\n", descr->data_status);
-               pr_err("data_error=x%08x\n", descr->data_error);
-               pr_err("bus_addr=x%08x\n", descr->bus_addr);
+                              hwdescr->dmac_cmd_status);
+               pr_err("buf_addr=x%08x\n", hwdescr->buf_addr);
+               pr_err("buf_size=x%08x\n", hwdescr->buf_size);
+               pr_err("next_descr_addr=x%08x\n", hwdescr->next_descr_addr);
+               pr_err("result_size=x%08x\n", hwdescr->result_size);
+               pr_err("valid_size=x%08x\n", hwdescr->valid_size);
+               pr_err("data_status=x%08x\n", hwdescr->data_status);
+               pr_err("data_error=x%08x\n", hwdescr->data_error);
                pr_err("which=%ld\n", descr - card->rx_chain.ring);
 
                card->spider_stats.rx_desc_error++;
@@ -1073,12 +1133,13 @@ spider_net_decode_one_descr(struct spider_net_card *card)
 
        /* Ok, we've got a packet in descr */
        spider_net_pass_skb_up(descr, card);
-       descr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
+       hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
        return 1;
 
 bad_desc:
        dev_kfree_skb_irq(descr->skb);
-       descr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
+       descr->skb = NULL;
+       hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
        return 0;
 }
 
@@ -1247,6 +1308,33 @@ spider_net_set_mac(struct net_device *netdev, void *p)
        return 0;
 }
 
+/**
+ * spider_net_link_reset
+ * @netdev: net device structure
+ *
+ * This is called when the PHY_LINK signal is asserted. For the blade this is
+ * not connected so we should never get here.
+ *
+ */
+static void
+spider_net_link_reset(struct net_device *netdev)
+{
+
+       struct spider_net_card *card = netdev_priv(netdev);
+
+       del_timer_sync(&card->aneg_timer);
+
+       /* clear interrupt, block further interrupts */
+       spider_net_write_reg(card, SPIDER_NET_GMACST,
+                            spider_net_read_reg(card, SPIDER_NET_GMACST));
+       spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0);
+
+       /* reset phy and setup aneg */
+       spider_net_setup_aneg(card);
+       mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER);
+
+}
+
 /**
  * spider_net_handle_error_irq - handles errors raised by an interrupt
  * @card: card structure
@@ -1359,8 +1447,8 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
                                switch (i)
        {
        case SPIDER_NET_GTMFLLINT:
-               if (netif_msg_intr(card) && net_ratelimit())
-                       pr_err("Spider TX RAM full\n");
+               /* TX RAM full may happen on a usual case.
+                * Logging is not needed. */
                show_error = 0;
                break;
        case SPIDER_NET_GRFDFLLINT: /* fallthrough */
@@ -1500,6 +1588,9 @@ spider_net_interrupt(int irq, void *ptr)
        if (status_reg & SPIDER_NET_TXINT)
                netif_rx_schedule(netdev);
 
+       if (status_reg & SPIDER_NET_LINKINT)
+               spider_net_link_reset(netdev);
+
        if (status_reg & SPIDER_NET_ERRINT )
                spider_net_handle_error_irq(card, status_reg);
 
@@ -1540,6 +1631,11 @@ spider_net_init_card(struct spider_net_card *card)
 
        spider_net_write_reg(card, SPIDER_NET_CKRCTRL,
                             SPIDER_NET_CKRCTRL_RUN_VALUE);
+
+       /* trigger ETOMOD signal */
+       spider_net_write_reg(card, SPIDER_NET_GMACOPEMD,
+               spider_net_read_reg(card, SPIDER_NET_GMACOPEMD) | 0x4);
+
 }
 
 /**
@@ -1624,8 +1720,6 @@ spider_net_enable_card(struct spider_net_card *card)
 
        spider_net_write_reg(card, SPIDER_NET_GMACLENLMT,
                             SPIDER_NET_LENLMT_VALUE);
-       spider_net_write_reg(card, SPIDER_NET_GMACMODE,
-                            SPIDER_NET_MACMODE_VALUE);
        spider_net_write_reg(card, SPIDER_NET_GMACOPEMD,
                             SPIDER_NET_OPMODE_VALUE);
 
@@ -1641,98 +1735,6 @@ spider_net_enable_card(struct spider_net_card *card)
                             SPIDER_NET_GDTBSTA);
 }
 
-/**
- * spider_net_open - called upon ifonfig up
- * @netdev: interface device structure
- *
- * returns 0 on success, <0 on failure
- *
- * spider_net_open allocates all the descriptors and memory needed for
- * operation, sets up multicast list and enables interrupts
- */
-int
-spider_net_open(struct net_device *netdev)
-{
-       struct spider_net_card *card = netdev_priv(netdev);
-       int result;
-
-       result = spider_net_init_chain(card, &card->tx_chain);
-       if (result)
-               goto alloc_tx_failed;
-       card->low_watermark = NULL;
-
-       result = spider_net_init_chain(card, &card->rx_chain);
-       if (result)
-               goto alloc_rx_failed;
-
-       /* Allocate rx skbs */
-       if (spider_net_alloc_rx_skbs(card))
-               goto alloc_skbs_failed;
-
-       spider_net_set_multi(netdev);
-
-       /* further enhancement: setup hw vlan, if needed */
-
-       result = -EBUSY;
-       if (request_irq(netdev->irq, spider_net_interrupt,
-                            IRQF_SHARED, netdev->name, netdev))
-               goto register_int_failed;
-
-       spider_net_enable_card(card);
-
-       netif_start_queue(netdev);
-       netif_carrier_on(netdev);
-       netif_poll_enable(netdev);
-
-       return 0;
-
-register_int_failed:
-       spider_net_free_rx_chain_contents(card);
-alloc_skbs_failed:
-       spider_net_free_chain(card, &card->rx_chain);
-alloc_rx_failed:
-       spider_net_free_chain(card, &card->tx_chain);
-alloc_tx_failed:
-       return result;
-}
-
-/**
- * spider_net_setup_phy - setup PHY
- * @card: card structure
- *
- * returns 0 on success, <0 on failure
- *
- * spider_net_setup_phy is used as part of spider_net_probe. Sets
- * the PHY to 1000 Mbps
- **/
-static int
-spider_net_setup_phy(struct spider_net_card *card)
-{
-       struct mii_phy *phy = &card->phy;
-
-       spider_net_write_reg(card, SPIDER_NET_GDTDMASEL,
-                            SPIDER_NET_DMASEL_VALUE);
-       spider_net_write_reg(card, SPIDER_NET_GPCCTRL,
-                            SPIDER_NET_PHY_CTRL_VALUE);
-       phy->mii_id = 1;
-       phy->dev = card->netdev;
-       phy->mdio_read = spider_net_read_phy;
-       phy->mdio_write = spider_net_write_phy;
-
-       mii_phy_probe(phy, phy->mii_id);
-
-       if (phy->def->ops->setup_forced)
-               phy->def->ops->setup_forced(phy, SPEED_1000, DUPLEX_FULL);
-
-       phy->def->ops->enable_fiber(phy);
-
-       phy->def->ops->read_link(phy);
-       pr_info("Found %s with %i Mbps, %s-duplex.\n", phy->def->name,
-               phy->speed, phy->duplex==1 ? "Full" : "Half");
-
-       return 0;
-}
-
 /**
  * spider_net_download_firmware - loads firmware into the adapter
  * @card: card structure
@@ -1851,6 +1853,179 @@ out_err:
        return err;
 }
 
+/**
+ * spider_net_open - called upon ifonfig up
+ * @netdev: interface device structure
+ *
+ * returns 0 on success, <0 on failure
+ *
+ * spider_net_open allocates all the descriptors and memory needed for
+ * operation, sets up multicast list and enables interrupts
+ */
+int
+spider_net_open(struct net_device *netdev)
+{
+       struct spider_net_card *card = netdev_priv(netdev);
+       int result;
+
+       result = spider_net_init_firmware(card);
+       if (result)
+               goto init_firmware_failed;
+
+       /* start probing with copper */
+       spider_net_setup_aneg(card);
+       if (card->phy.def->phy_id)
+               mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER);
+
+       result = spider_net_init_chain(card, &card->tx_chain);
+       if (result)
+               goto alloc_tx_failed;
+       card->low_watermark = NULL;
+
+       result = spider_net_init_chain(card, &card->rx_chain);
+       if (result)
+               goto alloc_rx_failed;
+
+       /* Allocate rx skbs */
+       if (spider_net_alloc_rx_skbs(card))
+               goto alloc_skbs_failed;
+
+       spider_net_set_multi(netdev);
+
+       /* further enhancement: setup hw vlan, if needed */
+
+       result = -EBUSY;
+       if (request_irq(netdev->irq, spider_net_interrupt,
+                            IRQF_SHARED, netdev->name, netdev))
+               goto register_int_failed;
+
+       spider_net_enable_card(card);
+
+       netif_start_queue(netdev);
+       netif_carrier_on(netdev);
+       netif_poll_enable(netdev);
+
+       return 0;
+
+register_int_failed:
+       spider_net_free_rx_chain_contents(card);
+alloc_skbs_failed:
+       spider_net_free_chain(card, &card->rx_chain);
+alloc_rx_failed:
+       spider_net_free_chain(card, &card->tx_chain);
+alloc_tx_failed:
+       del_timer_sync(&card->aneg_timer);
+init_firmware_failed:
+       return result;
+}
+
+/**
+ * spider_net_link_phy
+ * @data: used for pointer to card structure
+ *
+ */
+static void spider_net_link_phy(unsigned long data)
+{
+       struct spider_net_card *card = (struct spider_net_card *)data;
+       struct mii_phy *phy = &card->phy;
+
+       /* if link didn't come up after SPIDER_NET_ANEG_TIMEOUT tries, setup phy again */
+       if (card->aneg_count > SPIDER_NET_ANEG_TIMEOUT) {
+
+               pr_info("%s: link is down trying to bring it up\n", card->netdev->name);
+
+               switch (card->medium) {
+               case BCM54XX_COPPER:
+                       /* enable fiber with autonegotiation first */
+                       if (phy->def->ops->enable_fiber)
+                               phy->def->ops->enable_fiber(phy, 1);
+                       card->medium = BCM54XX_FIBER;
+                       break;
+
+               case BCM54XX_FIBER:
+                       /* fiber didn't come up, try to disable fiber autoneg */
+                       if (phy->def->ops->enable_fiber)
+                               phy->def->ops->enable_fiber(phy, 0);
+                       card->medium = BCM54XX_UNKNOWN;
+                       break;
+
+               case BCM54XX_UNKNOWN:
+                       /* copper, fiber with and without failed,
+                        * retry from beginning */
+                       spider_net_setup_aneg(card);
+                       card->medium = BCM54XX_COPPER;
+                       break;
+               }
+
+               card->aneg_count = 0;
+               mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER);
+               return;
+       }
+
+       /* link still not up, try again later */
+       if (!(phy->def->ops->poll_link(phy))) {
+               card->aneg_count++;
+               mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER);
+               return;
+       }
+
+       /* link came up, get abilities */
+       phy->def->ops->read_link(phy);
+
+       spider_net_write_reg(card, SPIDER_NET_GMACST,
+                            spider_net_read_reg(card, SPIDER_NET_GMACST));
+       spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0x4);
+
+       if (phy->speed == 1000)
+               spider_net_write_reg(card, SPIDER_NET_GMACMODE, 0x00000001);
+       else
+               spider_net_write_reg(card, SPIDER_NET_GMACMODE, 0);
+
+       card->aneg_count = 0;
+
+       pr_debug("Found %s with %i Mbps, %s-duplex %sautoneg.\n",
+               phy->def->name, phy->speed, phy->duplex==1 ? "Full" : "Half",
+               phy->autoneg==1 ? "" : "no ");
+
+       return;
+}
+
+/**
+ * spider_net_setup_phy - setup PHY
+ * @card: card structure
+ *
+ * returns 0 on success, <0 on failure
+ *
+ * spider_net_setup_phy is used as part of spider_net_probe.
+ **/
+static int
+spider_net_setup_phy(struct spider_net_card *card)
+{
+       struct mii_phy *phy = &card->phy;
+
+       spider_net_write_reg(card, SPIDER_NET_GDTDMASEL,
+                            SPIDER_NET_DMASEL_VALUE);
+       spider_net_write_reg(card, SPIDER_NET_GPCCTRL,
+                            SPIDER_NET_PHY_CTRL_VALUE);
+
+       phy->dev = card->netdev;
+       phy->mdio_read = spider_net_read_phy;
+       phy->mdio_write = spider_net_write_phy;
+
+       for (phy->mii_id = 1; phy->mii_id <= 31; phy->mii_id++) {
+               unsigned short id;
+               id = spider_net_read_phy(card->netdev, phy->mii_id, MII_BMSR);
+               if (id != 0x0000 && id != 0xffff) {
+                       if (!mii_phy_probe(phy, phy->mii_id)) {
+                               pr_info("Found %s.\n", phy->def->name);
+                               break;
+                       }
+               }
+       }
+
+       return 0;
+}
+
 /**
  * spider_net_workaround_rxramfull - work around firmware bug
  * @card: card structure
@@ -1900,14 +2075,15 @@ spider_net_stop(struct net_device *netdev)
        netif_carrier_off(netdev);
        netif_stop_queue(netdev);
        del_timer_sync(&card->tx_timer);
+       del_timer_sync(&card->aneg_timer);
 
        /* disable/mask all interrupts */
        spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0);
        spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0);
        spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0);
+       spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0);
 
-       /* free_irq(netdev->irq, netdev);*/
-       free_irq(to_pci_dev(netdev->dev.parent)->irq, netdev);
+       free_irq(netdev->irq, netdev);
 
        spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
                             SPIDER_NET_DMA_TX_FEND_VALUE);
@@ -1919,8 +2095,6 @@ spider_net_stop(struct net_device *netdev)
        spider_net_release_tx_chain(card, 1);
        spider_net_free_rx_chain_contents(card);
 
-       spider_net_free_rx_chain_contents(card);
-
        spider_net_free_chain(card, &card->tx_chain);
        spider_net_free_chain(card, &card->rx_chain);
 
@@ -1952,8 +2126,6 @@ spider_net_tx_timeout_task(struct work_struct *work)
 
        if (spider_net_setup_phy(card))
                goto out;
-       if (spider_net_init_firmware(card))
-               goto out;
 
        spider_net_open(netdev);
        spider_net_kick_tx_dma(card);
@@ -2046,10 +2218,12 @@ spider_net_setup_netdev(struct spider_net_card *card)
        card->tx_timer.data = (unsigned long) card;
        netdev->irq = card->pdev->irq;
 
-       card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT;
+       card->aneg_count = 0;
+       init_timer(&card->aneg_timer);
+       card->aneg_timer.function = spider_net_link_phy;
+       card->aneg_timer.data = (unsigned long) card;
 
-       card->tx_chain.num_desc = tx_descriptors;
-       card->rx_chain.num_desc = rx_descriptors;
+       card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT;
 
        spider_net_setup_netdev_ops(netdev);
 
@@ -2098,8 +2272,11 @@ spider_net_alloc_card(void)
 {
        struct net_device *netdev;
        struct spider_net_card *card;
+       size_t alloc_size;
 
-       netdev = alloc_etherdev(sizeof(struct spider_net_card));
+       alloc_size = sizeof(struct spider_net_card) +
+          (tx_descriptors + rx_descriptors) * sizeof(struct spider_net_descr);
+       netdev = alloc_etherdev(alloc_size);
        if (!netdev)
                return NULL;
 
@@ -2110,6 +2287,11 @@ spider_net_alloc_card(void)
        init_waitqueue_head(&card->waitq);
        atomic_set(&card->tx_timeout_task_counter, 0);
 
+       card->rx_chain.num_desc = rx_descriptors;
+       card->rx_chain.ring = card->darray;
+       card->tx_chain.num_desc = tx_descriptors;
+       card->tx_chain.ring = card->darray + rx_descriptors;
+
        return card;
 }
 
@@ -2220,10 +2402,6 @@ spider_net_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (err)
                goto out_undo_pci;
 
-       err = spider_net_init_firmware(card);
-       if (err)
-               goto out_undo_pci;
-
        err = spider_net_setup_netdev(card);
        if (err)
                goto out_undo_pci;
index 2fec5cf76926d31d18bc8f1b278e47fdcc13e86b..4a1e0d28a502b1be6e532bb2fafd0357aafce93c 100644 (file)
@@ -1,7 +1,8 @@
 /*
- * Network device driver for Cell Processor-Based Blade
+ * Network device driver for Cell Processor-Based Blade and Celleb platform
  *
  * (C) Copyright IBM Corp. 2005
+ * (C) Copyright 2006 TOSHIBA CORPORATION
  *
  * Authors : Utz Bacher <utz.bacher@de.ibm.com>
  *           Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
@@ -24,7 +25,7 @@
 #ifndef _SPIDER_NET_H
 #define _SPIDER_NET_H
 
-#define VERSION "1.6 B"
+#define VERSION "2.0 A"
 
 #include "sungem_phy.h"
 
@@ -50,6 +51,8 @@ extern char spider_net_driver_name[];
 #define SPIDER_NET_TX_DESCRIPTORS_MAX          512
 
 #define SPIDER_NET_TX_TIMER                    (HZ/5)
+#define SPIDER_NET_ANEG_TIMER                  (HZ)
+#define SPIDER_NET_ANEG_TIMEOUT                        2
 
 #define SPIDER_NET_RX_CSUM_DEFAULT             1
 
@@ -104,6 +107,7 @@ extern char spider_net_driver_name[];
 
 #define SPIDER_NET_GMACOPEMD           0x00000100
 #define SPIDER_NET_GMACLENLMT          0x00000108
+#define SPIDER_NET_GMACST              0x00000110
 #define SPIDER_NET_GMACINTEN           0x00000118
 #define SPIDER_NET_GMACPHYCTRL         0x00000120
 
@@ -181,7 +185,8 @@ extern char spider_net_driver_name[];
 
 /* pause frames: automatic, no upper retransmission count */
 /* outside loopback mode: ETOMOD signal dont matter, not connected */
-#define SPIDER_NET_OPMODE_VALUE                0x00000063
+/* ETOMOD signal is brought to PHY reset. bit 2 must be 1 in Celleb */
+#define SPIDER_NET_OPMODE_VALUE                0x00000067
 /*#define SPIDER_NET_OPMODE_VALUE              0x001b0062*/
 #define SPIDER_NET_LENLMT_VALUE                0x00000908
 
@@ -333,9 +338,12 @@ enum spider_net_int2_status {
 /* We rely on flagged descriptor interrupts */
 #define SPIDER_NET_RXINT       ( (1 << SPIDER_NET_GDAFDCINT) )
 
+#define SPIDER_NET_LINKINT     ( 1 << SPIDER_NET_GMAC2INT )
+
 #define SPIDER_NET_ERRINT      ( 0xffffffff & \
                                  (~SPIDER_NET_TXINT) & \
-                                 (~SPIDER_NET_RXINT) )
+                                 (~SPIDER_NET_RXINT) & \
+                                 (~SPIDER_NET_LINKINT) )
 
 #define SPIDER_NET_GPREXEC                     0x80000000
 #define SPIDER_NET_GPRDAT_MASK                 0x0000ffff
@@ -356,8 +364,8 @@ enum spider_net_int2_status {
 #define SPIDER_NET_DESCR_NOT_IN_USE            0xF0000000
 #define SPIDER_NET_DESCR_TXDESFLG              0x00800000
 
-struct spider_net_descr {
-       /* as defined by the hardware */
+/* Descriptor, as defined by the hardware */
+struct spider_net_hw_descr {
        u32 buf_addr;
        u32 buf_size;
        u32 next_descr_addr;
@@ -366,13 +374,15 @@ struct spider_net_descr {
        u32 valid_size; /* all zeroes for tx */
        u32 data_status;
        u32 data_error; /* all zeroes for tx */
+} __attribute__((aligned(32)));
 
-       /* used in the driver */
+struct spider_net_descr {
+       struct spider_net_hw_descr *hwdescr;
        struct sk_buff *skb;
        u32 bus_addr;
        struct spider_net_descr *next;
        struct spider_net_descr *prev;
-} __attribute__((aligned(32)));
+};
 
 struct spider_net_descr_chain {
        spinlock_t lock;
@@ -380,6 +390,7 @@ struct spider_net_descr_chain {
        struct spider_net_descr *tail;
        struct spider_net_descr *ring;
        int num_desc;
+       struct spider_net_hw_descr *hwring;
        dma_addr_t dma_addr;
 };
 
@@ -436,12 +447,16 @@ struct spider_net_card {
        struct pci_dev *pdev;
        struct mii_phy phy;
 
+       int medium;
+
        void __iomem *regs;
 
        struct spider_net_descr_chain tx_chain;
        struct spider_net_descr_chain rx_chain;
        struct spider_net_descr *low_watermark;
 
+       int aneg_count;
+       struct timer_list aneg_timer;
        struct timer_list tx_timer;
        struct work_struct tx_timeout_task;
        atomic_t tx_timeout_task_counter;
@@ -452,6 +467,9 @@ struct spider_net_card {
        struct net_device_stats netdev_stats;
        struct spider_net_extra_stats spider_stats;
        struct spider_net_options options;
+
+       /* Must be last item in struct */
+       struct spider_net_descr darray[0];
 };
 
 #define pr_err(fmt,arg...) \
index bf873ea2579733f572f25886b9a0ab9d358cbf3d..8bba2e3da7e168d86c4c702d7b1da7ee4581bdee 100644 (file)
@@ -677,8 +677,7 @@ static void netdev_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
        spin_lock(&np->lock);
        if (debug > 1)
                printk("%s: removing vlanid %d from vlan filter\n", dev->name, vid);
-       if (np->vlgrp)
-               np->vlgrp->vlan_devices[vid] = NULL;
+       vlan_group_set_device(np->vlgrp, vid, NULL);
        set_rx_mode(dev);
        spin_unlock(&np->lock);
 }
@@ -1738,7 +1737,7 @@ static void set_rx_mode(struct net_device *dev)
                int vlan_count = 0;
                void __iomem *filter_addr = ioaddr + HashTable + 8;
                for (i = 0; i < VLAN_VID_MASK; i++) {
-                       if (np->vlgrp->vlan_devices[i]) {
+                       if (vlan_group_get_device(np->vlgrp, i)) {
                                if (vlan_count >= 32)
                                        break;
                                writew(cpu_to_be16(i), filter_addr);
index a3220a96524f0ead88f6a6b0089ec569007627ea..4757aa647c7a22be22d8d4c96a540d9c3119389a 100644 (file)
@@ -28,8 +28,6 @@ static int automatic_resume = 0; /* experimental .. better should be zero */
 static int rfdadd = 0; /* rfdadd=1 may be better for 8K MEM cards */
 static int fifo=0x8;   /* don't change */
 
-/* #define REALLY_SLOW_IO */
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
index 701ba4f3b69d865a87a51ae9eebf8698d6c91edc..56a110ca5e6ffce292ff9287ffb6703202879e21 100644 (file)
@@ -310,6 +310,107 @@ static int bcm5411_init(struct mii_phy* phy)
        return 0;
 }
 
+static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
+{
+       u16 ctl, adv;
+
+       phy->autoneg = 1;
+       phy->speed = SPEED_10;
+       phy->duplex = DUPLEX_HALF;
+       phy->pause = 0;
+       phy->advertising = advertise;
+
+       /* Setup standard advertise */
+       adv = phy_read(phy, MII_ADVERTISE);
+       adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+       if (advertise & ADVERTISED_10baseT_Half)
+               adv |= ADVERTISE_10HALF;
+       if (advertise & ADVERTISED_10baseT_Full)
+               adv |= ADVERTISE_10FULL;
+       if (advertise & ADVERTISED_100baseT_Half)
+               adv |= ADVERTISE_100HALF;
+       if (advertise & ADVERTISED_100baseT_Full)
+               adv |= ADVERTISE_100FULL;
+       phy_write(phy, MII_ADVERTISE, adv);
+
+       /* Start/Restart aneg */
+       ctl = phy_read(phy, MII_BMCR);
+       ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+       phy_write(phy, MII_BMCR, ctl);
+
+       return 0;
+}
+
+static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
+{
+       u16 ctl;
+
+       phy->autoneg = 0;
+       phy->speed = speed;
+       phy->duplex = fd;
+       phy->pause = 0;
+
+       ctl = phy_read(phy, MII_BMCR);
+       ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_ANENABLE);
+
+       /* First reset the PHY */
+       phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
+
+       /* Select speed & duplex */
+       switch(speed) {
+       case SPEED_10:
+               break;
+       case SPEED_100:
+               ctl |= BMCR_SPEED100;
+               break;
+       case SPEED_1000:
+       default:
+               return -EINVAL;
+       }
+       if (fd == DUPLEX_FULL)
+               ctl |= BMCR_FULLDPLX;
+       phy_write(phy, MII_BMCR, ctl);
+
+       return 0;
+}
+
+static int genmii_poll_link(struct mii_phy *phy)
+{
+       u16 status;
+
+       (void)phy_read(phy, MII_BMSR);
+       status = phy_read(phy, MII_BMSR);
+       if ((status & BMSR_LSTATUS) == 0)
+               return 0;
+       if (phy->autoneg && !(status & BMSR_ANEGCOMPLETE))
+               return 0;
+       return 1;
+}
+
+static int genmii_read_link(struct mii_phy *phy)
+{
+       u16 lpa;
+
+       if (phy->autoneg) {
+               lpa = phy_read(phy, MII_LPA);
+
+               if (lpa & (LPA_10FULL | LPA_100FULL))
+                       phy->duplex = DUPLEX_FULL;
+               else
+                       phy->duplex = DUPLEX_HALF;
+               if (lpa & (LPA_100FULL | LPA_100HALF))
+                       phy->speed = SPEED_100;
+               else
+                       phy->speed = SPEED_10;
+               phy->pause = 0;
+       }
+       /* On non-aneg, we assume what we put in BMCR is the speed,
+        * though magic-aneg shouldn't prevent this case from occurring
+        */
+
+        return 0;
+}
+
 static int generic_suspend(struct mii_phy* phy)
 {
        phy_write(phy, MII_BMCR, BMCR_PDOWN);
@@ -364,30 +465,6 @@ static int bcm5421_init(struct mii_phy* phy)
        return 0;
 }
 
-static int bcm5421_enable_fiber(struct mii_phy* phy)
-{
-       /* enable fiber mode */
-       phy_write(phy, MII_NCONFIG, 0x9020);
-       /* LEDs active in both modes, autosense prio = fiber */
-       phy_write(phy, MII_NCONFIG, 0x945f);
-
-       /* switch off fibre autoneg */
-       phy_write(phy, MII_NCONFIG, 0xfc01);
-       phy_write(phy, 0x0b, 0x0004);
-
-       return 0;
-}
-
-static int bcm5461_enable_fiber(struct mii_phy* phy)
-{
-       phy_write(phy, MII_NCONFIG, 0xfc0c);
-       phy_write(phy, MII_BMCR, 0x4140);
-       phy_write(phy, MII_NCONFIG, 0xfc0b);
-       phy_write(phy, MII_BMCR, 0x0140);
-
-       return 0;
-}
-
 static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise)
 {
        u16 ctl, adv;
@@ -515,6 +592,155 @@ static int marvell88e1111_init(struct mii_phy* phy)
        return 0;
 }
 
+#define BCM5421_MODE_MASK      (1 << 5)
+
+static int bcm5421_poll_link(struct mii_phy* phy)
+{
+       u32 phy_reg;
+       int mode;
+
+       /* find out in what mode we are */
+       phy_write(phy, MII_NCONFIG, 0x1000);
+       phy_reg = phy_read(phy, MII_NCONFIG);
+
+       mode = (phy_reg & BCM5421_MODE_MASK) >> 5;
+
+       if ( mode == BCM54XX_COPPER)
+               return genmii_poll_link(phy);
+
+       /* try to find out wether we have a link */
+       phy_write(phy, MII_NCONFIG, 0x2000);
+       phy_reg = phy_read(phy, MII_NCONFIG);
+
+       if (phy_reg & 0x0020)
+               return 0;
+       else
+               return 1;
+}
+
+static int bcm5421_read_link(struct mii_phy* phy)
+{
+       u32 phy_reg;
+       int mode;
+
+       /* find out in what mode we are */
+       phy_write(phy, MII_NCONFIG, 0x1000);
+       phy_reg = phy_read(phy, MII_NCONFIG);
+
+       mode = (phy_reg & BCM5421_MODE_MASK ) >> 5;
+
+       if ( mode == BCM54XX_COPPER)
+               return bcm54xx_read_link(phy);
+
+       phy->speed = SPEED_1000;
+
+       /* find out wether we are running half- or full duplex */
+       phy_write(phy, MII_NCONFIG, 0x2000);
+       phy_reg = phy_read(phy, MII_NCONFIG);
+
+       if ( (phy_reg & 0x0080) >> 7)
+               phy->duplex |=  DUPLEX_HALF;
+       else
+               phy->duplex |=  DUPLEX_FULL;
+
+       return 0;
+}
+
+static int bcm5421_enable_fiber(struct mii_phy* phy, int autoneg)
+{
+       /* enable fiber mode */
+       phy_write(phy, MII_NCONFIG, 0x9020);
+       /* LEDs active in both modes, autosense prio = fiber */
+       phy_write(phy, MII_NCONFIG, 0x945f);
+
+       if (!autoneg) {
+               /* switch off fibre autoneg */
+               phy_write(phy, MII_NCONFIG, 0xfc01);
+               phy_write(phy, 0x0b, 0x0004);
+       }
+
+       phy->autoneg = autoneg;
+
+       return 0;
+}
+
+#define BCM5461_FIBER_LINK     (1 << 2)
+#define BCM5461_MODE_MASK      (3 << 1)
+
+static int bcm5461_poll_link(struct mii_phy* phy)
+{
+       u32 phy_reg;
+       int mode;
+
+       /* find out in what mode we are */
+       phy_write(phy, MII_NCONFIG, 0x7c00);
+       phy_reg = phy_read(phy, MII_NCONFIG);
+
+       mode = (phy_reg & BCM5461_MODE_MASK ) >> 1;
+
+       if ( mode == BCM54XX_COPPER)
+               return genmii_poll_link(phy);
+
+       /* find out wether we have a link */
+       phy_write(phy, MII_NCONFIG, 0x7000);
+       phy_reg = phy_read(phy, MII_NCONFIG);
+
+       if (phy_reg & BCM5461_FIBER_LINK)
+               return 1;
+       else
+               return 0;
+}
+
+#define BCM5461_FIBER_DUPLEX   (1 << 3)
+
+static int bcm5461_read_link(struct mii_phy* phy)
+{
+       u32 phy_reg;
+       int mode;
+
+       /* find out in what mode we are */
+       phy_write(phy, MII_NCONFIG, 0x7c00);
+       phy_reg = phy_read(phy, MII_NCONFIG);
+
+       mode = (phy_reg & BCM5461_MODE_MASK ) >> 1;
+
+       if ( mode == BCM54XX_COPPER) {
+               return bcm54xx_read_link(phy);
+       }
+
+       phy->speed = SPEED_1000;
+
+       /* find out wether we are running half- or full duplex */
+       phy_write(phy, MII_NCONFIG, 0x7000);
+       phy_reg = phy_read(phy, MII_NCONFIG);
+
+       if (phy_reg & BCM5461_FIBER_DUPLEX)
+               phy->duplex |=  DUPLEX_FULL;
+       else
+               phy->duplex |=  DUPLEX_HALF;
+
+       return 0;
+}
+
+static int bcm5461_enable_fiber(struct mii_phy* phy, int autoneg)
+{
+       /* select fiber mode, enable 1000 base-X registers */
+       phy_write(phy, MII_NCONFIG, 0xfc0b);
+
+       if (autoneg) {
+               /* enable fiber with no autonegotiation */
+               phy_write(phy, MII_ADVERTISE, 0x01e0);
+               phy_write(phy, MII_BMCR, 0x1140);
+       } else {
+               /* enable fiber with autonegotiation */
+               phy_write(phy, MII_BMCR, 0x0140);
+       }
+
+       phy->autoneg = autoneg;
+
+       return 0;
+}
+
 static int marvell_setup_aneg(struct mii_phy *phy, u32 advertise)
 {
        u16 ctl, adv;
@@ -645,113 +871,6 @@ static int marvell_read_link(struct mii_phy *phy)
        return 0;
 }
 
-static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
-{
-       u16 ctl, adv;
-
-       phy->autoneg = 1;
-       phy->speed = SPEED_10;
-       phy->duplex = DUPLEX_HALF;
-       phy->pause = 0;
-       phy->advertising = advertise;
-
-       /* Setup standard advertise */
-       adv = phy_read(phy, MII_ADVERTISE);
-       adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
-       if (advertise & ADVERTISED_10baseT_Half)
-               adv |= ADVERTISE_10HALF;
-       if (advertise & ADVERTISED_10baseT_Full)
-               adv |= ADVERTISE_10FULL;
-       if (advertise & ADVERTISED_100baseT_Half)
-               adv |= ADVERTISE_100HALF;
-       if (advertise & ADVERTISED_100baseT_Full)
-               adv |= ADVERTISE_100FULL;
-       if (advertise & ADVERTISED_Pause)
-               adv |= ADVERTISE_PAUSE_CAP;
-       if (advertise & ADVERTISED_Asym_Pause)
-               adv |= ADVERTISE_PAUSE_ASYM;
-       phy_write(phy, MII_ADVERTISE, adv);
-
-       /* Start/Restart aneg */
-       ctl = phy_read(phy, MII_BMCR);
-       ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
-       phy_write(phy, MII_BMCR, ctl);
-
-       return 0;
-}
-
-static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
-{
-       u16 ctl;
-
-       phy->autoneg = 0;
-       phy->speed = speed;
-       phy->duplex = fd;
-       phy->pause = 0;
-
-       ctl = phy_read(phy, MII_BMCR);
-       ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_ANENABLE);
-
-       /* First reset the PHY */
-       phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
-
-       /* Select speed & duplex */
-       switch(speed) {
-       case SPEED_10:
-               break;
-       case SPEED_100:
-               ctl |= BMCR_SPEED100;
-               break;
-       case SPEED_1000:
-       default:
-               return -EINVAL;
-       }
-       if (fd == DUPLEX_FULL)
-               ctl |= BMCR_FULLDPLX;
-       phy_write(phy, MII_BMCR, ctl);
-
-       return 0;
-}
-
-static int genmii_poll_link(struct mii_phy *phy)
-{
-       u16 status;
-
-       (void)phy_read(phy, MII_BMSR);
-       status = phy_read(phy, MII_BMSR);
-       if ((status & BMSR_LSTATUS) == 0)
-               return 0;
-       if (phy->autoneg && !(status & BMSR_ANEGCOMPLETE))
-               return 0;
-       return 1;
-}
-
-static int genmii_read_link(struct mii_phy *phy)
-{
-       u16 lpa;
-
-       if (phy->autoneg) {
-               lpa = phy_read(phy, MII_LPA);
-
-               if (lpa & (LPA_10FULL | LPA_100FULL))
-                       phy->duplex = DUPLEX_FULL;
-               else
-                       phy->duplex = DUPLEX_HALF;
-               if (lpa & (LPA_100FULL | LPA_100HALF))
-                       phy->speed = SPEED_100;
-               else
-                       phy->speed = SPEED_10;
-               phy->pause = (phy->duplex == DUPLEX_FULL) &&
-                       ((lpa & LPA_PAUSE) != 0);
-       }
-       /* On non-aneg, we assume what we put in BMCR is the speed,
-        * though magic-aneg shouldn't prevent this case from occurring
-        */
-
-        return 0;
-}
-
-
 #define MII_BASIC_FEATURES \
        (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |      \
         SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |    \
@@ -885,8 +1004,8 @@ static struct mii_phy_ops bcm5421_phy_ops = {
        .suspend        = generic_suspend,
        .setup_aneg     = bcm54xx_setup_aneg,
        .setup_forced   = bcm54xx_setup_forced,
-       .poll_link      = genmii_poll_link,
-       .read_link      = bcm54xx_read_link,
+       .poll_link      = bcm5421_poll_link,
+       .read_link      = bcm5421_read_link,
        .enable_fiber   = bcm5421_enable_fiber,
 };
 
@@ -923,8 +1042,8 @@ static struct mii_phy_ops bcm5461_phy_ops = {
        .suspend        = generic_suspend,
        .setup_aneg     = bcm54xx_setup_aneg,
        .setup_forced   = bcm54xx_setup_forced,
-       .poll_link      = genmii_poll_link,
-       .read_link      = bcm54xx_read_link,
+       .poll_link      = bcm5461_poll_link,
+       .read_link      = bcm5461_read_link,
        .enable_fiber   = bcm5461_enable_fiber,
 };
 
index 1d70ba6f9f10e65648484d6f99a9bd63a7682848..af02f9479cbbab0c7dcfd85da2a91a0d2cee26eb 100644 (file)
@@ -12,7 +12,7 @@ struct mii_phy_ops
        int             (*setup_forced)(struct mii_phy *phy, int speed, int fd);
        int             (*poll_link)(struct mii_phy *phy);
        int             (*read_link)(struct mii_phy *phy);
-       int             (*enable_fiber)(struct mii_phy *phy);
+       int             (*enable_fiber)(struct mii_phy *phy, int autoneg);
 };
 
 /* Structure used to statically define an mii/gii based PHY */
@@ -26,6 +26,14 @@ struct mii_phy_def
        const struct mii_phy_ops*       ops;
 };
 
+enum {
+       BCM54XX_COPPER,
+       BCM54XX_FIBER,
+       BCM54XX_GBIC,
+       BCM54XX_SGMII,
+       BCM54XX_UNKNOWN,
+};
+
 /* An instance of a PHY, partially borrowed from mii_if_info */
 struct mii_phy
 {
index 81ed82f0b52073da356b58be80c5b09fd75ab9aa..e3a7e3ceab772e42de6f3481bc262a1527c8de03 100644 (file)
@@ -657,7 +657,7 @@ tc35815_init_queues(struct net_device *dev)
                dma_cache_wback_inv((unsigned long)lp->fd_buf, PAGE_SIZE * FD_PAGE_NUM);
 #endif
        } else {
-               clear_page(lp->fd_buf);
+               memset(lp->fd_buf, 0, PAGE_SIZE * FD_PAGE_NUM);
 #ifdef __mips__
                dma_cache_wback_inv((unsigned long)lp->fd_buf, PAGE_SIZE * FD_PAGE_NUM);
 #endif
@@ -1703,19 +1703,6 @@ static void tc35815_chip_init(struct net_device *dev)
        spin_unlock_irqrestore(&lp->lock, flags);
 }
 
-/* XXX */
-void
-tc35815_killall(void)
-{
-       struct net_device *dev;
-
-       for (dev = root_tc35815_dev; dev; dev = ((struct tc35815_local *)dev->priv)->next_module) {
-               if (dev->flags&IFF_UP){
-                       dev->stop(dev);
-               }
-       }
-}
-
 static struct pci_driver tc35815_driver = {
        .name = TC35815_MODULE_NAME,
        .probe = tc35815_probe,
@@ -1732,6 +1719,11 @@ static void __exit tc35815_cleanup_module(void)
 {
        struct net_device *next_dev;
 
+       /*
+        * TODO: implement a tc35815_driver.remove hook, and
+        * move this code into that function.  Then, delete
+        * all root_tc35815_dev list handling code.
+        */
        while (root_tc35815_dev) {
                struct net_device *dev = root_tc35815_dev;
                next_dev = ((struct tc35815_local *)dev->priv)->next_module;
@@ -1740,6 +1732,9 @@ static void __exit tc35815_cleanup_module(void)
                free_netdev(dev);
                root_tc35815_dev = next_dev;
        }
+
+       pci_unregister_driver(&tc35815_driver);
 }
+
 module_init(tc35815_init_module);
 module_exit(tc35815_cleanup_module);
index 81a1c2e1a3f5c98fd75404f51d7b04aafa82426d..8c8f9f4d47a599c8b0ef91fcfef65bfffda5df79 100644 (file)
@@ -64,8 +64,8 @@
 
 #define DRV_MODULE_NAME                "tg3"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "3.73"
-#define DRV_MODULE_RELDATE     "February 12, 2007"
+#define DRV_MODULE_VERSION     "3.74"
+#define DRV_MODULE_RELDATE     "February 20, 2007"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
@@ -3993,7 +3993,10 @@ static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb)
        /* Estimate the number of fragments in the worst case */
        if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->gso_segs * 3))) {
                netif_stop_queue(tp->dev);
-               return NETDEV_TX_BUSY;
+               if (tg3_tx_avail(tp) <= (skb_shinfo(skb)->gso_segs * 3))
+                       return NETDEV_TX_BUSY;
+
+               netif_wake_queue(tp->dev);
        }
 
        segs = skb_gso_segment(skb, tp->dev->features & ~NETIF_F_TSO);
@@ -4061,7 +4064,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
 
                hdr_len = ip_tcp_len + tcp_opt_len;
                if (unlikely((ETH_HLEN + hdr_len) > 80) &&
-                            (tp->tg3_flags2 & TG3_FLG2_HW_TSO_1_BUG))
+                            (tp->tg3_flags2 & TG3_FLG2_TSO_BUG))
                        return (tg3_tso_bug(tp, skb));
 
                base_flags |= (TXD_FLAG_CPU_PRE_DMA |
@@ -8137,7 +8140,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
            (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) ||
            (ering->tx_pending > TG3_TX_RING_SIZE - 1) ||
            (ering->tx_pending <= MAX_SKB_FRAGS) ||
-           ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_1_BUG) &&
+           ((tp->tg3_flags2 & TG3_FLG2_TSO_BUG) &&
             (ering->tx_pending <= (MAX_SKB_FRAGS * 3))))
                return -EINVAL;
 
@@ -9111,8 +9114,7 @@ static void tg3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
                tg3_netif_stop(tp);
 
        tg3_full_lock(tp, 0);
-       if (tp->vlgrp)
-               tp->vlgrp->vlan_devices[vid] = NULL;
+       vlan_group_set_device(tp->vlgrp, vid, NULL);
        tg3_full_unlock(tp);
 
        if (netif_running(dev))
@@ -10557,12 +10559,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                        tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2;
                        tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI;
                } else {
-                       tp->tg3_flags2 |= TG3_FLG2_HW_TSO_1 |
-                                         TG3_FLG2_HW_TSO_1_BUG;
+                       tp->tg3_flags2 |= TG3_FLG2_HW_TSO_1 | TG3_FLG2_TSO_BUG;
                        if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
                                ASIC_REV_5750 &&
                            tp->pci_chip_rev_id >= CHIPREV_ID_5750_C2)
-                               tp->tg3_flags2 &= ~TG3_FLG2_HW_TSO_1_BUG;
+                               tp->tg3_flags2 &= ~TG3_FLG2_TSO_BUG;
                }
        }
 
@@ -11867,7 +11868,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
            (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0) {
                tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE;
        } else {
-               tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE;
+               tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE | TG3_FLG2_TSO_BUG;
        }
 
        /* TSO is on by default on chips that support hardware TSO.
index 45d477e8f3744f4f10d3ab7ff952b5676804dd63..086892d8c1f17433afc44bf1b78f921b915dd6fc 100644 (file)
@@ -2227,7 +2227,7 @@ struct tg3 {
 #define TG3_FLAG_INIT_COMPLETE         0x80000000
        u32                             tg3_flags2;
 #define TG3_FLG2_RESTART_TIMER         0x00000001
-#define TG3_FLG2_HW_TSO_1_BUG          0x00000002
+#define TG3_FLG2_TSO_BUG               0x00000002
 #define TG3_FLG2_NO_ETH_WIRE_SPEED     0x00000004
 #define TG3_FLG2_IS_5788               0x00000008
 #define TG3_FLG2_MAX_RXPEND_64         0x00000010
index 0d97e10ccac580e16d3dffbe4a9a88144360e64a..36202e94ee916330bb8a8ee32e712f70e2f897cb 100644 (file)
@@ -186,7 +186,6 @@ static char __devinit *adapter_def(char type)
 #define TRC_INITV 0x02         /*  verbose init trace points     */
 static unsigned char ibmtr_debug_trace = 0;
 
-static int     ibmtr_probe(struct net_device *dev);
 static int     ibmtr_probe1(struct net_device *dev, int ioaddr);
 static unsigned char get_sram_size(struct tok_info *adapt_info);
 static int     trdev_init(struct net_device *dev);
@@ -335,17 +334,6 @@ static void ibmtr_cleanup_card(struct net_device *dev)
 #endif         
 }
 
-int ibmtr_probe_card(struct net_device *dev)
-{
-       int err = ibmtr_probe(dev);
-       if (!err) {
-               err = register_netdev(dev);
-               if (err)
-                       ibmtr_cleanup_card(dev);
-       }
-       return err;
-}
-
 /****************************************************************************
  *     ibmtr_probe():  Routine specified in the network device structure
  *     to probe for an IBM Token Ring Adapter.  Routine outline:
@@ -358,7 +346,7 @@ int ibmtr_probe_card(struct net_device *dev)
  *     which references it.
  ****************************************************************************/
 
-static int ibmtr_probe(struct net_device *dev)
+static int __init ibmtr_probe(struct net_device *dev)
 {
        int i;
        int base_addr = dev->base_addr;
@@ -378,6 +366,17 @@ static int ibmtr_probe(struct net_device *dev)
        return -ENODEV;
 }
 
+int __init ibmtr_probe_card(struct net_device *dev)
+{
+       int err = ibmtr_probe(dev);
+       if (!err) {
+               err = register_netdev(dev);
+               if (err)
+                       ibmtr_cleanup_card(dev);
+       }
+       return err;
+}
+
 /*****************************************************************************/
 
 static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr)
index 9d67f11422ec5ed8317eb477eb3d1f524b034528..c82befa209a220730a521e212240bc20537f1dc0 100644 (file)
@@ -63,7 +63,7 @@ MODULE_PARM_DESC (debug, "de2104x bitmapped message enable number");
 
 /* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */
 #if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \
-        || defined(__sparc_) || defined(__ia64__) \
+        || defined(__sparc__) || defined(__ia64__) \
         || defined(__sh__) || defined(__mips__)
 static int rx_copybreak = 1518;
 #else
@@ -1685,7 +1685,7 @@ static const struct ethtool_ops de_ethtool_ops = {
        .get_regs               = de_get_regs,
 };
 
-static void __init de21040_get_mac_address (struct de_private *de)
+static void __devinit de21040_get_mac_address (struct de_private *de)
 {
        unsigned i;
 
@@ -1703,7 +1703,7 @@ static void __init de21040_get_mac_address (struct de_private *de)
        }
 }
 
-static void __init de21040_get_media_info(struct de_private *de)
+static void __devinit de21040_get_media_info(struct de_private *de)
 {
        unsigned int i;
 
@@ -1765,7 +1765,7 @@ static unsigned __devinit tulip_read_eeprom(void __iomem *regs, int location, in
        return retval;
 }
 
-static void __init de21041_get_srom_info (struct de_private *de)
+static void __devinit de21041_get_srom_info (struct de_private *de)
 {
        unsigned i, sa_offset = 0, ofs;
        u8 ee_data[DE_EEPROM_SIZE + 6] = {};
index 7f59a3d4fda2c01fe5f903696e8501f683e7bd15..24a29c99ba94c1f8b86ce39c4f2fb1cbd0b3576e 100644 (file)
 #define DMFE_TX_TIMEOUT ((3*HZ)/2)     /* tx packet time-out time 1.5 s" */
 #define DMFE_TX_KICK   (HZ/2)  /* tx packet Kick-out time 0.5 s" */
 
-#define DMFE_DBUG(dbug_now, msg, value) if (dmfe_debug || (dbug_now)) printk(KERN_ERR DRV_NAME ": %s %lx\n", (msg), (long) (value))
+#define DMFE_DBUG(dbug_now, msg, value) \
+       do { \
+               if (dmfe_debug || (dbug_now)) \
+                       printk(KERN_ERR DRV_NAME ": %s %lx\n",\
+                               (msg), (long) (value)); \
+       } while (0)
 
-#define SHOW_MEDIA_TYPE(mode) printk(KERN_ERR DRV_NAME ": Change Speed to %sMhz %s duplex\n",mode & 1 ?"100":"10", mode & 4 ? "full":"half");
+#define SHOW_MEDIA_TYPE(mode) \
+       printk (KERN_INFO DRV_NAME ": Change Speed to %sMhz %s duplex\n" , \
+               (mode & 1) ? "100":"10", (mode & 4) ? "full":"half");
 
 
 /* CR9 definition: SROM/MII */
 
 #define SROM_V41_CODE   0x14
 
-#define SROM_CLK_WRITE(data, ioaddr) outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr);udelay(5);outl(data|CR9_SROM_READ|CR9_SRCS|CR9_SRCLK,ioaddr);udelay(5);outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr);udelay(5);
+#define SROM_CLK_WRITE(data, ioaddr) \
+       outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr); \
+       udelay(5); \
+       outl(data|CR9_SROM_READ|CR9_SRCS|CR9_SRCLK,ioaddr); \
+       udelay(5); \
+       outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr); \
+       udelay(5);
+
+#define __CHK_IO_SIZE(pci_id, dev_rev) \
+ (( ((pci_id)==PCI_DM9132_ID) || ((dev_rev) >= 0x02000030) ) ? \
+       DM9102A_IO_SIZE: DM9102_IO_SIZE)
 
-#define __CHK_IO_SIZE(pci_id, dev_rev) ( ((pci_id)==PCI_DM9132_ID) || ((dev_rev) >= 0x02000030) ) ? DM9102A_IO_SIZE: DM9102_IO_SIZE
-#define CHK_IO_SIZE(pci_dev, dev_rev) __CHK_IO_SIZE(((pci_dev)->device << 16) | (pci_dev)->vendor, dev_rev)
+#define CHK_IO_SIZE(pci_dev, dev_rev) \
+       (__CHK_IO_SIZE(((pci_dev)->device << 16) | (pci_dev)->vendor, dev_rev))
 
 /* Sten Check */
 #define DEVICE net_device
@@ -187,7 +204,7 @@ struct rx_desc {
 struct dmfe_board_info {
        u32 chip_id;                    /* Chip vendor/Device ID */
        u32 chip_revision;              /* Chip revision */
-       struct DEVICE *dev;             /* net device */
+       struct DEVICE *next_dev;        /* next device */
        struct pci_dev *pdev;           /* PCI device */
        spinlock_t lock;
 
@@ -231,7 +248,6 @@ struct dmfe_board_info {
        u8 media_mode;                  /* user specify media mode */
        u8 op_mode;                     /* real work media mode */
        u8 phy_addr;
-       u8 link_failed;                 /* Ever link failed */
        u8 wait_reset;                  /* Hardware failed, need to reset */
        u8 dm910x_chk_mode;             /* Operating mode check */
        u8 first_in_callback;           /* Flag to record state */
@@ -329,7 +345,7 @@ static void dmfe_program_DM9802(struct dmfe_board_info *);
 static void dmfe_HPNA_remote_cmd_chk(struct dmfe_board_info * );
 static void dmfe_set_phyxcer(struct dmfe_board_info *);
 
-/* DM910X network baord routine ---------------------------- */
+/* DM910X network board routine ---------------------------- */
 
 /*
  *     Search DM910X board ,allocate space and register it
@@ -356,7 +372,8 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
        SET_NETDEV_DEV(dev, &pdev->dev);
 
        if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
-               printk(KERN_WARNING DRV_NAME ": 32-bit PCI DMA not available.\n");
+               printk(KERN_WARNING DRV_NAME
+                       ": 32-bit PCI DMA not available.\n");
                err = -ENODEV;
                goto err_out_free;
        }
@@ -399,11 +416,12 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
        /* Init system & device */
        db = netdev_priv(dev);
 
-       db->dev = dev;
-
        /* Allocate Tx/Rx descriptor memory */
-       db->desc_pool_ptr = pci_alloc_consistent(pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20, &db->desc_pool_dma_ptr);
-       db->buf_pool_ptr = pci_alloc_consistent(pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4, &db->buf_pool_dma_ptr);
+       db->desc_pool_ptr = pci_alloc_consistent(pdev, sizeof(struct tx_desc) *
+                       DESC_ALL_CNT + 0x20, &db->desc_pool_dma_ptr);
+
+       db->buf_pool_ptr = pci_alloc_consistent(pdev, TX_BUF_ALLOC *
+                       TX_DESC_CNT + 4, &db->buf_pool_dma_ptr);
 
        db->first_tx_desc = (struct tx_desc *) db->desc_pool_ptr;
        db->first_tx_desc_dma = db->desc_pool_dma_ptr;
@@ -428,7 +446,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
        dev->poll_controller = &poll_dmfe;
 #endif
        dev->ethtool_ops = &netdev_ethtool_ops;
-       netif_carrier_off(db->dev);
+       netif_carrier_off(dev);
        spin_lock_init(&db->lock);
 
        pci_read_config_dword(pdev, 0x50, &pci_pmr);
@@ -440,7 +458,8 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
 
        /* read 64 word srom data */
        for (i = 0; i < 64; i++)
-               ((u16 *) db->srom)[i] = cpu_to_le16(read_srom_word(db->ioaddr, i));
+               ((u16 *) db->srom)[i] =
+                       cpu_to_le16(read_srom_word(db->ioaddr, i));
 
        /* Set Node address */
        for (i = 0; i < 6; i++)
@@ -482,14 +501,17 @@ static void __devexit dmfe_remove_one (struct pci_dev *pdev)
        DMFE_DBUG(0, "dmfe_remove_one()", 0);
 
        if (dev) {
+
+               unregister_netdev(dev);
+
                pci_free_consistent(db->pdev, sizeof(struct tx_desc) *
                                        DESC_ALL_CNT + 0x20, db->desc_pool_ptr,
                                        db->desc_pool_dma_ptr);
                pci_free_consistent(db->pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4,
                                        db->buf_pool_ptr, db->buf_pool_dma_ptr);
-               unregister_netdev(dev);
                pci_release_regions(pdev);
                free_netdev(dev);       /* free board information */
+
                pci_set_drvdata(pdev, NULL);
        }
 
@@ -509,7 +531,8 @@ static int dmfe_open(struct DEVICE *dev)
 
        DMFE_DBUG(0, "dmfe_open", 0);
 
-       ret = request_irq(dev->irq, &dmfe_interrupt, IRQF_SHARED, dev->name, dev);
+       ret = request_irq(dev->irq, &dmfe_interrupt,
+                         IRQF_SHARED, dev->name, dev);
        if (ret)
                return ret;
 
@@ -518,7 +541,6 @@ static int dmfe_open(struct DEVICE *dev)
        db->tx_packet_cnt = 0;
        db->tx_queue_cnt = 0;
        db->rx_avail_cnt = 0;
-       db->link_failed = 1;
        db->wait_reset = 0;
 
        db->first_in_callback = 0;
@@ -650,7 +672,8 @@ static int dmfe_start_xmit(struct sk_buff *skb, struct DEVICE *dev)
        /* No Tx resource check, it never happen nromally */
        if (db->tx_queue_cnt >= TX_FREE_DESC_CNT) {
                spin_unlock_irqrestore(&db->lock, flags);
-               printk(KERN_ERR DRV_NAME ": No Tx resource %ld\n", db->tx_queue_cnt);
+               printk(KERN_ERR DRV_NAME ": No Tx resource %ld\n",
+                      db->tx_queue_cnt);
                return 1;
        }
 
@@ -722,7 +745,8 @@ static int dmfe_stop(struct DEVICE *dev)
 
 #if 0
        /* show statistic counter */
-       printk(DRV_NAME ": FU:%lx EC:%lx LC:%lx NC:%lx LOC:%lx TXJT:%lx RESET:%lx RCR8:%lx FAL:%lx TT:%lx\n",
+       printk(DRV_NAME ": FU:%lx EC:%lx LC:%lx NC:%lx"
+               " LOC:%lx TXJT:%lx RESET:%lx RCR8:%lx FAL:%lx TT:%lx\n",
                db->tx_fifo_underrun, db->tx_excessive_collision,
                db->tx_late_collision, db->tx_no_carrier, db->tx_loss_carrier,
                db->tx_jabber_timeout, db->reset_count, db->reset_cr8,
@@ -905,7 +929,7 @@ static inline u32 cal_CRC(unsigned char * Data, unsigned int Len, u8 flag)
 static void dmfe_rx_packet(struct DEVICE *dev, struct dmfe_board_info * db)
 {
        struct rx_desc *rxptr;
-       struct sk_buff *skb;
+       struct sk_buff *skb, *newskb;
        int rxlen;
        u32 rdes0;
 
@@ -919,7 +943,9 @@ static void dmfe_rx_packet(struct DEVICE *dev, struct dmfe_board_info * db)
                db->rx_avail_cnt--;
                db->interval_rx_cnt++;
 
-               pci_unmap_single(db->pdev, le32_to_cpu(rxptr->rdes2), RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE);
+               pci_unmap_single(db->pdev, le32_to_cpu(rxptr->rdes2),
+                                RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE);
+
                if ( (rdes0 & 0x300) != 0x300) {
                        /* A packet without First/Last flag */
                        /* reuse this SKB */
@@ -956,9 +982,11 @@ static void dmfe_rx_packet(struct DEVICE *dev, struct dmfe_board_info * db)
                                } else {
                                        /* Good packet, send to upper layer */
                                        /* Shorst packet used new SKB */
-                                       if ( (rxlen < RX_COPY_SIZE) &&
-                                               ( (skb = dev_alloc_skb(rxlen + 2) )
-                                               != NULL) ) {
+                                       if ((rxlen < RX_COPY_SIZE) &&
+                                               ((newskb = dev_alloc_skb(rxlen + 2))
+                                               != NULL)) {
+
+                                               skb = newskb;
                                                /* size less than COPY_SIZE, allocate a rxlen SKB */
                                                skb->dev = dev;
                                                skb_reserve(skb, 2); /* 16byte align */
@@ -1069,6 +1097,8 @@ static void dmfe_timer(unsigned long data)
        struct dmfe_board_info *db = netdev_priv(dev);
        unsigned long flags;
 
+       int link_ok, link_ok_phy;
+
        DMFE_DBUG(0, "dmfe_timer()", 0);
        spin_lock_irqsave(&db->lock, flags);
 
@@ -1078,7 +1108,8 @@ static void dmfe_timer(unsigned long data)
                if (db->chip_type && (db->chip_id==PCI_DM9102_ID)) {
                        db->cr6_data &= ~0x40000;
                        update_cr6(db->cr6_data, db->ioaddr);
-                       phy_write(db->ioaddr, db->phy_addr, 0, 0x1000, db->chip_id);
+                       phy_write(db->ioaddr,
+                                 db->phy_addr, 0, 0x1000, db->chip_id);
                        db->cr6_data |= 0x40000;
                        update_cr6(db->cr6_data, db->ioaddr);
                        db->timer.expires = DMFE_TIMER_WUT + HZ * 2;
@@ -1139,21 +1170,41 @@ static void dmfe_timer(unsigned long data)
                (db->chip_revision == 0x02000010)) ) {
                /* DM9102A Chip */
                if (tmp_cr12 & 2)
-                       tmp_cr12 = 0x0;         /* Link failed */
+                       link_ok = 0;
                else
-                       tmp_cr12 = 0x3; /* Link OK */
+                       link_ok = 1;
        }
+       else
+               /*0x43 is used instead of 0x3 because bit 6 should represent
+                       link status of external PHY */
+               link_ok = (tmp_cr12 & 0x43) ? 1 : 0;
+
+
+       /* If chip reports that link is failed it could be because external
+               PHY link status pin is not conected correctly to chip
+               To be sure ask PHY too.
+       */
+
+       /* need a dummy read because of PHY's register latch*/
+       phy_read (db->ioaddr, db->phy_addr, 1, db->chip_id);
+       link_ok_phy = (phy_read (db->ioaddr,
+                      db->phy_addr, 1, db->chip_id) & 0x4) ? 1 : 0;
 
-       if ( !(tmp_cr12 & 0x3) && !db->link_failed ) {
+       if (link_ok_phy != link_ok) {
+               DMFE_DBUG (0, "PHY and chip report different link status", 0);
+               link_ok = link_ok | link_ok_phy;
+       }
+
+       if ( !link_ok && netif_carrier_ok(dev)) {
                /* Link Failed */
                DMFE_DBUG(0, "Link Failed", tmp_cr12);
-               db->link_failed = 1;
-               netif_carrier_off(db->dev);
+               netif_carrier_off(dev);
 
                /* For Force 10/100M Half/Full mode: Enable Auto-Nego mode */
                /* AUTO or force 1M Homerun/Longrun don't need */
                if ( !(db->media_mode & 0x38) )
-                       phy_write(db->ioaddr, db->phy_addr, 0, 0x1000, db->chip_id);
+                       phy_write(db->ioaddr, db->phy_addr,
+                                 0, 0x1000, db->chip_id);
 
                /* AUTO mode, if INT phyxcer link failed, select EXT device */
                if (db->media_mode & DMFE_AUTO) {
@@ -1162,21 +1213,19 @@ static void dmfe_timer(unsigned long data)
                        db->cr6_data&=~0x00000200;      /* bit9=0, HD mode */
                        update_cr6(db->cr6_data, db->ioaddr);
                }
-       } else
-               if ((tmp_cr12 & 0x3) && db->link_failed) {
-                       DMFE_DBUG(0, "Link link OK", tmp_cr12);
-                       db->link_failed = 0;
-
-                       /* Auto Sense Speed */
-                       if ( (db->media_mode & DMFE_AUTO) &&
-                               dmfe_sense_speed(db) )
-                               db->link_failed = 1;
-                       else
-                               netif_carrier_on(db->dev);
-                       dmfe_process_mode(db);
-                       /* SHOW_MEDIA_TYPE(db->op_mode); */
+       } else if (!netif_carrier_ok(dev)) {
+
+               DMFE_DBUG(0, "Link link OK", tmp_cr12);
+
+               /* Auto Sense Speed */
+               if ( !(db->media_mode & DMFE_AUTO) || !dmfe_sense_speed(db)) {
+                       netif_carrier_on(dev);
+                       SHOW_MEDIA_TYPE(db->op_mode);
                }
 
+               dmfe_process_mode(db);
+       }
+
        /* HPNA remote command check */
        if (db->HPNA_command & 0xf00) {
                db->HPNA_timer--;
@@ -1221,7 +1270,7 @@ static void dmfe_dynamic_reset(struct DEVICE *dev)
        db->tx_packet_cnt = 0;
        db->tx_queue_cnt = 0;
        db->rx_avail_cnt = 0;
-       db->link_failed = 1;
+       netif_carrier_off(dev);
        db->wait_reset = 0;
 
        /* Re-initilize DM910X board */
@@ -1259,7 +1308,8 @@ static void dmfe_reuse_skb(struct dmfe_board_info *db, struct sk_buff * skb)
 
        if (!(rxptr->rdes0 & cpu_to_le32(0x80000000))) {
                rxptr->rx_skb_ptr = skb;
-               rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->data, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) );
+               rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev,
+                           skb->data, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) );
                wmb();
                rxptr->rdes0 = cpu_to_le32(0x80000000);
                db->rx_avail_cnt++;
@@ -1291,8 +1341,11 @@ static void dmfe_descriptor_init(struct dmfe_board_info *db, unsigned long ioadd
        outl(db->first_tx_desc_dma, ioaddr + DCR4);     /* TX DESC address */
 
        /* rx descriptor start pointer */
-       db->first_rx_desc = (void *)db->first_tx_desc + sizeof(struct tx_desc) * TX_DESC_CNT;
-       db->first_rx_desc_dma =  db->first_tx_desc_dma + sizeof(struct tx_desc) * TX_DESC_CNT;
+       db->first_rx_desc = (void *)db->first_tx_desc +
+                       sizeof(struct tx_desc) * TX_DESC_CNT;
+
+       db->first_rx_desc_dma =  db->first_tx_desc_dma +
+                       sizeof(struct tx_desc) * TX_DESC_CNT;
        db->rx_insert_ptr = db->first_rx_desc;
        db->rx_ready_ptr = db->first_rx_desc;
        outl(db->first_rx_desc_dma, ioaddr + DCR3);     /* RX DESC address */
@@ -1470,7 +1523,8 @@ static void allocate_rx_buffer(struct dmfe_board_info *db)
                if ( ( skb = dev_alloc_skb(RX_ALLOC_SIZE) ) == NULL )
                        break;
                rxptr->rx_skb_ptr = skb; /* FIXME (?) */
-               rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->data, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) );
+               rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->data,
+                                   RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) );
                wmb();
                rxptr->rdes0 = cpu_to_le32(0x80000000);
                rxptr = rxptr->next_rx_desc;
@@ -1510,7 +1564,8 @@ static u16 read_srom_word(long ioaddr, int offset)
        for (i = 16; i > 0; i--) {
                outl(CR9_SROM_READ | CR9_SRCS | CR9_SRCLK, cr9_ioaddr);
                udelay(5);
-               srom_data = (srom_data << 1) | ((inl(cr9_ioaddr) & CR9_CRDOUT) ? 1 : 0);
+               srom_data = (srom_data << 1) |
+                               ((inl(cr9_ioaddr) & CR9_CRDOUT) ? 1 : 0);
                outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
                udelay(5);
        }
@@ -1537,9 +1592,11 @@ static u8 dmfe_sense_speed(struct dmfe_board_info * db)
 
        if ( (phy_mode & 0x24) == 0x24 ) {
                if (db->chip_id == PCI_DM9132_ID)       /* DM9132 */
-                       phy_mode = phy_read(db->ioaddr, db->phy_addr, 7, db->chip_id) & 0xf000;
+                       phy_mode = phy_read(db->ioaddr,
+                                   db->phy_addr, 7, db->chip_id) & 0xf000;
                else                            /* DM9102/DM9102A */
-                       phy_mode = phy_read(db->ioaddr, db->phy_addr, 17, db->chip_id) & 0xf000;
+                       phy_mode = phy_read(db->ioaddr,
+                                   db->phy_addr, 17, db->chip_id) & 0xf000;
                /* printk(DRV_NAME ": Phy_mode %x ",phy_mode); */
                switch (phy_mode) {
                case 0x1000: db->op_mode = DMFE_10MHF; break;
@@ -1576,8 +1633,11 @@ static void dmfe_set_phyxcer(struct dmfe_board_info *db)
 
        /* DM9009 Chip: Phyxcer reg18 bit12=0 */
        if (db->chip_id == PCI_DM9009_ID) {
-               phy_reg = phy_read(db->ioaddr, db->phy_addr, 18, db->chip_id) & ~0x1000;
-               phy_write(db->ioaddr, db->phy_addr, 18, phy_reg, db->chip_id);
+               phy_reg = phy_read(db->ioaddr,
+                                  db->phy_addr, 18, db->chip_id) & ~0x1000;
+
+               phy_write(db->ioaddr,
+                         db->phy_addr, 18, phy_reg, db->chip_id);
        }
 
        /* Phyxcer capability setting */
@@ -1650,10 +1710,12 @@ static void dmfe_process_mode(struct dmfe_board_info *db)
                        case DMFE_100MHF: phy_reg = 0x2000; break;
                        case DMFE_100MFD: phy_reg = 0x2100; break;
                        }
-                       phy_write(db->ioaddr, db->phy_addr, 0, phy_reg, db->chip_id);
+                       phy_write(db->ioaddr,
+                                 db->phy_addr, 0, phy_reg, db->chip_id);
                                if ( db->chip_type && (db->chip_id == PCI_DM9102_ID) )
                                mdelay(20);
-                       phy_write(db->ioaddr, db->phy_addr, 0, phy_reg, db->chip_id);
+                       phy_write(db->ioaddr,
+                                 db->phy_addr, 0, phy_reg, db->chip_id);
                }
        }
 }
@@ -1663,7 +1725,8 @@ static void dmfe_process_mode(struct dmfe_board_info *db)
  *     Write a word to Phy register
  */
 
-static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset, u16 phy_data, u32 chip_id)
+static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset,
+                     u16 phy_data, u32 chip_id)
 {
        u16 i;
        unsigned long ioaddr;
@@ -1689,11 +1752,13 @@ static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset, u16 phy_data
 
                /* Send Phy address */
                for (i = 0x10; i > 0; i = i >> 1)
-                       phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0);
+                       phy_write_1bit(ioaddr,
+                                      phy_addr & i ? PHY_DATA_1 : PHY_DATA_0);
 
                /* Send register address */
                for (i = 0x10; i > 0; i = i >> 1)
-                       phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : PHY_DATA_0);
+                       phy_write_1bit(ioaddr,
+                                      offset & i ? PHY_DATA_1 : PHY_DATA_0);
 
                /* written trasnition */
                phy_write_1bit(ioaddr, PHY_DATA_1);
@@ -1701,7 +1766,8 @@ static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset, u16 phy_data
 
                /* Write a word data to PHY controller */
                for ( i = 0x8000; i > 0; i >>= 1)
-                       phy_write_1bit(ioaddr, phy_data & i ? PHY_DATA_1 : PHY_DATA_0);
+                       phy_write_1bit(ioaddr,
+                                      phy_data & i ? PHY_DATA_1 : PHY_DATA_0);
        }
 }
 
@@ -1738,11 +1804,13 @@ static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset, u32 chip_id)
 
                /* Send Phy address */
                for (i = 0x10; i > 0; i = i >> 1)
-                       phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0);
+                       phy_write_1bit(ioaddr,
+                                      phy_addr & i ? PHY_DATA_1 : PHY_DATA_0);
 
                /* Send register address */
                for (i = 0x10; i > 0; i = i >> 1)
-                       phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : PHY_DATA_0);
+                       phy_write_1bit(ioaddr,
+                                      offset & i ? PHY_DATA_1 : PHY_DATA_0);
 
                /* Skip transition state */
                phy_read_1bit(ioaddr);
@@ -1963,7 +2031,8 @@ static void dmfe_HPNA_remote_cmd_chk(struct dmfe_board_info * db)
 
        /* Check remote device status match our setting ot not */
        if ( phy_reg != (db->HPNA_command & 0x0f00) ) {
-               phy_write(db->ioaddr, db->phy_addr, 16, db->HPNA_command, db->chip_id);
+               phy_write(db->ioaddr, db->phy_addr, 16, db->HPNA_command,
+                         db->chip_id);
                db->HPNA_timer=8;
        } else
                db->HPNA_timer=600;     /* Match, every 10 minutes, check */
@@ -2003,8 +2072,11 @@ module_param(HPNA_tx_cmd, byte, 0);
 module_param(HPNA_NoiseFloor, byte, 0);
 module_param(SF_mode, byte, 0);
 MODULE_PARM_DESC(debug, "Davicom DM9xxx enable debugging (0-1)");
-MODULE_PARM_DESC(mode, "Davicom DM9xxx: Bit 0: 10/100Mbps, bit 2: duplex, bit 8: HomePNA");
-MODULE_PARM_DESC(SF_mode, "Davicom DM9xxx special function (bit 0: VLAN, bit 1 Flow Control, bit 2: TX pause packet)");
+MODULE_PARM_DESC(mode, "Davicom DM9xxx: "
+               "Bit 0: 10/100Mbps, bit 2: duplex, bit 8: HomePNA");
+
+MODULE_PARM_DESC(SF_mode, "Davicom DM9xxx special function "
+               "(bit 0: VLAN, bit 1 Flow Control, bit 2: TX pause packet)");
 
 /*     Description:
  *     when user used insmod to add module, system invoked init_module()
index 5a35354aa523fb6dee18a02ea80b0ef558334f9b..e3774a5223723f8835d40d79146bd78be3a1972e 100644 (file)
@@ -67,7 +67,7 @@ const char * const medianame[32] = {
 
 /* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */
 #if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \
-       || defined(__sparc_) || defined(__ia64__) \
+       || defined(__sparc__) || defined(__ia64__) \
        || defined(__sh__) || defined(__mips__)
 static int rx_copybreak = 1518;
 #else
index 9781b16bb8b66ffe727dee15537f7a855bb16d42..0d91d094edd97bd63407e929682a58d2a2143b40 100644 (file)
@@ -746,8 +746,7 @@ typhoon_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 {
        struct typhoon *tp = netdev_priv(dev);
        spin_lock_bh(&tp->state_lock);
-       if(tp->vlgrp)
-               tp->vlgrp->vlan_devices[vid] = NULL;
+       vlan_group_set_device(tp->vlgrp, vid, NULL);
        spin_unlock_bh(&tp->state_lock);
 }
 
index a2fc2bbcf97f71c623baab814250d61463d7a95a..dab88b958d6ea9c33c051649077a14e93b8434a9 100644 (file)
@@ -3598,17 +3598,20 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        /* Move to next BD in the ring */
        if (!(bd_status & T_W))
-               ugeth->txBd[txQ] = bd + sizeof(struct qe_bd);
+               bd += sizeof(struct qe_bd);
        else
-               ugeth->txBd[txQ] = ugeth->p_tx_bd_ring[txQ];
+               bd = ugeth->p_tx_bd_ring[txQ];
 
        /* If the next BD still needs to be cleaned up, then the bds
           are full.  We need to tell the kernel to stop sending us stuff. */
        if (bd == ugeth->confBd[txQ]) {
                if (!netif_queue_stopped(dev))
                        netif_stop_queue(dev);
+               return NETDEV_TX_BUSY;
        }
 
+       ugeth->txBd[txQ] = bd;
+
        if (ugeth->p_scheduler) {
                ugeth->cpucount[txQ]++;
                /* Indicate to QE that there are more Tx bds ready for
@@ -3620,7 +3623,7 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        spin_unlock_irq(&ugeth->lock);
 
-       return 0;
+       return NETDEV_TX_OK;
 }
 
 static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit)
@@ -3722,7 +3725,7 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ)
                /* Handle the transmitted buffer and release */
                /* the BD to be used with the current frame  */
 
-               if ((bd = ugeth->txBd[txQ]) && (netif_queue_stopped(dev) == 0))
+               if ((bd == ugeth->txBd[txQ]) && (netif_queue_stopped(dev) == 0))
                        break;
 
                ugeth->stats.tx_packets++;
@@ -3741,10 +3744,12 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ)
 
                /* Advance the confirmation BD pointer */
                if (!(bd_status & T_W))
-                       ugeth->confBd[txQ] += sizeof(struct qe_bd);
+                       bd += sizeof(struct qe_bd);
                else
-                       ugeth->confBd[txQ] = ugeth->p_tx_bd_ring[txQ];
+                       bd = ugeth->p_tx_bd_ring[txQ];
+               bd_status = in_be32((u32 *)bd);
        }
+       ugeth->confBd[txQ] = bd;
        return 0;
 }
 
@@ -4199,9 +4204,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
        ugeth->ug_info = ug_info;
        ugeth->dev = dev;
 
-       mac_addr = get_property(np, "mac-address", NULL);
-       if (mac_addr == NULL)
-               mac_addr = get_property(np, "local-mac-address", NULL);
+       mac_addr = of_get_mac_address(np);
        if (mac_addr)
                memcpy(dev->dev_addr, mac_addr, 6);
 
index ebbda1d8f542539891087086855107a829e6e759..f3a972e74e9ada2983afd620b13fe29ccec6b880 100644 (file)
@@ -30,8 +30,8 @@
 */
 
 #define DRV_NAME       "via-rhine"
-#define DRV_VERSION    "1.4.2"
-#define DRV_RELDATE    "Sept-11-2006"
+#define DRV_VERSION    "1.4.3"
+#define DRV_RELDATE    "2007-03-06"
 
 
 /* A few user-configurable values.
@@ -105,6 +105,7 @@ static const int multicast_filter_limit = 32;
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
+#include <linux/dmi.h>
 
 /* These identify the driver base version and may not be removed. */
 static char version[] __devinitdata =
@@ -1995,6 +1996,23 @@ static struct pci_driver rhine_driver = {
        .shutdown =     rhine_shutdown,
 };
 
+static struct dmi_system_id __initdata rhine_dmi_table[] = {
+       {
+               .ident = "EPIA-M",
+               .matches = {
+                       DMI_MATCH(DMI_BIOS_VENDOR, "Award Software International, Inc."),
+                       DMI_MATCH(DMI_BIOS_VERSION, "6.00 PG"),
+               },
+       },
+       {
+               .ident = "KV7",
+               .matches = {
+                       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "6.00 PG"),
+               },
+       },
+       { NULL }
+};
 
 static int __init rhine_init(void)
 {
@@ -2002,6 +2020,16 @@ static int __init rhine_init(void)
 #ifdef MODULE
        printk(version);
 #endif
+       if (dmi_check_system(rhine_dmi_table)) {
+               /* these BIOSes fail at PXE boot if chip is in D3 */
+               avoid_D3 = 1;
+               printk(KERN_WARNING "%s: Broken BIOS detected, avoid_D3 "
+                                   "enabled.\n",
+                      DRV_NAME);
+       }
+       else if (avoid_D3)
+               printk(KERN_INFO "%s: avoid_D3 set.\n", DRV_NAME);
+
        return pci_register_driver(&rhine_driver);
 }
 
index e91b5a84a20a5ce2adb3e03f3a4fccc8b6c92589..5b82e4fd0d735a206d7a75bace529bd513ae4039 100644 (file)
@@ -94,7 +94,6 @@
 #include <linux/device.h>
 
 #undef COSA_SLOW_IO    /* for testing purposes only */
-#undef REALLY_SLOW_IO
 
 #include <asm/io.h>
 #include <asm/dma.h>
index 9040d7cf651e585d6b3976b76159ddef7125c7ee..65ad2e24caf071a5aa16a0a710a7b07c05c75aa3 100644 (file)
@@ -38,7 +38,7 @@
 #include <linux/hdlc.h>
 
 
-static const char* version = "HDLC support module revision 1.20";
+static const char* version = "HDLC support module revision 1.21";
 
 #undef DEBUG_LINK
 
@@ -222,19 +222,31 @@ int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        return -EINVAL;
 }
 
+static void hdlc_setup_dev(struct net_device *dev)
+{
+       /* Re-init all variables changed by HDLC protocol drivers,
+        * including ether_setup() called from hdlc_raw_eth.c.
+        */
+       dev->get_stats           = hdlc_get_stats;
+       dev->flags               = IFF_POINTOPOINT | IFF_NOARP;
+       dev->mtu                 = HDLC_MAX_MTU;
+       dev->type                = ARPHRD_RAWHDLC;
+       dev->hard_header_len     = 16;
+       dev->addr_len            = 0;
+       dev->hard_header         = NULL;
+       dev->rebuild_header      = NULL;
+       dev->set_mac_address     = NULL;
+       dev->hard_header_cache   = NULL;
+       dev->header_cache_update = NULL;
+       dev->change_mtu          = hdlc_change_mtu;
+       dev->hard_header_parse   = NULL;
+}
+
 static void hdlc_setup(struct net_device *dev)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
 
-       dev->get_stats = hdlc_get_stats;
-       dev->change_mtu = hdlc_change_mtu;
-       dev->mtu = HDLC_MAX_MTU;
-
-       dev->type = ARPHRD_RAWHDLC;
-       dev->hard_header_len = 16;
-
-       dev->flags = IFF_POINTOPOINT | IFF_NOARP;
-
+       hdlc_setup_dev(dev);
        hdlc->carrier = 1;
        hdlc->open = 0;
        spin_lock_init(&hdlc->state_lock);
@@ -294,6 +306,7 @@ void detach_hdlc_protocol(struct net_device *dev)
        }
        kfree(hdlc->state);
        hdlc->state = NULL;
+       hdlc_setup_dev(dev);
 }
 
 
index b0bc5ddcf1b11df483912a33160ce074c75ffa5c..c9664fd8a917eaf0889dedcd0b931db3e544a390 100644 (file)
@@ -365,10 +365,7 @@ static int cisco_ioctl(struct net_device *dev, struct ifreq *ifr)
                memcpy(&state(hdlc)->settings, &new_settings, size);
                dev->hard_start_xmit = hdlc->xmit;
                dev->hard_header = cisco_hard_header;
-               dev->hard_header_cache = NULL;
                dev->type = ARPHRD_CISCO;
-               dev->flags = IFF_POINTOPOINT | IFF_NOARP;
-               dev->addr_len = 0;
                netif_dormant_on(dev);
                return 0;
        }
index b45ab680d2d624b52c4b44f4d1d51cb4c268de5d..c6c3c757d6f13c850307a9e8d71316ce898631a5 100644 (file)
@@ -1289,10 +1289,7 @@ static int fr_ioctl(struct net_device *dev, struct ifreq *ifr)
                memcpy(&state(hdlc)->settings, &new_settings, size);
 
                dev->hard_start_xmit = hdlc->xmit;
-               dev->hard_header = NULL;
                dev->type = ARPHRD_FRAD;
-               dev->flags = IFF_POINTOPOINT | IFF_NOARP;
-               dev->addr_len = 0;
                return 0;
 
        case IF_PROTO_FR_ADD_PVC:
index e9f717070fde0d58bc4f1c103472510c7f9b9fff..4591437dd2f3dca75470b5d259bdaed8f1d65c5e 100644 (file)
@@ -127,9 +127,7 @@ static int ppp_ioctl(struct net_device *dev, struct ifreq *ifr)
                if (result)
                        return result;
                dev->hard_start_xmit = hdlc->xmit;
-               dev->hard_header = NULL;
                dev->type = ARPHRD_PPP;
-               dev->addr_len = 0;
                netif_dormant_off(dev);
                return 0;
        }
index fe3cae5c6b9d07a267fde91d3051c950ea11e906..e23bc6656267401270488809d0a73d886203adb8 100644 (file)
@@ -88,10 +88,7 @@ static int raw_ioctl(struct net_device *dev, struct ifreq *ifr)
                        return result;
                memcpy(hdlc->state, &new_settings, size);
                dev->hard_start_xmit = hdlc->xmit;
-               dev->hard_header = NULL;
                dev->type = ARPHRD_RAWHDLC;
-               dev->flags = IFF_POINTOPOINT | IFF_NOARP;
-               dev->addr_len = 0;
                netif_dormant_off(dev);
                return 0;
        }
index e4bb9f8ad4337e1cb34bb7b9835732119877c3b3..cd7b22f50edc562d9fa9f35bf809656fc834227b 100644 (file)
@@ -215,9 +215,7 @@ static int x25_ioctl(struct net_device *dev, struct ifreq *ifr)
                                                   x25_rx, 0)) != 0)
                        return result;
                dev->hard_start_xmit = x25_xmit;
-               dev->hard_header = NULL;
                dev->type = ARPHRD_X25;
-               dev->addr_len = 0;
                netif_dormant_off(dev);
                return 0;
        }
index 8dbcf83bb5f360a96d4b2b1320489e7af78eb5e7..8b4540bfc1b0b3b7949b86ae5cd6de58ab043b2f 100644 (file)
@@ -407,7 +407,7 @@ static void z8530_tx(struct z8530_channel *c)
        while(c->txcount) {
                /* FIFO full ? */
                if(!(read_zsreg(c, R0)&4))
-                       break;
+                       return;
                c->txcount--;
                /*
                 *      Shovel out the byte
index b08055abe83a3982345bde47937567af90b2e121..a8c2bfe26c2715291253628782cde302f3d63b39 100644 (file)
@@ -1623,7 +1623,7 @@ static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen,
 
        crypto_cipher_setkey(tfm, pkey, 16);
        counter = 0;
-       for (i = 0; i < (sizeof(context->coeff)/sizeof(context->coeff[0])); ) {
+       for (i = 0; i < ARRAY_SIZE(context->coeff); ) {
                aes_counter[15] = (u8)(counter >> 0);
                aes_counter[14] = (u8)(counter >> 8);
                aes_counter[13] = (u8)(counter >> 16);
@@ -1632,7 +1632,7 @@ static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen,
                memcpy (plain, aes_counter, 16);
                crypto_cipher_encrypt_one(tfm, plain, plain);
                cipher = plain;
-               for (j=0; (j<16) && (i< (sizeof(context->coeff)/sizeof(context->coeff[0]))); ) {
+               for (j = 0; (j < 16) && (i < ARRAY_SIZE(context->coeff)); ) {
                        context->coeff[i++] = ntohl(*(u32 *)&cipher[j]);
                        j += 4;
                }
index 0e790efae683cfdbe2e17e204ad7667af56871ed..95ff175d8f334227485ee75e995c8993f290f9eb 100644 (file)
@@ -21,7 +21,7 @@
 #define PFX                            KBUILD_MODNAME ": "
 
 #define BCM43xx_SWITCH_CORE_MAX_RETRIES        50
-#define BCM43xx_IRQWAIT_MAX_RETRIES    50
+#define BCM43xx_IRQWAIT_MAX_RETRIES    100
 
 #define BCM43xx_IO_SIZE                        8192
 
 #define BCM43xx_SBF_PS2                        0x04000000
 #define BCM43xx_SBF_NO_SSID_BCAST      0x08000000
 #define BCM43xx_SBF_TIME_UPDATE                0x10000000
-#define BCM43xx_SBF_80000000           0x80000000 /*FIXME: fix name*/
+#define BCM43xx_SBF_MODE_G             0x80000000
 
 /* Microcode */
 #define BCM43xx_UCODE_REVISION         0x0000
@@ -507,8 +507,6 @@ struct bcm43xx_sprominfo {
        u8 et1macaddr[6];
        u8 et0phyaddr:5;
        u8 et1phyaddr:5;
-       u8 et0mdcport:1;
-       u8 et1mdcport:1;
        u8 boardrev;
        u8 locale:4;
        u8 antennas_aphy:2;
@@ -542,7 +540,7 @@ struct bcm43xx_lopair {
 
 struct bcm43xx_phyinfo {
        /* Hardware Data */
-       u8 version;
+       u8 analog;
        u8 type;
        u8 rev;
        u16 antenna_diversity;
index ad8e569d1faf494bf9ffad04a942dc1828c09b45..f2b8dbac55a44182383de9d8da41b2d63a50c4f9 100644 (file)
@@ -325,6 +325,21 @@ void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val)
        }
 }
 
+void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val)
+{
+       if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) {
+               bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset);
+               mmiowb();
+               bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA2, (val & 0xFFFF0000) >> 16);
+               bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val & 0x0000FFFF);
+       } else {
+               bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset);
+               mmiowb();
+               bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA2, (val & 0xFFFF0000) >> 16);
+               bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, val & 0x0000FFFF);
+       }
+}
+
 u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset)
 {
        if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) {
index 464521abf73c3ece36b3134425e9bc35d5524b39..d7eaf5f25b7f1947cd3f1de6504384a7ecfac192 100644 (file)
@@ -27,6 +27,7 @@ extern const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE];
 
 
 void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val);
+void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val);
 u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset);
 
 #endif /* BCM43xx_ILT_H_ */
index 2e400aacc436e2a72d10ab2f18a7875a15e0bfa5..80cb88eb98c61d4dbbff27ecebaf48cb1e81c529 100644 (file)
@@ -851,8 +851,6 @@ static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm)
        value = sprom[BCM43xx_SPROM_ETHPHY];
        bcm->sprom.et0phyaddr = (value & 0x001F);
        bcm->sprom.et1phyaddr = (value & 0x03E0) >> 5;
-       bcm->sprom.et0mdcport = (value & (1 << 14)) >> 14;
-       bcm->sprom.et1mdcport = (value & (1 << 15)) >> 15;
 
        /* boardrev, antennas, locale */
        value = sprom[BCM43xx_SPROM_BOARDREV];
@@ -1449,12 +1447,10 @@ static void handle_irq_transmit_status(struct bcm43xx_private *bcm)
 
                bcm43xx_debugfs_log_txstat(bcm, &stat);
 
-               if (stat.flags & BCM43xx_TXSTAT_FLAG_IGNORE)
+               if (stat.flags & BCM43xx_TXSTAT_FLAG_AMPDU)
+                       continue;
+               if (stat.flags & BCM43xx_TXSTAT_FLAG_INTER)
                        continue;
-               if (!(stat.flags & BCM43xx_TXSTAT_FLAG_ACK)) {
-                       //TODO: packet was not acked (was lost)
-               }
-               //TODO: There are more (unknown) flags to test. see bcm43xx_main.h
 
                if (bcm43xx_using_pio(bcm))
                        bcm43xx_pio_handle_xmitstatus(bcm, &stat);
@@ -1862,9 +1858,6 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id)
 
        spin_lock(&bcm->irq_lock);
 
-       assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
-       assert(bcm->current_core->id == BCM43xx_COREID_80211);
-
        reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
        if (reason == 0xffffffff) {
                /* irq not for us (shared irq) */
@@ -1875,6 +1868,9 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id)
        if (!reason)
                goto out;
 
+       assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
+       assert(bcm->current_core->id == BCM43xx_COREID_80211);
+
        bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA0_REASON)
                             & 0x0001DC00;
        bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON)
@@ -2737,8 +2733,9 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
                                 * dangling pins on the second core. Be careful
                                 * and ignore these cores here.
                                 */
-                               if (bcm->pci_dev->device != 0x4324) {
-                                       dprintk(KERN_INFO PFX "Ignoring additional 802.11 core.\n");
+                               if (1 /*bcm->pci_dev->device != 0x4324*/ ) {
+                               /* TODO: A PHY */
+                                       dprintk(KERN_INFO PFX "Ignoring additional 802.11a core.\n");
                                        continue;
                                }
                        }
@@ -3696,7 +3693,7 @@ static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm)
 {
        struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
        u16 value;
-       u8 phy_version;
+       u8 phy_analog;
        u8 phy_type;
        u8 phy_rev;
        int phy_rev_ok = 1;
@@ -3704,12 +3701,12 @@ static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm)
 
        value = bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER);
 
-       phy_version = (value & 0xF000) >> 12;
+       phy_analog = (value & 0xF000) >> 12;
        phy_type = (value & 0x0F00) >> 8;
        phy_rev = (value & 0x000F);
 
-       dprintk(KERN_INFO PFX "Detected PHY: Version: %x, Type %x, Revision %x\n",
-               phy_version, phy_type, phy_rev);
+       dprintk(KERN_INFO PFX "Detected PHY: Analog: %x, Type %x, Revision %x\n",
+               phy_analog, phy_type, phy_rev);
 
        switch (phy_type) {
        case BCM43xx_PHYTYPE_A:
@@ -3752,7 +3749,7 @@ static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm)
                       phy_rev);
        }
 
-       phy->version = phy_version;
+       phy->analog = phy_analog;
        phy->type = phy_type;
        phy->rev = phy_rev;
        if ((phy_type == BCM43xx_PHYTYPE_B) || (phy_type == BCM43xx_PHYTYPE_G)) {
index 52ce2a9334fb12eee4fa0d831950b04ea3128178..cae89258a64071df728c8f0f1878ad92348f593d 100644 (file)
@@ -205,8 +205,8 @@ static void bcm43xx_phy_init_pctl(struct bcm43xx_private *bcm)
            (bcm->board_type == 0x0416))
                return;
 
-       bcm43xx_write16(bcm, 0x03E6, bcm43xx_read16(bcm, 0x03E6) & 0xFFDF);
        bcm43xx_phy_write(bcm, 0x0028, 0x8018);
+       bcm43xx_write16(bcm, 0x03E6, bcm43xx_read16(bcm, 0x03E6) & 0xFFDF);
 
        if (phy->type == BCM43xx_PHYTYPE_G) {
                if (!phy->connected)
@@ -317,6 +317,13 @@ static void bcm43xx_phy_agcsetup(struct bcm43xx_private *bcm)
        bcm43xx_ilt_write(bcm, offset + 0x0801, 7);
        bcm43xx_ilt_write(bcm, offset + 0x0802, 16);
        bcm43xx_ilt_write(bcm, offset + 0x0803, 28);
+
+       if (phy->rev >= 6) {
+               bcm43xx_phy_write(bcm, 0x0426, (bcm43xx_phy_read(bcm, 0x0426)
+                                 & 0xFFFC));
+               bcm43xx_phy_write(bcm, 0x0426, (bcm43xx_phy_read(bcm, 0x0426)
+                                 & 0xEFFF));
+       }
 }
 
 static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm)
@@ -337,7 +344,7 @@ static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm)
                for (i = 0; i < BCM43xx_ILT_NOISEG1_SIZE; i++)
                        bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg1[i]);
                for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++)
-                       bcm43xx_ilt_write(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
+                       bcm43xx_ilt_write32(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
        } else {
                /* nrssi values are signed 6-bit values. Not sure why we write 0x7654 here... */
                bcm43xx_nrssi_hw_write(bcm, 0xBA98, (s16)0x7654);
@@ -377,7 +384,7 @@ static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm)
        
        if (phy->rev == 1) {
                for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++)
-                       bcm43xx_ilt_write(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
+                       bcm43xx_ilt_write32(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
                for (i = 0; i < 4; i++) {
                        bcm43xx_ilt_write(bcm, 0x5404 + i, 0x0020);
                        bcm43xx_ilt_write(bcm, 0x5408 + i, 0x0020);
@@ -500,10 +507,10 @@ static void bcm43xx_phy_setupa(struct bcm43xx_private *bcm)
                for (i = 0; i < BCM43xx_ILT_NOISEA2_SIZE; i++)
                        bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea2[i]);
                for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++)
-                       bcm43xx_ilt_write(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
+                       bcm43xx_ilt_write32(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
                bcm43xx_phy_init_noisescaletbl(bcm);
                for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++)
-                       bcm43xx_ilt_write(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
+                       bcm43xx_ilt_write32(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
                break;
        case 3:
                for (i = 0; i < 64; i++)
@@ -729,19 +736,19 @@ static void bcm43xx_phy_initb5(struct bcm43xx_private *bcm)
        struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
        struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
        u16 offset;
+       u16 value;
+       u8 old_channel;
 
-       if (phy->version == 1 &&
-           radio->version == 0x2050) {
+       if (phy->analog == 1)
                bcm43xx_radio_write16(bcm, 0x007A,
                                      bcm43xx_radio_read16(bcm, 0x007A)
                                      | 0x0050);
-       }
        if ((bcm->board_vendor != PCI_VENDOR_ID_BROADCOM) &&
            (bcm->board_type != 0x0416)) {
+               value = 0x2120;
                for (offset = 0x00A8 ; offset < 0x00C7; offset++) {
-                       bcm43xx_phy_write(bcm, offset,
-                                         (bcm43xx_phy_read(bcm, offset) + 0x2020)
-                                         & 0x3F3F);
+                       bcm43xx_phy_write(bcm, offset, value);
+                       value += 0x0202;
                }
        }
        bcm43xx_phy_write(bcm, 0x0035,
@@ -750,7 +757,7 @@ static void bcm43xx_phy_initb5(struct bcm43xx_private *bcm)
        if (radio->version == 0x2050)
                bcm43xx_phy_write(bcm, 0x0038, 0x0667);
 
-       if (phy->connected) {
+       if (phy->type == BCM43xx_PHYTYPE_G) {
                if (radio->version == 0x2050) {
                        bcm43xx_radio_write16(bcm, 0x007A,
                                              bcm43xx_radio_read16(bcm, 0x007A)
@@ -776,7 +783,7 @@ static void bcm43xx_phy_initb5(struct bcm43xx_private *bcm)
                                  bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | (1 << 11));
        }
 
-       if (phy->version == 1 && radio->version == 0x2050) {
+       if (phy->analog == 1) {
                bcm43xx_phy_write(bcm, 0x0026, 0xCE00);
                bcm43xx_phy_write(bcm, 0x0021, 0x3763);
                bcm43xx_phy_write(bcm, 0x0022, 0x1BC3);
@@ -787,14 +794,15 @@ static void bcm43xx_phy_initb5(struct bcm43xx_private *bcm)
        bcm43xx_phy_write(bcm, 0x0030, 0x00C6);
        bcm43xx_write16(bcm, 0x03EC, 0x3F22);
 
-       if (phy->version == 1 && radio->version == 0x2050)
+       if (phy->analog == 1)
                bcm43xx_phy_write(bcm, 0x0020, 0x3E1C);
        else
                bcm43xx_phy_write(bcm, 0x0020, 0x301C);
 
-       if (phy->version == 0)
+       if (phy->analog == 0)
                bcm43xx_write16(bcm, 0x03E4, 0x3000);
 
+       old_channel = radio->channel;
        /* Force to channel 7, even if not supported. */
        bcm43xx_radio_selectchannel(bcm, 7, 0);
 
@@ -816,11 +824,11 @@ static void bcm43xx_phy_initb5(struct bcm43xx_private *bcm)
 
        bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0007);
 
-       bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
+       bcm43xx_radio_selectchannel(bcm, old_channel, 0);
 
        bcm43xx_phy_write(bcm, 0x0014, 0x0080);
        bcm43xx_phy_write(bcm, 0x0032, 0x00CA);
-       bcm43xx_phy_write(bcm, 0x88A3, 0x002A);
+       bcm43xx_phy_write(bcm, 0x002A, 0x88A3);
 
        bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
 
@@ -835,61 +843,29 @@ static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm)
        struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
        struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
        u16 offset, val;
+       u8 old_channel;
 
        bcm43xx_phy_write(bcm, 0x003E, 0x817A);
        bcm43xx_radio_write16(bcm, 0x007A,
                              (bcm43xx_radio_read16(bcm, 0x007A) | 0x0058));
-       if ((radio->manufact == 0x17F) &&
-           (radio->version == 0x2050) &&
-           (radio->revision == 3 ||
-            radio->revision == 4 ||
-            radio->revision == 5)) {
-               bcm43xx_radio_write16(bcm, 0x0051, 0x001F);
-               bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
-               bcm43xx_radio_write16(bcm, 0x0053, 0x005B);
-               bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
+       if (radio->revision == 4 ||
+            radio->revision == 5) {
+               bcm43xx_radio_write16(bcm, 0x0051, 0x0037);
+               bcm43xx_radio_write16(bcm, 0x0052, 0x0070);
+               bcm43xx_radio_write16(bcm, 0x0053, 0x00B3);
+               bcm43xx_radio_write16(bcm, 0x0054, 0x009B);
                bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
                bcm43xx_radio_write16(bcm, 0x005B, 0x0088);
                bcm43xx_radio_write16(bcm, 0x005D, 0x0088);
                bcm43xx_radio_write16(bcm, 0x005E, 0x0088);
                bcm43xx_radio_write16(bcm, 0x007D, 0x0088);
+               bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+                                   BCM43xx_UCODEFLAGS_OFFSET,
+                                   (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+                                   BCM43xx_UCODEFLAGS_OFFSET)
+                                   | 0x00000200));
        }
-       if ((radio->manufact == 0x17F) &&
-           (radio->version == 0x2050) &&
-           (radio->revision == 6)) {
-               bcm43xx_radio_write16(bcm, 0x0051, 0x0000);
-               bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
-               bcm43xx_radio_write16(bcm, 0x0053, 0x00B7);
-               bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
-               bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
-               bcm43xx_radio_write16(bcm, 0x005B, 0x008B);
-               bcm43xx_radio_write16(bcm, 0x005C, 0x00B5);
-               bcm43xx_radio_write16(bcm, 0x005D, 0x0088);
-               bcm43xx_radio_write16(bcm, 0x005E, 0x0088);
-               bcm43xx_radio_write16(bcm, 0x007D, 0x0088);
-               bcm43xx_radio_write16(bcm, 0x007C, 0x0001);
-               bcm43xx_radio_write16(bcm, 0x007E, 0x0008);
-       }
-       if ((radio->manufact == 0x17F) &&
-           (radio->version == 0x2050) &&
-           (radio->revision == 7)) {
-               bcm43xx_radio_write16(bcm, 0x0051, 0x0000);
-               bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
-               bcm43xx_radio_write16(bcm, 0x0053, 0x00B7);
-               bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
-               bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
-               bcm43xx_radio_write16(bcm, 0x005B, 0x00A8);
-               bcm43xx_radio_write16(bcm, 0x005C, 0x0075);
-               bcm43xx_radio_write16(bcm, 0x005D, 0x00F5);
-               bcm43xx_radio_write16(bcm, 0x005E, 0x00B8);
-               bcm43xx_radio_write16(bcm, 0x007D, 0x00E8);
-               bcm43xx_radio_write16(bcm, 0x007C, 0x0001);
-               bcm43xx_radio_write16(bcm, 0x007E, 0x0008);
-               bcm43xx_radio_write16(bcm, 0x007B, 0x0000);
-       }
-       if ((radio->manufact == 0x17F) &&
-           (radio->version == 0x2050) &&
-           (radio->revision == 8)) {
+       if (radio->revision == 8) {
                bcm43xx_radio_write16(bcm, 0x0051, 0x0000);
                bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
                bcm43xx_radio_write16(bcm, 0x0053, 0x00B7);
@@ -933,20 +909,26 @@ static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm)
                                  bcm43xx_phy_read(bcm, 0x0802) | 0x0100);
                bcm43xx_phy_write(bcm, 0x042B,
                                  bcm43xx_phy_read(bcm, 0x042B) | 0x2000);
+               bcm43xx_phy_write(bcm, 0x5B, 0x0000);
+               bcm43xx_phy_write(bcm, 0x5C, 0x0000);
        }
 
-       /* Force to channel 7, even if not supported. */
-       bcm43xx_radio_selectchannel(bcm, 7, 0);
+       old_channel = radio->channel;
+       if (old_channel >= 8)
+               bcm43xx_radio_selectchannel(bcm, 1, 0);
+       else
+               bcm43xx_radio_selectchannel(bcm, 13, 0);
 
        bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
        bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
        udelay(40);
-       bcm43xx_radio_write16(bcm, 0x007C, (bcm43xx_radio_read16(bcm, 0x007C) | 0x0002));
-       bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
-       if (radio->manufact == 0x17F &&
-           radio->version == 0x2050 &&
-           radio->revision <= 2) {
+       if (radio->revision < 6 || radio-> revision == 8) {
+               bcm43xx_radio_write16(bcm, 0x007C, (bcm43xx_radio_read16(bcm, 0x007C)
+                                     | 0x0002));
                bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+       }
+       if (radio->revision <= 2) {
+               bcm43xx_radio_write16(bcm, 0x007C, 0x0020);
                bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
                bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
                bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
@@ -954,46 +936,42 @@ static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm)
        bcm43xx_radio_write16(bcm, 0x007A,
                              (bcm43xx_radio_read16(bcm, 0x007A) & 0x00F8) | 0x0007);
 
-       bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
+       bcm43xx_radio_selectchannel(bcm, old_channel, 0);
 
        bcm43xx_phy_write(bcm, 0x0014, 0x0200);
-       if (radio->version == 0x2050){
-               if (radio->revision == 3 ||
-                   radio->revision == 4 ||
-                   radio->revision == 5)
-                       bcm43xx_phy_write(bcm, 0x002A, 0x8AC0);
-               else
-                       bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
-       }
+       if (radio->revision >= 6)
+               bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
+       else
+               bcm43xx_phy_write(bcm, 0x002A, 0x8AC0);
        bcm43xx_phy_write(bcm, 0x0038, 0x0668);
        bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
-       if (radio->version == 0x2050) {
-               if (radio->revision == 3 ||
-                   radio->revision == 4 ||
-                   radio->revision == 5)
-                       bcm43xx_phy_write(bcm, 0x005D, bcm43xx_phy_read(bcm, 0x005D) | 0x0003);
-               else if (radio->revision <= 2)
-                       bcm43xx_radio_write16(bcm, 0x005D, 0x000D);
-       }
+       if (radio->revision <= 5)
+               bcm43xx_phy_write(bcm, 0x005D, (bcm43xx_phy_read(bcm, 0x005D)
+                                 & 0xFF80) | 0x0003);
+       if (radio->revision <= 2)
+               bcm43xx_radio_write16(bcm, 0x005D, 0x000D);
        
-       if (phy->rev == 4)
-               bcm43xx_phy_write(bcm, 0x0002, (bcm43xx_phy_read(bcm, 0x0002) & 0xFFC0) | 0x0004);
-       else
+       if (phy->analog == 4){
                bcm43xx_write16(bcm, 0x03E4, 0x0009);
+               bcm43xx_phy_write(bcm, 0x61, bcm43xx_phy_read(bcm, 0x61) & 0xFFF);
+       } else {
+               bcm43xx_phy_write(bcm, 0x0002, (bcm43xx_phy_read(bcm, 0x0002) & 0xFFC0) | 0x0004);
+       }
+       if (phy->type == BCM43xx_PHYTYPE_G)
+               bcm43xx_write16(bcm, 0x03E6, 0x0);
        if (phy->type == BCM43xx_PHYTYPE_B) {
                bcm43xx_write16(bcm, 0x03E6, 0x8140);
                bcm43xx_phy_write(bcm, 0x0016, 0x0410);
                bcm43xx_phy_write(bcm, 0x0017, 0x0820);
                bcm43xx_phy_write(bcm, 0x0062, 0x0007);
-               (void) bcm43xx_radio_calibrationvalue(bcm);
-               bcm43xx_phy_lo_b_measure(bcm);
+               bcm43xx_radio_init2050(bcm);
+               bcm43xx_phy_lo_g_measure(bcm);
                if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
                        bcm43xx_calc_nrssi_slope(bcm);
                        bcm43xx_calc_nrssi_threshold(bcm);
                }
                bcm43xx_phy_init_pctl(bcm);
-       } else
-               bcm43xx_write16(bcm, 0x03E6, 0x0);
+       }
 }
 
 static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm)
@@ -1063,7 +1041,7 @@ static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm)
        bcm43xx_phy_write(bcm, 0x005A, 0x0780);
        bcm43xx_phy_write(bcm, 0x0059, 0xC810);
        bcm43xx_phy_write(bcm, 0x0058, 0x000D);
-       if (phy->version == 0) {
+       if (phy->analog == 0) {
                bcm43xx_phy_write(bcm, 0x0003, 0x0122);
        } else {
                bcm43xx_phy_write(bcm, 0x000A,
@@ -1205,27 +1183,30 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm)
        if (phy->rev >= 2) {
                bcm43xx_phy_write(bcm, 0x0814, 0x0000);
                bcm43xx_phy_write(bcm, 0x0815, 0x0000);
-               if (phy->rev == 2)
-                       bcm43xx_phy_write(bcm, 0x0811, 0x0000);
-               else if (phy->rev >= 3)
-                       bcm43xx_phy_write(bcm, 0x0811, 0x0400);
+       }
+       if (phy->rev == 2) {
+               bcm43xx_phy_write(bcm, 0x0811, 0x0000);
                bcm43xx_phy_write(bcm, 0x0015, 0x00C0);
-               if (phy->connected) {
-                       tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF;
-                       if (tmp < 6) {
-                               bcm43xx_phy_write(bcm, 0x04C2, 0x1816);
-                               bcm43xx_phy_write(bcm, 0x04C3, 0x8006);
-                               if (tmp != 3) {
-                                       bcm43xx_phy_write(bcm, 0x04CC,
-                                                         (bcm43xx_phy_read(bcm, 0x04CC)
-                                                          & 0x00FF) | 0x1F00);
-                               }
+       }
+       if (phy->rev >= 3) {
+               bcm43xx_phy_write(bcm, 0x0811, 0x0400);
+               bcm43xx_phy_write(bcm, 0x0015, 0x00C0);
+       }
+       if (phy->connected) {
+               tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF;
+               if (tmp < 6) {
+                       bcm43xx_phy_write(bcm, 0x04C2, 0x1816);
+                       bcm43xx_phy_write(bcm, 0x04C3, 0x8006);
+                       if (tmp != 3) {
+                               bcm43xx_phy_write(bcm, 0x04CC,
+                                                 (bcm43xx_phy_read(bcm, 0x04CC)
+                                                  & 0x00FF) | 0x1F00);
                        }
                }
        }
        if (phy->rev < 3 && phy->connected)
                bcm43xx_phy_write(bcm, 0x047E, 0x0078);
-       if (phy->rev >= 6 && phy->rev <= 8) {
+       if (radio->revision == 8) {
                bcm43xx_phy_write(bcm, 0x0801, bcm43xx_phy_read(bcm, 0x0801) | 0x0080);
                bcm43xx_phy_write(bcm, 0x043E, bcm43xx_phy_read(bcm, 0x043E) | 0x0004);
        }
@@ -1638,14 +1619,14 @@ void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm,
        struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
        u16 value;
 
-       if (phy->version == 0) {
+       if (phy->analog == 0) {
                value = (bcm43xx_read16(bcm, 0x03E6) & 0xFFF0);
                value |= (baseband_attenuation & 0x000F);
                bcm43xx_write16(bcm, 0x03E6, value);
                return;
        }
 
-       if (phy->version > 1) {
+       if (phy->analog > 1) {
                value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C;
                value |= (baseband_attenuation << 2) & 0x003C;
        } else {
index af19a07032a3ed8ba59a6ff031b97f9dbae1b3d4..32beb91b7164a5d27ebb9d23f1546de85610d87a 100644 (file)
@@ -1393,11 +1393,12 @@ u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm)
        backup[12] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
 
        // Initialization
-       if (phy->version == 0) {
+       if (phy->analog == 0) {
                bcm43xx_write16(bcm, 0x03E6, 0x0122);
        } else {
-               if (phy->version >= 2)
-                       bcm43xx_write16(bcm, 0x03E6, 0x0040);
+               if (phy->analog >= 2)
+                       bcm43xx_phy_write(bcm, 0x0003, (bcm43xx_phy_read(bcm, 0x0003)
+                                       & 0xFFBF) | 0x0040);
                bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
                                (bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) | 0x2000));
        }
@@ -1405,7 +1406,7 @@ u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm)
        ret = bcm43xx_radio_calibrationvalue(bcm);
 
        if (phy->type == BCM43xx_PHYTYPE_B)
-               bcm43xx_radio_write16(bcm, 0x0078, 0x0003);
+               bcm43xx_radio_write16(bcm, 0x0078, 0x0026);
 
        bcm43xx_phy_write(bcm, 0x0015, 0xBFAF);
        bcm43xx_phy_write(bcm, 0x002B, 0x1403);
@@ -1416,7 +1417,7 @@ u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm)
                              (bcm43xx_radio_read16(bcm, 0x0051) | 0x0004));
        bcm43xx_radio_write16(bcm, 0x0052, 0x0000);
        bcm43xx_radio_write16(bcm, 0x0043,
-                             bcm43xx_radio_read16(bcm, 0x0043) | 0x0009);
+                             (bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0) | 0x0009);
        bcm43xx_phy_write(bcm, 0x0058, 0x0000);
 
        for (i = 0; i < 16; i++) {
@@ -1488,7 +1489,7 @@ u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm)
        bcm43xx_phy_write(bcm, 0x0059, backup[17]);
        bcm43xx_phy_write(bcm, 0x0058, backup[18]);
        bcm43xx_write16(bcm, 0x03E6, backup[11]);
-       if (phy->version != 0)
+       if (phy->analog != 0)
                bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[12]);
        bcm43xx_phy_write(bcm, 0x0035, backup[10]);
        bcm43xx_radio_selectchannel(bcm, radio->channel, 1);
index 7b665e2386a8caaa888b355e80e58510d7e3a201..d6d9413d7f23cdd662eadf09cc675dd667b2fda1 100644 (file)
@@ -105,18 +105,24 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev,
        struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
        unsigned long flags;
        u8 channel;
+       s8 expon;
        int freq;
        int err = -EINVAL;
 
        mutex_lock(&bcm->mutex);
        spin_lock_irqsave(&bcm->irq_lock, flags);
 
-       if ((data->freq.m >= 0) && (data->freq.m <= 1000)) {
+       if ((data->freq.e == 0) &&
+           (data->freq.m >= 0) && (data->freq.m <= 1000)) {
                channel = data->freq.m;
                freq = bcm43xx_channel_to_freq(bcm, channel);
        } else {
-               channel = bcm43xx_freq_to_channel(bcm, data->freq.m);
                freq = data->freq.m;
+               expon = 6 - data->freq.e;
+               while (--expon >= 0)    /* scale down the frequency to MHz */
+                       freq /= 10;
+               assert(freq > 1000);
+               channel = bcm43xx_freq_to_channel(bcm, freq);
        }
        if (!ieee80211_is_valid_channel(bcm->ieee, channel))
                goto out_unlock;
index 2aed19e35c770ed6ff886e32758a171b843cbacd..9ecf2bf0d25ddb100773ba759839180ab10ee367 100644 (file)
@@ -137,14 +137,8 @@ struct bcm43xx_xmitstatus {
        u16 unknown; //FIXME
 };
 
-#define BCM43xx_TXSTAT_FLAG_ACK                0x01
-//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x02
-//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x04
-//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x08
-//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x10
-#define BCM43xx_TXSTAT_FLAG_IGNORE     0x20
-//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x40
-//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x80
+#define BCM43xx_TXSTAT_FLAG_AMPDU      0x10
+#define BCM43xx_TXSTAT_FLAG_INTER      0x20
 
 u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate);
 u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate);
index e89c890d16fd7c0864ab964b675270f5c55b07ea..ef37a75d550b863cf4180fb4b466b00f4233b79f 100644 (file)
@@ -2,13 +2,14 @@
 #define HOSTAP_H
 
 #include <linux/ethtool.h>
+#include <linux/kernel.h>
 
 #include "hostap_wlan.h"
 #include "hostap_ap.h"
 
 static const long freq_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
                                  2447, 2452, 2457, 2462, 2467, 2472, 2484 };
-#define FREQ_COUNT (sizeof(freq_list) / sizeof(freq_list[0]))
+#define FREQ_COUNT ARRAY_SIZE(freq_list)
 
 /* hostap.c */
 
index d0639a45cd2c4fbc083695b2ed4a6bf657e4f9f4..ad6e4a42835598bee37d96342d546fccbbbc45b2 100644 (file)
@@ -2888,7 +2888,7 @@ static int __ipw2100_tx_process(struct ipw2100_priv *priv)
 
 #ifdef CONFIG_IPW2100_DEBUG
                if (packet->info.c_struct.cmd->host_command_reg <
-                   sizeof(command_types) / sizeof(*command_types))
+                   ARRAY_SIZE(command_types))
                        IPW_DEBUG_TX("Command '%s (%d)' processed: %d.\n",
                                     command_types[packet->info.c_struct.cmd->
                                                   host_command_reg],
@@ -3736,7 +3736,7 @@ static ssize_t show_registers(struct device *d, struct device_attribute *attr,
 
        out += sprintf(out, "%30s [Address ] : Hex\n", "Register");
 
-       for (i = 0; i < (sizeof(hw_data) / sizeof(*hw_data)); i++) {
+       for (i = 0; i < ARRAY_SIZE(hw_data); i++) {
                read_register(dev, hw_data[i].addr, &val);
                out += sprintf(out, "%30s [%08X] : %08X\n",
                               hw_data[i].name, hw_data[i].addr, val);
@@ -3757,7 +3757,7 @@ static ssize_t show_hardware(struct device *d, struct device_attribute *attr,
 
        out += sprintf(out, "%30s [Address ] : Hex\n", "NIC entry");
 
-       for (i = 0; i < (sizeof(nic_data) / sizeof(*nic_data)); i++) {
+       for (i = 0; i < ARRAY_SIZE(nic_data); i++) {
                u8 tmp8;
                u16 tmp16;
                u32 tmp32;
@@ -3894,13 +3894,11 @@ static ssize_t show_ordinals(struct device *d, struct device_attribute *attr,
        if (priv->status & STATUS_RF_KILL_MASK)
                return 0;
 
-       if (loop >= sizeof(ord_data) / sizeof(*ord_data))
+       if (loop >= ARRAY_SIZE(ord_data))
                loop = 0;
 
        /* sysfs provides us PAGE_SIZE buffer */
-       while (len < PAGE_SIZE - 128 &&
-              loop < (sizeof(ord_data) / sizeof(*ord_data))) {
-
+       while (len < PAGE_SIZE - 128 && loop < ARRAY_SIZE(ord_data)) {
                val_len = sizeof(u32);
 
                if (ipw2100_get_ordinal(priv, ord_data[loop].index, &val,
@@ -6589,7 +6587,7 @@ static const long ipw2100_rates_11b[] = {
        11000000
 };
 
-#define RATE_COUNT (sizeof(ipw2100_rates_11b) / sizeof(ipw2100_rates_11b[0]))
+#define RATE_COUNT ARRAY_SIZE(ipw2100_rates_11b)
 
 static int ipw2100_wx_get_name(struct net_device *dev,
                               struct iw_request_info *info,
index 838d510213c60ef74b3e6c1e04d24b156e27db01..841b3c136ad951d47ed6ca0aeb53b8d605550061 100644 (file)
@@ -1395,11 +1395,16 @@ static int prism54_set_auth(struct net_device *ndev,
                break;
 
        case IW_AUTH_RX_UNENCRYPTED_EAPOL:
-               dot1x = param->value ? 1 : 0;
+               /* dot1x should be the opposite of RX_UNENCRYPTED_EAPOL;
+                * turn off dot1x when allowing receipt of unencrypted EAPOL
+                * frames, turn on dot1x when receipt should be disallowed
+                */
+               dot1x = param->value ? 0 : 0x01;
                break;
 
        case IW_AUTH_PRIVACY_INVOKED:
                privinvoked = param->value ? 1 : 0;
+               break;
 
        case IW_AUTH_DROP_UNENCRYPTED:
                exunencrypt = param->value ? 1 : 0;
@@ -1589,6 +1594,7 @@ static int prism54_set_encodeext(struct net_device *ndev,
                        }
                        key.type = DOT11_PRIV_TKIP;
                        key.length = KEY_SIZE_TKIP;
+                       break;
                default:
                        return -EINVAL;
                }
index e6cf9df2c20655699618bd3f18595a99862772e3..42780320cd5cbef6ab1a2b9b13f91877b996c719 100644 (file)
@@ -16,6 +16,8 @@
  *
  */
 
+#include <linux/kernel.h>
+
 #include "prismcompat.h"
 #include "islpci_dev.h"
 #include "islpci_mgt.h"
@@ -692,7 +694,7 @@ mgt_update_addr(islpci_private *priv)
        return ret;
 }
 
-#define VEC_SIZE(a) (sizeof(a)/sizeof(a[0]))
+#define VEC_SIZE(a) ARRAY_SIZE(a)
 
 int
 mgt_commit(islpci_private *priv)
index 24221e476cd3ee938e667dc46f51bf44a346c817..2aa3c761dd83a1006b4b9d56c7a7908df365c94b 100644 (file)
@@ -28,7 +28,7 @@
  */
 static u8 wv_irq_to_psa(int irq)
 {
-       if (irq < 0 || irq >= NELS(irqvals))
+       if (irq < 0 || irq >= ARRAY_SIZE(irqvals))
                return 0;
 
        return irqvals[irq];
@@ -42,7 +42,7 @@ static int __init wv_psa_to_irq(u8 irqval)
 {
        int irq;
 
-       for (irq = 0; irq < NELS(irqvals); irq++)
+       for (irq = 0; irq < ARRAY_SIZE(irqvals); irq++)
                if (irqvals[irq] == irqval)
                        return irq;
 
@@ -1695,7 +1695,7 @@ static int wv_frequency_list(unsigned long ioaddr,        /* I/O port of the card */
                /* Look in the table if the frequency is allowed */
                if (table[9 - (freq / 16)] & (1 << (freq % 16))) {
                        /* Compute approximate channel number */
-                       while ((c < NELS(channel_bands)) &&
+                       while ((c < ARRAY_SIZE(channel_bands)) &&
                                (((channel_bands[c] >> 1) - 24) < freq)) 
                                c++;
                        list[i].i = c;  /* Set the list index */
@@ -4269,7 +4269,7 @@ struct net_device * __init wavelan_probe(int unit)
                printk(KERN_DEBUG "%s: <-wavelan_probe()\n", dev->name);
 #endif
        } else { /* Scan all possible addresses of the WaveLAN hardware. */
-               for (i = 0; i < NELS(iobase); i++) {
+               for (i = 0; i < ARRAY_SIZE(iobase); i++) {
                        dev->irq = def_irq;
                        if (wavelan_config(dev, iobase[i]) == 0) {
 #ifdef DEBUG_CALLBACK_TRACE
@@ -4280,7 +4280,7 @@ struct net_device * __init wavelan_probe(int unit)
                                break;
                        }
                }
-               if (i == NELS(iobase))
+               if (i == ARRAY_SIZE(iobase))
                        r = -ENODEV;
        }
        if (r) 
@@ -4327,14 +4327,14 @@ int __init init_module(void)
 #endif
 
                /* Copy the basic set of address to be probed. */
-               for (i = 0; i < NELS(iobase); i++)
+               for (i = 0; i < ARRAY_SIZE(iobase); i++)
                        io[i] = iobase[i];
        }
 
 
        /* Loop on all possible base addresses. */
        i = -1;
-       while ((io[++i] != 0) && (i < NELS(io))) {
+       while ((io[++i] != 0) && (i < ARRAY_SIZE(io))) {
                struct net_device *dev = alloc_etherdev(sizeof(net_local));
                if (!dev)
                        break;
index 72b646c77d5a3885caca1182dcbaab50ef8b3919..fe242812d858e6161aa4272d43e4461c22cdfeb7 100644 (file)
@@ -449,9 +449,6 @@ static const char   *version        = "wavelan.c : v24 (SMP + wireless extensions) 11/12/
 /* Watchdog temporisation */
 #define        WATCHDOG_JIFFIES        (512*HZ/100)
 
-/* Macro to get the number of elements in an array */
-#define        NELS(a)                         (sizeof(a) / sizeof(a[0]))
-
 /* ------------------------ PRIVATE IOCTL ------------------------ */
 
 #define SIOCSIPQTHR    SIOCIWFIRSTPRIV         /* Set quality threshold */
index c250f08c8dd51dd99206123d1bf3025985dae567..ce9230b2f630e518870c4210a987ce61f4d2c03c 100644 (file)
@@ -26,7 +26,6 @@
  * Tested with Planet AP in 2.5.73-bk, 216 Kbytes/s in Infrastructure mode
  * with a SMP machine (dual pentium 100), using pktgen, 432 pps (pkt_size = 60)
  */
-#undef REALLY_SLOW_IO  /* most systems can safely undef this */
 
 #include <linux/delay.h>
 #include <linux/types.h>
index 12dfc0b6efe6796b2f371b53a357e23dc1a558f6..9c64f894b71b180fecb9f9742b29fdaac0d46162 100644 (file)
@@ -113,7 +113,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),
index 07dc2b6d4e933e3ade9c442e308bd022fa3ac5dd..9bb4db552f3ceeb96e72c3093f4b73f0bc69a7f2 100644 (file)
 ** the Free Software Foundation; either version 2 of the License, or
 ** (at your option) any later version.
 **
-** This Driver currently only supports the console (port 0) on the MUX.
-** Additional work will be needed on this driver to enable the full
-** functionality of the MUX.
-**
 */
 
 #include <linux/types.h>
@@ -67,7 +63,7 @@ static int hppb_probe(struct parisc_device *dev)
                }
                card = card->next;
        }
-        printk(KERN_INFO "Found GeckoBoa at 0x%lx\n", dev->hpa.start);
+        printk(KERN_INFO "Found GeckoBoa at 0x%x\n", dev->hpa.start);
 
        card->hpa = dev->hpa.start;
        card->mmio_region.name = "HP-PB Bus";
@@ -78,16 +74,18 @@ static int hppb_probe(struct parisc_device *dev)
 
        status = ccio_request_resource(dev, &card->mmio_region);
        if(status < 0) {
-               printk(KERN_ERR "%s: failed to claim HP-PB bus space (%08lx, %08lx)\n",
+               printk(KERN_ERR "%s: failed to claim HP-PB bus space (%08x, %08x)\n",
                        __FILE__, card->mmio_region.start, card->mmio_region.end);
        }
 
         return 0;
 }
 
-
 static struct parisc_device_id hppb_tbl[] = {
-        { HPHW_BCPORT, HVERSION_REV_ANY_ID, 0x500, 0xc }, 
+        { HPHW_BCPORT, HVERSION_REV_ANY_ID, 0x500, 0xc }, /* E25 and K */
+        { HPHW_BCPORT, 0x0, 0x501, 0xc }, /* E35 */
+        { HPHW_BCPORT, 0x0, 0x502, 0xc }, /* E45 */
+        { HPHW_BCPORT, 0x0, 0x503, 0xc }, /* E55 */
         { 0, }
 };
 
index 41e7ec2a44aa8f423627b3cc0143a5353be33f37..6e05e30a2450a052c9d1f4d0d460826a10514b52 100644 (file)
@@ -132,7 +132,7 @@ struct iosapic_irt {
 struct vector_info {
        struct iosapic_info *iosapic;   /* I/O SAPIC this vector is on */
        struct irt_entry *irte;         /* IRT entry */
-       u32     *eoi_addr;              /* precalculate EOI reg address */
+       u32 __iomem *eoi_addr;          /* precalculate EOI reg address */
        u32     eoi_data;               /* IA64: ?       PA: swapped txn_data */
        int     txn_irq;                /* virtual IRQ number for processor */
        ulong   txn_addr;               /* IA64: id_eid  PA: partial HPA */
index ba6769934c771718035f8ed35c2a99c89021afce..21c4c299b3d6c823ae92b6f8af86741a86207484 100644 (file)
@@ -168,7 +168,8 @@ lba_dump_res(struct resource *r, int d)
 
        printk(KERN_DEBUG "(%p)", r->parent);
        for (i = d; i ; --i) printk(" ");
-       printk(KERN_DEBUG "%p [%lx,%lx]/%lx\n", r, r->start, r->end, r->flags);
+       printk(KERN_DEBUG "%p [%lx,%lx]/%lx\n", r,
+               (long)r->start, (long)r->end, r->flags);
        lba_dump_res(r->child, d+2);
        lba_dump_res(r->sibling, d);
 }
@@ -647,7 +648,7 @@ truncate_pat_collision(struct resource *root, struct resource *new)
        printk(KERN_WARNING "LBA: Truncating lmmio_space [%lx/%lx] "
                                        "to [%lx,%lx]\n",
                        start, end,
-                       new->start, new->end );
+                       (long)new->start, (long)new->end );
 
        return 0;       /* truncation successful */
 }
@@ -715,8 +716,8 @@ lba_fixup_bus(struct pci_bus *bus)
 
                                printk("FAILED: lba_fixup_bus() request for "
                                                "elmmio_space [%lx/%lx]\n",
-                                               ldev->hba.elmmio_space.start,
-                                               ldev->hba.elmmio_space.end);
+                                               (long)ldev->hba.elmmio_space.start,
+                                               (long)ldev->hba.elmmio_space.end);
 
                                /* lba_dump_res(&iomem_resource, 2); */
                                /* BUG(); */
@@ -738,15 +739,15 @@ lba_fixup_bus(struct pci_bus *bus)
                                        &(ldev->hba.lmmio_space))) {
 
                        printk(KERN_WARNING "LBA: lmmio_space [%lx/%lx] duplicate!\n",
-                                       ldev->hba.lmmio_space.start,
-                                       ldev->hba.lmmio_space.end);
+                                       (long)ldev->hba.lmmio_space.start,
+                                       (long)ldev->hba.lmmio_space.end);
                } else {
                        err = request_resource(&iomem_resource, &(ldev->hba.lmmio_space));
                        if (err < 0) {
                                printk(KERN_ERR "FAILED: lba_fixup_bus() request for "
                                        "lmmio_space [%lx/%lx]\n",
-                                       ldev->hba.lmmio_space.start,
-                                       ldev->hba.lmmio_space.end);
+                                       (long)ldev->hba.lmmio_space.start,
+                                       (long)ldev->hba.lmmio_space.end);
                        } else
                                bus->resource[i++] = &(ldev->hba.lmmio_space);
                }
@@ -758,8 +759,8 @@ lba_fixup_bus(struct pci_bus *bus)
                        if (err < 0) {
                                printk("FAILED: lba_fixup_bus() request for "
                                        "gmmio_space [%lx/%lx]\n",
-                                       ldev->hba.gmmio_space.start,
-                                       ldev->hba.gmmio_space.end);
+                                       (long)ldev->hba.gmmio_space.start,
+                                       (long)ldev->hba.gmmio_space.end);
                                lba_dump_res(&iomem_resource, 2);
                                BUG();
                        }
@@ -980,7 +981,7 @@ LBA_PORT_IN(32, 0)
 #define LBA_PORT_OUT(size, mask) \
 static void lba_pat_out##size (struct pci_hba_data *l, u16 addr, u##size val) \
 { \
-       void *where = (void *) PIOP_TO_GMMIO(LBA_DEV(l), addr); \
+       void __iomem *where = PIOP_TO_GMMIO(LBA_DEV(l), addr); \
        DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, l, addr, val); \
        WRITE_REG##size(val, where); \
        /* flush the I/O down to the elroy at least */ \
@@ -1063,16 +1064,16 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
                        /* used to fix up pre-initialized MEM BARs */
                        if (!lba_dev->hba.lmmio_space.start) {
                                sprintf(lba_dev->hba.lmmio_name,
-                                               "PCI%02lx LMMIO",
-                                               lba_dev->hba.bus_num.start);
+                                               "PCI%02x LMMIO",
+                                               (int)lba_dev->hba.bus_num.start);
                                lba_dev->hba.lmmio_space_offset = p->start -
                                        io->start;
                                r = &lba_dev->hba.lmmio_space;
                                r->name = lba_dev->hba.lmmio_name;
                        } else if (!lba_dev->hba.elmmio_space.start) {
                                sprintf(lba_dev->hba.elmmio_name,
-                                               "PCI%02lx ELMMIO",
-                                               lba_dev->hba.bus_num.start);
+                                               "PCI%02x ELMMIO",
+                                               (int)lba_dev->hba.bus_num.start);
                                r = &lba_dev->hba.elmmio_space;
                                r->name = lba_dev->hba.elmmio_name;
                        } else {
@@ -1089,8 +1090,8 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
 
                case PAT_GMMIO:
                        /* MMIO space > 4GB phys addr; for 64-bit BAR */
-                       sprintf(lba_dev->hba.gmmio_name, "PCI%02lx GMMIO",
-                                       lba_dev->hba.bus_num.start);
+                       sprintf(lba_dev->hba.gmmio_name, "PCI%02x GMMIO",
+                                       (int)lba_dev->hba.bus_num.start);
                        r = &lba_dev->hba.gmmio_space;
                        r->name  = lba_dev->hba.gmmio_name;
                        r->start  = p->start;
@@ -1112,8 +1113,8 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
                        */
                        lba_dev->iop_base = ioremap_nocache(p->start, 64 * 1024 * 1024);
 
-                       sprintf(lba_dev->hba.io_name, "PCI%02lx Ports",
-                                       lba_dev->hba.bus_num.start);
+                       sprintf(lba_dev->hba.io_name, "PCI%02x Ports",
+                                       (int)lba_dev->hba.bus_num.start);
                        r = &lba_dev->hba.io_space;
                        r->name  = lba_dev->hba.io_name;
                        r->start  = HBA_PORT_BASE(lba_dev->hba.hba_num);
@@ -1166,8 +1167,8 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
        ** Legacy boxes but it's nice to see in /proc/iomem.
        */
        r = &(lba_dev->hba.lmmio_space);
-       sprintf(lba_dev->hba.lmmio_name, "PCI%02lx LMMIO",
-                                       lba_dev->hba.bus_num.start);
+       sprintf(lba_dev->hba.lmmio_name, "PCI%02x LMMIO",
+                                       (int)lba_dev->hba.bus_num.start);
        r->name  = lba_dev->hba.lmmio_name;
 
 #if 1
@@ -1275,8 +1276,8 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
        ** an existing (but unused portion of) distributed range.
        */
        r = &(lba_dev->hba.elmmio_space);
-       sprintf(lba_dev->hba.elmmio_name, "PCI%02lx ELMMIO",
-                                       lba_dev->hba.bus_num.start);
+       sprintf(lba_dev->hba.elmmio_name, "PCI%02x ELMMIO",
+                                       (int)lba_dev->hba.bus_num.start);
        r->name  = lba_dev->hba.elmmio_name;
 
 #if 1
@@ -1297,8 +1298,8 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
 #endif
 
        r = &(lba_dev->hba.io_space);
-       sprintf(lba_dev->hba.io_name, "PCI%02lx Ports",
-                                       lba_dev->hba.bus_num.start);
+       sprintf(lba_dev->hba.io_name, "PCI%02x Ports",
+                                       (int)lba_dev->hba.bus_num.start);
        r->name  = lba_dev->hba.io_name;
        r->flags = IORESOURCE_IO;
        r->start = READ_REG32(lba_dev->hba.base_addr + LBA_IOS_BASE) & ~1L;
@@ -1406,13 +1407,20 @@ lba_hw_init(struct lba_device *d)
        return 0;
 }
 
-
+/*
+ * Unfortunately, when firmware numbers busses, it doesn't take into account
+ * Cardbus bridges.  So we have to renumber the busses to suit ourselves.
+ * Elroy/Mercury don't actually know what bus number they're attached to;
+ * we use bus 0 to indicate the directly attached bus and any other bus
+ * number will be taken care of by the PCI-PCI bridge.
+ */
+static unsigned int lba_next_bus = 0;
 
 /*
-** Determine if lba should claim this chip (return 0) or not (return 1).
-** If so, initialize the chip and tell other partners in crime they
-** have work to do.
-*/
+ * Determine if lba should claim this chip (return 0) or not (return 1).
+ * If so, initialize the chip and tell other partners in crime they
+ * have work to do.
+ */
 static int __init
 lba_driver_probe(struct parisc_device *dev)
 {
@@ -1440,7 +1448,7 @@ lba_driver_probe(struct parisc_device *dev)
                }
 
                printk(KERN_INFO "Elroy version %s (0x%x) found at 0x%lx\n",
-                      version, func_class & 0xf, dev->hpa.start);
+                      version, func_class & 0xf, (long)dev->hpa.start);
 
                if (func_class < 2) {
                        printk(KERN_WARNING "Can't support LBA older than "
@@ -1470,17 +1478,16 @@ lba_driver_probe(struct parisc_device *dev)
                  */ 
                printk(KERN_INFO "%s version TR%d.%d (0x%x) found at 0x%lx\n",
                       IS_MERCURY(dev) ? "Mercury" : "Quicksilver", major,
-                      minor, func_class, dev->hpa.start);
+                      minor, func_class, (long)dev->hpa.start);
 
                cfg_ops = &mercury_cfg_ops;
        } else {
-               printk(KERN_ERR "Unknown LBA found at 0x%lx\n", dev->hpa.start);
+               printk(KERN_ERR "Unknown LBA found at 0x%lx\n",
+                       (long)dev->hpa.start);
                return -ENODEV;
        }
 
-       /*
-       ** Tell I/O SAPIC driver we have a IRQ handler/region.
-       */
+       /* Tell I/O SAPIC driver we have a IRQ handler/region. */
        tmp_obj = iosapic_register(dev->hpa.start + LBA_IOSAPIC_BASE);
 
        /* NOTE: PCI devices (e.g. 103c:1005 graphics card) which don't
@@ -1529,16 +1536,17 @@ lba_driver_probe(struct parisc_device *dev)
                lba_legacy_resources(dev, lba_dev);
        }
 
-       /* 
-       ** Tell PCI support another PCI bus was found.
-       ** Walks PCI bus for us too.
-       */
+       if (lba_dev->hba.bus_num.start < lba_next_bus)
+               lba_dev->hba.bus_num.start = lba_next_bus;
+
        dev->dev.platform_data = lba_dev;
        lba_bus = lba_dev->hba.hba_bus =
                pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start,
                                cfg_ops, NULL);
-       if (lba_bus)
+       if (lba_bus) {
+               lba_next_bus = lba_bus->subordinate + 1;
                pci_bus_add_devices(lba_bus);
+       }
 
        /* This is in lieu of calling pci_assign_unassigned_resources() */
        if (is_pdc_pat()) {
index 9a731c101d102ed11305372a6416b9b92ac3d76c..d190c05d87edf3e8b598dd74576704eafad6bcbf 100644 (file)
@@ -66,8 +66,8 @@ static char lcd_text_default[32]  __read_mostly;
 
 
 static struct workqueue_struct *led_wq;
-static void led_work_func(void *);
-static DECLARE_WORK(led_task, led_work_func, NULL);
+static void led_work_func(struct work_struct *);
+static DECLARE_DELAYED_WORK(led_task, led_work_func);
 
 #if 0
 #define DPRINTK(x)     printk x
@@ -136,7 +136,7 @@ static int start_task(void)
 
        /* Create the work queue and queue the LED task */
        led_wq = create_singlethread_workqueue("led_wq");       
-       queue_work(led_wq, &led_task);
+       queue_delayed_work(led_wq, &led_task, 0);
 
        return 0;
 }
@@ -441,7 +441,7 @@ static __inline__ int led_get_diskio_activity(void)
 
 #define LED_UPDATE_INTERVAL (1 + (HZ*19/1000))
 
-static void led_work_func (void *unused)
+static void led_work_func (struct work_struct *unused)
 {
        static unsigned long last_jiffies;
        static unsigned long count_HZ; /* counter in range 0..HZ */
@@ -588,7 +588,7 @@ int __init register_led_driver(int model, unsigned long cmd_reg, unsigned long d
 
        /* Ensure the work is queued */
        if (led_wq) {
-               queue_work(led_wq, &led_task);
+               queue_delayed_work(led_wq, &led_task, 0);
        }
 
        return 0;
@@ -629,7 +629,7 @@ void __init register_led_regions(void)
    ** avoid a race condition while writing the CMD/DATA register pair.
    **
  */
-int lcd_print( char *str )
+int lcd_print( const char *str )
 {
        int i;
 
@@ -658,7 +658,7 @@ int lcd_print( char *str )
        
        /* re-queue the work */
        if (led_wq) {
-               queue_work(led_wq, &led_task);
+               queue_delayed_work(led_wq, &led_task, 0);
        }
 
        return lcd_info.lcd_width;
index 97e9dc066f95fc278cbc34bc1e49753bbf2f431d..6dedbdef7106518ba583eb72bd81f70bd130bb6e 100644 (file)
@@ -2,7 +2,7 @@
  * linux/drivers/parisc/power.c
  * HP PARISC soft power switch support driver
  *
- * Copyright (c) 2001-2005 Helge Deller <deller@gmx.de>
+ * Copyright (c) 2001-2007 Helge Deller <deller@gmx.de>
  * All rights reserved.
  *
  *
@@ -29,7 +29,6 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  *
  *
- * 
  *  HINT:
  *  Support of the soft power switch button may be enabled or disabled at
  *  runtime through the "/proc/sys/kernel/power" procfs entry.
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/string.h>
 #include <linux/notifier.h>
 #include <linux/reboot.h>
 #include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/workqueue.h>
+#include <linux/kthread.h>
 
 #include <asm/pdc.h>
 #include <asm/io.h>
 #include <asm/led.h>
-#include <asm/uaccess.h>
 
+#define DRIVER_NAME  "powersw"
+#define KTHREAD_NAME "kpowerswd"
 
-#ifdef DEBUG
-# define DPRINTK(x...) printk(x)
-#else
-# define DPRINTK(x...)
-#endif
-
-
-/* filename in /proc which can be used to enable/disable the power switch */
-#define SYSCTL_FILENAME                "sys/kernel/power"
+/* how often should the power button be polled ? */
+#define POWERSWITCH_POLL_PER_SEC 2
 
+/* how long does the power button needs to be down until we react ? */
+#define POWERSWITCH_DOWN_SEC 2
 
+/* assembly code to access special registers */
+/* taken from PCXL ERS page 82 */
 #define DIAG_CODE(code)                (0x14000000 + ((code)<<5))
 
-/* this will go to processor.h or any other place... */
-/* taken from PCXL ERS page 82 */
 #define MFCPU_X(rDiagReg, t_ch, t_th, code) \
        (DIAG_CODE(code) + ((rDiagReg)<<21) + ((t_ch)<<16) + ((t_th)<<0) )
        
 #define __getDIAG(dr) ( {                      \
         register unsigned long __res asm("r28");\
         __asm__ __volatile__ (                 \
-               ".word %1\n nop\n" : "=&r" (__res) : "i" (MFCPU_T(dr,28)) \
+               ".word %1" : "=&r" (__res) : "i" (MFCPU_T(dr,28) ) \
        );                                      \
        __res;                                  \
 } )
 
-
-static void deferred_poweroff(void *dummy)
-{
-       if (kill_cad_pid(SIGINT, 1)) {
-               /* just in case killing init process failed */
-               machine_power_off();
-       }
-}
-
-/*
- * This function gets called from interrupt context.
- * As it's called within an interrupt, it wouldn't sync if we don't
- * use schedule_work().
- */
-
-static DECLARE_WORK(poweroff_work, deferred_poweroff, NULL);
-
-static void poweroff(void)
-{
-       static int powering_off __read_mostly;
-
-       if (powering_off)
-               return;
-
-       powering_off++;
-       schedule_work(&poweroff_work);
-}
-
-
-/* local time-counter for shutdown */
+/* local shutdown counter */
 static int shutdown_timer __read_mostly;
 
 /* check, give feedback and start shutdown after one second */
 static void process_shutdown(void)
 {
        if (shutdown_timer == 0)
-               DPRINTK(KERN_INFO "Shutdown requested...\n");
+               printk(KERN_ALERT KTHREAD_NAME ": Shutdown requested...\n");
 
        shutdown_timer++;
        
        /* wait until the button was pressed for 1 second */
-       if (shutdown_timer == HZ) {
-#if defined (DEBUG) || defined(CONFIG_CHASSIS_LCD_LED)
-               static char msg[] = "Shutting down...";
-#endif
-               DPRINTK(KERN_INFO "%s\n", msg);
+       if (shutdown_timer == (POWERSWITCH_DOWN_SEC*POWERSWITCH_POLL_PER_SEC)) {
+               static const char msg[] = "Shutting down...";
+               printk(KERN_INFO KTHREAD_NAME ": %s\n", msg);
                lcd_print(msg);
-               poweroff();
+
+               /* send kill signal */
+               if (kill_cad_pid(SIGINT, 1)) {
+                       /* just in case killing init process failed */
+                       if (pm_power_off)
+                               pm_power_off();
+               }
        }
 }
 
 
-/* main power switch tasklet struct (scheduled from time.c) */
-DECLARE_TASKLET_DISABLED(power_tasklet, NULL, 0);
+/* main power switch task struct */
+static struct task_struct *power_task;
+
+/* filename in /proc which can be used to enable/disable the power switch */
+#define SYSCTL_FILENAME        "sys/kernel/power"
 
 /* soft power switch enabled/disabled */
 int pwrsw_enabled __read_mostly = 1;
 
-/*
- * On gecko style machines (e.g. 712/xx and 715/xx) 
- * the power switch status is stored in Bit 0 ("the highest bit")
- * of CPU diagnose register 25.
- * 
- */
-static void gecko_tasklet_func(unsigned long unused)
+/* main kernel thread worker. It polls the button state */
+static int kpowerswd(void *param)
 {
-       if (unlikely(!pwrsw_enabled))
-               return;
-
-       if (__getDIAG(25) & 0x80000000) {
-               /* power switch button not pressed or released again */
-               /* Warning: Some machines do never reset this DIAG flag! */
-               shutdown_timer = 0;
-       } else {
-               process_shutdown();
-       }
-}
-
+       __set_current_state(TASK_RUNNING);
+
+       do {
+               int button_not_pressed;
+               unsigned long soft_power_reg = (unsigned long) param;
+
+               schedule_timeout_interruptible(pwrsw_enabled ? HZ : HZ/POWERSWITCH_POLL_PER_SEC);
+               __set_current_state(TASK_RUNNING);
+
+               if (unlikely(!pwrsw_enabled))
+                       continue;
+
+               if (soft_power_reg) {
+                       /*
+                        * Non-Gecko-style machines:
+                        * Check the power switch status which is read from the
+                        * real I/O location at soft_power_reg.
+                        * Bit 31 ("the lowest bit) is the status of the power switch.
+                        * This bit is "1" if the button is NOT pressed.
+                        */
+                       button_not_pressed = (gsc_readl(soft_power_reg) & 0x1);
+               } else {
+                       /*
+                        * On gecko style machines (e.g. 712/xx and 715/xx) 
+                        * the power switch status is stored in Bit 0 ("the highest bit")
+                        * of CPU diagnose register 25.
+                        * Warning: Some machines never reset the DIAG flag, even if
+                        * the button has been released again.
+                        */
+                       button_not_pressed = (__getDIAG(25) & 0x80000000);
+               }
+
+               if (likely(button_not_pressed)) {
+                       if (unlikely(shutdown_timer && /* avoid writing if not necessary */
+                               shutdown_timer < (POWERSWITCH_DOWN_SEC*POWERSWITCH_POLL_PER_SEC))) {
+                               shutdown_timer = 0;
+                               printk(KERN_INFO KTHREAD_NAME ": Shutdown request aborted.\n");
+                       }
+               } else
+                       process_shutdown();
+
+
+       } while (!kthread_should_stop());
 
-
-/*
- * Check the power switch status which is read from the
- * real I/O location at soft_power_reg.
- * Bit 31 ("the lowest bit) is the status of the power switch.
- */
-
-static void polling_tasklet_func(unsigned long soft_power_reg)
-{
-        unsigned long current_status;
-       
-       if (unlikely(!pwrsw_enabled))
-               return;
-
-       current_status = gsc_readl(soft_power_reg);
-       if (current_status & 0x1) {
-               /* power switch button not pressed */
-               shutdown_timer = 0;
-       } else {
-               process_shutdown();
-       }
+       return 0;
 }
 
 
@@ -220,7 +197,7 @@ static struct notifier_block parisc_panic_block = {
 static int __init power_init(void)
 {
        unsigned long ret;
-       unsigned long soft_power_reg = 0;
+       unsigned long soft_power_reg;
 
 #if 0
        request_irq( IRQ_FROM_REGION(CPU_IRQ_REGION)+2, &powerfail_interrupt,
@@ -235,44 +212,44 @@ static int __init power_init(void)
                soft_power_reg = -1UL;
        
        switch (soft_power_reg) {
-       case 0:         printk(KERN_INFO "Gecko-style soft power switch enabled.\n");
-                       power_tasklet.func = gecko_tasklet_func;
+       case 0:         printk(KERN_INFO DRIVER_NAME ": Gecko-style soft power switch enabled.\n");
                        break;
                        
-       case -1UL:      printk(KERN_INFO "Soft power switch support not available.\n");
+       case -1UL:      printk(KERN_INFO DRIVER_NAME ": Soft power switch support not available.\n");
                        return -ENODEV;
        
-       default:        printk(KERN_INFO "Soft power switch enabled, polling @ 0x%08lx.\n",
+       default:        printk(KERN_INFO DRIVER_NAME ": Soft power switch at 0x%08lx enabled.\n",
                                soft_power_reg);
-                       power_tasklet.data = soft_power_reg;
-                       power_tasklet.func = polling_tasklet_func;
+       }
+
+       power_task = kthread_run(kpowerswd, (void*)soft_power_reg, KTHREAD_NAME);
+       if (IS_ERR(power_task)) {
+               printk(KERN_ERR DRIVER_NAME ": thread creation failed.  Driver not loaded.\n");
+               pdc_soft_power_button(0);
+               return -EIO;
        }
 
        /* Register a call for panic conditions. */
        atomic_notifier_chain_register(&panic_notifier_list,
                        &parisc_panic_block);
 
-       tasklet_enable(&power_tasklet);
-
        return 0;
 }
 
 static void __exit power_exit(void)
 {
-       if (!power_tasklet.func)
-               return;
+       kthread_stop(power_task);
 
-       tasklet_disable(&power_tasklet);
        atomic_notifier_chain_unregister(&panic_notifier_list,
                        &parisc_panic_block);
-       power_tasklet.func = NULL;
+
        pdc_soft_power_button(0);
 }
 
-module_init(power_init);
+arch_initcall(power_init);
 module_exit(power_exit);
 
 
-MODULE_AUTHOR("Helge Deller");
+MODULE_AUTHOR("Helge Deller <deller@gmx.de>");
 MODULE_DESCRIPTION("Soft power switch driver");
 MODULE_LICENSE("Dual BSD/GPL");
index 76a29dadd519d79c7f1a6d04c57529cb38c5fead..322957ac2ad1d2c03bda2139641838d4a88fcd4e 100644 (file)
@@ -109,7 +109,7 @@ static unsigned long piranha_bad_128k = 0;
 
 #ifdef SBA_AGP_SUPPORT
 static int sba_reserve_agpgart = 1;
-module_param(sba_reserve_agpgart, int, 1);
+module_param(sba_reserve_agpgart, int, 0444);
 MODULE_PARM_DESC(sba_reserve_agpgart, "Reserve half of IO pdir as AGPGART");
 #endif
 
@@ -846,7 +846,7 @@ static void *sba_alloc_consistent(struct device *hwdev, size_t size,
        if (!hwdev) {
                /* only support PCI */
                *dma_handle = 0;
-               return 0;
+               return NULL;
        }
 
         ret = (void *) __get_free_pages(gfp, get_order(size));
index b61c17b3e298a8f3f81121a1d46e207cc7ace60a..3de2623afa13b39815690686c6141a4cfa40a74b 100644 (file)
@@ -1546,7 +1546,7 @@ static void __devinit detect_and_report_smsc (void)
 }
 #endif /* CONFIG_PARPORT_PC_SUPERIO */
 
-static int __devinit get_superio_dma (struct parport *p)
+static int get_superio_dma (struct parport *p)
 {
        int i=0;
        while( (superios[i].io != p->base) && (i<NR_SUPERIOS))
@@ -2106,7 +2106,7 @@ static int parport_irq_probe(struct parport *pb)
 /* --- DMA detection -------------------------------------- */
 
 /* Only if chipset conforms to ECP ISA Interface Standard */
-static int __devinit programmable_dma_support (struct parport *p)
+static int programmable_dma_support (struct parport *p)
 {
        unsigned char oecr = inb (ECONTROL (p));
        int dma;
@@ -2123,7 +2123,7 @@ static int __devinit programmable_dma_support (struct parport *p)
        return dma;
 }
 
-static int __devinit parport_dma_probe (struct parport *p)
+static int parport_dma_probe (struct parport *p)
 {
        const struct parport_pc_private *priv = p->private_data;
        if (priv->ecr)
index 68555c11f55614f8e312a5eb00bc10b18a5a7dca..01869b1782e4c460affcd7d655a340f620e9e7a8 100644 (file)
@@ -38,6 +38,36 @@ static int msi_cache_init(void)
        return 0;
 }
 
+static void msi_set_enable(struct pci_dev *dev, int enable)
+{
+       int pos;
+       u16 control;
+
+       pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+       if (pos) {
+               pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
+               control &= ~PCI_MSI_FLAGS_ENABLE;
+               if (enable)
+                       control |= PCI_MSI_FLAGS_ENABLE;
+               pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
+       }
+}
+
+static void msix_set_enable(struct pci_dev *dev, int enable)
+{
+       int pos;
+       u16 control;
+
+       pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+       if (pos) {
+               pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
+               control &= ~PCI_MSIX_FLAGS_ENABLE;
+               if (enable)
+                       control |= PCI_MSIX_FLAGS_ENABLE;
+               pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
+       }
+}
+
 static void msi_set_mask_bit(unsigned int irq, int flag)
 {
        struct msi_desc *entry;
@@ -55,6 +85,8 @@ static void msi_set_mask_bit(unsigned int irq, int flag)
                        mask_bits &= ~(1);
                        mask_bits |= flag;
                        pci_write_config_dword(entry->dev, pos, mask_bits);
+               } else {
+                       msi_set_enable(entry->dev, !flag);
                }
                break;
        case PCI_CAP_ID_MSIX:
@@ -192,44 +224,6 @@ static struct msi_desc* alloc_msi_entry(void)
        return entry;
 }
 
-static void enable_msi_mode(struct pci_dev *dev, int pos, int type)
-{
-       u16 control;
-
-       pci_read_config_word(dev, msi_control_reg(pos), &control);
-       if (type == PCI_CAP_ID_MSI) {
-               /* Set enabled bits to single MSI & enable MSI_enable bit */
-               msi_enable(control, 1);
-               pci_write_config_word(dev, msi_control_reg(pos), control);
-               dev->msi_enabled = 1;
-       } else {
-               msix_enable(control);
-               pci_write_config_word(dev, msi_control_reg(pos), control);
-               dev->msix_enabled = 1;
-       }
-
-       pci_intx(dev, 0);  /* disable intx */
-}
-
-void disable_msi_mode(struct pci_dev *dev, int pos, int type)
-{
-       u16 control;
-
-       pci_read_config_word(dev, msi_control_reg(pos), &control);
-       if (type == PCI_CAP_ID_MSI) {
-               /* Set enabled bits to single MSI & enable MSI_enable bit */
-               msi_disable(control);
-               pci_write_config_word(dev, msi_control_reg(pos), control);
-               dev->msi_enabled = 0;
-       } else {
-               msix_disable(control);
-               pci_write_config_word(dev, msi_control_reg(pos), control);
-               dev->msix_enabled = 0;
-       }
-
-       pci_intx(dev, 1);  /* enable intx */
-}
-
 #ifdef CONFIG_PM
 static int __pci_save_msi_state(struct pci_dev *dev)
 {
@@ -238,12 +232,11 @@ static int __pci_save_msi_state(struct pci_dev *dev)
        struct pci_cap_saved_state *save_state;
        u32 *cap;
 
-       pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
-       if (pos <= 0 || dev->no_msi)
+       if (!dev->msi_enabled)
                return 0;
 
-       pci_read_config_word(dev, msi_control_reg(pos), &control);
-       if (!(control & PCI_MSI_FLAGS_ENABLE))
+       pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+       if (pos <= 0)
                return 0;
 
        save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u32) * 5,
@@ -276,13 +269,18 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
        struct pci_cap_saved_state *save_state;
        u32 *cap;
 
+       if (!dev->msi_enabled)
+               return;
+
        save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSI);
        pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
        if (!save_state || pos <= 0)
                return;
        cap = &save_state->data[0];
 
+       pci_intx(dev, 0);               /* disable intx */
        control = cap[i++] >> 16;
+       msi_set_enable(dev, 0);
        pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, cap[i++]);
        if (control & PCI_MSI_FLAGS_64BIT) {
                pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, cap[i++]);
@@ -292,7 +290,6 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
        if (control & PCI_MSI_FLAGS_MASKBIT)
                pci_write_config_dword(dev, pos + PCI_MSI_MASK_BIT, cap[i++]);
        pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
-       enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
        pci_remove_saved_cap(save_state);
        kfree(save_state);
 }
@@ -308,13 +305,11 @@ static int __pci_save_msix_state(struct pci_dev *dev)
                return 0;
 
        pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
-       if (pos <= 0 || dev->no_msi)
+       if (pos <= 0)
                return 0;
 
        /* save the capability */
        pci_read_config_word(dev, msi_control_reg(pos), &control);
-       if (!(control & PCI_MSIX_FLAGS_ENABLE))
-               return 0;
        save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u16),
                GFP_KERNEL);
        if (!save_state) {
@@ -376,6 +371,8 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
                return;
 
        /* route the table */
+       pci_intx(dev, 0);               /* disable intx */
+       msix_set_enable(dev, 0);
        irq = head = dev->first_msi_irq;
        while (head != tail) {
                entry = get_irq_msi(irq);
@@ -386,7 +383,6 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
        }
 
        pci_write_config_word(dev, msi_control_reg(pos), save);
-       enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
 }
 
 void pci_restore_msi_state(struct pci_dev *dev)
@@ -411,6 +407,8 @@ static int msi_capability_init(struct pci_dev *dev)
        int pos, irq;
        u16 control;
 
+       msi_set_enable(dev, 0); /* Ensure msi is disabled as I set it up */
+
        pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
        pci_read_config_word(dev, msi_control_reg(pos), &control);
        /* MSI Entry Initialization */
@@ -454,7 +452,9 @@ static int msi_capability_init(struct pci_dev *dev)
        set_irq_msi(irq, entry);
 
        /* Set MSI enabled bits  */
-       enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
+       pci_intx(dev, 0);               /* disable intx */
+       msi_set_enable(dev, 1);
+       dev->msi_enabled = 1;
 
        dev->irq = irq;
        return 0;
@@ -481,6 +481,8 @@ static int msix_capability_init(struct pci_dev *dev,
        u8 bir;
        void __iomem *base;
 
+       msix_set_enable(dev, 0);/* Ensure msix is disabled as I set it up */
+
        pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
        /* Request & Map MSI-X table region */
        pci_read_config_word(dev, msi_control_reg(pos), &control);
@@ -549,7 +551,9 @@ static int msix_capability_init(struct pci_dev *dev,
        }
        dev->first_msi_irq = entries[0].vector;
        /* Set MSI-X enabled bits */
-       enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
+       pci_intx(dev, 0);               /* disable intx */
+       msix_set_enable(dev, 1);
+       dev->msix_enabled = 1;
 
        return 0;
 }
@@ -611,12 +615,11 @@ int pci_enable_msi(struct pci_dev* dev)
        WARN_ON(!!dev->msi_enabled);
 
        /* Check whether driver already requested for MSI-X irqs */
-       pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
-       if (pos > 0 && dev->msix_enabled) {
-                       printk(KERN_INFO "PCI: %s: Can't enable MSI.  "
-                              "Device already has MSI-X enabled\n",
-                              pci_name(dev));
-                       return -EINVAL;
+       if (dev->msix_enabled) {
+               printk(KERN_INFO "PCI: %s: Can't enable MSI.  "
+                       "Device already has MSI-X enabled\n",
+                       pci_name(dev));
+               return -EINVAL;
        }
        status = msi_capability_init(dev);
        return status;
@@ -625,8 +628,7 @@ int pci_enable_msi(struct pci_dev* dev)
 void pci_disable_msi(struct pci_dev* dev)
 {
        struct msi_desc *entry;
-       int pos, default_irq;
-       u16 control;
+       int default_irq;
 
        if (!pci_msi_enable)
                return;
@@ -636,16 +638,9 @@ void pci_disable_msi(struct pci_dev* dev)
        if (!dev->msi_enabled)
                return;
 
-       pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
-       if (!pos)
-               return;
-
-       pci_read_config_word(dev, msi_control_reg(pos), &control);
-       if (!(control & PCI_MSI_FLAGS_ENABLE))
-               return;
-
-
-       disable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
+       msi_set_enable(dev, 0);
+       pci_intx(dev, 1);               /* enable intx */
+       dev->msi_enabled = 0;
 
        entry = get_irq_msi(dev->first_msi_irq);
        if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) {
@@ -746,8 +741,7 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
        WARN_ON(!!dev->msix_enabled);
 
        /* Check whether driver already requested for MSI irq */
-       if (pci_find_capability(dev, PCI_CAP_ID_MSI) > 0 &&
-               dev->msi_enabled) {
+       if (dev->msi_enabled) {
                printk(KERN_INFO "PCI: %s: Can't enable MSI-X.  "
                       "Device already has an MSI irq assigned\n",
                       pci_name(dev));
@@ -760,8 +754,6 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
 void pci_disable_msix(struct pci_dev* dev)
 {
        int irq, head, tail = 0, warning = 0;
-       int pos;
-       u16 control;
 
        if (!pci_msi_enable)
                return;
@@ -771,15 +763,9 @@ void pci_disable_msix(struct pci_dev* dev)
        if (!dev->msix_enabled)
                return;
 
-       pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
-       if (!pos)
-               return;
-
-       pci_read_config_word(dev, msi_control_reg(pos), &control);
-       if (!(control & PCI_MSIX_FLAGS_ENABLE))
-               return;
-
-       disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
+       msix_set_enable(dev, 0);
+       pci_intx(dev, 1);               /* enable intx */
+       dev->msix_enabled = 0;
 
        irq = head = dev->first_msi_irq;
        while (head != tail) {
index 1e74e1ee8bd89a4f90c4579e50dc033eace44028..a32db0628157126bd7c93f0860fd8d70c69e5640 100644 (file)
@@ -757,7 +757,8 @@ int pci_enable_device(struct pci_dev *dev)
  * when a device is enabled using managed PCI device enable interface.
  */
 struct pci_devres {
-       unsigned int disable:1;
+       unsigned int enabled:1;
+       unsigned int pinned:1;
        unsigned int orig_intx:1;
        unsigned int restore_intx:1;
        u32 region_mask;
@@ -781,7 +782,7 @@ static void pcim_release(struct device *gendev, void *res)
        if (this->restore_intx)
                pci_intx(dev, this->orig_intx);
 
-       if (this->disable)
+       if (this->enabled && !this->pinned)
                pci_disable_device(dev);
 }
 
@@ -820,12 +821,12 @@ int pcim_enable_device(struct pci_dev *pdev)
        dr = get_pci_dr(pdev);
        if (unlikely(!dr))
                return -ENOMEM;
-       WARN_ON(!!dr->disable);
+       WARN_ON(!!dr->enabled);
 
        rc = pci_enable_device(pdev);
        if (!rc) {
                pdev->is_managed = 1;
-               dr->disable = 1;
+               dr->enabled = 1;
        }
        return rc;
 }
@@ -843,9 +844,9 @@ void pcim_pin_device(struct pci_dev *pdev)
        struct pci_devres *dr;
 
        dr = find_pci_dr(pdev);
-       WARN_ON(!dr || !dr->disable);
+       WARN_ON(!dr || !dr->enabled);
        if (dr)
-               dr->disable = 0;
+               dr->pinned = 1;
 }
 
 /**
@@ -876,18 +877,11 @@ pci_disable_device(struct pci_dev *dev)
 
        dr = find_pci_dr(dev);
        if (dr)
-               dr->disable = 0;
+               dr->enabled = 0;
 
        if (atomic_sub_return(1, &dev->enable_cnt) != 0)
                return;
 
-       if (dev->msi_enabled)
-               disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI),
-                       PCI_CAP_ID_MSI);
-       if (dev->msix_enabled)
-               disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI),
-                       PCI_CAP_ID_MSIX);
-
        pci_read_config_word(dev, PCI_COMMAND, &pci_command);
        if (pci_command & PCI_COMMAND_MASTER) {
                pci_command &= ~PCI_COMMAND_MASTER;
@@ -1277,6 +1271,33 @@ pci_intx(struct pci_dev *pdev, int enable)
        }
 }
 
+/**
+ * pci_msi_off - disables any msi or msix capabilities
+ * @pdev: the PCI device to operate on
+ *
+ * If you want to use msi see pci_enable_msi and friends.
+ * This is a lower level primitive that allows us to disable
+ * msi operation at the device level.
+ */
+void pci_msi_off(struct pci_dev *dev)
+{
+       int pos;
+       u16 control;
+
+       pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+       if (pos) {
+               pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
+               control &= ~PCI_MSI_FLAGS_ENABLE;
+               pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
+       }
+       pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+       if (pos) {
+               pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
+               control &= ~PCI_MSIX_FLAGS_ENABLE;
+               pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
+       }
+}
+
 #ifndef HAVE_ARCH_PCI_SET_DMA_MASK
 /*
  * These can be overridden by arch-specific implementations
index a4f2d580625e2eb685a7cb49f3557edc745611c3..ae7a975995a5a61dd9b59e419d8b81b69a4fc6c6 100644 (file)
@@ -46,10 +46,8 @@ extern struct rw_semaphore pci_bus_sem;
 extern unsigned int pci_pm_d3_delay;
 
 #ifdef CONFIG_PCI_MSI
-void disable_msi_mode(struct pci_dev *dev, int pos, int type);
 void pci_no_msi(void);
 #else
-static inline void disable_msi_mode(struct pci_dev *dev, int pos, int type) { }
 static inline void pci_no_msi(void) { }
 #endif
 
index b164de050d4f2635e129070a3eca66b31343023b..db6ad8e763ac91dd7d86a4ab55469e1e1dd8128b 100644 (file)
@@ -66,7 +66,7 @@ static struct pci_error_handlers aer_error_handlers = {
        .resume = aer_error_resume,
 };
 
-static struct pcie_port_service_driver aerdrv = {
+static struct pcie_port_service_driver aerdriver = {
        .name           = "aer",
        .id_table       = &aer_id[0],
 
@@ -328,7 +328,7 @@ static void aer_error_resume(struct pci_dev *dev)
  **/
 static int __init aer_service_init(void)
 {
-       return pcie_port_service_register(&aerdrv);
+       return pcie_port_service_register(&aerdriver);
 }
 
 /**
@@ -338,7 +338,7 @@ static int __init aer_service_init(void)
  **/
 static void __exit aer_service_exit(void)
 {
-       pcie_port_service_unregister(&aerdrv);
+       pcie_port_service_unregister(&aerdriver);
 }
 
 module_init(aer_service_init);
index f17e7ed2b2a5d8a81d169e313a3ff1514f09da95..0be5a0b307250802e40f1ed1577bf0d338621e23 100644 (file)
@@ -276,7 +276,7 @@ static struct pci_error_handlers pcie_portdrv_err_handler = {
                .resume = pcie_portdrv_err_resume,
 };
 
-static struct pci_driver pcie_portdrv = {
+static struct pci_driver pcie_portdriver = {
        .name           = (char *)device_name,
        .id_table       = &port_pci_ids[0],
 
@@ -298,7 +298,7 @@ static int __init pcie_portdrv_init(void)
                printk(KERN_WARNING "PCIE: bus_register error: %d\n", retval);
                goto out;
        }
-       retval = pci_register_driver(&pcie_portdrv);
+       retval = pci_register_driver(&pcie_portdriver);
        if (retval)
                pcie_port_bus_unregister();
  out:
@@ -307,7 +307,7 @@ static int __init pcie_portdrv_init(void)
 
 static void __exit pcie_portdrv_exit(void) 
 {
-       pci_unregister_driver(&pcie_portdrv);
+       pci_unregister_driver(&pcie_portdriver);
        pcie_port_bus_unregister();
 }
 
index 2fe1d690eb137087ac1c957c9e16f2890a962616..a4a96826d9e0e9a31057aa920bc4b9fd72683d0d 100644 (file)
@@ -682,7 +682,34 @@ static void pci_read_irq(struct pci_dev *dev)
        dev->irq = irq;
 }
 
-#define LEGACY_IO_RESOURCE     (IORESOURCE_IO | IORESOURCE_PCI_FIXED)
+static void change_legacy_io_resource(struct pci_dev * dev, unsigned index,
+                                      unsigned start, unsigned end)
+{
+       unsigned base = start & PCI_BASE_ADDRESS_IO_MASK;
+       unsigned len = (end | ~PCI_BASE_ADDRESS_IO_MASK) - base + 1;
+
+       /*
+        * Some X versions get confused when the BARs reported through
+        * /sys or /proc differ from those seen in config space, thus
+        * try to update the config space values, too.
+        */
+       if (!(pci_resource_flags(dev, index) & IORESOURCE_IO))
+               printk(KERN_WARNING "%s: cannot adjust BAR%u (not I/O)\n",
+                      pci_name(dev), index);
+       else if (pci_resource_len(dev, index) != len)
+               printk(KERN_WARNING "%s: cannot adjust BAR%u (size %04X)\n",
+                      pci_name(dev), index, (unsigned)pci_resource_len(dev, index));
+       else {
+               printk(KERN_INFO "%s: trying to change BAR%u from %04X to %04X\n",
+                      pci_name(dev), index,
+                      (unsigned)pci_resource_start(dev, index), base);
+               pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + index * 4, base);
+       }
+       pci_resource_start(dev, index) = start;
+       pci_resource_end(dev, index)   = end;
+       pci_resource_flags(dev, index) =
+               IORESOURCE_IO | IORESOURCE_PCI_FIXED | PCI_BASE_ADDRESS_SPACE_IO;
+}
 
 /**
  * pci_setup_device - fill in class and map information of a device
@@ -735,20 +762,12 @@ static int pci_setup_device(struct pci_dev * dev)
                        u8 progif;
                        pci_read_config_byte(dev, PCI_CLASS_PROG, &progif);
                        if ((progif & 1) == 0) {
-                               dev->resource[0].start = 0x1F0;
-                               dev->resource[0].end = 0x1F7;
-                               dev->resource[0].flags = LEGACY_IO_RESOURCE;
-                               dev->resource[1].start = 0x3F6;
-                               dev->resource[1].end = 0x3F6;
-                               dev->resource[1].flags = LEGACY_IO_RESOURCE;
+                               change_legacy_io_resource(dev, 0, 0x1F0, 0x1F7);
+                               change_legacy_io_resource(dev, 1, 0x3F6, 0x3F6);
                        }
                        if ((progif & 4) == 0) {
-                               dev->resource[2].start = 0x170;
-                               dev->resource[2].end = 0x177;
-                               dev->resource[2].flags = LEGACY_IO_RESOURCE;
-                               dev->resource[3].start = 0x376;
-                               dev->resource[3].end = 0x376;
-                               dev->resource[3].flags = LEGACY_IO_RESOURCE;
+                               change_legacy_io_resource(dev, 2, 0x170, 0x177);
+                               change_legacy_io_resource(dev, 3, 0x376, 0x376);
                        }
                }
                break;
index 1e6eda25c0d82c800cf260a832209ee70899d9b7..7f94fc098cd342e37bc7bad1acc770d074f46441 100644 (file)
@@ -1218,45 +1218,68 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA,     PCI_DEVICE_ID_VIA_8237, asus_hides_a
  *     do this early on to make the additional device appear during
  *     the PCI scanning.
  */
-
-static void quirk_jmicron_dualfn(struct pci_dev *pdev)
+static void quirk_jmicron_ata(struct pci_dev *pdev)
 {
-       u32 conf;
+       u32 conf1, conf5, class;
        u8 hdr;
 
        /* Only poke fn 0 */
        if (PCI_FUNC(pdev->devfn))
                return;
 
-       switch(pdev->device) {
-               case PCI_DEVICE_ID_JMICRON_JMB365:
-               case PCI_DEVICE_ID_JMICRON_JMB366:
-                       /* Redirect IDE second PATA port to the right spot */
-                       pci_read_config_dword(pdev, 0x80, &conf);
-                       conf |= (1 << 24);
-                       /* Fall through */
-                       pci_write_config_dword(pdev, 0x80, conf);
-               case PCI_DEVICE_ID_JMICRON_JMB361:
-               case PCI_DEVICE_ID_JMICRON_JMB363:
-                       pci_read_config_dword(pdev, 0x40, &conf);
-                       /* Enable dual function mode, AHCI on fn 0, IDE fn1 */
-                       /* Set the class codes correctly and then direct IDE 0 */
-                       conf &= ~0x000FF200; /* Clear bit 9 and 12-19 */
-                       conf |=  0x00C2A102; /* Set 1, 8, 13, 15, 17, 22, 23 */
-                       pci_write_config_dword(pdev, 0x40, conf);
-
-                       /* Reconfigure so that the PCI scanner discovers the
-                          device is now multifunction */
-
-                       pci_read_config_byte(pdev, PCI_HEADER_TYPE, &hdr);
-                       pdev->hdr_type = hdr & 0x7f;
-                       pdev->multifunction = !!(hdr & 0x80);
+       pci_read_config_dword(pdev, 0x40, &conf1);
+       pci_read_config_dword(pdev, 0x80, &conf5);
 
-                       break;
+       conf1 &= ~0x00CFF302; /* Clear bit 1, 8, 9, 12-19, 22, 23 */
+       conf5 &= ~(1 << 24);  /* Clear bit 24 */
+
+       switch (pdev->device) {
+       case PCI_DEVICE_ID_JMICRON_JMB360:
+               /* The controller should be in single function ahci mode */
+               conf1 |= 0x0002A100; /* Set 8, 13, 15, 17 */
+               break;
+
+       case PCI_DEVICE_ID_JMICRON_JMB365:
+       case PCI_DEVICE_ID_JMICRON_JMB366:
+               /* Redirect IDE second PATA port to the right spot */
+               conf5 |= (1 << 24);
+               /* Fall through */
+       case PCI_DEVICE_ID_JMICRON_JMB361:
+       case PCI_DEVICE_ID_JMICRON_JMB363:
+               /* Enable dual function mode, AHCI on fn 0, IDE fn1 */
+               /* Set the class codes correctly and then direct IDE 0 */
+               conf1 |= 0x00C2A102; /* Set 1, 8, 13, 15, 17, 22, 23 */
+               break;
+
+       case PCI_DEVICE_ID_JMICRON_JMB368:
+               /* The controller should be in single function IDE mode */
+               conf1 |= 0x00C00000; /* Set 22, 23 */
+               break;
        }
-}
-DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, quirk_jmicron_dualfn);
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, quirk_jmicron_dualfn);
+
+       pci_write_config_dword(pdev, 0x40, conf1);
+       pci_write_config_dword(pdev, 0x80, conf5);
+
+       /* Update pdev accordingly */
+       pci_read_config_byte(pdev, PCI_HEADER_TYPE, &hdr);
+       pdev->hdr_type = hdr & 0x7f;
+       pdev->multifunction = !!(hdr & 0x80);
+
+       pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class);
+       pdev->class = class >> 8;
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB360, quirk_jmicron_ata);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, quirk_jmicron_ata);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, quirk_jmicron_ata);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, quirk_jmicron_ata);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, quirk_jmicron_ata);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, quirk_jmicron_ata);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB360, quirk_jmicron_ata);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, quirk_jmicron_ata);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, quirk_jmicron_ata);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, quirk_jmicron_ata);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, quirk_jmicron_ata);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, quirk_jmicron_ata);
 
 #endif
 
@@ -1415,8 +1438,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,      PCI_DEVICE_ID_INTEL_E7525_MCH,  quir
  */
 static void __devinit quirk_pcie_pxh(struct pci_dev *dev)
 {
-       disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI),
-                                       PCI_CAP_ID_MSI);
+       pci_msi_off(dev);
+
        dev->no_msi = 1;
 
        printk(KERN_WARNING "PCI: PXH quirk detected, "
index ff98eaddaa73868777ae19564122c5bff4d0cd3e..2dd8681d6b312a3b6c3c2362315dadddf9bf1de5 100644 (file)
@@ -15,7 +15,7 @@
 
 DECLARE_RWSEM(pci_bus_sem);
 
-static struct pci_bus * __devinit
+static struct pci_bus *
 pci_do_find_bus(struct pci_bus* bus, unsigned char busnr)
 {
        struct pci_bus* child;
index caca0dc9d30f74f4d05adc50444e927a48e202a9..f2e810f53c81ca67b172e7b4789b60d9b2d3b473 100644 (file)
@@ -907,7 +907,7 @@ static int __init init_hs(void)
 
        for (i=0; i<HS_MAX_SOCKETS; i++) {
                unsigned int ret;
-               hs_sockets[i].socket.dev.dev = &hd64465_device.dev;             
+               hs_sockets[i].socket.dev.parent = &hd64465_device.dev;
                hs_sockets[i].number = i;
                ret = pcmcia_register_socket(&hs_sockets[i].socket);
                if (ret && i)
index e4a94108aab9578b0897510c6bc6e9a5196e1b5a..91da15b5a81ea0e3df861a7923fae76b9538faea 100644 (file)
@@ -760,7 +760,7 @@ static int __init init_m32r_pcc(void)
        /* Set up interrupt handler(s) */
 
        for (i = 0 ; i < pcc_sockets ; i++) {
-               socket[i].socket.dev.dev = &pcc_device.dev;
+               socket[i].socket.dev.parent = &pcc_device.dev;
                socket[i].socket.ops = &pcc_operations;
                socket[i].socket.resource_ops = &pccard_nonstatic_ops;
                socket[i].socket.owner = THIS_MODULE;
index d059c9196172330ca02b307bc6ea51236fa73f0b..9721ed7bf5023e704726af89073a51e9e54a85b7 100644 (file)
@@ -1321,7 +1321,7 @@ static int __init m8xx_init(void)
                socket[i].socket.ops = &m8xx_services;
                socket[i].socket.resource_ops = &pccard_iodyn_ops;
                socket[i].socket.cb_dev = NULL;
-               socket[i].socket.dev.dev = &m8xx_device.dev;
+               socket[i].socket.dev.parent = &m8xx_device.dev;
        }
 
        for (i = 0; i < PCMCIA_SOCKETS_NO; i++)
index 76f7cbc62a8b95311ccc52ad610b45fecb39ff79..d77f75129f8ab1fde2cd090c2db0c4e926fc920e 100644 (file)
@@ -291,7 +291,7 @@ static int __devinit omap_cf_probe(struct device *dev)
                omap_cf_present() ? "present" : "(not present)");
 
        cf->socket.owner = THIS_MODULE;
-       cf->socket.dev.dev = dev;
+       cf->socket.dev.parent = dev;
        cf->socket.ops = &omap_cf_ops;
        cf->socket.resource_ops = &pccard_static_ops;
        cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP
index 81dfc2cac2b4f722bd84e9cf121695ad23083099..ce2226273aaa72fa4f55b8d5d718c9014a231602 100644 (file)
@@ -232,7 +232,7 @@ static struct resource *iodyn_find_io_region(unsigned long base, int num,
                unsigned long align, struct pcmcia_socket *s)
 {
        struct resource *res = make_resource(0, num, IORESOURCE_IO,
-                                            s->dev.class_id);
+                                            s->dev.bus_id);
        struct pcmcia_align_data data;
        unsigned long min = base;
        int ret;
index 206e26c918076bd578497429b7c1788997a0f661..eee2f1cb213c76e35726b6c09df0eed9d6db060e 100644 (file)
@@ -596,7 +596,7 @@ static int __devinit vrc4171_add_sockets(void)
                }
 
                sprintf(socket->name, "NEC VRC4171 Card Slot %1c", 'A' + slot);
-               socket->pcmcia_socket.dev.dev = &vrc4171_card_device.dev;
+               socket->pcmcia_socket.dev.parent = &vrc4171_card_device.dev;
                socket->pcmcia_socket.ops = &vrc4171_pccard_operations;
                socket->pcmcia_socket.owner = THIS_MODULE;
 
index 7a535542fe9204a0bb5336f0e0c7894c38726f3e..118ac9779b3cf5bffc479a0ded1ba55db3e92da7 100644 (file)
@@ -89,6 +89,7 @@ pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, u32 gsi,
                return;
 
        res->irq_resource[i].flags = IORESOURCE_IRQ;  // Also clears _UNSET flag
+       res->irq_resource[i].flags |= irq_flags(triggering, polarity);
        irq = acpi_register_gsi(gsi, triggering, polarity);
        if (irq < 0) {
                res->irq_resource[i].flags |= IORESOURCE_DISABLED;
@@ -103,8 +104,52 @@ pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, u32 gsi,
        pcibios_penalize_isa_irq(irq, 1);
 }
 
+static int dma_flags(int type, int bus_master, int transfer)
+{
+       int flags = 0;
+
+       if (bus_master)
+               flags |= IORESOURCE_DMA_MASTER;
+       switch (type) {
+       case ACPI_COMPATIBILITY:
+               flags |= IORESOURCE_DMA_COMPATIBLE;
+               break;
+       case ACPI_TYPE_A:
+               flags |= IORESOURCE_DMA_TYPEA;
+               break;
+       case ACPI_TYPE_B:
+               flags |= IORESOURCE_DMA_TYPEB;
+               break;
+       case ACPI_TYPE_F:
+               flags |= IORESOURCE_DMA_TYPEF;
+               break;
+       default:
+               /* Set a default value ? */
+               flags |= IORESOURCE_DMA_COMPATIBLE;
+               pnp_err("Invalid DMA type");
+       }
+       switch (transfer) {
+       case ACPI_TRANSFER_8:
+               flags |= IORESOURCE_DMA_8BIT;
+               break;
+       case ACPI_TRANSFER_8_16:
+               flags |= IORESOURCE_DMA_8AND16BIT;
+               break;
+       case ACPI_TRANSFER_16:
+               flags |= IORESOURCE_DMA_16BIT;
+               break;
+       default:
+               /* Set a default value ? */
+               flags |= IORESOURCE_DMA_8AND16BIT;
+               pnp_err("Invalid DMA transfer type");
+       }
+
+       return flags;
+}
+
 static void
-pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, u32 dma)
+pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, u32 dma,
+       int type, int bus_master, int transfer)
 {
        int i = 0;
        while (i < PNP_MAX_DMA &&
@@ -112,6 +157,7 @@ pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, u32 dma)
                i++;
        if (i < PNP_MAX_DMA) {
                res->dma_resource[i].flags = IORESOURCE_DMA;  // Also clears _UNSET flag
+               res->dma_resource[i].flags |= dma_flags(type, bus_master, transfer);
                if (dma == -1) {
                        res->dma_resource[i].flags |= IORESOURCE_DISABLED;
                        return;
@@ -123,7 +169,7 @@ pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, u32 dma)
 
 static void
 pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res,
-       u64 io, u64 len)
+       u64 io, u64 len, int io_decode)
 {
        int i = 0;
        while (!(res->port_resource[i].flags & IORESOURCE_UNSET) &&
@@ -131,6 +177,8 @@ pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res,
                i++;
        if (i < PNP_MAX_PORT) {
                res->port_resource[i].flags = IORESOURCE_IO;  // Also clears _UNSET flag
+               if (io_decode == ACPI_DECODE_16)
+                       res->port_resource[i].flags |= PNP_PORT_FLAG_16BITADDR;
                if (len <= 0 || (io + len -1) >= 0x10003) {
                        res->port_resource[i].flags |= IORESOURCE_DISABLED;
                        return;
@@ -142,7 +190,7 @@ pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res,
 
 static void
 pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res,
-       u64 mem, u64 len)
+       u64 mem, u64 len, int write_protect)
 {
        int i = 0;
        while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) &&
@@ -154,6 +202,9 @@ pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res,
                        res->mem_resource[i].flags |= IORESOURCE_DISABLED;
                        return;
                }
+               if(write_protect == ACPI_READ_WRITE_MEMORY)
+                       res->mem_resource[i].flags |= IORESOURCE_MEM_WRITEABLE;
+
                res->mem_resource[i].start = mem;
                res->mem_resource[i].end = mem + len - 1;
        }
@@ -178,10 +229,11 @@ pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res_table,
 
        if (p->resource_type == ACPI_MEMORY_RANGE)
                pnpacpi_parse_allocated_memresource(res_table,
-                               p->minimum, p->address_length);
+                               p->minimum, p->address_length, p->info.mem.write_protect);
        else if (p->resource_type == ACPI_IO_RANGE)
                pnpacpi_parse_allocated_ioresource(res_table,
-                               p->minimum, p->address_length);
+                               p->minimum, p->address_length,
+                               p->granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16);
 }
 
 static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
@@ -208,13 +260,17 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
        case ACPI_RESOURCE_TYPE_DMA:
                if (res->data.dma.channel_count > 0)
                        pnpacpi_parse_allocated_dmaresource(res_table,
-                                       res->data.dma.channels[0]);
+                                       res->data.dma.channels[0],
+                                       res->data.dma.type,
+                                       res->data.dma.bus_master,
+                                       res->data.dma.transfer);
                break;
 
        case ACPI_RESOURCE_TYPE_IO:
                pnpacpi_parse_allocated_ioresource(res_table,
                                res->data.io.minimum,
-                               res->data.io.address_length);
+                               res->data.io.address_length,
+                               res->data.io.io_decode);
                break;
 
        case ACPI_RESOURCE_TYPE_START_DEPENDENT:
@@ -224,7 +280,8 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
        case ACPI_RESOURCE_TYPE_FIXED_IO:
                pnpacpi_parse_allocated_ioresource(res_table,
                                res->data.fixed_io.address,
-                               res->data.fixed_io.address_length);
+                               res->data.fixed_io.address_length,
+                               ACPI_DECODE_10);
                break;
 
        case ACPI_RESOURCE_TYPE_VENDOR:
@@ -236,17 +293,20 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
        case ACPI_RESOURCE_TYPE_MEMORY24:
                pnpacpi_parse_allocated_memresource(res_table,
                                res->data.memory24.minimum,
-                               res->data.memory24.address_length);
+                               res->data.memory24.address_length,
+                               res->data.memory24.write_protect);
                break;
        case ACPI_RESOURCE_TYPE_MEMORY32:
                pnpacpi_parse_allocated_memresource(res_table,
                                res->data.memory32.minimum,
-                               res->data.memory32.address_length);
+                               res->data.memory32.address_length,
+                               res->data.memory32.write_protect);
                break;
        case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
                pnpacpi_parse_allocated_memresource(res_table,
                                res->data.fixed_memory32.address,
-                               res->data.fixed_memory32.address_length);
+                               res->data.fixed_memory32.address_length,
+                               res->data.fixed_memory32.write_protect);
                break;
        case ACPI_RESOURCE_TYPE_ADDRESS16:
        case ACPI_RESOURCE_TYPE_ADDRESS32:
@@ -304,42 +364,8 @@ static void pnpacpi_parse_dma_option(struct pnp_option *option, struct acpi_reso
 
        for(i = 0; i < p->channel_count; i++)
                dma->map |= 1 << p->channels[i];
-       dma->flags = 0;
-       if (p->bus_master)
-               dma->flags |= IORESOURCE_DMA_MASTER;
-       switch (p->type) {
-       case ACPI_COMPATIBILITY:
-               dma->flags |= IORESOURCE_DMA_COMPATIBLE;
-               break;
-       case ACPI_TYPE_A:
-               dma->flags |= IORESOURCE_DMA_TYPEA;
-               break;
-       case ACPI_TYPE_B:
-               dma->flags |= IORESOURCE_DMA_TYPEB;
-               break;
-       case ACPI_TYPE_F:
-               dma->flags |= IORESOURCE_DMA_TYPEF;
-               break;
-       default:
-               /* Set a default value ? */
-               dma->flags |= IORESOURCE_DMA_COMPATIBLE;
-               pnp_err("Invalid DMA type");
-       }
-       switch (p->transfer) {
-       case ACPI_TRANSFER_8:
-               dma->flags |= IORESOURCE_DMA_8BIT;
-               break;
-       case ACPI_TRANSFER_8_16:
-               dma->flags |= IORESOURCE_DMA_8AND16BIT;
-               break;
-       case ACPI_TRANSFER_16:
-               dma->flags |= IORESOURCE_DMA_16BIT;
-               break;
-       default:
-               /* Set a default value ? */
-               dma->flags |= IORESOURCE_DMA_8AND16BIT;
-               pnp_err("Invalid DMA transfer type");
-       }
+
+       dma->flags = dma_flags(p->type, p->bus_master, p->transfer);
 
        pnp_register_dma_resource(option, dma);
        return;
index 4bbca500d3d212bf264ddff889da7c05b258b5f5..95826b92ca4b5d91cc83ec0c31c7beb1f0308101 100644 (file)
@@ -101,7 +101,7 @@ comment "RTC drivers"
 
 config RTC_DRV_CMOS
        tristate "PC-style 'CMOS' real time clock"
-       depends on RTC_CLASS && (X86_PC || ALPHA || ARM26 || ARM \
+       depends on RTC_CLASS && (X86 || ALPHA || ARM26 || ARM \
                || M32R || ATARI || POWERPC)
        help
          Say "yes" here to get direct support for the real time clock
@@ -207,10 +207,12 @@ config RTC_DRV_PCF8563
 
 config RTC_DRV_PCF8583
        tristate "Philips PCF8583"
-       depends on RTC_CLASS && I2C
+       depends on RTC_CLASS && I2C && ARCH_RPC
        help
-         If you say yes here you get support for the
-         Philips PCF8583 RTC chip.
+         If you say yes here you get support for the Philips PCF8583
+         RTC chip found on Acorn RiscPCs.  This driver supports the
+         platform specific method of retrieving the current year from
+         the RTC's SRAM.
 
          This driver can also be built as a module. If so, the module
          will be called rtc-pcf8583.
index 7a0d8ee2de9c9aa95f973b86dec3d5955d348798..04aaa634723467ac90cbd8bd4d41419bdfc89647 100644 (file)
@@ -113,10 +113,16 @@ EXPORT_SYMBOL_GPL(rtc_device_register);
  */
 void rtc_device_unregister(struct rtc_device *rtc)
 {
-       mutex_lock(&rtc->ops_lock);
-       rtc->ops = NULL;
-       mutex_unlock(&rtc->ops_lock);
-       class_device_unregister(&rtc->class_dev);
+       if (class_device_get(&rtc->class_dev) != NULL) {
+               mutex_lock(&rtc->ops_lock);
+               /* remove innards of this RTC, then disable it, before
+                * letting any rtc_class_open() users access it again
+                */
+               class_device_unregister(&rtc->class_dev);
+               rtc->ops = NULL;
+               mutex_unlock(&rtc->ops_lock);
+               class_device_put(&rtc->class_dev);
+       }
 }
 EXPORT_SYMBOL_GPL(rtc_device_unregister);
 
index 6f11f6dfdd9dccc699b5a1a958132d55dec5daa6..ef40df0f169d2a1039ddca745f586dd122731afa 100644 (file)
@@ -179,7 +179,7 @@ struct class_device *rtc_class_open(char *name)
        down(&rtc_class->sem);
        list_for_each_entry(class_dev_tmp, &rtc_class->children, node) {
                if (strncmp(class_dev_tmp->class_id, name, BUS_ID_SIZE) == 0) {
-                       class_dev = class_dev_tmp;
+                       class_dev = class_device_get(class_dev_tmp);
                        break;
                }
        }
@@ -197,6 +197,7 @@ EXPORT_SYMBOL_GPL(rtc_class_open);
 void rtc_class_close(struct class_device *class_dev)
 {
        module_put(to_rtc_device(class_dev)->owner);
+       class_device_put(class_dev);
 }
 EXPORT_SYMBOL_GPL(rtc_class_close);
 
index a724ab49a7973bfd474681b2d1d0680d540b27e5..ac0e68e2f025d388504c4005519d90e006496b1f 100644 (file)
@@ -164,6 +164,7 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
        tm.tm_min = alrm->time.tm_min;
        tm.tm_sec = alrm->time.tm_sec;
 
+       at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM);
        at91_sys_write(AT91_RTC_TIMALR,
                  BIN2BCD(tm.tm_sec) << 0
                | BIN2BCD(tm.tm_min) << 8
@@ -174,6 +175,9 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
                | BIN2BCD(tm.tm_mday) << 24
                | AT91_RTC_DATEEN | AT91_RTC_MTHEN);
 
+       if (alrm->enabled)
+               at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM);
+
        pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
                at91_alarm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour,
                tm.tm_min, tm.tm_sec);
@@ -303,6 +307,12 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
                return ret;
        }
 
+       /* cpu init code should really have flagged this device as
+        * being wake-capable; if it didn't, do that here.
+        */
+       if (!device_can_wakeup(&pdev->dev))
+               device_init_wakeup(&pdev->dev, 1);
+
        rtc = rtc_device_register(pdev->name, &pdev->dev,
                                &at91_rtc_ops, THIS_MODULE);
        if (IS_ERR(rtc)) {
@@ -310,7 +320,6 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
                return PTR_ERR(rtc);
        }
        platform_set_drvdata(pdev, rtc);
-       device_init_wakeup(&pdev->dev, 1);
 
        printk(KERN_INFO "AT91 Real Time Clock driver.\n");
        return 0;
@@ -319,7 +328,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
 /*
  * Disable and remove the RTC driver
  */
-static int __devexit at91_rtc_remove(struct platform_device *pdev)
+static int __exit at91_rtc_remove(struct platform_device *pdev)
 {
        struct rtc_device *rtc = platform_get_drvdata(pdev);
 
@@ -331,7 +340,6 @@ static int __devexit at91_rtc_remove(struct platform_device *pdev)
 
        rtc_device_unregister(rtc);
        platform_set_drvdata(pdev, NULL);
-       device_init_wakeup(&pdev->dev, 0);
 
        return 0;
 }
@@ -404,8 +412,7 @@ static int at91_rtc_resume(struct platform_device *pdev)
 #endif
 
 static struct platform_driver at91_rtc_driver = {
-       .probe          = at91_rtc_probe,
-       .remove         = at91_rtc_remove,
+       .remove         = __exit_p(at91_rtc_remove),
        .suspend        = at91_rtc_suspend,
        .resume         = at91_rtc_resume,
        .driver         = {
@@ -416,7 +423,7 @@ static struct platform_driver at91_rtc_driver = {
 
 static int __init at91_rtc_init(void)
 {
-       return platform_driver_register(&at91_rtc_driver);
+       return platform_driver_probe(&at91_rtc_driver, at91_rtc_probe);
 }
 
 static void __exit at91_rtc_exit(void)
index 5875ebb8c79d9c3070c025860a8a5b1cf428fbec..d48b033745868bb28f801b957dc874d3328acd78 100644 (file)
@@ -40,7 +40,7 @@ struct pcf8583 {
 #define CTRL_ALARM     0x02
 #define CTRL_TIMER     0x01
 
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+static unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END };
 
 /* Module parameters */
 I2C_CLIENT_INSMOD;
@@ -81,11 +81,11 @@ static int pcf8583_get_datetime(struct i2c_client *client, struct rtc_time *dt)
                buf[4] &= 0x3f;
                buf[5] &= 0x1f;
 
-               dt->tm_sec = BCD_TO_BIN(buf[1]);
-               dt->tm_min = BCD_TO_BIN(buf[2]);
-               dt->tm_hour = BCD_TO_BIN(buf[3]);
-               dt->tm_mday = BCD_TO_BIN(buf[4]);
-               dt->tm_mon = BCD_TO_BIN(buf[5]);
+               dt->tm_sec = BCD2BIN(buf[1]);
+               dt->tm_min = BCD2BIN(buf[2]);
+               dt->tm_hour = BCD2BIN(buf[3]);
+               dt->tm_mday = BCD2BIN(buf[4]);
+               dt->tm_mon = BCD2BIN(buf[5]) - 1;
        }
 
        return ret == 2 ? 0 : -EIO;
@@ -99,14 +99,14 @@ static int pcf8583_set_datetime(struct i2c_client *client, struct rtc_time *dt,
        buf[0] = 0;
        buf[1] = get_ctrl(client) | 0x80;
        buf[2] = 0;
-       buf[3] = BIN_TO_BCD(dt->tm_sec);
-       buf[4] = BIN_TO_BCD(dt->tm_min);
-       buf[5] = BIN_TO_BCD(dt->tm_hour);
+       buf[3] = BIN2BCD(dt->tm_sec);
+       buf[4] = BIN2BCD(dt->tm_min);
+       buf[5] = BIN2BCD(dt->tm_hour);
 
        if (datetoo) {
                len = 8;
-               buf[6] = BIN_TO_BCD(dt->tm_mday) | (dt->tm_year << 6);
-               buf[7] = BIN_TO_BCD(dt->tm_mon)  | (dt->tm_wday << 5);
+               buf[6] = BIN2BCD(dt->tm_mday) | (dt->tm_year << 6);
+               buf[7] = BIN2BCD(dt->tm_mon + 1)  | (dt->tm_wday << 5);
        }
 
        ret = i2c_master_send(client, (char *)buf, len);
@@ -226,7 +226,7 @@ static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm)
                 */
                year_offset += 4;
 
-       tm->tm_year = real_year + year_offset + year[1] * 100;
+       tm->tm_year = (real_year + year_offset + year[1] * 100) - 1900;
 
        return 0;
 }
@@ -237,6 +237,7 @@ static int pcf8583_rtc_set_time(struct device *dev, struct rtc_time *tm)
        unsigned char year[2], chk;
        struct rtc_mem cmos_year  = { CMOS_YEAR, sizeof(year), year };
        struct rtc_mem cmos_check = { CMOS_CHECKSUM, 1, &chk };
+       unsigned int proper_year = tm->tm_year + 1900;
        int ret;
 
        /*
@@ -258,8 +259,8 @@ static int pcf8583_rtc_set_time(struct device *dev, struct rtc_time *tm)
 
        chk -= year[1] + year[0];
 
-       year[1] = tm->tm_year / 100;
-       year[0] = tm->tm_year % 100;
+       year[1] = proper_year / 100;
+       year[0] = proper_year % 100;
 
        chk += year[1] + year[0];
 
index 9c8ead43a59c38561c1393ea32a1b66b187e0578..677bae820dc3f681ff8cb3c115699033d519defc 100644 (file)
@@ -263,8 +263,12 @@ static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm)
 
 static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
+       u32     rtsr;
+
        memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time));
-       alrm->pending = RTSR & RTSR_AL ? 1 : 0;
+       rtsr = RTSR;
+       alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0;
+       alrm->pending = (rtsr & RTSR_AL) ? 1 : 0;
        return 0;
 }
 
@@ -275,12 +279,10 @@ static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        spin_lock_irq(&sa1100_rtc_lock);
        ret = rtc_update_alarm(&alrm->time);
        if (ret == 0) {
-               memcpy(&rtc_alarm, &alrm->time, sizeof(struct rtc_time));
-
                if (alrm->enabled)
-                       enable_irq_wake(IRQ_RTCAlrm);
+                       RTSR |= RTSR_ALE;
                else
-                       disable_irq_wake(IRQ_RTCAlrm);
+                       RTSR &= ~RTSR_ALE;
        }
        spin_unlock_irq(&sa1100_rtc_lock);
 
index 4b8a95fba1e5dc706e4e5e8b2bbfaf0185f57cad..a1dc8c466ec9ba895c6470bea0044c8937452f76 100644 (file)
@@ -461,6 +461,7 @@ int dasd_eer_enable(struct dasd_device *device)
        cqr->device = device;
        cqr->retries = 255;
        cqr->expires = 10 * HZ;
+       clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
 
        cqr->cpaddr->cmd_code = DASD_ECKD_CCW_SNSS;
        cqr->cpaddr->count = SNSS_DATA_SIZE;
index ffa9282ce97a97b65a0874d516c9b7c10b60df5f..baa8fe669ed206240280e3619503a536b33ac220 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/atomic.h>
 #include <asm/ptrace.h>
 #include <asm/sigp.h>
+#include <asm/smp.h>
 
 #include "sclp.h"
 
index 7a76ec413a3a15ac239367f821ffed0458420dd2..2a1af4e60be0919226217471beec3b1ea8f2b7b7 100644 (file)
@@ -647,7 +647,10 @@ tape_std_mtcompression(struct tape_device *device, int mt_count)
                return PTR_ERR(request);
        request->op = TO_NOP;
        /* setup ccws */
-       *device->modeset_byte = (mt_count == 0) ? 0x00 : 0x08;
+       if (mt_count == 0)
+               *device->modeset_byte &= ~0x08;
+       else
+               *device->modeset_byte |= 0x08;
        tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
        tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL);
        /* execute it */
index b3a56dc5f68a2fd5144dad6d7bd6abef50369fd0..9cb129ab5be5092ae421b7f104a39cbb48ff9ec9 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/irq_regs.h>
 #include <asm/setup.h>
 #include <asm/reset.h>
+#include <asm/ipl.h>
 #include "airq.h"
 #include "cio.h"
 #include "css.h"
@@ -1047,7 +1048,7 @@ void reipl_ccw_dev(struct ccw_dev_id *devid)
        do_reipl_asm(*((__u32*)&schid));
 }
 
-extern struct schib ipl_schib;
+static struct schib __initdata ipl_schib;
 
 /*
  * ipl_save_parameters gets called very early. It is not allowed to access
index 51238e7555bb9d34bcbc23272f265e2769e481d7..089a3ddd6265351a8131762696e77481e99a0e87 100644 (file)
@@ -144,8 +144,8 @@ ccw_device_cancel_halt_clear(struct ccw_device *cdev)
        ret = stsch(sch->schid, &sch->schib);
        if (ret || !sch->schib.pmcw.dnv)
                return -ENODEV; 
-       if (!sch->schib.pmcw.ena || sch->schib.scsw.actl == 0)
-               /* Not operational or no activity -> done. */
+       if (!sch->schib.pmcw.ena)
+               /* Not operational -> done. */
                return 0;
        /* Stage 1: cancel io. */
        if (!(sch->schib.scsw.actl & SCSW_ACTL_HALT_PEND) &&
@@ -334,20 +334,29 @@ ccw_device_oper_notify(struct work_struct *work)
        struct ccw_device *cdev;
        struct subchannel *sch;
        int ret;
+       unsigned long flags;
 
        priv = container_of(work, struct ccw_device_private, kick_work);
        cdev = priv->cdev;
+       spin_lock_irqsave(cdev->ccwlock, flags);
        sch = to_subchannel(cdev->dev.parent);
-       ret = (sch->driver && sch->driver->notify) ?
-               sch->driver->notify(&sch->dev, CIO_OPER) : 0;
-       if (!ret)
-               /* Driver doesn't want device back. */
-               ccw_device_do_unreg_rereg(work);
-       else {
+       if (sch->driver && sch->driver->notify) {
+               spin_unlock_irqrestore(cdev->ccwlock, flags);
+               ret = sch->driver->notify(&sch->dev, CIO_OPER);
+               spin_lock_irqsave(cdev->ccwlock, flags);
+       } else
+               ret = 0;
+       if (ret) {
                /* Reenable channel measurements, if needed. */
+               spin_unlock_irqrestore(cdev->ccwlock, flags);
                cmf_reenable(cdev);
+               spin_lock_irqsave(cdev->ccwlock, flags);
                wake_up(&cdev->private->wait_q);
        }
+       spin_unlock_irqrestore(cdev->ccwlock, flags);
+       if (!ret)
+               /* Driver doesn't want device back. */
+               ccw_device_do_unreg_rereg(work);
 }
 
 /*
@@ -534,15 +543,21 @@ ccw_device_nopath_notify(struct work_struct *work)
        struct ccw_device *cdev;
        struct subchannel *sch;
        int ret;
+       unsigned long flags;
 
        priv = container_of(work, struct ccw_device_private, kick_work);
        cdev = priv->cdev;
+       spin_lock_irqsave(cdev->ccwlock, flags);
        sch = to_subchannel(cdev->dev.parent);
        /* Extra sanity. */
        if (sch->lpm)
-               return;
-       ret = (sch->driver && sch->driver->notify) ?
-               sch->driver->notify(&sch->dev, CIO_NO_PATH) : 0;
+               goto out_unlock;
+       if (sch->driver && sch->driver->notify) {
+               spin_unlock_irqrestore(cdev->ccwlock, flags);
+               ret = sch->driver->notify(&sch->dev, CIO_NO_PATH);
+               spin_lock_irqsave(cdev->ccwlock, flags);
+       } else
+               ret = 0;
        if (!ret) {
                if (get_device(&sch->dev)) {
                        /* Driver doesn't want to keep device. */
@@ -562,6 +577,8 @@ ccw_device_nopath_notify(struct work_struct *work)
                cdev->private->state = DEV_STATE_DISCONNECTED;
                wake_up(&cdev->private->wait_q);
        }
+out_unlock:
+       spin_unlock_irqrestore(cdev->ccwlock, flags);
 }
 
 void
@@ -607,10 +624,13 @@ ccw_device_verify_done(struct ccw_device *cdev, int err)
        default:
                /* Reset oper notify indication after verify error. */
                cdev->private->flags.donotify = 0;
-               PREPARE_WORK(&cdev->private->kick_work,
-                            ccw_device_nopath_notify);
-               queue_work(ccw_device_notify_work, &cdev->private->kick_work);
-               ccw_device_done(cdev, DEV_STATE_NOT_OPER);
+               if (cdev->online) {
+                       PREPARE_WORK(&cdev->private->kick_work,
+                                    ccw_device_nopath_notify);
+                       queue_work(ccw_device_notify_work,
+                                  &cdev->private->kick_work);
+               } else
+                       ccw_device_done(cdev, DEV_STATE_NOT_OPER);
                break;
        }
 }
@@ -756,15 +776,22 @@ static void
 ccw_device_online_notoper(struct ccw_device *cdev, enum dev_event dev_event)
 {
        struct subchannel *sch;
+       int ret;
 
        sch = to_subchannel(cdev->dev.parent);
-       if (sch->driver->notify &&
-           sch->driver->notify(&sch->dev, sch->lpm ? CIO_GONE : CIO_NO_PATH)) {
-                       ccw_device_set_timeout(cdev, 0);
-                       cdev->private->flags.fake_irb = 0;
-                       cdev->private->state = DEV_STATE_DISCONNECTED;
-                       wake_up(&cdev->private->wait_q);
-                       return;
+       if (sch->driver->notify) {
+               spin_unlock_irq(cdev->ccwlock);
+               ret = sch->driver->notify(&sch->dev,
+                                         sch->lpm ? CIO_GONE : CIO_NO_PATH);
+               spin_lock_irq(cdev->ccwlock);
+       } else
+               ret = 0;
+       if (ret) {
+               ccw_device_set_timeout(cdev, 0);
+               cdev->private->flags.fake_irb = 0;
+               cdev->private->state = DEV_STATE_DISCONNECTED;
+               wake_up(&cdev->private->wait_q);
+               return;
        }
        cdev->private->state = DEV_STATE_NOT_OPER;
        cio_disable_subchannel(sch);
@@ -969,18 +996,12 @@ ccw_device_killing_irq(struct ccw_device *cdev, enum dev_event dev_event)
 
        sch = to_subchannel(cdev->dev.parent);
        ccw_device_set_timeout(cdev, 0);
+       /* Start delayed path verification. */
+       ccw_device_online_verify(cdev, 0);
        /* OK, i/o is dead now. Call interrupt handler. */
-       cdev->private->state = DEV_STATE_ONLINE;
        if (cdev->handler)
                cdev->handler(cdev, cdev->private->intparm,
                              ERR_PTR(-EIO));
-       if (!sch->lpm) {
-               PREPARE_WORK(&cdev->private->kick_work,
-                            ccw_device_nopath_notify);
-               queue_work(ccw_device_notify_work, &cdev->private->kick_work);
-       } else if (cdev->private->flags.doverify)
-               /* Start delayed path verification. */
-               ccw_device_online_verify(cdev, 0);
 }
 
 static void
@@ -993,21 +1014,8 @@ ccw_device_killing_timeout(struct ccw_device *cdev, enum dev_event dev_event)
                ccw_device_set_timeout(cdev, 3*HZ);
                return;
        }
-       if (ret == -ENODEV) {
-               struct subchannel *sch;
-
-               sch = to_subchannel(cdev->dev.parent);
-               if (!sch->lpm) {
-                       PREPARE_WORK(&cdev->private->kick_work,
-                                    ccw_device_nopath_notify);
-                       queue_work(ccw_device_notify_work,
-                                  &cdev->private->kick_work);
-               } else
-                       dev_fsm_event(cdev, DEV_EVENT_NOTOPER);
-               return;
-       }
-       //FIXME: Can we get here?
-       cdev->private->state = DEV_STATE_ONLINE;
+       /* Start delayed path verification. */
+       ccw_device_online_verify(cdev, 0);
        if (cdev->handler)
                cdev->handler(cdev, cdev->private->intparm,
                              ERR_PTR(-EIO));
@@ -1025,26 +1033,11 @@ void device_kill_io(struct subchannel *sch)
                cdev->private->state = DEV_STATE_TIMEOUT_KILL;
                return;
        }
-       if (ret == -ENODEV) {
-               if (!sch->lpm) {
-                       PREPARE_WORK(&cdev->private->kick_work,
-                                    ccw_device_nopath_notify);
-                       queue_work(ccw_device_notify_work,
-                                  &cdev->private->kick_work);
-               } else
-                       dev_fsm_event(cdev, DEV_EVENT_NOTOPER);
-               return;
-       }
+       /* Start delayed path verification. */
+       ccw_device_online_verify(cdev, 0);
        if (cdev->handler)
                cdev->handler(cdev, cdev->private->intparm,
                              ERR_PTR(-EIO));
-       if (!sch->lpm) {
-               PREPARE_WORK(&cdev->private->kick_work,
-                            ccw_device_nopath_notify);
-               queue_work(ccw_device_notify_work, &cdev->private->kick_work);
-       } else
-               /* Start delayed path verification. */
-               ccw_device_online_verify(cdev, 0);
 }
 
 static void
index 2257e45594b3dde36ccebc4a4ee0985f91629025..d8a86f5af379fe3d2b0a17ed58b4de05c11fb085 100644 (file)
@@ -3654,7 +3654,7 @@ qeth_verify_vlan_dev(struct net_device *dev, struct qeth_card *card)
                return rc;
 
        for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++){
-               if (vg->vlan_devices[i] == dev){
+               if (vlan_group_get_device(vg, i) == dev){
                        rc = QETH_VLAN_CARD;
                        break;
                }
@@ -5261,7 +5261,7 @@ qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid)
        QETH_DBF_TEXT(trace, 4, "frvaddr4");
 
        rcu_read_lock();
-       in_dev = __in_dev_get_rcu(card->vlangrp->vlan_devices[vid]);
+       in_dev = __in_dev_get_rcu(vlan_group_get_device(card->vlangrp, vid));
        if (!in_dev)
                goto out;
        for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
@@ -5288,7 +5288,7 @@ qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid)
 
        QETH_DBF_TEXT(trace, 4, "frvaddr6");
 
-       in6_dev = in6_dev_get(card->vlangrp->vlan_devices[vid]);
+       in6_dev = in6_dev_get(vlan_group_get_device(card->vlangrp, vid));
        if (!in6_dev)
                return;
        for (ifa = in6_dev->addr_list; ifa; ifa = ifa->lst_next){
@@ -5360,7 +5360,7 @@ qeth_layer2_process_vlans(struct qeth_card *card, int clear)
        if (!card->vlangrp)
                return;
        for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
-               if (card->vlangrp->vlan_devices[i] == NULL)
+               if (vlan_group_get_device(card->vlangrp, i) == NULL)
                        continue;
                if (clear)
                        qeth_layer2_send_setdelvlan(card, i, IPA_CMD_DELVLAN);
@@ -5398,8 +5398,7 @@ qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
        spin_lock_irqsave(&card->vlanlock, flags);
        /* unregister IP addresses of vlan device */
        qeth_free_vlan_addresses(card, vid);
-       if (card->vlangrp)
-               card->vlangrp->vlan_devices[vid] = NULL;
+       vlan_group_set_device(card->vlangrp, vid, NULL);
        spin_unlock_irqrestore(&card->vlanlock, flags);
        if (card->options.layer2)
                qeth_layer2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
@@ -5662,10 +5661,11 @@ qeth_add_vlan_mc(struct qeth_card *card)
 
        vg = card->vlangrp;
        for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
-               if (vg->vlan_devices[i] == NULL ||
-                   !(vg->vlan_devices[i]->flags & IFF_UP))
+               struct net_device *netdev = vlan_group_get_device(vg, i);
+               if (netdev == NULL ||
+                   !(netdev->flags & IFF_UP))
                        continue;
-               in_dev = in_dev_get(vg->vlan_devices[i]);
+               in_dev = in_dev_get(netdev);
                if (!in_dev)
                        continue;
                read_lock(&in_dev->mc_list_lock);
@@ -5749,10 +5749,11 @@ qeth_add_vlan_mc6(struct qeth_card *card)
 
        vg = card->vlangrp;
        for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
-               if (vg->vlan_devices[i] == NULL ||
-                   !(vg->vlan_devices[i]->flags & IFF_UP))
+               struct net_device *netdev = vlan_group_get_device(vg, i);
+               if (netdev == NULL ||
+                   !(netdev->flags & IFF_UP))
                        continue;
-               in_dev = in6_dev_get(vg->vlan_devices[i]);
+               in_dev = in6_dev_get(netdev);
                if (!in_dev)
                        continue;
                read_lock(&in_dev->lock);
index 3a8152906bf64edb7f343282269d6ead81614e18..35a73168333f6a8a13747d4776cb46089fb1dc05 100644 (file)
@@ -46,13 +46,6 @@ config SUN_VIDEOPIX
          based on the Phillips SAA9051, can handle NTSC and PAL/SECAM and
          SVIDEO signals.
 
-config SUN_AURORA
-       tristate "Aurora Multiboard 1600se (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && BROKEN
-       help
-         The Aurora Multiboard is a multi-port high-speed serial controller.
-         If you have one of these, say Y.
-
 config TADPOLE_TS102_UCTRL
        tristate "Tadpole TS102 Microcontroller support (EXPERIMENTAL)"
        depends on EXPERIMENTAL && SPARC32
index 3a5ea1dc789a16303bb572a7c0fe775ae5f925cf..7ab060e9a5fe25cd50b8bbfe75c0355a14fb065c 100644 (file)
@@ -19,7 +19,6 @@ obj-$(CONFIG_SUN_OPENPROMIO)          += openprom.o
 obj-$(CONFIG_SUN_MOSTEK_RTC)           += rtc.o
 obj-$(CONFIG_SUN_BPP)                  += bpp.o
 obj-$(CONFIG_SUN_VIDEOPIX)             += vfc.o
-obj-$(CONFIG_SUN_AURORA)               += aurora.o
 obj-$(CONFIG_TADPOLE_TS102_UCTRL)      += uctrl.o
 obj-$(CONFIG_SUN_JSFLASH)              += jsflash.o
 obj-$(CONFIG_BBC_I2C)                  += bbc.o
diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c
deleted file mode 100644 (file)
index a54b4ac..0000000
+++ /dev/null
@@ -1,2364 +0,0 @@
-/*     $Id: aurora.c,v 1.19 2002/01/08 16:00:16 davem Exp $
- *     linux/drivers/sbus/char/aurora.c -- Aurora multiport driver
- *
- *     Copyright (c) 1999 by Oliver Aldulea (oli at bv dot ro)
- *
- *     This code is based on the RISCom/8 multiport serial driver written
- *     by Dmitry Gorodchanin (pgmdsg@ibi.com), based on the Linux serial
- *     driver, written by Linus Torvalds, Theodore T'so and others.
- *     The Aurora multiport programming info was obtained mainly from the
- *     Cirrus Logic CD180 documentation (available on the web), and by
- *     doing heavy tests on the board. Many thanks to Eddie C. Dost for the
- *     help on the sbus interface.
- *
- *     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.
- *
- *     Revision 1.0
- *
- *     This is the first public release.
- *
- *     Most of the information you need is in the aurora.h file. Please
- *     read that file before reading this one.
- *
- *     Several parts of the code do not have comments yet.
- * 
- * n.b.  The board can support 115.2 bit rates, but only on a few
- * ports. The total badwidth of one chip (ports 0-7 or 8-15) is equal
- * to OSC_FREQ div 16. In case of my board, each chip can take 6
- * channels of 115.2 kbaud.  This information is not well-tested.
- * 
- * Fixed to use tty_get_baud_rate().
- *   Theodore Ts'o <tytso@mit.edu>, 2001-Oct-12
- */
-
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#ifdef AURORA_INT_DEBUG
-#include <linux/timer.h>
-#endif
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/bitops.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/oplib.h>
-#include <asm/system.h>
-#include <asm/kdebug.h>
-#include <asm/sbus.h>
-#include <asm/uaccess.h>
-
-#include "aurora.h"
-#include "cd180.h"
-
-unsigned char irqs[4] = {
-       0, 0, 0, 0
-};
-
-#ifdef AURORA_INT_DEBUG
-int irqhit=0;
-#endif
-
-static struct tty_driver *aurora_driver;
-static struct Aurora_board aurora_board[AURORA_NBOARD] = {
-       {0,},
-};
-
-static struct Aurora_port aurora_port[AURORA_TNPORTS] =  {
-       { 0, },
-};
-
-/* no longer used. static struct Aurora_board * IRQ_to_board[16] = { NULL, } ;*/
-static unsigned char * tmp_buf = NULL;
-
-DECLARE_TASK_QUEUE(tq_aurora);
-
-static inline int aurora_paranoia_check(struct Aurora_port const * port,
-                                   char *name, const char *routine)
-{
-#ifdef AURORA_PARANOIA_CHECK
-       static const char *badmagic =
-               KERN_DEBUG "aurora: Warning: bad aurora port magic number for device %s in %s\n";
-       static const char *badinfo =
-               KERN_DEBUG "aurora: Warning: null aurora port for device %s in %s\n";
-
-       if (!port) {
-               printk(badinfo, name, routine);
-               return 1;
-       }
-       if (port->magic != AURORA_MAGIC) {
-               printk(badmagic, name, routine);
-               return 1;
-       }
-#endif
-       return 0;
-}
-
-/*
- * 
- *  Service functions for aurora driver.
- * 
- */
-
-/* Get board number from pointer */
-static inline int board_No (struct Aurora_board const * bp)
-{
-       return bp - aurora_board;
-}
-
-/* Get port number from pointer */
-static inline int port_No (struct Aurora_port const * port)
-{
-       return AURORA_PORT(port - aurora_port); 
-}
-
-/* Get pointer to board from pointer to port */
-static inline struct Aurora_board * port_Board(struct Aurora_port const * port)
-{
-       return &aurora_board[AURORA_BOARD(port - aurora_port)];
-}
-
-/* Wait for Channel Command Register ready */
-static inline void aurora_wait_CCR(struct aurora_reg128 * r)
-{
-       unsigned long delay;
-
-#ifdef AURORA_DEBUG
-printk("aurora_wait_CCR\n");
-#endif
-       /* FIXME: need something more descriptive than 100000 :) */
-       for (delay = 100000; delay; delay--) 
-               if (!sbus_readb(&r->r[CD180_CCR]))
-                       return;
-       printk(KERN_DEBUG "aurora: Timeout waiting for CCR.\n");
-}
-
-/*
- *  aurora probe functions.
- */
-
-/* Must be called with enabled interrupts */
-static inline void aurora_long_delay(unsigned long delay)
-{
-       unsigned long i;
-
-#ifdef AURORA_DEBUG
-       printk("aurora_long_delay: start\n");
-#endif
-       for (i = jiffies + delay; time_before(jiffies, i); ) ;
-#ifdef AURORA_DEBUG
-       printk("aurora_long_delay: end\n");
-#endif
-}
-
-/* Reset and setup CD180 chip */
-static int aurora_init_CD180(struct Aurora_board * bp, int chip)
-{
-       unsigned long flags;
-       int id;
-       
-#ifdef AURORA_DEBUG
-       printk("aurora_init_CD180: start %d:%d\n",
-              board_No(bp), chip);
-#endif
-       save_flags(flags); cli();
-       sbus_writeb(0, &bp->r[chip]->r[CD180_CAR]);
-       sbus_writeb(0, &bp->r[chip]->r[CD180_GSVR]);
-
-       /* Wait for CCR ready        */
-       aurora_wait_CCR(bp->r[chip]);
-
-       /* Reset CD180 chip          */
-       sbus_writeb(CCR_HARDRESET, &bp->r[chip]->r[CD180_CCR]);
-       udelay(1);
-       sti();
-       id=1000;
-       while((--id) &&
-             (sbus_readb(&bp->r[chip]->r[CD180_GSVR])!=0xff))udelay(100);
-       if(!id) {
-               printk(KERN_ERR "aurora%d: Chip %d failed init.\n",
-                      board_No(bp), chip);
-               restore_flags(flags);
-               return(-1);
-       }
-       cli();
-       sbus_writeb((board_No(bp)<<5)|((chip+1)<<3),
-                   &bp->r[chip]->r[CD180_GSVR]); /* Set ID for this chip      */
-       sbus_writeb(0x80|bp->ACK_MINT,
-                   &bp->r[chip]->r[CD180_MSMR]); /* Prio for modem intr       */
-       sbus_writeb(0x80|bp->ACK_TINT,
-                   &bp->r[chip]->r[CD180_TSMR]); /* Prio for transmitter intr */
-       sbus_writeb(0x80|bp->ACK_RINT,
-                   &bp->r[chip]->r[CD180_RSMR]); /* Prio for receiver intr    */
-       /* Setting up prescaler. We need 4 tick per 1 ms */
-       sbus_writeb((bp->oscfreq/(1000000/AURORA_TPS)) >> 8,
-                   &bp->r[chip]->r[CD180_PPRH]);
-       sbus_writeb((bp->oscfreq/(1000000/AURORA_TPS)) & 0xff,
-                   &bp->r[chip]->r[CD180_PPRL]);
-
-       sbus_writeb(SRCR_AUTOPRI|SRCR_GLOBPRI,
-                   &bp->r[chip]->r[CD180_SRCR]);
-
-       id = sbus_readb(&bp->r[chip]->r[CD180_GFRCR]);
-       printk(KERN_INFO "aurora%d: Chip %d id %02x: ",
-              board_No(bp), chip,id);
-       if(sbus_readb(&bp->r[chip]->r[CD180_SRCR]) & 128) {
-               switch (id) {
-                       case 0x82:printk("CL-CD1864 rev A\n");break;
-                       case 0x83:printk("CL-CD1865 rev A\n");break;
-                       case 0x84:printk("CL-CD1865 rev B\n");break;
-                       case 0x85:printk("CL-CD1865 rev C\n");break;
-                       default:printk("Unknown.\n");
-               };
-       } else {
-               switch (id) {
-                       case 0x81:printk("CL-CD180 rev B\n");break;
-                       case 0x82:printk("CL-CD180 rev C\n");break;
-                       default:printk("Unknown.\n");
-               };
-       }
-       restore_flags(flags);
-#ifdef AURORA_DEBUG
-       printk("aurora_init_CD180: end\n");
-#endif
-       return 0;
-}
-
-static int valid_irq(unsigned char irq)
-{
-int i;
-for(i=0;i<TYPE_1_IRQS;i++)
-       if (type_1_irq[i]==irq) return 1;
-return 0;
-}
-
-static irqreturn_t aurora_interrupt(int irq, void * dev_id);
-
-/* Main probing routine, also sets irq. */
-static int aurora_probe(void)
-{
-       struct sbus_bus *sbus;
-       struct sbus_dev *sdev;
-       int grrr;
-       char buf[30];
-       int bn = 0;
-       struct Aurora_board *bp;
-
-       for_each_sbus(sbus) {
-               for_each_sbusdev(sdev, sbus) {
-/*                     printk("Try: %x %s\n",sdev,sdev->prom_name);*/
-                       if (!strcmp(sdev->prom_name, "sio16")) {
-#ifdef AURORA_DEBUG
-                               printk(KERN_INFO "aurora: sio16 at %p\n",sdev);
-#endif
-                               if((sdev->reg_addrs[0].reg_size!=1) &&
-                                  (sdev->reg_addrs[1].reg_size!=128) &&
-                                  (sdev->reg_addrs[2].reg_size!=128) &&
-                                  (sdev->reg_addrs[3].reg_size!=4)) {
-                                       printk(KERN_ERR "aurora%d: registers' sizes "
-                                              "do not match.\n", bn);
-                                       break;
-                               }
-                               bp = &aurora_board[bn];
-                               bp->r0 = (struct aurora_reg1 *)
-                                       sbus_ioremap(&sdev->resource[0], 0,
-                                                    sdev->reg_addrs[0].reg_size,
-                                                    "sio16");
-                               if (bp->r0 == NULL) {
-                                       printk(KERN_ERR "aurora%d: can't map "
-                                              "reg_addrs[0]\n", bn);
-                                       break;
-                               }
-#ifdef AURORA_DEBUG
-                               printk("Map reg 0: %p\n", bp->r0);
-#endif
-                               bp->r[0] = (struct aurora_reg128 *)
-                                       sbus_ioremap(&sdev->resource[1], 0,
-                                                    sdev->reg_addrs[1].reg_size,
-                                                    "sio16");
-                               if (bp->r[0] == NULL) {
-                                       printk(KERN_ERR "aurora%d: can't map "
-                                              "reg_addrs[1]\n", bn);
-                                       break;
-                               }
-#ifdef AURORA_DEBUG
-                               printk("Map reg 1: %p\n", bp->r[0]);
-#endif
-                               bp->r[1] = (struct aurora_reg128 *)
-                                       sbus_ioremap(&sdev->resource[2], 0,
-                                                    sdev->reg_addrs[2].reg_size,
-                                                    "sio16");
-                               if (bp->r[1] == NULL) {
-                                       printk(KERN_ERR "aurora%d: can't map "
-                                              "reg_addrs[2]\n", bn);
-                                       break;
-                               }
-#ifdef AURORA_DEBUG
-                               printk("Map reg 2: %p\n", bp->r[1]);
-#endif
-                               bp->r3 = (struct aurora_reg4 *)
-                                       sbus_ioremap(&sdev->resource[3], 0,
-                                                    sdev->reg_addrs[3].reg_size,
-                                                    "sio16");
-                               if (bp->r3 == NULL) {
-                                       printk(KERN_ERR "aurora%d: can't map "
-                                              "reg_addrs[3]\n", bn);
-                                       break;
-                               }
-#ifdef AURORA_DEBUG
-                               printk("Map reg 3: %p\n", bp->r3);
-#endif
-                               /* Variables setup */
-                               bp->flags = 0;
-#ifdef AURORA_DEBUG
-                               grrr=prom_getint(sdev->prom_node,"intr");
-                               printk("intr pri %d\n", grrr);
-#endif
-                               if ((bp->irq=irqs[bn]) && valid_irq(bp->irq) &&
-                                   !request_irq(bp->irq|0x30, aurora_interrupt, IRQF_SHARED, "sio16", bp)) {
-                                       free_irq(bp->irq|0x30, bp);
-                               } else
-                               if ((bp->irq=prom_getint(sdev->prom_node, "bintr")) && valid_irq(bp->irq) &&
-                                   !request_irq(bp->irq|0x30, aurora_interrupt, IRQF_SHARED, "sio16", bp)) {
-                                       free_irq(bp->irq|0x30, bp);
-                               } else
-                               if ((bp->irq=prom_getint(sdev->prom_node, "intr")) && valid_irq(bp->irq) &&
-                                   !request_irq(bp->irq|0x30, aurora_interrupt, IRQF_SHARED, "sio16", bp)) {
-                                       free_irq(bp->irq|0x30, bp);
-                               } else
-                               for(grrr=0;grrr<TYPE_1_IRQS;grrr++) {
-                                       if ((bp->irq=type_1_irq[grrr])&&!request_irq(bp->irq|0x30, aurora_interrupt, IRQF_SHARED, "sio16", bp)) {
-                                               free_irq(bp->irq|0x30, bp);
-                                               break;
-                                       } else {
-                                       printk(KERN_ERR "aurora%d: Could not get an irq for this board !!!\n",bn);
-                                       bp->flags=0xff;
-                                       }
-                               }
-                               if(bp->flags==0xff)break;
-                               printk(KERN_INFO "aurora%d: irq %d\n",bn,bp->irq&0x0f);
-                               buf[0]=0;
-                               grrr=prom_getproperty(sdev->prom_node,"dtr_rts",buf,sizeof(buf));
-                               if(!strcmp(buf,"swapped")){
-                                       printk(KERN_INFO "aurora%d: Swapped DTR and RTS\n",bn);
-                                       bp->DTR=MSVR_RTS;
-                                       bp->RTS=MSVR_DTR;
-                                       bp->MSVDTR=CD180_MSVRTS;
-                                       bp->MSVRTS=CD180_MSVDTR;
-                                       bp->flags|=AURORA_BOARD_DTR_FLOW_OK;
-                                       }else{
-                                       #ifdef AURORA_FORCE_DTR_FLOW
-                                       printk(KERN_INFO "aurora%d: Forcing swapped DTR-RTS\n",bn);
-                                       bp->DTR=MSVR_RTS;
-                                       bp->RTS=MSVR_DTR;
-                                       bp->MSVDTR=CD180_MSVRTS;
-                                       bp->MSVRTS=CD180_MSVDTR;
-                                       bp->flags|=AURORA_BOARD_DTR_FLOW_OK;
-                                       #else
-                                       printk(KERN_INFO "aurora%d: Normal DTR and RTS\n",bn);
-                                       bp->DTR=MSVR_DTR;
-                                       bp->RTS=MSVR_RTS;
-                                       bp->MSVDTR=CD180_MSVDTR;
-                                       bp->MSVRTS=CD180_MSVRTS;
-                                       #endif
-                               }
-                               bp->oscfreq=prom_getint(sdev->prom_node,"clk")*100;
-                               printk(KERN_INFO "aurora%d: Oscillator: %d Hz\n",bn,bp->oscfreq);
-                               grrr=prom_getproperty(sdev->prom_node,"chip",buf,sizeof(buf));
-                               printk(KERN_INFO "aurora%d: Chips: %s\n",bn,buf);
-                               grrr=prom_getproperty(sdev->prom_node,"manu",buf,sizeof(buf));
-                               printk(KERN_INFO "aurora%d: Manufacturer: %s\n",bn,buf);
-                               grrr=prom_getproperty(sdev->prom_node,"model",buf,sizeof(buf));
-                               printk(KERN_INFO "aurora%d: Model: %s\n",bn,buf);
-                               grrr=prom_getproperty(sdev->prom_node,"rev",buf,sizeof(buf));
-                               printk(KERN_INFO "aurora%d: Revision: %s\n",bn,buf);
-                               grrr=prom_getproperty(sdev->prom_node,"mode",buf,sizeof(buf));
-                               printk(KERN_INFO "aurora%d: Mode: %s\n",bn,buf);
-                               #ifdef MODULE
-                               bp->count=0;
-                               #endif
-                               bp->flags = AURORA_BOARD_PRESENT;
-                               /* hardware ack */
-                               bp->ACK_MINT=1;
-                               bp->ACK_TINT=2;
-                               bp->ACK_RINT=3;
-                               bn++;
-                       }
-               }
-       }
-       return bn;
-}
-
-static void aurora_release_io_range(struct Aurora_board *bp)
-{
-       sbus_iounmap((unsigned long)bp->r0, 1);
-       sbus_iounmap((unsigned long)bp->r[0], 128);
-       sbus_iounmap((unsigned long)bp->r[1], 128);
-       sbus_iounmap((unsigned long)bp->r3, 4);
-}
-
-static inline void aurora_mark_event(struct Aurora_port * port, int event)
-{
-#ifdef AURORA_DEBUG
-       printk("aurora_mark_event: start\n");
-#endif
-       set_bit(event, &port->event);
-       queue_task(&port->tqueue, &tq_aurora);
-       mark_bh(AURORA_BH);
-#ifdef AURORA_DEBUG
-       printk("aurora_mark_event: end\n");
-#endif
-}
-
-static __inline__ struct Aurora_port * aurora_get_port(struct Aurora_board const * bp,
-                                                      int chip,
-                                                      unsigned char const *what)
-{
-       unsigned char channel;
-       struct Aurora_port * port;
-
-       channel = ((chip << 3) |
-                  ((sbus_readb(&bp->r[chip]->r[CD180_GSCR]) & GSCR_CHAN) >> GSCR_CHAN_OFF));
-       port = &aurora_port[board_No(bp) * AURORA_NPORT * AURORA_NCD180 + channel];
-       if (port->flags & ASYNC_INITIALIZED)
-               return port;
-
-       printk(KERN_DEBUG "aurora%d: %s interrupt from invalid port %d\n",
-              board_No(bp), what, channel);
-       return NULL;
-}
-
-static void aurora_receive_exc(struct Aurora_board const * bp, int chip)
-{
-       struct Aurora_port *port;
-       struct tty_struct *tty;
-       unsigned char status;
-       unsigned char ch;
-       
-       if (!(port = aurora_get_port(bp, chip, "Receive_x")))
-               return;
-
-       tty = port->tty;
-       if (tty->flip.count >= TTY_FLIPBUF_SIZE)  {
-#ifdef AURORA_INTNORM
-               printk("aurora%d: port %d: Working around flip buffer overflow.\n",
-                      board_No(bp), port_No(port));
-#endif
-               return;
-       }
-       
-#ifdef AURORA_REPORT_OVERRUN   
-       status = sbus_readb(&bp->r[chip]->r[CD180_RCSR]);
-       if (status & RCSR_OE)  {
-               port->overrun++;
-#if 1
-               printk("aurora%d: port %d: Overrun. Total %ld overruns.\n",
-                      board_No(bp), port_No(port), port->overrun);
-#endif         
-       }
-       status &= port->mark_mask;
-#else  
-       status = sbus_readb(&bp->r[chip]->r[CD180_RCSR]) & port->mark_mask;
-#endif 
-       ch = sbus_readb(&bp->r[chip]->r[CD180_RDR]);
-       if (!status)
-               return;
-
-       if (status & RCSR_TOUT)  {
-/*             printk("aurora%d: port %d: Receiver timeout. Hardware problems ?\n",
-                      board_No(bp), port_No(port));*/
-               return;
-               
-       } else if (status & RCSR_BREAK)  {
-               printk(KERN_DEBUG "aurora%d: port %d: Handling break...\n",
-                      board_No(bp), port_No(port));
-               *tty->flip.flag_buf_ptr++ = TTY_BREAK;
-               if (port->flags & ASYNC_SAK)
-                       do_SAK(tty);
-               
-       } else if (status & RCSR_PE) 
-               *tty->flip.flag_buf_ptr++ = TTY_PARITY;
-       
-       else if (status & RCSR_FE) 
-               *tty->flip.flag_buf_ptr++ = TTY_FRAME;
-       
-        else if (status & RCSR_OE)
-               *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
-       
-       else
-               *tty->flip.flag_buf_ptr++ = 0;
-       
-       *tty->flip.char_buf_ptr++ = ch;
-       tty->flip.count++;
-       queue_task(&tty->flip.tqueue, &tq_timer);
-}
-
-static void aurora_receive(struct Aurora_board const * bp, int chip)
-{
-       struct Aurora_port *port;
-       struct tty_struct *tty;
-       unsigned char count,cnt;
-
-       if (!(port = aurora_get_port(bp, chip, "Receive")))
-               return;
-       
-       tty = port->tty;
-       
-       count = sbus_readb(&bp->r[chip]->r[CD180_RDCR]);
-
-#ifdef AURORA_REPORT_FIFO
-       port->hits[count > 8 ? 9 : count]++;
-#endif
-
-       while (count--)  {
-               if (tty->flip.count >= TTY_FLIPBUF_SIZE)  {
-#ifdef AURORA_INTNORM
-                       printk("aurora%d: port %d: Working around flip buffer overflow.\n",
-                              board_No(bp), port_No(port));
-#endif
-                       break;
-               }
-               cnt = sbus_readb(&bp->r[chip]->r[CD180_RDR]);
-               *tty->flip.char_buf_ptr++ = cnt;
-               *tty->flip.flag_buf_ptr++ = 0;
-               tty->flip.count++;
-       }
-       queue_task(&tty->flip.tqueue, &tq_timer);
-}
-
-static void aurora_transmit(struct Aurora_board const * bp, int chip)
-{
-       struct Aurora_port *port;
-       struct tty_struct *tty;
-       unsigned char count;
-       
-       if (!(port = aurora_get_port(bp, chip, "Transmit")))
-               return;
-               
-       tty = port->tty;
-       
-       if (port->SRER & SRER_TXEMPTY)  {
-               /* FIFO drained */
-               sbus_writeb(port_No(port) & 7,
-                           &bp->r[chip]->r[CD180_CAR]);
-               udelay(1);
-               port->SRER &= ~SRER_TXEMPTY;
-               sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]);
-               return;
-       }
-       
-       if ((port->xmit_cnt <= 0 && !port->break_length)
-           || tty->stopped || tty->hw_stopped)  {
-               sbus_writeb(port_No(port) & 7,
-                           &bp->r[chip]->r[CD180_CAR]);
-               udelay(1);
-               port->SRER &= ~SRER_TXRDY;
-               sbus_writeb(port->SRER,
-                           &bp->r[chip]->r[CD180_SRER]);
-               return;
-       }
-       
-       if (port->break_length)  {
-               if (port->break_length > 0)  {
-                       if (port->COR2 & COR2_ETC)  {
-                               sbus_writeb(CD180_C_ESC,
-                                           &bp->r[chip]->r[CD180_TDR]);
-                               sbus_writeb(CD180_C_SBRK,
-                                           &bp->r[chip]->r[CD180_TDR]);
-                               port->COR2 &= ~COR2_ETC;
-                       }
-                       count = min(port->break_length, 0xff);
-                       sbus_writeb(CD180_C_ESC,
-                                   &bp->r[chip]->r[CD180_TDR]);
-                       sbus_writeb(CD180_C_DELAY,
-                                   &bp->r[chip]->r[CD180_TDR]);
-                       sbus_writeb(count,
-                                   &bp->r[chip]->r[CD180_TDR]);
-                       if (!(port->break_length -= count))
-                               port->break_length--;
-               } else  {
-                       sbus_writeb(CD180_C_ESC,
-                                   &bp->r[chip]->r[CD180_TDR]);
-                       sbus_writeb(CD180_C_EBRK,
-                                   &bp->r[chip]->r[CD180_TDR]);
-                       sbus_writeb(port->COR2,
-                                   &bp->r[chip]->r[CD180_COR2]);
-                       aurora_wait_CCR(bp->r[chip]);
-                       sbus_writeb(CCR_CORCHG2,
-                                   &bp->r[chip]->r[CD180_CCR]);
-                       port->break_length = 0;
-               }
-               return;
-       }
-       
-       count = CD180_NFIFO;
-       do {
-               u8 byte = port->xmit_buf[port->xmit_tail++];
-
-               sbus_writeb(byte, &bp->r[chip]->r[CD180_TDR]);
-               port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1);
-               if (--port->xmit_cnt <= 0)
-                       break;
-       } while (--count > 0);
-       
-       if (port->xmit_cnt <= 0)  {
-               sbus_writeb(port_No(port) & 7,
-                           &bp->r[chip]->r[CD180_CAR]);
-               udelay(1);
-               port->SRER &= ~SRER_TXRDY;
-               sbus_writeb(port->SRER,
-                           &bp->r[chip]->r[CD180_SRER]);
-       }
-       if (port->xmit_cnt <= port->wakeup_chars)
-               aurora_mark_event(port, RS_EVENT_WRITE_WAKEUP);
-}
-
-static void aurora_check_modem(struct Aurora_board const * bp, int chip)
-{
-       struct Aurora_port *port;
-       struct tty_struct *tty;
-       unsigned char mcr;
-       
-       if (!(port = aurora_get_port(bp, chip, "Modem")))
-               return;
-               
-       tty = port->tty;
-       
-       mcr = sbus_readb(&bp->r[chip]->r[CD180_MCR]);
-       if (mcr & MCR_CDCHG)  {
-               if (sbus_readb(&bp->r[chip]->r[CD180_MSVR]) & MSVR_CD) 
-                       wake_up_interruptible(&port->open_wait);
-               else
-                       schedule_task(&port->tqueue_hangup);
-       }
-       
-/* We don't have such things yet. My aurora board has DTR and RTS swapped, but that doesn't count in this driver. Let's hope
- * Aurora didn't made any boards with CTS or DSR broken...
- */
-/* #ifdef AURORA_BRAIN_DAMAGED_CTS
-       if (mcr & MCR_CTSCHG)  {
-               if (aurora_in(bp, CD180_MSVR) & MSVR_CTS)  {
-                       tty->hw_stopped = 0;
-                       port->SRER |= SRER_TXRDY;
-                       if (port->xmit_cnt <= port->wakeup_chars)
-                               aurora_mark_event(port, RS_EVENT_WRITE_WAKEUP);
-               } else  {
-                       tty->hw_stopped = 1;
-                       port->SRER &= ~SRER_TXRDY;
-               }
-               sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]);
-       }
-       if (mcr & MCR_DSRCHG)  {
-               if (aurora_in(bp, CD180_MSVR) & MSVR_DSR)  {
-                       tty->hw_stopped = 0;
-                       port->SRER |= SRER_TXRDY;
-                       if (port->xmit_cnt <= port->wakeup_chars)
-                               aurora_mark_event(port, RS_EVENT_WRITE_WAKEUP);
-               } else  {
-                       tty->hw_stopped = 1;
-                       port->SRER &= ~SRER_TXRDY;
-               }
-               sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]);
-       }
-#endif AURORA_BRAIN_DAMAGED_CTS */
-       
-       /* Clear change bits */
-       sbus_writeb(0, &bp->r[chip]->r[CD180_MCR]);
-}
-
-/* The main interrupt processing routine */
-static irqreturn_t aurora_interrupt(int irq, void * dev_id)
-{
-       unsigned char status;
-       unsigned char ack,chip/*,chip_id*/;
-       struct Aurora_board * bp = (struct Aurora_board *) dev_id;
-       unsigned long loop = 0;
-
-#ifdef AURORA_INT_DEBUG
-       printk("IRQ%d %d\n",irq,++irqhit);
-#ifdef AURORA_FLOODPRO
-       if (irqhit>=AURORA_FLOODPRO)
-               sbus_writeb(8, &bp->r0->r);
-#endif
-#endif
-       
-/* old bp = IRQ_to_board[irq&0x0f];*/
-       
-       if (!bp || !(bp->flags & AURORA_BOARD_ACTIVE))
-               return IRQ_NONE;
-
-/*     The while() below takes care of this.
-       status = sbus_readb(&bp->r[0]->r[CD180_SRSR]);
-#ifdef AURORA_INT_DEBUG
-       printk("mumu: %02x\n", status);
-#endif
-       if (!(status&SRSR_ANYINT))
-               return IRQ_NONE; * Nobody has anything to say, so exit *
-*/
-       while ((loop++ < 48) &&
-              (status = sbus_readb(&bp->r[0]->r[CD180_SRSR]) & SRSR_ANYINT)){
-#ifdef AURORA_INT_DEBUG
-               printk("SRSR: %02x\n", status);
-#endif
-               if (status & SRSR_REXT) {
-                       ack = sbus_readb(&bp->r3->r[bp->ACK_RINT]);
-#ifdef AURORA_INT_DEBUG
-                       printk("R-ACK %02x\n", ack);
-#endif
-                       if ((ack >> 5) == board_No(bp)) {
-                               if ((chip=((ack>>3)&3)-1) < AURORA_NCD180) {
-                                       if ((ack&GSVR_ITMASK)==GSVR_IT_RGD) {
-                                               aurora_receive(bp,chip);
-                                               sbus_writeb(0,
-                                                        &bp->r[chip]->r[CD180_EOSRR]);
-                                       } else if ((ack & GSVR_ITMASK) == GSVR_IT_REXC) {
-                                               aurora_receive_exc(bp,chip);
-                                               sbus_writeb(0,
-                                                        &bp->r[chip]->r[CD180_EOSRR]);
-                                       }
-                               }
-                       }
-               } else if (status & SRSR_TEXT) {
-                       ack = sbus_readb(&bp->r3->r[bp->ACK_TINT]);
-#ifdef AURORA_INT_DEBUG
-                       printk("T-ACK %02x\n", ack);
-#endif
-                       if ((ack >> 5) == board_No(bp)) {
-                               if ((chip=((ack>>3)&3)-1) < AURORA_NCD180) {
-                                       if ((ack&GSVR_ITMASK)==GSVR_IT_TX) {
-                                               aurora_transmit(bp,chip);
-                                               sbus_writeb(0,
-                                                        &bp->r[chip]->r[CD180_EOSRR]);
-                                       }
-                               }
-                       }
-               } else if (status & SRSR_MEXT) {
-                       ack = sbus_readb(&bp->r3->r[bp->ACK_MINT]);
-#ifdef AURORA_INT_DEBUG
-                       printk("M-ACK %02x\n", ack);
-#endif
-                       if ((ack >> 5) == board_No(bp)) {
-                               if ((chip = ((ack>>3)&3)-1) < AURORA_NCD180) {
-                                       if ((ack&GSVR_ITMASK)==GSVR_IT_MDM) {
-                                               aurora_check_modem(bp,chip);
-                                               sbus_writeb(0,
-                                                        &bp->r[chip]->r[CD180_EOSRR]);
-                                       }
-                               }
-                       }
-               }
-       }
-/* I guess this faster code can be used with CD1865, using AUROPRI and GLOBPRI. */
-#if 0
-       while ((loop++ < 48)&&(status=bp->r[0]->r[CD180_SRSR]&SRSR_ANYINT)){
-#ifdef AURORA_INT_DEBUG
-               printk("SRSR: %02x\n",status);
-#endif
-               ack = sbus_readb(&bp->r3->r[0]);
-#ifdef AURORA_INT_DEBUG
-               printk("ACK: %02x\n",ack);
-#endif
-               if ((ack>>5)==board_No(bp)) {
-                       if ((chip=((ack>>3)&3)-1) < AURORA_NCD180) {
-                               ack&=GSVR_ITMASK;
-                               if (ack==GSVR_IT_RGD) {
-                                       aurora_receive(bp,chip);
-                                       sbus_writeb(0,
-                                                   &bp->r[chip]->r[CD180_EOSRR]);
-                               } else if (ack==GSVR_IT_REXC) {
-                                       aurora_receive_exc(bp,chip);
-                                       sbus_writeb(0,
-                                                   &bp->r[chip]->r[CD180_EOSRR]);
-                               } else if (ack==GSVR_IT_TX) {
-                                       aurora_transmit(bp,chip);
-                                       sbus_writeb(0,
-                                                   &bp->r[chip]->r[CD180_EOSRR]);
-                               } else if (ack==GSVR_IT_MDM) {
-                                       aurora_check_modem(bp,chip);
-                                       sbus_writeb(0,
-                                                   &bp->r[chip]->r[CD180_EOSRR]);
-                               }
-                       }
-               }
-       }
-#endif
-
-/* This is the old handling routine, used in riscom8 for only one CD180. I keep it here for reference. */
-#if 0
-       for(chip=0;chip<AURORA_NCD180;chip++){
-               chip_id=(board_No(bp)<<5)|((chip+1)<<3);
-               loop=0;
-               while ((loop++ < 1) &&
-                      ((status = sbus_readb(&bp->r[chip]->r[CD180_SRSR])) &
-                       (SRSR_TEXT | SRSR_MEXT | SRSR_REXT))) {
-
-                       if (status & SRSR_REXT) {
-                               ack = sbus_readb(&bp->r3->r[bp->ACK_RINT]);
-                               if (ack == (chip_id | GSVR_IT_RGD)) {
-#ifdef AURORA_INTMSG
-                                       printk("RX ACK\n");
-#endif
-                                       aurora_receive(bp,chip);
-                               } else if (ack == (chip_id | GSVR_IT_REXC)) {
-#ifdef AURORA_INTMSG
-                                       printk("RXC ACK\n");
-#endif
-                                       aurora_receive_exc(bp,chip);
-                               } else {
-#ifdef AURORA_INTNORM
-                                       printk("aurora%d-%d: Bad receive ack 0x%02x.\n",
-                                              board_No(bp), chip, ack);
-#endif
-                               }
-                       } else if (status & SRSR_TEXT) {
-                               ack = sbus_readb(&bp->r3->r[bp->ACK_TINT]);
-                               if (ack == (chip_id | GSVR_IT_TX)){
-#ifdef AURORA_INTMSG
-                                       printk("TX ACK\n");
-#endif
-                                       aurora_transmit(bp,chip);
-                               } else {
-#ifdef AURORA_INTNORM
-                                       printk("aurora%d-%d: Bad transmit ack 0x%02x.\n",
-                                              board_No(bp), chip, ack);
-#endif
-                               }
-                       } else  if (status & SRSR_MEXT)  {
-                               ack = sbus_readb(&bp->r3->r[bp->ACK_MINT]);
-                               if (ack == (chip_id | GSVR_IT_MDM)){
-#ifdef AURORA_INTMSG
-                                       printk("MDM ACK\n");
-#endif
-                                       aurora_check_modem(bp,chip);
-                               } else {
-#ifdef AURORA_INTNORM
-                                       printk("aurora%d-%d: Bad modem ack 0x%02x.\n",
-                                              board_No(bp), chip, ack);
-#endif
-                               }
-                       }
-                       sbus_writeb(0, &bp->r[chip]->r[CD180_EOSRR]);
-               }
-       }
-#endif
-
-       return IRQ_HANDLED;
-}
-
-#ifdef AURORA_INT_DEBUG
-static void aurora_timer (unsigned long ignored);
-
-static DEFINE_TIMER(aurora_poll_timer, aurora_timer, 0, 0);
-
-static void
-aurora_timer (unsigned long ignored)
-{
-       unsigned long flags;
-       int i;
-
-       save_flags(flags); cli();
-
-       printk("SRSR: %02x,%02x - ",
-              sbus_readb(&aurora_board[0].r[0]->r[CD180_SRSR]),
-              sbus_readb(&aurora_board[0].r[1]->r[CD180_SRSR]));
-       for (i = 0; i < 4; i++) {
-               udelay(1);
-               printk("%02x ",
-                      sbus_readb(&aurora_board[0].r3->r[i]));
-       }
-       printk("\n");
-
-       aurora_poll_timer.expires = jiffies + 300;
-       add_timer (&aurora_poll_timer);
-
-       restore_flags(flags);
-}
-#endif
-
-/*
- *  Routines for open & close processing.
- */
-
-/* Called with disabled interrupts */
-static int aurora_setup_board(struct Aurora_board * bp)
-{
-       int error;
-       
-#ifdef AURORA_ALLIRQ
-       int i;
-       for (i = 0; i < AURORA_ALLIRQ; i++) {
-               error = request_irq(allirq[i]|0x30, aurora_interrupt, IRQF_SHARED,
-                                   "sio16", bp);
-               if (error)
-                       printk(KERN_ERR "IRQ%d request error %d\n",
-                              allirq[i], error);
-       }
-#else
-       error = request_irq(bp->irq|0x30, aurora_interrupt, IRQF_SHARED,
-                           "sio16", bp);
-       if (error) {
-               printk(KERN_ERR "IRQ request error %d\n", error);
-               return error;
-       }
-#endif
-       /* Board reset */
-       sbus_writeb(0, &bp->r0->r);
-       udelay(1);
-       if (bp->flags & AURORA_BOARD_TYPE_2) {
-               /* unknown yet */
-       } else {
-               sbus_writeb((AURORA_CFG_ENABLE_IO | AURORA_CFG_ENABLE_IRQ |
-                            (((bp->irq)&0x0f)>>2)),
-                           &bp->r0->r);
-       }
-       udelay(10000);
-
-       if (aurora_init_CD180(bp,0))error=1;error=0;
-       if (aurora_init_CD180(bp,1))error++;
-       if (error == AURORA_NCD180) {
-               printk(KERN_ERR "Both chips failed initialisation.\n");
-               return -EIO;
-       }
-
-#ifdef AURORA_INT_DEBUG
-       aurora_poll_timer.expires= jiffies + 1;
-       add_timer(&aurora_poll_timer);
-#endif
-#ifdef AURORA_DEBUG
-       printk("aurora_setup_board: end\n");
-#endif
-       return 0;
-}
-
-/* Called with disabled interrupts */
-static void aurora_shutdown_board(struct Aurora_board *bp)
-{
-       int i;
-
-#ifdef AURORA_DEBUG
-       printk("aurora_shutdown_board: start\n");
-#endif
-
-#ifdef AURORA_INT_DEBUG
-       del_timer(&aurora_poll_timer);
-#endif
-
-#ifdef AURORA_ALLIRQ
-       for(i=0;i<AURORA_ALLIRQ;i++){
-               free_irq(allirq[i]|0x30, bp);
-/*             IRQ_to_board[allirq[i]&0xf] = NULL;*/
-       }
-#else
-       free_irq(bp->irq|0x30, bp);
-/*     IRQ_to_board[bp->irq&0xf] = NULL;*/
-#endif 
-       /* Drop all DTR's */
-       for(i=0;i<16;i++){
-               sbus_writeb(i & 7, &bp->r[i>>3]->r[CD180_CAR]);
-               udelay(1);
-               sbus_writeb(0, &bp->r[i>>3]->r[CD180_MSVR]);
-               udelay(1);
-       }
-       /* Board shutdown */
-       sbus_writeb(0, &bp->r0->r);
-
-#ifdef AURORA_DEBUG
-       printk("aurora_shutdown_board: end\n");
-#endif
-}
-
-/* Setting up port characteristics. 
- * Must be called with disabled interrupts
- */
-static void aurora_change_speed(struct Aurora_board *bp, struct Aurora_port *port)
-{
-       struct tty_struct *tty;
-       unsigned long baud;
-       long tmp;
-       unsigned char cor1 = 0, cor3 = 0;
-       unsigned char mcor1 = 0, mcor2 = 0,chip;
-       
-#ifdef AURORA_DEBUG
-       printk("aurora_change_speed: start\n");
-#endif
-       if (!(tty = port->tty) || !tty->termios)
-               return;
-               
-       chip = AURORA_CD180(port_No(port));
-
-       port->SRER  = 0;
-       port->COR2 = 0;
-       port->MSVR = MSVR_RTS|MSVR_DTR;
-       
-       baud = tty_get_baud_rate(tty);
-       
-       /* Select port on the board */
-       sbus_writeb(port_No(port) & 7,
-                   &bp->r[chip]->r[CD180_CAR]);
-       udelay(1);
-       
-       if (!baud)  {
-               /* Drop DTR & exit */
-               port->MSVR &= ~(bp->DTR|bp->RTS);
-               sbus_writeb(port->MSVR,
-                           &bp->r[chip]->r[CD180_MSVR]);
-               return;
-       } else  {
-               /* Set DTR on */
-               port->MSVR |= bp->DTR;
-               sbus_writeb(port->MSVR,
-                           &bp->r[chip]->r[CD180_MSVR]);
-       }
-       
-       /* Now we must calculate some speed dependent things. */
-       
-       /* Set baud rate for port. */
-       tmp = (((bp->oscfreq + baud/2) / baud +
-               CD180_TPC/2) / CD180_TPC);
-
-/*     tmp = (bp->oscfreq/7)/baud;
-       if((tmp%10)>4)tmp=tmp/10+1;else tmp=tmp/10;*/
-/*     printk("Prescaler period: %d\n",tmp);*/
-
-       sbus_writeb((tmp >> 8) & 0xff,
-                   &bp->r[chip]->r[CD180_RBPRH]);
-       sbus_writeb((tmp >> 8) & 0xff,
-                   &bp->r[chip]->r[CD180_TBPRH]);
-       sbus_writeb(tmp & 0xff, &bp->r[chip]->r[CD180_RBPRL]);
-       sbus_writeb(tmp & 0xff, &bp->r[chip]->r[CD180_TBPRL]);
-       
-       baud = (baud + 5) / 10;   /* Estimated CPS */
-       
-       /* Two timer ticks seems enough to wakeup something like SLIP driver */
-       tmp = ((baud + HZ/2) / HZ) * 2 - CD180_NFIFO;           
-       port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?
-                                             SERIAL_XMIT_SIZE - 1 : tmp);
-       
-       /* Receiver timeout will be transmission time for 1.5 chars */
-       tmp = (AURORA_TPS + AURORA_TPS/2 + baud/2) / baud;
-       tmp = (tmp > 0xff) ? 0xff : tmp;
-       sbus_writeb(tmp, &bp->r[chip]->r[CD180_RTPR]);
-       
-       switch (C_CSIZE(tty))  {
-        case CS5:
-               cor1 |= COR1_5BITS;
-               break;
-        case CS6:
-               cor1 |= COR1_6BITS;
-               break;
-        case CS7:
-               cor1 |= COR1_7BITS;
-               break;
-        case CS8:
-               cor1 |= COR1_8BITS;
-               break;
-       }
-       
-       if (C_CSTOPB(tty)) 
-               cor1 |= COR1_2SB;
-       
-       cor1 |= COR1_IGNORE;
-       if (C_PARENB(tty))  {
-               cor1 |= COR1_NORMPAR;
-               if (C_PARODD(tty)) 
-                       cor1 |= COR1_ODDP;
-               if (I_INPCK(tty)) 
-                       cor1 &= ~COR1_IGNORE;
-       }
-       /* Set marking of some errors */
-       port->mark_mask = RCSR_OE | RCSR_TOUT;
-       if (I_INPCK(tty)) 
-               port->mark_mask |= RCSR_FE | RCSR_PE;
-       if (I_BRKINT(tty) || I_PARMRK(tty)) 
-               port->mark_mask |= RCSR_BREAK;
-       if (I_IGNPAR(tty)) 
-               port->mark_mask &= ~(RCSR_FE | RCSR_PE);
-       if (I_IGNBRK(tty))  {
-               port->mark_mask &= ~RCSR_BREAK;
-               if (I_IGNPAR(tty)) 
-                       /* Real raw mode. Ignore all */
-                       port->mark_mask &= ~RCSR_OE;
-       }
-       /* Enable Hardware Flow Control */
-       if (C_CRTSCTS(tty))  {
-/*#ifdef AURORA_BRAIN_DAMAGED_CTS
-               port->SRER |= SRER_DSR | SRER_CTS;
-               mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD;
-               mcor2 |= MCOR2_DSROD | MCOR2_CTSOD;
-               tty->hw_stopped = !(aurora_in(bp, CD180_MSVR) & (MSVR_CTS|MSVR_DSR));
-#else*/
-               port->COR2 |= COR2_CTSAE;
-/*#endif*/
-               if (bp->flags&AURORA_BOARD_DTR_FLOW_OK) {
-                       mcor1 |= AURORA_RXTH;
-               }
-       }
-       /* Enable Software Flow Control. FIXME: I'm not sure about this */
-       /* Some people reported that it works, but I still doubt */
-       if (I_IXON(tty))  {
-               port->COR2 |= COR2_TXIBE;
-               cor3 |= (COR3_FCT | COR3_SCDE);
-               if (I_IXANY(tty))
-                       port->COR2 |= COR2_IXM;
-               sbus_writeb(START_CHAR(tty),
-                           &bp->r[chip]->r[CD180_SCHR1]);
-               sbus_writeb(STOP_CHAR(tty),
-                           &bp->r[chip]->r[CD180_SCHR2]);
-               sbus_writeb(START_CHAR(tty),
-                           &bp->r[chip]->r[CD180_SCHR3]);
-               sbus_writeb(STOP_CHAR(tty),
-                           &bp->r[chip]->r[CD180_SCHR4]);
-       }
-       if (!C_CLOCAL(tty))  {
-               /* Enable CD check */
-               port->SRER |= SRER_CD;
-               mcor1 |= MCOR1_CDZD;
-               mcor2 |= MCOR2_CDOD;
-       }
-       
-       if (C_CREAD(tty)) 
-               /* Enable receiver */
-               port->SRER |= SRER_RXD;
-       
-       /* Set input FIFO size (1-8 bytes) */
-       cor3 |= AURORA_RXFIFO; 
-       /* Setting up CD180 channel registers */
-       sbus_writeb(cor1, &bp->r[chip]->r[CD180_COR1]);
-       sbus_writeb(port->COR2, &bp->r[chip]->r[CD180_COR2]);
-       sbus_writeb(cor3, &bp->r[chip]->r[CD180_COR3]);
-       /* Make CD180 know about registers change */
-       aurora_wait_CCR(bp->r[chip]);
-       sbus_writeb(CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3,
-                   &bp->r[chip]->r[CD180_CCR]);
-       /* Setting up modem option registers */
-       sbus_writeb(mcor1, &bp->r[chip]->r[CD180_MCOR1]);
-       sbus_writeb(mcor2, &bp->r[chip]->r[CD180_MCOR2]);
-       /* Enable CD180 transmitter & receiver */
-       aurora_wait_CCR(bp->r[chip]);
-       sbus_writeb(CCR_TXEN | CCR_RXEN, &bp->r[chip]->r[CD180_CCR]);
-       /* Enable interrupts */
-       sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]);
-       /* And finally set RTS on */
-       sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]);
-#ifdef AURORA_DEBUG
-       printk("aurora_change_speed: end\n");
-#endif
-}
-
-/* Must be called with interrupts enabled */
-static int aurora_setup_port(struct Aurora_board *bp, struct Aurora_port *port)
-{
-       unsigned long flags;
-       
-#ifdef AURORA_DEBUG
-       printk("aurora_setup_port: start %d\n",port_No(port));
-#endif
-       if (port->flags & ASYNC_INITIALIZED)
-               return 0;
-               
-       if (!port->xmit_buf) {
-               /* We may sleep in get_zeroed_page() */
-               unsigned long tmp;
-               
-               if (!(tmp = get_zeroed_page(GFP_KERNEL)))
-                       return -ENOMEM;
-                   
-               if (port->xmit_buf) {
-                       free_page(tmp);
-                       return -ERESTARTSYS;
-               }
-               port->xmit_buf = (unsigned char *) tmp;
-       }
-               
-       save_flags(flags); cli();
-               
-       if (port->tty) 
-               clear_bit(TTY_IO_ERROR, &port->tty->flags);
-               
-#ifdef MODULE
-       if ((port->count == 1) && ((++bp->count) == 1))
-                       bp->flags |= AURORA_BOARD_ACTIVE;
-#endif
-
-       port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-       aurora_change_speed(bp, port);
-       port->flags |= ASYNC_INITIALIZED;
-               
-       restore_flags(flags);
-#ifdef AURORA_DEBUG
-       printk("aurora_setup_port: end\n");
-#endif
-       return 0;
-}
-
-/* Must be called with interrupts disabled */
-static void aurora_shutdown_port(struct Aurora_board *bp, struct Aurora_port *port)
-{
-       struct tty_struct *tty;
-       unsigned char chip;
-
-#ifdef AURORA_DEBUG
-       printk("aurora_shutdown_port: start\n");
-#endif
-       if (!(port->flags & ASYNC_INITIALIZED)) 
-               return;
-       
-       chip = AURORA_CD180(port_No(port));
-       
-#ifdef AURORA_REPORT_OVERRUN
-       printk("aurora%d: port %d: Total %ld overruns were detected.\n",
-              board_No(bp), port_No(port), port->overrun);
-#endif 
-#ifdef AURORA_REPORT_FIFO
-       {
-               int i;
-               
-               printk("aurora%d: port %d: FIFO hits [ ",
-                      board_No(bp), port_No(port));
-               for (i = 0; i < 10; i++)  {
-                       printk("%ld ", port->hits[i]);
-               }
-               printk("].\n");
-       }
-#endif 
-       if (port->xmit_buf)  {
-               free_page((unsigned long) port->xmit_buf);
-               port->xmit_buf = NULL;
-       }
-
-       if (!(tty = port->tty) || C_HUPCL(tty))  {
-               /* Drop DTR */
-               port->MSVR &= ~(bp->DTR|bp->RTS);
-               sbus_writeb(port->MSVR,
-                           &bp->r[chip]->r[CD180_MSVR]);
-       }
-       
-        /* Select port */
-       sbus_writeb(port_No(port) & 7,
-                   &bp->r[chip]->r[CD180_CAR]);
-       udelay(1);
-
-       /* Reset port */
-       aurora_wait_CCR(bp->r[chip]);
-       sbus_writeb(CCR_SOFTRESET, &bp->r[chip]->r[CD180_CCR]);
-
-       /* Disable all interrupts from this port */
-       port->SRER = 0;
-       sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]);
-       
-       if (tty)  
-               set_bit(TTY_IO_ERROR, &tty->flags);
-       port->flags &= ~ASYNC_INITIALIZED;
-
-#ifdef MODULE
-       if (--bp->count < 0)  {
-               printk(KERN_DEBUG "aurora%d: aurora_shutdown_port: "
-                      "bad board count: %d\n",
-                      board_No(bp), bp->count);
-               bp->count = 0;
-       }
-       
-       if (!bp->count)
-               bp->flags &= ~AURORA_BOARD_ACTIVE;
-#endif
-
-#ifdef AURORA_DEBUG
-       printk("aurora_shutdown_port: end\n");
-#endif
-}
-
-       
-static int block_til_ready(struct tty_struct *tty, struct file * filp,
-                          struct Aurora_port *port)
-{
-       DECLARE_WAITQUEUE(wait, current);
-       struct Aurora_board *bp = port_Board(port);
-       int    retval;
-       int    do_clocal = 0;
-       int    CD;
-       unsigned char chip;
-       
-#ifdef AURORA_DEBUG
-       printk("block_til_ready: start\n");
-#endif
-       chip = AURORA_CD180(port_No(port));
-
-       /* If the device is in the middle of being closed, then block
-        * until it's done, and then try again.
-        */
-       if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
-               interruptible_sleep_on(&port->close_wait);
-               if (port->flags & ASYNC_HUP_NOTIFY)
-                       return -EAGAIN;
-               else
-                       return -ERESTARTSYS;
-       }
-
-       /* If non-blocking mode is set, or the port is not enabled,
-        * then make the check up front and then exit.
-        */
-       if ((filp->f_flags & O_NONBLOCK) ||
-           (tty->flags & (1 << TTY_IO_ERROR))) {
-               port->flags |= ASYNC_NORMAL_ACTIVE;
-               return 0;
-       }
-
-       if (C_CLOCAL(tty))  
-               do_clocal = 1;
-
-       /* Block waiting for the carrier detect and the line to become
-        * free (i.e., not in use by the callout).  While we are in
-        * this loop, info->count is dropped by one, so that
-        * rs_close() knows when to free things.  We restore it upon
-        * exit, either normal or abnormal.
-        */
-       retval = 0;
-       add_wait_queue(&port->open_wait, &wait);
-       cli();
-       if (!tty_hung_up_p(filp))
-               port->count--;
-       sti();
-       port->blocked_open++;
-       while (1) {
-               cli();
-               sbus_writeb(port_No(port) & 7,
-                           &bp->r[chip]->r[CD180_CAR]);
-               udelay(1);
-               CD = sbus_readb(&bp->r[chip]->r[CD180_MSVR]) & MSVR_CD;
-               port->MSVR=bp->RTS;
-
-               /* auto drops DTR */
-               sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]);
-               sti();
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (tty_hung_up_p(filp) ||
-                   !(port->flags & ASYNC_INITIALIZED)) {
-                       if (port->flags & ASYNC_HUP_NOTIFY)
-                               retval = -EAGAIN;
-                       else
-                               retval = -ERESTARTSYS;  
-                       break;
-               }
-               if (!(port->flags & ASYNC_CLOSING) &&
-                   (do_clocal || CD))
-                       break;
-               if (signal_pending(current)) {
-                       retval = -ERESTARTSYS;
-                       break;
-               }
-               schedule();
-       }
-       current->state = TASK_RUNNING;
-       remove_wait_queue(&port->open_wait, &wait);
-       if (!tty_hung_up_p(filp))
-               port->count++;
-       port->blocked_open--;
-       if (retval)
-               return retval;
-       
-       port->flags |= ASYNC_NORMAL_ACTIVE;
-#ifdef AURORA_DEBUG
-       printk("block_til_ready: end\n");
-#endif
-       return 0;
-}      
-
-static int aurora_open(struct tty_struct * tty, struct file * filp)
-{
-       int board;
-       int error;
-       struct Aurora_port * port;
-       struct Aurora_board * bp;
-       unsigned long flags;
-       
-#ifdef AURORA_DEBUG
-       printk("aurora_open: start\n");
-#endif
-       
-       board = AURORA_BOARD(tty->index);
-       if (board > AURORA_NBOARD ||
-           !(aurora_board[board].flags & AURORA_BOARD_PRESENT)) {
-#ifdef AURORA_DEBUG
-               printk("aurora_open: error board %d present %d\n",
-                      board, aurora_board[board].flags & AURORA_BOARD_PRESENT);
-#endif
-               return -ENODEV;
-       }
-       
-       bp = &aurora_board[board];
-       port = aurora_port + board * AURORA_NPORT * AURORA_NCD180 + AURORA_PORT(tty->index);
-       if ((aurora_paranoia_check(port, tty->name, "aurora_open")) {
-#ifdef AURORA_DEBUG
-               printk("aurora_open: error paranoia check\n");
-#endif
-               return -ENODEV;
-       }
-       
-       port->count++;
-       tty->driver_data = port;
-       port->tty = tty;
-       
-       if ((error = aurora_setup_port(bp, port))) {
-#ifdef AURORA_DEBUG
-               printk("aurora_open: error aurora_setup_port ret %d\n",error);
-#endif
-               return error;
-       }
-
-       if ((error = block_til_ready(tty, filp, port))) {
-#ifdef AURORA_DEBUG
-               printk("aurora_open: error block_til_ready ret %d\n",error);
-#endif
-               return error;
-       }
-       
-#ifdef AURORA_DEBUG
-       printk("aurora_open: end\n");
-#endif
-       return 0;
-}
-
-static void aurora_close(struct tty_struct * tty, struct file * filp)
-{
-       struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
-       struct Aurora_board *bp;
-       unsigned long flags;
-       unsigned long timeout;
-       unsigned char chip;
-       
-#ifdef AURORA_DEBUG
-       printk("aurora_close: start\n");
-#endif
-       
-       if (!port || (aurora_paranoia_check(port, tty->name, "close"))
-               return;
-       
-       chip = AURORA_CD180(port_No(port));
-
-       save_flags(flags); cli();
-       if (tty_hung_up_p(filp))  {
-               restore_flags(flags);
-               return;
-       }
-       
-       bp = port_Board(port);
-       if ((tty->count == 1) && (port->count != 1))  {
-               printk(KERN_DEBUG "aurora%d: aurora_close: bad port count; "
-                      "tty->count is 1, port count is %d\n",
-                      board_No(bp), port->count);
-               port->count = 1;
-       }
-       if (--port->count < 0)  {
-               printk(KERN_DEBUG "aurora%d: aurora_close: bad port "
-                      "count for tty%d: %d\n",
-                      board_No(bp), port_No(port), port->count);
-               port->count = 0;
-       }
-       if (port->count)  {
-               restore_flags(flags);
-               return;
-       }
-       port->flags |= ASYNC_CLOSING;
-
-       /* Now we wait for the transmit buffer to clear; and we notify 
-        * the line discipline to only process XON/XOFF characters.
-        */
-       tty->closing = 1;
-       if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE){
-#ifdef AURORA_DEBUG
-               printk("aurora_close: waiting to flush...\n");
-#endif
-               tty_wait_until_sent(tty, port->closing_wait);
-       }
-
-       /* At this point we stop accepting input.  To do this, we
-        * disable the receive line status interrupts, and tell the
-        * interrupt driver to stop checking the data ready bit in the
-        * line status register.
-        */
-       port->SRER &= ~SRER_RXD;
-       if (port->flags & ASYNC_INITIALIZED) {
-               port->SRER &= ~SRER_TXRDY;
-               port->SRER |= SRER_TXEMPTY;
-               sbus_writeb(port_No(port) & 7,
-                           &bp->r[chip]->r[CD180_CAR]);
-               udelay(1);
-               sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]);
-               /*
-                * Before we drop DTR, make sure the UART transmitter
-                * has completely drained; this is especially
-                * important if there is a transmit FIFO!
-                */
-               timeout = jiffies+HZ;
-               while(port->SRER & SRER_TXEMPTY)  {
-                       msleep_interruptible(jiffies_to_msecs(port->timeout));
-                       if (time_after(jiffies, timeout))
-                               break;
-               }
-       }
-#ifdef AURORA_DEBUG
-       printk("aurora_close: shutdown_port\n");
-#endif
-       aurora_shutdown_port(bp, port);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
-       tty_ldisc_flush(tty);
-       tty->closing = 0;
-       port->event = 0;
-       port->tty = 0;
-       if (port->blocked_open) {
-               if (port->close_delay) {
-                       msleep_interruptible(jiffies_to_msecs(port->close_delay));
-               }
-               wake_up_interruptible(&port->open_wait);
-       }
-       port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-       wake_up_interruptible(&port->close_wait);
-       restore_flags(flags);
-#ifdef AURORA_DEBUG
-       printk("aurora_close: end\n");
-#endif
-}
-
-static int aurora_write(struct tty_struct * tty, 
-                       const unsigned char *buf, int count)
-{
-       struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
-       struct Aurora_board *bp;
-       int c, total = 0;
-       unsigned long flags;
-       unsigned char chip;
-
-#ifdef AURORA_DEBUG
-       printk("aurora_write: start %d\n",count);
-#endif
-       if ((aurora_paranoia_check(port, tty->name, "aurora_write"))
-               return 0;
-               
-       chip = AURORA_CD180(port_No(port));
-       
-       bp = port_Board(port);
-
-       if (!tty || !port->xmit_buf || !tmp_buf)
-               return 0;
-
-       save_flags(flags);
-       while (1) {
-               cli();
-               c = min(count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-                                  SERIAL_XMIT_SIZE - port->xmit_head));
-               if (c <= 0) {
-                       restore_flags(flags);
-                       break;
-               }
-               memcpy(port->xmit_buf + port->xmit_head, buf, c);
-               port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-               port->xmit_cnt += c;
-               restore_flags(flags);
-
-               buf += c;
-               count -= c;
-               total += c;
-       }
-
-       cli();
-       if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
-           !(port->SRER & SRER_TXRDY)) {
-               port->SRER |= SRER_TXRDY;
-               sbus_writeb(port_No(port) & 7,
-                           &bp->r[chip]->r[CD180_CAR]);
-               udelay(1);
-               sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]);
-       }
-       restore_flags(flags);
-#ifdef AURORA_DEBUG
-       printk("aurora_write: end %d\n",total);
-#endif
-       return total;
-}
-
-static void aurora_put_char(struct tty_struct * tty, unsigned char ch)
-{
-       struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
-       unsigned long flags;
-
-#ifdef AURORA_DEBUG
-       printk("aurora_put_char: start %c\n",ch);
-#endif
-       if ((aurora_paranoia_check(port, tty->name, "aurora_put_char"))
-               return;
-
-       if (!tty || !port->xmit_buf)
-               return;
-
-       save_flags(flags); cli();
-       
-       if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
-               restore_flags(flags);
-               return;
-       }
-
-       port->xmit_buf[port->xmit_head++] = ch;
-       port->xmit_head &= SERIAL_XMIT_SIZE - 1;
-       port->xmit_cnt++;
-       restore_flags(flags);
-#ifdef AURORA_DEBUG
-       printk("aurora_put_char: end\n");
-#endif
-}
-
-static void aurora_flush_chars(struct tty_struct * tty)
-{
-       struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
-       unsigned long flags;
-       unsigned char chip;
-
-/*#ifdef AURORA_DEBUG
-       printk("aurora_flush_chars: start\n");
-#endif*/
-       if ((aurora_paranoia_check(port, tty->name, "aurora_flush_chars"))
-               return;
-               
-       chip = AURORA_CD180(port_No(port));
-       
-       if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
-           !port->xmit_buf)
-               return;
-
-       save_flags(flags); cli();
-       port->SRER |= SRER_TXRDY;
-       sbus_writeb(port_No(port) & 7,
-                   &port_Board(port)->r[chip]->r[CD180_CAR]);
-       udelay(1);
-       sbus_writeb(port->SRER,
-                   &port_Board(port)->r[chip]->r[CD180_SRER]);
-       restore_flags(flags);
-/*#ifdef AURORA_DEBUG
-       printk("aurora_flush_chars: end\n");
-#endif*/
-}
-
-static int aurora_write_room(struct tty_struct * tty)
-{
-       struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
-       int     ret;
-
-#ifdef AURORA_DEBUG
-       printk("aurora_write_room: start\n");
-#endif
-       if ((aurora_paranoia_check(port, tty->name, "aurora_write_room"))
-               return 0;
-
-       ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
-       if (ret < 0)
-               ret = 0;
-#ifdef AURORA_DEBUG
-       printk("aurora_write_room: end\n");
-#endif
-       return ret;
-}
-
-static int aurora_chars_in_buffer(struct tty_struct *tty)
-{
-       struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
-                               
-       if ((aurora_paranoia_check(port, tty->name, "aurora_chars_in_buffer"))
-               return 0;
-       
-       return port->xmit_cnt;
-}
-
-static void aurora_flush_buffer(struct tty_struct *tty)
-{
-       struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
-       unsigned long flags;
-
-#ifdef AURORA_DEBUG
-       printk("aurora_flush_buffer: start\n");
-#endif
-       if ((aurora_paranoia_check(port, tty->name, "aurora_flush_buffer"))
-               return;
-
-       save_flags(flags); cli();
-       port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-       restore_flags(flags);
-       
-       tty_wakeup(tty);
-#ifdef AURORA_DEBUG
-       printk("aurora_flush_buffer: end\n");
-#endif
-}
-
-static int aurora_tiocmget(struct tty_struct *tty, struct file *file)
-{
-       struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
-       struct Aurora_board * bp;
-       unsigned char status,chip;
-       unsigned int result;
-       unsigned long flags;
-
-#ifdef AURORA_DEBUG
-       printk("aurora_get_modem_info: start\n");
-#endif
-       if ((aurora_paranoia_check(port, tty->name, __FUNCTION__))
-               return -ENODEV;
-
-       chip = AURORA_CD180(port_No(port));
-
-       bp = port_Board(port);
-
-       save_flags(flags); cli();
-
-       sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]);
-       udelay(1);
-
-       status = sbus_readb(&bp->r[chip]->r[CD180_MSVR]);
-       result = 0/*bp->r[chip]->r[AURORA_RI] & (1u << port_No(port)) ? 0 : TIOCM_RNG*/;
-
-       restore_flags(flags);
-
-       result |= ((status & bp->RTS) ? TIOCM_RTS : 0)
-               | ((status & bp->DTR) ? TIOCM_DTR : 0)
-               | ((status & MSVR_CD)  ? TIOCM_CAR : 0)
-               | ((status & MSVR_DSR) ? TIOCM_DSR : 0)
-               | ((status & MSVR_CTS) ? TIOCM_CTS : 0);
-
-#ifdef AURORA_DEBUG
-       printk("aurora_get_modem_info: end\n");
-#endif
-       return result;
-}
-
-static int aurora_tiocmset(struct tty_struct *tty, struct file *file,
-                          unsigned int set, unsigned int clear)
-{
-       struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
-       unsigned int arg;
-       unsigned long flags;
-       struct Aurora_board *bp = port_Board(port);
-       unsigned char chip;
-
-#ifdef AURORA_DEBUG
-       printk("aurora_set_modem_info: start\n");
-#endif
-       if ((aurora_paranoia_check(port, tty->name, __FUNCTION__))
-               return -ENODEV;
-
-       chip = AURORA_CD180(port_No(port));
-
-       save_flags(flags); cli();
-       if (set & TIOCM_RTS)
-               port->MSVR |= bp->RTS;
-       if (set & TIOCM_DTR)
-               port->MSVR |= bp->DTR;
-       if (clear & TIOCM_RTS)
-               port->MSVR &= ~bp->RTS;
-       if (clear & TIOCM_DTR)
-               port->MSVR &= ~bp->DTR;
-
-       sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]);
-       udelay(1);
-
-       sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]);
-
-       restore_flags(flags);
-#ifdef AURORA_DEBUG
-       printk("aurora_set_modem_info: end\n");
-#endif
-       return 0;
-}
-
-static void aurora_send_break(struct Aurora_port * port, unsigned long length)
-{
-       struct Aurora_board *bp = port_Board(port);
-       unsigned long flags;
-       unsigned char chip;
-       
-#ifdef AURORA_DEBUG
-       printk("aurora_send_break: start\n");
-#endif
-       chip = AURORA_CD180(port_No(port));
-       
-       save_flags(flags); cli();
-
-       port->break_length = AURORA_TPS / HZ * length;
-       port->COR2 |= COR2_ETC;
-       port->SRER  |= SRER_TXRDY;
-       sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]);
-       udelay(1);
-
-       sbus_writeb(port->COR2, &bp->r[chip]->r[CD180_COR2]);
-       sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]);
-       aurora_wait_CCR(bp->r[chip]);
-
-       sbus_writeb(CCR_CORCHG2, &bp->r[chip]->r[CD180_CCR]);
-       aurora_wait_CCR(bp->r[chip]);
-
-       restore_flags(flags);
-#ifdef AURORA_DEBUG
-       printk("aurora_send_break: end\n");
-#endif
-}
-
-static int aurora_set_serial_info(struct Aurora_port * port,
-                                 struct serial_struct * newinfo)
-{
-       struct serial_struct tmp;
-       struct Aurora_board *bp = port_Board(port);
-       int change_speed;
-       unsigned long flags;
-
-#ifdef AURORA_DEBUG
-       printk("aurora_set_serial_info: start\n");
-#endif
-       if (copy_from_user(&tmp, newinfo, sizeof(tmp)))
-               return -EFAULT;
-#if 0  
-       if ((tmp.irq != bp->irq) ||
-           (tmp.port != bp->base) ||
-           (tmp.type != PORT_CIRRUS) ||
-           (tmp.baud_base != (bp->oscfreq + CD180_TPC/2) / CD180_TPC) ||
-           (tmp.custom_divisor != 0) ||
-           (tmp.xmit_fifo_size != CD180_NFIFO) ||
-           (tmp.flags & ~AURORA_LEGAL_FLAGS))
-               return -EINVAL;
-#endif 
-       
-       change_speed = ((port->flags & ASYNC_SPD_MASK) !=
-                       (tmp.flags & ASYNC_SPD_MASK));
-       
-       if (!capable(CAP_SYS_ADMIN)) {
-               if ((tmp.close_delay != port->close_delay) ||
-                   (tmp.closing_wait != port->closing_wait) ||
-                   ((tmp.flags & ~ASYNC_USR_MASK) !=
-                    (port->flags & ~ASYNC_USR_MASK)))  
-                       return -EPERM;
-               port->flags = ((port->flags & ~ASYNC_USR_MASK) |
-                              (tmp.flags & ASYNC_USR_MASK));
-       } else  {
-               port->flags = ((port->flags & ~ASYNC_FLAGS) |
-                              (tmp.flags & ASYNC_FLAGS));
-               port->close_delay = tmp.close_delay;
-               port->closing_wait = tmp.closing_wait;
-       }
-       if (change_speed)  {
-               save_flags(flags); cli();
-               aurora_change_speed(bp, port);
-               restore_flags(flags);
-       }
-#ifdef AURORA_DEBUG
-       printk("aurora_set_serial_info: end\n");
-#endif
-       return 0;
-}
-
-extern int aurora_get_serial_info(struct Aurora_port * port,
-                                 struct serial_struct * retinfo)
-{
-       struct serial_struct tmp;
-       struct Aurora_board *bp = port_Board(port);
-       
-#ifdef AURORA_DEBUG
-       printk("aurora_get_serial_info: start\n");
-#endif
-       if (!access_ok(VERIFY_WRITE, (void *) retinfo, sizeof(tmp)))
-               return -EFAULT;
-       
-       memset(&tmp, 0, sizeof(tmp));
-       tmp.type = PORT_CIRRUS;
-       tmp.line = port - aurora_port;
-       tmp.port = 0;
-       tmp.irq  = bp->irq;
-       tmp.flags = port->flags;
-       tmp.baud_base = (bp->oscfreq + CD180_TPC/2) / CD180_TPC;
-       tmp.close_delay = port->close_delay * HZ/100;
-       tmp.closing_wait = port->closing_wait * HZ/100;
-       tmp.xmit_fifo_size = CD180_NFIFO;
-       copy_to_user(retinfo, &tmp, sizeof(tmp));
-#ifdef AURORA_DEBUG
-printk("aurora_get_serial_info: end\n");
-#endif
-       return 0;
-}
-
-static int aurora_ioctl(struct tty_struct * tty, struct file * filp, 
-                   unsigned int cmd, unsigned long arg)
-                   
-{
-       struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
-       int retval;
-
-#ifdef AURORA_DEBUG
-       printk("aurora_ioctl: start\n");
-#endif
-       if ((aurora_paranoia_check(port, tty->name, "aurora_ioctl"))
-               return -ENODEV;
-       
-       switch (cmd) {
-       case TCSBRK:    /* SVID version: non-zero arg --> no break */
-               retval = tty_check_change(tty);
-               if (retval)
-                       return retval;
-               tty_wait_until_sent(tty, 0);
-               if (!arg)
-                       aurora_send_break(port, HZ/4);  /* 1/4 second */
-               return 0;
-       case TCSBRKP:   /* support for POSIX tcsendbreak() */
-               retval = tty_check_change(tty);
-               if (retval)
-                       return retval;
-               tty_wait_until_sent(tty, 0);
-               aurora_send_break(port, arg ? arg*(HZ/10) : HZ/4);
-               return 0;
-       case TIOCGSOFTCAR:
-               return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *)arg);
-       case TIOCSSOFTCAR:
-               if (get_user(arg,(unsigned long *)arg))
-                       return -EFAULT;
-               tty->termios->c_cflag =
-                       ((tty->termios->c_cflag & ~CLOCAL) |
-                        (arg ? CLOCAL : 0));
-               return 0;
-       case TIOCGSERIAL:       
-               return aurora_get_serial_info(port, (struct serial_struct *) arg);
-       case TIOCSSERIAL:       
-               return aurora_set_serial_info(port, (struct serial_struct *) arg);
-       default:
-               return -ENOIOCTLCMD;
-       };
-#ifdef AURORA_DEBUG
-       printk("aurora_ioctl: end\n");
-#endif
-       return 0;
-}
-
-static void aurora_throttle(struct tty_struct * tty)
-{
-       struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
-       struct Aurora_board *bp;
-       unsigned long flags;
-       unsigned char chip;
-
-#ifdef AURORA_DEBUG
-       printk("aurora_throttle: start\n");
-#endif
-       if ((aurora_paranoia_check(port, tty->name, "aurora_throttle"))
-               return;
-       
-       bp = port_Board(port);
-       chip = AURORA_CD180(port_No(port));
-       
-       save_flags(flags); cli();
-       port->MSVR &= ~bp->RTS;
-       sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]);
-       udelay(1);
-       if (I_IXOFF(tty))  {
-               aurora_wait_CCR(bp->r[chip]);
-               sbus_writeb(CCR_SSCH2, &bp->r[chip]->r[CD180_CCR]);
-               aurora_wait_CCR(bp->r[chip]);
-       }
-       sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]);
-       restore_flags(flags);
-#ifdef AURORA_DEBUG
-       printk("aurora_throttle: end\n");
-#endif
-}
-
-static void aurora_unthrottle(struct tty_struct * tty)
-{
-       struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
-       struct Aurora_board *bp;
-       unsigned long flags;
-       unsigned char chip;
-
-#ifdef AURORA_DEBUG
-       printk("aurora_unthrottle: start\n");
-#endif
-       if ((aurora_paranoia_check(port, tty->name, "aurora_unthrottle"))
-               return;
-       
-       bp = port_Board(port);
-       
-       chip = AURORA_CD180(port_No(port));
-       
-       save_flags(flags); cli();
-       port->MSVR |= bp->RTS;
-       sbus_writeb(port_No(port) & 7,
-                   &bp->r[chip]->r[CD180_CAR]);
-       udelay(1);
-       if (I_IXOFF(tty))  {
-               aurora_wait_CCR(bp->r[chip]);
-               sbus_writeb(CCR_SSCH1,
-                           &bp->r[chip]->r[CD180_CCR]);
-               aurora_wait_CCR(bp->r[chip]);
-       }
-       sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]);
-       restore_flags(flags);
-#ifdef AURORA_DEBUG
-       printk("aurora_unthrottle: end\n");
-#endif
-}
-
-static void aurora_stop(struct tty_struct * tty)
-{
-       struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
-       struct Aurora_board *bp;
-       unsigned long flags;
-       unsigned char chip;
-
-#ifdef AURORA_DEBUG
-       printk("aurora_stop: start\n");
-#endif
-       if ((aurora_paranoia_check(port, tty->name, "aurora_stop"))
-               return;
-       
-       bp = port_Board(port);
-       
-       chip = AURORA_CD180(port_No(port));
-       
-       save_flags(flags); cli();
-       port->SRER &= ~SRER_TXRDY;
-       sbus_writeb(port_No(port) & 7,
-                   &bp->r[chip]->r[CD180_CAR]);
-       udelay(1);
-       sbus_writeb(port->SRER,
-                   &bp->r[chip]->r[CD180_SRER]);
-       restore_flags(flags);
-#ifdef AURORA_DEBUG
-       printk("aurora_stop: end\n");
-#endif
-}
-
-static void aurora_start(struct tty_struct * tty)
-{
-       struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
-       struct Aurora_board *bp;
-       unsigned long flags;
-       unsigned char chip;
-
-#ifdef AURORA_DEBUG
-       printk("aurora_start: start\n");
-#endif
-       if ((aurora_paranoia_check(port, tty->name, "aurora_start"))
-               return;
-       
-       bp = port_Board(port);
-       
-       chip = AURORA_CD180(port_No(port));
-       
-       save_flags(flags); cli();
-       if (port->xmit_cnt && port->xmit_buf && !(port->SRER & SRER_TXRDY))  {
-               port->SRER |= SRER_TXRDY;
-               sbus_writeb(port_No(port) & 7,
-                           &bp->r[chip]->r[CD180_CAR]);
-               udelay(1);
-               sbus_writeb(port->SRER,
-                           &bp->r[chip]->r[CD180_SRER]);
-       }
-       restore_flags(flags);
-#ifdef AURORA_DEBUG
-       printk("aurora_start: end\n");
-#endif
-}
-
-/*
- * This routine is called from the scheduler tqueue when the interrupt
- * routine has signalled that a hangup has occurred.  The path of
- * hangup processing is:
- *
- *     serial interrupt routine -> (scheduler tqueue) ->
- *     do_aurora_hangup() -> tty->hangup() -> aurora_hangup()
- * 
- */
-static void do_aurora_hangup(void *private_)
-{
-       struct Aurora_port      *port = (struct Aurora_port *) private_;
-       struct tty_struct       *tty;
-
-#ifdef AURORA_DEBUG
-       printk("do_aurora_hangup: start\n");
-#endif
-       tty = port->tty;
-       if (tty != NULL) {
-               tty_hangup(tty);        /* FIXME: module removal race - AKPM */
-#ifdef AURORA_DEBUG
-               printk("do_aurora_hangup: end\n");
-#endif
-       }
-}
-
-static void aurora_hangup(struct tty_struct * tty)
-{
-       struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
-       struct Aurora_board *bp;
-                               
-#ifdef AURORA_DEBUG
-       printk("aurora_hangup: start\n");
-#endif
-       if ((aurora_paranoia_check(port, tty->name, "aurora_hangup"))
-               return;
-       
-       bp = port_Board(port);
-       
-       aurora_shutdown_port(bp, port);
-       port->event = 0;
-       port->count = 0;
-       port->flags &= ~ASYNC_NORMAL_ACTIVE;
-       port->tty = 0;
-       wake_up_interruptible(&port->open_wait);
-#ifdef AURORA_DEBUG
-       printk("aurora_hangup: end\n");
-#endif
-}
-
-static void aurora_set_termios(struct tty_struct * tty, struct termios * old_termios)
-{
-       struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
-       unsigned long flags;
-
-#ifdef AURORA_DEBUG
-       printk("aurora_set_termios: start\n");
-#endif
-       if ((aurora_paranoia_check(port, tty->name, "aurora_set_termios"))
-               return;
-       
-       if (tty->termios->c_cflag == old_termios->c_cflag &&
-           tty->termios->c_iflag == old_termios->c_iflag)
-               return;
-
-       save_flags(flags); cli();
-       aurora_change_speed(port_Board(port), port);
-       restore_flags(flags);
-
-       if ((old_termios->c_cflag & CRTSCTS) &&
-           !(tty->termios->c_cflag & CRTSCTS)) {
-               tty->hw_stopped = 0;
-               aurora_start(tty);
-       }
-#ifdef AURORA_DEBUG
-       printk("aurora_set_termios: end\n");
-#endif
-}
-
-static void do_aurora_bh(void)
-{
-        run_task_queue(&tq_aurora);
-}
-
-static void do_softint(void *private_)
-{
-       struct Aurora_port      *port = (struct Aurora_port *) private_;
-       struct tty_struct       *tty;
-
-#ifdef AURORA_DEBUG
-       printk("do_softint: start\n");
-#endif
-       tty = port->tty;
-       if (tty == NULL)
-               return;
-
-       if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
-               tty_wakeup(tty);
-       }
-#ifdef AURORA_DEBUG
-       printk("do_softint: end\n");
-#endif
-}
-
-static const struct tty_operations aurora_ops = {
-       .open  = aurora_open,
-       .close = aurora_close,
-       .write = aurora_write,
-       .put_char = aurora_put_char,
-       .flush_chars = aurora_flush_chars,
-       .write_room = aurora_write_room,
-       .chars_in_buffer = aurora_chars_in_buffer,
-       .flush_buffer = aurora_flush_buffer,
-       .ioctl = aurora_ioctl,
-       .throttle = aurora_throttle,
-       .unthrottle = aurora_unthrottle,
-       .set_termios = aurora_set_termios,
-       .stop = aurora_stop,
-       .start = aurora_start,
-       .hangup = aurora_hangup,
-       .tiocmget = aurora_tiocmget,
-       .tiocmset = aurora_tiocmset,
-};
-
-static int aurora_init_drivers(void)
-{
-       int error;
-       int i;
-
-#ifdef AURORA_DEBUG
-       printk("aurora_init_drivers: start\n");
-#endif
-       tmp_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL);
-       if (tmp_buf == NULL) {
-               printk(KERN_ERR "aurora: Couldn't get free page.\n");
-               return 1;
-       }
-       init_bh(AURORA_BH, do_aurora_bh);
-       aurora_driver = alloc_tty_driver(AURORA_INPORTS);
-       if (!aurora_driver) {
-               printk(KERN_ERR "aurora: Couldn't allocate tty driver.\n");
-               free_page((unsigned long) tmp_buf);
-               return 1;
-       }
-       aurora_driver->owner = THIS_MODULE;
-       aurora_driver->name = "ttyA";
-       aurora_driver->major = AURORA_MAJOR;
-       aurora_driver->type = TTY_DRIVER_TYPE_SERIAL;
-       aurora_driver->subtype = SERIAL_TYPE_NORMAL;
-       aurora_driver->init_termios = tty_std_termios;
-       aurora_driver->init_termios.c_cflag =
-               B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-       aurora_driver->flags = TTY_DRIVER_REAL_RAW;
-       tty_set_operations(aurora_driver, &aurora_ops);
-       error = tty_register_driver(aurora_driver);
-       if (error) {
-               put_tty_driver(aurora_driver);
-               free_page((unsigned long) tmp_buf);
-               printk(KERN_ERR "aurora: Couldn't register aurora driver, error = %d\n",
-                      error);
-               return 1;
-       }
-       
-       memset(aurora_port, 0, sizeof(aurora_port));
-       for (i = 0; i < AURORA_TNPORTS; i++)  {
-               aurora_port[i].magic = AURORA_MAGIC;
-               aurora_port[i].tqueue.routine = do_softint;
-               aurora_port[i].tqueue.data = &aurora_port[i];
-               aurora_port[i].tqueue_hangup.routine = do_aurora_hangup;
-               aurora_port[i].tqueue_hangup.data = &aurora_port[i];
-               aurora_port[i].close_delay = 50 * HZ/100;
-               aurora_port[i].closing_wait = 3000 * HZ/100;
-               init_waitqueue_head(&aurora_port[i].open_wait);
-               init_waitqueue_head(&aurora_port[i].close_wait);
-       }
-#ifdef AURORA_DEBUG
-       printk("aurora_init_drivers: end\n");
-#endif
-       return 0;
-}
-
-static void aurora_release_drivers(void)
-{
-#ifdef AURORA_DEBUG
-       printk("aurora_release_drivers: start\n");
-#endif
-       free_page((unsigned long)tmp_buf);
-       tty_unregister_driver(aurora_driver);
-       put_tty_driver(aurora_driver);
-#ifdef AURORA_DEBUG
-       printk("aurora_release_drivers: end\n");
-#endif
-}
-
-/*
- * Called at boot time.
- *
- * You can specify IO base for up to RC_NBOARD cards,
- * using line "riscom8=0xiobase1,0xiobase2,.." at LILO prompt.
- * Note that there will be no probing at default
- * addresses in this case.
- *
- */
-void __init aurora_setup(char *str, int *ints)
-{
-       int i;
-
-       for(i=0;(i<ints[0])&&(i<4);i++) {
-               if (ints[i+1]) irqs[i]=ints[i+1];
-               }
-}
-
-static int __init aurora_real_init(void)
-{
-       int found;
-       int i;
-
-       printk(KERN_INFO "aurora: Driver starting.\n");
-       if(aurora_init_drivers())
-               return -EIO;
-       found = aurora_probe();
-       if(!found) {
-               aurora_release_drivers();
-               printk(KERN_INFO "aurora: No Aurora Multiport boards detected.\n");
-               return -EIO;
-       } else {
-               printk(KERN_INFO "aurora: %d boards found.\n", found);
-       }
-       for (i = 0; i < found; i++) {
-               int ret = aurora_setup_board(&aurora_board[i]);
-
-               if (ret) {
-#ifdef AURORA_DEBUG
-                       printk(KERN_ERR "aurora_init: error aurora_setup_board ret %d\n",
-                              ret);
-#endif
-                       return ret;
-               }
-       }
-       return 0;
-}
-
-int irq  = 0;
-int irq1 = 0;
-int irq2 = 0;
-int irq3 = 0;
-module_param(irq , int, 0);
-module_param(irq1, int, 0);
-module_param(irq2, int, 0);
-module_param(irq3, int, 0);
-
-static int __init aurora_init(void) 
-{
-       if (irq ) irqs[0]=irq ;
-       if (irq1) irqs[1]=irq1;
-       if (irq2) irqs[2]=irq2;
-       if (irq3) irqs[3]=irq3;
-       return aurora_real_init();
-}
-       
-static void __exit aurora_cleanup(void)
-{
-       int i;
-       
-#ifdef AURORA_DEBUG
-printk("cleanup_module: aurora_release_drivers\n");
-#endif
-
-       aurora_release_drivers();
-       for (i = 0; i < AURORA_NBOARD; i++)
-               if (aurora_board[i].flags & AURORA_BOARD_PRESENT) {
-                       aurora_shutdown_board(&aurora_board[i]);
-                       aurora_release_io_range(&aurora_board[i]);
-               }
-}
-
-module_init(aurora_init);
-module_exit(aurora_cleanup);
-MODULE_LICENSE("GPL");
diff --git a/drivers/sbus/char/aurora.h b/drivers/sbus/char/aurora.h
deleted file mode 100644 (file)
index b8b5476..0000000
+++ /dev/null
@@ -1,276 +0,0 @@
-/*     $Id: aurora.h,v 1.6 2001/06/05 12:23:38 davem Exp $
- *     linux/drivers/sbus/char/aurora.h -- Aurora multiport driver
- *
- *     Copyright (c) 1999 by Oliver Aldulea (oli@bv.ro)
- *
- *     This code is based on the RISCom/8 multiport serial driver written
- *     by Dmitry Gorodchanin (pgmdsg@ibi.com), based on the Linux serial
- *     driver, written by Linus Torvalds, Theodore T'so and others.
- *     The Aurora multiport programming info was obtained mainly from the
- *     Cirrus Logic CD180 documentation (available on the web), and by
- *     doing heavy tests on the board. Many thanks to Eddie C. Dost for the
- *     help on the sbus interface.
- *
- *     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.
- *
- *     Revision 1.0
- *
- *     This is the first public release.
- *
- *     This version needs a lot of feedback. This is the version that works
- *     with _my_ board. My board is model 1600se, revision '@(#)1600se.fth
- *     1.2 3/28/95 1'. The driver might work with your board, but I do not
- *     guarantee it. If you have _any_ type of board, I need to know if the
- *     driver works or not, I need to know exactly your board parameters
- *     (get them with 'cd /proc/openprom/iommu/sbus/sio16/; ls *; cat *')
- *     Also, I need your board revision code, which is written on the board.
- *     Send me the output of my driver too (it outputs through klogd).
- *
- *     If the driver does not work, you can try enabling the debug options
- *     to see what's wrong or what should be done.
- *
- *     I'm sorry about the alignment of the code. It was written in a
- *     128x48 environment.
- *
- *     I must say that I do not like Aurora Technologies' policy. I asked
- *     them to help me do this driver faster, but they ended by something
- *     like "don't call us, we'll call you", and I never heard anything
- *     from them. They told me "knowing the way the board works, I don't
- *     doubt you and others on the net will make the driver."
- *     The truth about this board is that it has nothing intelligent on it.
- *     If you want to say to somebody what kind of board you have, say that
- *     it uses Cirrus Logic processors (CD180). The power of the board is
- *     in those two chips. The rest of the board is the interface to the
- *     sbus and to the peripherals. Still, they did something smart: they
- *     reversed DTR and RTS to make on-board automatic hardware flow
- *     control usable.
- *     Thanks to Aurora Technologies for wasting my time, nerves and money.
- */
-
-#ifndef __LINUX_AURORA_H
-#define __LINUX_AURORA_H
-
-#include <linux/serial.h>
-#include <linux/serialP.h>
-
-#ifdef __KERNEL__
-
-/* This is the number of boards to support. I've only tested this driver with
- * one board, so it might not work.
- */
-#define AURORA_NBOARD 1
-
-/* Useful ? Yes. But you can safely comment the warnings if they annoy you
- * (let me say that again: the warnings in the code, not this define). 
- */
-#define AURORA_PARANOIA_CHECK
-
-/* Well, after many lost nights, I found that the IRQ for this board is
- * selected from four built-in values by writing some bits in the
- * configuration register. This causes a little problem to occur: which
- * IRQ to select ? Which one is the best for the user ? Well, I finally
- * decided for the following algorithm: if the "bintr" value is not acceptable
- * (not within type_1_irq[], then test the "intr" value, if that fails too,
- * try each value from type_1_irq until succeded. Hope it's ok.
- * You can safely reorder the irq's.
- */
-#define TYPE_1_IRQS 4
-unsigned char type_1_irq[TYPE_1_IRQS] = {
-       3, 5, 9, 13
-};
-/* I know something about another method of interrupt setting, but not enough.
- * Also, this is for another type of board, so I first have to learn how to
- * detect it.
-#define TYPE_2_IRQS 3
-unsigned char type_2_irq[TYPE_2_IRQS] = {
-       0, 0, 0 ** could anyone find these for me ? (see AURORA_ALLIRQ below) **
-       };
-unsigned char type_2_mask[TYPE_2_IRQS] = {
-       32, 64, 128
-       };
-*/
-
-/* The following section should only be modified by those who know what
- * they're doing (or don't, but want to help with some feedback). Modifying
- * anything raises a _big_ probability for your system to hang, but the
- * sacrifice worths. (I sacrificed my ext2fs many, many times...)
- */
-
-/* This one tries to dump to console the name of almost every function called,
- * and many other debugging info.
- */
-#undef AURORA_DEBUG
-
-/* These are the most dangerous and useful defines. They do printk() during
- * the interrupt processing routine(s), so if you manage to get "flooded" by
- * irq's, start thinking about the "Power off/on" button...
- */
-#undef AURORA_INTNORM  /* This one enables the "normal" messages, but some
-                        * of them cause flood, so I preffered putting
-                        * them under a define */
-#undef AURORA_INT_DEBUG /* This one is really bad. */
-
-/* Here's something helpful: after n irq's, the board will be disabled. This
- * prevents irq flooding during debug (no need to think about power
- * off/on anymore...)
- */
-#define AURORA_FLOODPRO        10
-
-/* This one helps finding which irq the board calls, in case of a strange/
- * unsupported board. AURORA_INT_DEBUG should be enabled, because I don't
- * think /proc/interrupts or any command will be available in case of an irq
- * flood... "allirq" is the list of all free irq's.
- */
-/*
-#define AURORA_ALLIRQ 6
-int allirq[AURORA_ALLIRQ]={
-       2,3,5,7,9,13
-       };
-*/
-
-/* These must not be modified. These values are assumed during the code for
- * performance optimisations.
- */
-#define AURORA_NCD180 2 /* two chips per board */
-#define AURORA_NPORT 8  /* 8 ports per chip */
-
-/* several utilities */
-#define AURORA_BOARD(line)     (((line) >> 4) & 0x01)
-#define AURORA_CD180(line)     (((line) >> 3) & 0x01)
-#define AURORA_PORT(line)      ((line) & 15)
-
-#define AURORA_TNPORTS (AURORA_NBOARD*AURORA_NCD180*AURORA_NPORT)
-
-/* Ticks per sec. Used for setting receiver timeout and break length */
-#define AURORA_TPS             4000
-
-#define AURORA_MAGIC   0x0A18
-
-/* Yeah, after heavy testing I decided it must be 6.
- * Sure, You can change it if needed.
- */
-#define AURORA_RXFIFO          6       /* Max. receiver FIFO size (1-8) */
-
-#define AURORA_RXTH            7
-
-struct aurora_reg1 {
-       __volatile__ unsigned char r;
-};
-
-struct aurora_reg128 {
-       __volatile__ unsigned char r[128];
-};
-       
-struct aurora_reg4 {
-       __volatile__ unsigned char r[4];
-};
-
-struct Aurora_board {
-       unsigned long           flags;
-       struct aurora_reg1      * r0;   /* This is the board configuration
-                                        * register (write-only). */
-       struct aurora_reg128    * r[2]; /* These are the registers for the
-                                        * two chips. */
-       struct aurora_reg4      * r3;   /* These are used for hardware-based
-                                        * acknowledge. Software-based ack is
-                                        * not supported by CD180. */
-       unsigned int            oscfreq; /* The on-board oscillator
-                                         * frequency, in Hz. */
-       unsigned char           irq;
-#ifdef MODULE
-       signed char             count;  /* counts the use of the board */
-#endif
-       /* Values for the dtr_rts swapped mode. */
-       unsigned char           DTR;
-       unsigned char           RTS;
-       unsigned char           MSVDTR;
-       unsigned char           MSVRTS;
-       /* Values for hardware acknowledge. */
-       unsigned char           ACK_MINT, ACK_TINT, ACK_RINT;
-};
-
-/* Board configuration register */
-#define AURORA_CFG_ENABLE_IO   8
-#define AURORA_CFG_ENABLE_IRQ  4
-
-/* Board flags */
-#define AURORA_BOARD_PRESENT           0x00000001
-#define AURORA_BOARD_ACTIVE            0x00000002
-#define AURORA_BOARD_TYPE_2            0x00000004      /* don't know how to
-                                                        * detect this yet */
-#define AURORA_BOARD_DTR_FLOW_OK       0x00000008
-
-/* The story goes like this: Cirrus programmed the CD-180 chip to do automatic
- * hardware flow control, and do it using CTS and DTR. CTS is ok, but, if you
- * have a modem and the chip drops DTR, then the modem will drop the carrier
- * (ain't that cute...). Luckily, the guys at Aurora decided to swap DTR and
- * RTS, which makes the flow control usable. I hope that all the boards made
- * by Aurora have these two signals swapped. If your's doesn't but you have a
- * breakout box, you can try to reverse them yourself, then set the following
- * flag.
- */
-#undef AURORA_FORCE_DTR_FLOW
-
-/* In fact, a few more words have to be said about hardware flow control.
- * This driver handles "output" flow control through the on-board facility
- * CTS Auto Enable. For the "input" flow control there are two cases when
- * the flow should be controlled. The first case is when the kernel is so
- * busy that it cannot process IRQ's in time; this flow control can only be
- * activated by the on-board chip, and if the board has RTS and DTR swapped,
- * this facility is usable. The second case is when the application is so
- * busy that it cannot receive bytes from the kernel, and this flow must be
- * activated by software. This second case is not yet implemented in this
- * driver. Unfortunately, I estimate that the second case is the one that
- * occurs the most.
- */
-
-
-struct Aurora_port {
-       int                     magic;
-       int                     baud_base;
-       int                     flags;
-       struct tty_struct       * tty;
-       int                     count;
-       int                     blocked_open;
-       long                    event;
-       int                     timeout;
-       int                     close_delay;
-       unsigned char           * xmit_buf;
-       int                     custom_divisor;
-       int                     xmit_head;
-       int                     xmit_tail;
-       int                     xmit_cnt;
-       wait_queue_head_t       open_wait;
-       wait_queue_head_t       close_wait;
-       struct tq_struct        tqueue;
-       struct tq_struct        tqueue_hangup;
-       short                   wakeup_chars;
-       short                   break_length;
-       unsigned short          closing_wait;
-       unsigned char           mark_mask;
-       unsigned char           SRER;
-       unsigned char           MSVR;
-       unsigned char           COR2;
-#ifdef AURORA_REPORT_OVERRUN
-       unsigned long           overrun;
-#endif 
-#ifdef AURORA_REPORT_FIFO
-       unsigned long           hits[10];
-#endif
-};
-
-#endif
-#endif /*__LINUX_AURORA_H*/
-
index 22631f8b9b481208ae19c6daacea6ae2bab3a2e6..8410587348f1dcc5084cafc0df55937c0279e193 100644 (file)
@@ -187,19 +187,20 @@ static int wait_for_pin(struct bbc_i2c_bus *bp, u8 *status)
        bp->waiting = 1;
        add_wait_queue(&bp->wq, &wait);
        while (limit-- > 0) {
-               u8 val;
-
-               set_current_state(TASK_INTERRUPTIBLE);
-               *status = val = readb(bp->i2c_control_regs + 0);
-               if ((val & I2C_PCF_PIN) == 0) {
+               unsigned long val;
+
+               val = wait_event_interruptible_timeout(
+                               bp->wq,
+                               (((*status = readb(bp->i2c_control_regs + 0))
+                                 & I2C_PCF_PIN) == 0),
+                               msecs_to_jiffies(250));
+               if (val > 0) {
                        ret = 0;
                        break;
                }
-               msleep_interruptible(250);
        }
        remove_wait_queue(&bp->wq, &wait);
        bp->waiting = 0;
-       current->state = TASK_RUNNING;
 
        return ret;
 }
@@ -340,7 +341,7 @@ static irqreturn_t bbc_i2c_interrupt(int irq, void *dev_id)
         */
        if (bp->waiting &&
            !(readb(bp->i2c_control_regs + 0x0) & I2C_PCF_PIN))
-               wake_up(&bp->wq);
+               wake_up_interruptible(&bp->wq);
 
        return IRQ_HANDLED;
 }
diff --git a/drivers/sbus/char/cd180.h b/drivers/sbus/char/cd180.h
deleted file mode 100644 (file)
index 445b86c..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-
-/* Definitions for Cirrus Logic CL-CD180 8-port async mux chip */
-#define CD180_NCH       8       /* Total number of channels                */
-#define CD180_TPC       16      /* Ticks per character                     */
-#define CD180_NFIFO    8       /* TX FIFO size                            */
-
-/* Global registers */
-#define CD180_GFRCR    0x6b    /* Global Firmware Revision Code Register  */
-#define CD180_SRCR     0x66    /* Service Request Configuration Register  */
-#define CD180_PPRH     0x70    /* Prescaler Period Register High          */
-#define CD180_PPRL     0x71    /* Prescaler Period Register Low           */
-#define CD180_MSMR     0x61    /* Modem Service Match Register            */
-#define CD180_TSMR     0x62    /* Transmit Service Match Register         */
-#define CD180_RSMR     0x63    /* Receive Service Match Register          */
-#define CD180_GSVR     0x40    /* Global Service Vector Register          */
-#define CD180_SRSR     0x65    /* Service Request Status Register         */
-#define CD180_GSCR     0x41    /* Global Service Channel Register         */
-#define CD180_CAR      0x64    /* Channel Access Register                 */
-
-/* Indexed registers */
-#define CD180_RDCR     0x07    /* Receive Data Count Register             */
-#define CD180_RDR      0x78    /* Receiver Data Register                  */
-#define CD180_RCSR     0x7a    /* Receiver Character Status Register      */
-#define CD180_TDR      0x7b    /* Transmit Data Register                  */
-#define CD180_EOSRR    0x7f    /* End of Service Request Register         */
-
-/* Channel Registers */
-#define CD180_SRER      0x02    /* Service Request Enable Register         */
-#define CD180_CCR       0x01    /* Channel Command Register                */
-#define CD180_COR1      0x03    /* Channel Option Register 1               */
-#define CD180_COR2      0x04    /* Channel Option Register 2               */
-#define CD180_COR3      0x05    /* Channel Option Register 3               */
-#define CD180_CCSR      0x06    /* Channel Control Status Register         */
-#define CD180_RTPR      0x18    /* Receive Timeout Period Register         */
-#define CD180_RBPRH     0x31    /* Receive Bit Rate Period Register High  */
-#define CD180_RBPRL     0x32    /* Receive Bit Rate Period Register Low   */
-#define CD180_TBPRH     0x39    /* Transmit Bit Rate Period Register High */
-#define CD180_TBPRL     0x3a    /* Transmit Bit Rate Period Register Low  */
-#define CD180_SCHR1     0x09    /* Special Character Register 1            */
-#define CD180_SCHR2     0x0a    /* Special Character Register 2            */
-#define CD180_SCHR3     0x0b    /* Special Character Register 3            */
-#define CD180_SCHR4     0x0c    /* Special Character Register 4            */
-#define CD180_MCR       0x12    /* Modem Change Register                   */
-#define CD180_MCOR1     0x10    /* Modem Change Option 1 Register          */
-#define CD180_MCOR2     0x11    /* Modem Change Option 2 Register          */
-#define CD180_MSVR      0x28    /* Modem Signal Value Register             */
-#define CD180_MSVRTS    0x29    /* Modem Signal Value RTS                  */
-#define CD180_MSVDTR    0x2a    /* Modem Signal Value DTR                  */
-
-/* Global Interrupt Vector Register (R/W) */
-
-#define GSVR_ITMASK     0x07     /* Interrupt type mask                     */
-#define  GSVR_IT_MDM     0x01    /* Modem Signal Change Interrupt           */
-#define  GSVR_IT_TX      0x02    /* Transmit Data Interrupt                 */
-#define  GSVR_IT_RGD     0x03    /* Receive Good Data Interrupt             */
-#define  GSVR_IT_REXC    0x07    /* Receive Exception Interrupt             */
-
-
-/* Global Interrupt Channel Register (R/W) */
-#define GSCR_CHAN       0x1c    /* Channel Number Mask                     */
-#define GSCR_CHAN_OFF   2       /* Channel Number Offset                   */
-
-
-/* Channel Address Register (R/W) */
-
-#define CAR_CHAN        0x07    /* Channel Number Mask                     */
-
-
-/* Receive Character Status Register (R/O) */
-
-#define RCSR_TOUT       0x80    /* Rx Timeout                              */
-#define RCSR_SCDET      0x70    /* Special Character Detected Mask         */
-#define  RCSR_NO_SC      0x00   /* No Special Characters Detected          */
-#define  RCSR_SC_1       0x10   /* Special Char 1 (or 1 & 3) Detected      */
-#define  RCSR_SC_2       0x20   /* Special Char 2 (or 2 & 4) Detected      */
-#define  RCSR_SC_3       0x30   /* Special Char 3 Detected                 */
-#define  RCSR_SC_4       0x40   /* Special Char 4 Detected                 */
-#define RCSR_BREAK      0x08    /* Break has been detected                 */
-#define RCSR_PE         0x04    /* Parity Error                            */
-#define RCSR_FE         0x02    /* Frame Error                             */
-#define RCSR_OE         0x01    /* Overrun Error                           */
-
-
-/* Channel Command Register (R/W) (commands in groups can be OR-ed) */
-
-#define CCR_HARDRESET   0x81    /* Reset the chip                          */
-
-#define CCR_SOFTRESET   0x80    /* Soft Channel Reset                      */
-
-#define CCR_CORCHG1     0x42    /* Channel Option Register 1 Changed       */
-#define CCR_CORCHG2     0x44    /* Channel Option Register 2 Changed       */
-#define CCR_CORCHG3     0x48    /* Channel Option Register 3 Changed       */
-
-#define CCR_SSCH1       0x21    /* Send Special Character 1                */
-
-#define CCR_SSCH2       0x22    /* Send Special Character 2                */
-
-#define CCR_SSCH3       0x23    /* Send Special Character 3                */
-
-#define CCR_SSCH4       0x24    /* Send Special Character 4                */
-
-#define CCR_TXEN        0x18    /* Enable Transmitter                      */
-#define CCR_RXEN        0x12    /* Enable Receiver                         */
-
-#define CCR_TXDIS       0x14    /* Disable Transmitter                     */
-#define CCR_RXDIS       0x11    /* Disable Receiver                        */
-
-
-/* Service Request Enable Register (R/W) */
-
-#define SRER_DSR         0x80    /* Enable interrupt on DSR change          */
-#define SRER_CD          0x40    /* Enable interrupt on CD change           */
-#define SRER_CTS         0x20    /* Enable interrupt on CTS change          */
-#define SRER_RXD         0x10    /* Enable interrupt on Receive Data        */
-#define SRER_RXSC        0x08    /* Enable interrupt on Receive Spec. Char  */
-#define SRER_TXRDY       0x04    /* Enable interrupt on TX FIFO empty       */
-#define SRER_TXEMPTY     0x02    /* Enable interrupt on TX completely empty */
-#define SRER_RET         0x01    /* Enable interrupt on RX Exc. Timeout     */
-
-
-/* Channel Option Register 1 (R/W) */
-
-#define COR1_ODDP       0x80    /* Odd Parity                              */
-#define COR1_PARMODE    0x60    /* Parity Mode mask                        */
-#define  COR1_NOPAR      0x00   /* No Parity                               */
-#define  COR1_FORCEPAR   0x20   /* Force Parity                            */
-#define  COR1_NORMPAR    0x40   /* Normal Parity                           */
-#define COR1_IGNORE     0x10    /* Ignore Parity on RX                     */
-#define COR1_STOPBITS   0x0c    /* Number of Stop Bits                     */
-#define  COR1_1SB        0x00   /* 1 Stop Bit                              */
-#define  COR1_15SB       0x04   /* 1.5 Stop Bits                           */
-#define  COR1_2SB        0x08   /* 2 Stop Bits                             */
-#define COR1_CHARLEN    0x03    /* Character Length                        */
-#define  COR1_5BITS      0x00   /* 5 bits                                  */
-#define  COR1_6BITS      0x01   /* 6 bits                                  */
-#define  COR1_7BITS      0x02   /* 7 bits                                  */
-#define  COR1_8BITS      0x03   /* 8 bits                                  */
-
-
-/* Channel Option Register 2 (R/W) */
-
-#define COR2_IXM        0x80    /* Implied XON mode                        */
-#define COR2_TXIBE      0x40    /* Enable In-Band (XON/XOFF) Flow Control  */
-#define COR2_ETC        0x20    /* Embedded Tx Commands Enable             */
-#define COR2_LLM        0x10    /* Local Loopback Mode                     */
-#define COR2_RLM        0x08    /* Remote Loopback Mode                    */
-#define COR2_RTSAO      0x04    /* RTS Automatic Output Enable             */
-#define COR2_CTSAE      0x02    /* CTS Automatic Enable                    */
-#define COR2_DSRAE      0x01    /* DSR Automatic Enable                    */
-
-
-/* Channel Option Register 3 (R/W) */
-
-#define COR3_XONCH      0x80    /* XON is a pair of characters (1 & 3)     */
-#define COR3_XOFFCH     0x40    /* XOFF is a pair of characters (2 & 4)    */
-#define COR3_FCT        0x20    /* Flow-Control Transparency Mode          */
-#define COR3_SCDE       0x10    /* Special Character Detection Enable      */
-#define COR3_RXTH       0x0f    /* RX FIFO Threshold value (1-8)           */
-
-
-/* Channel Control Status Register (R/O) */
-
-#define CCSR_RXEN       0x80    /* Receiver Enabled                        */
-#define CCSR_RXFLOFF    0x40    /* Receive Flow Off (XOFF was sent)        */
-#define CCSR_RXFLON     0x20    /* Receive Flow On (XON was sent)          */
-#define CCSR_TXEN       0x08    /* Transmitter Enabled                     */
-#define CCSR_TXFLOFF    0x04    /* Transmit Flow Off (got XOFF)            */
-#define CCSR_TXFLON     0x02    /* Transmit Flow On (got XON)              */
-
-
-/* Modem Change Option Register 1 (R/W) */
-
-#define MCOR1_DSRZD     0x80    /* Detect 0->1 transition of DSR           */
-#define MCOR1_CDZD      0x40    /* Detect 0->1 transition of CD            */
-#define MCOR1_CTSZD     0x20    /* Detect 0->1 transition of CTS           */
-#define MCOR1_DTRTH     0x0f    /* Auto DTR flow control Threshold (1-8)   */
-#define  MCOR1_NODTRFC   0x0     /* Automatic DTR flow control disabled     */
-
-
-/* Modem Change Option Register 2 (R/W) */
-
-#define MCOR2_DSROD     0x80    /* Detect 1->0 transition of DSR           */
-#define MCOR2_CDOD      0x40    /* Detect 1->0 transition of CD            */
-#define MCOR2_CTSOD     0x20    /* Detect 1->0 transition of CTS           */
-
-
-/* Modem Change Register (R/W) */
-
-#define MCR_DSRCHG      0x80    /* DSR Changed                             */
-#define MCR_CDCHG       0x40    /* CD Changed                              */
-#define MCR_CTSCHG      0x20    /* CTS Changed                             */
-
-
-/* Modem Signal Value Register (R/W) */
-
-#define MSVR_DSR        0x80    /* Current state of DSR input              */
-#define MSVR_CD         0x40    /* Current state of CD input               */
-#define MSVR_CTS        0x20    /* Current state of CTS input              */
-#define MSVR_DTR        0x02    /* Current state of DTR output             */
-#define MSVR_RTS        0x01    /* Current state of RTS output             */
-
-
-/* Service Request Status Register */
-
-#define SRSR_CMASK     0xC0    /* Current Service Context Mask            */
-#define  SRSR_CNONE    0x00    /* Not in a service context                */
-#define  SRSR_CRX      0x40    /* Rx Context                              */
-#define  SRSR_CTX      0x80    /* Tx Context                              */
-#define  SRSR_CMDM     0xC0    /* Modem Context                           */
-#define SRSR_ANYINT    0x6F    /* Any interrupt flag                      */
-#define SRSR_RINT      0x10    /* Receive Interrupt                       */
-#define SRSR_TINT      0x04    /* Transmit Interrupt                      */
-#define SRSR_MINT      0x01    /* Modem Interrupt                         */
-#define SRSR_REXT      0x20    /* Receive External Interrupt              */
-#define SRSR_TEXT      0x08    /* Transmit External Interrupt             */
-#define SRSR_MEXT      0x02    /* Modem External Interrupt                */
-
-
-/* Service Request Configuration Register */
-
-#define SRCR_PKGTYPE    0x80
-#define SRCR_REGACKEN   0x40
-#define SRCR_DAISYEN    0x20
-#define SRCR_GLOBPRI    0x10
-#define SRCR_UNFAIR     0x08
-#define SRCR_AUTOPRI    0x02
-#define SRCR_PRISEL     0x01
-
-/* Values for register-based Interrupt ACKs */
-#define CD180_ACK_MINT 0x75    /* goes to MSMR                            */
-#define CD180_ACK_TINT 0x76    /* goes to TSMR                            */
-#define CD180_ACK_RINT 0x77    /* goes to RSMR                            */
-
-/* Escape characters */
-
-#define CD180_C_ESC     0x00    /* Escape character                        */
-#define CD180_C_SBRK    0x81    /* Start sending BREAK                     */
-#define CD180_C_DELAY   0x82    /* Delay output                            */
-#define CD180_C_EBRK    0x83    /* Stop sending BREAK                      */
index 45cf5bc0bbee210f1d3b9106a80194e4937aef66..44d2ef906ac732aa7b0a4c92467602ad128ab9e6 100644 (file)
@@ -364,6 +364,7 @@ static int __init ts102_uctrl_init(void)
        struct linux_prom_irqs tmp_irq[2];
         unsigned int vaddr[2] = { 0, 0 };
        int tmpnode, uctrlnode = prom_getchild(prom_root_node);
+       int err;
 
        tmpnode = prom_searchsiblings(uctrlnode, "obio");
 
@@ -389,7 +390,12 @@ static int __init ts102_uctrl_init(void)
        if(!driver->irq) 
                driver->irq = tmp_irq[0].pri;
 
-       request_irq(driver->irq, uctrl_interrupt, 0, "uctrl", driver);
+       err = request_irq(driver->irq, uctrl_interrupt, 0, "uctrl", driver);
+       if (err) {
+               printk("%s: unable to register irq %d\n",
+                      __FUNCTION__, driver->irq);
+               return err;
+       }
 
        if (misc_register(&uctrl_dev)) {
                printk("%s: unable to get misc minor %d\n",
index d2d51dc51ab83727f8761ab7c25425ac32ad77a3..82add77ad1316714fbe7cb3b28b65f996e1ac824 100644 (file)
@@ -178,10 +178,10 @@ cumanascsi_2_dma_setup(struct Scsi_Host *host, struct scsi_pointer *SCp,
                        dma_dir = DMA_MODE_READ,
                        alatch_dir = ALATCH_DMA_IN;
 
-               dma_map_sg(dev, info->sg, bufs + 1, map_dir);
+               dma_map_sg(dev, info->sg, bufs, map_dir);
 
                disable_dma(dmach);
-               set_dma_sg(dmach, info->sg, bufs + 1);
+               set_dma_sg(dmach, info->sg, bufs);
                writeb(alatch_dir, info->base + CUMANASCSI2_ALATCH);
                set_dma_mode(dmach, dma_dir);
                enable_dma(dmach);
index d4136524fc46aafc3f794a5f3a37975177535636..ed06a8c19ad649aafcdc06c3ee5bf7fe4ca29815 100644 (file)
@@ -175,10 +175,10 @@ eesoxscsi_dma_setup(struct Scsi_Host *host, struct scsi_pointer *SCp,
                        map_dir = DMA_FROM_DEVICE,
                        dma_dir = DMA_MODE_READ;
 
-               dma_map_sg(dev, info->sg, bufs + 1, map_dir);
+               dma_map_sg(dev, info->sg, bufs, map_dir);
 
                disable_dma(dmach);
-               set_dma_sg(dmach, info->sg, bufs + 1);
+               set_dma_sg(dmach, info->sg, bufs);
                set_dma_mode(dmach, dma_dir);
                enable_dma(dmach);
                return fasdma_real_all;
index 2969cc0ff2599229e8e092de1d35f86c30daa6df..fb5f20284389fd424c092adbd25be039d0e7b042 100644 (file)
@@ -633,7 +633,7 @@ static void fas216_updateptrs(FAS216_Info *info, int bytes_transferred)
 
        BUG_ON(bytes_transferred < 0);
 
-       info->SCpnt->request_bufflen -= bytes_transferred;
+       SCp->phase -= bytes_transferred;
 
        while (bytes_transferred != 0) {
                if (SCp->this_residual > bytes_transferred)
@@ -715,7 +715,7 @@ static void fas216_cleanuptransfer(FAS216_Info *info)
                return;
 
        if (dmatype == fasdma_real_all)
-               total = info->SCpnt->request_bufflen;
+               total = info->scsi.SCp.phase;
        else
                total = info->scsi.SCp.this_residual;
 
@@ -753,7 +753,7 @@ static void fas216_transfer(FAS216_Info *info)
        fas216_log(info, LOG_BUFFER,
                   "starttransfer: buffer %p length 0x%06x reqlen 0x%06x",
                   info->scsi.SCp.ptr, info->scsi.SCp.this_residual,
-                  info->SCpnt->request_bufflen);
+                  info->scsi.SCp.phase);
 
        if (!info->scsi.SCp.ptr) {
                fas216_log(info, LOG_ERROR, "null buffer passed to "
@@ -784,7 +784,7 @@ static void fas216_transfer(FAS216_Info *info)
        info->dma.transfer_type = dmatype;
 
        if (dmatype == fasdma_real_all)
-               fas216_set_stc(info, info->SCpnt->request_bufflen);
+               fas216_set_stc(info, info->scsi.SCp.phase);
        else
                fas216_set_stc(info, info->scsi.SCp.this_residual);
 
@@ -2114,6 +2114,7 @@ request_sense:
        SCpnt->SCp.buffers_residual = 0;
        SCpnt->SCp.ptr = (char *)SCpnt->sense_buffer;
        SCpnt->SCp.this_residual = sizeof(SCpnt->sense_buffer);
+       SCpnt->SCp.phase = sizeof(SCpnt->sense_buffer);
        SCpnt->SCp.Message = 0;
        SCpnt->SCp.Status = 0;
        SCpnt->request_bufflen = sizeof(SCpnt->sense_buffer);
index f9cd20bfb95890f9ae79cb1d162e41865bf12f4f..159047a34997e99638f2cead22b3d634d8dadb0b 100644 (file)
@@ -148,10 +148,10 @@ powertecscsi_dma_setup(struct Scsi_Host *host, struct scsi_pointer *SCp,
                        map_dir = DMA_FROM_DEVICE,
                        dma_dir = DMA_MODE_READ;
 
-               dma_map_sg(dev, info->sg, bufs + 1, map_dir);
+               dma_map_sg(dev, info->sg, bufs, map_dir);
 
                disable_dma(dmach);
-               set_dma_sg(dmach, info->sg, bufs + 1);
+               set_dma_sg(dmach, info->sg, bufs);
                set_dma_mode(dmach, dma_dir);
                enable_dma(dmach);
                return fasdma_real_all;
@@ -342,6 +342,7 @@ powertecscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
        info->base = base;
        powertecscsi_terminator_ctl(host, term[ec->slot_no]);
 
+       info->ec = ec;
        info->info.scsi.io_base         = base + POWERTEC_FAS216_OFFSET;
        info->info.scsi.io_shift        = POWERTEC_FAS216_SHIFT;
        info->info.scsi.irq             = ec->irq;
index 3a39579bd08e9841064e012d0bb2579beb363452..21ba57155beacd1617440b4e9b0506c708f72d01 100644 (file)
@@ -80,6 +80,7 @@ static inline void init_SCp(struct scsi_cmnd *SCpnt)
                         (page_address(SCpnt->SCp.buffer->page) +
                          SCpnt->SCp.buffer->offset);
                SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
+               SCpnt->SCp.phase = SCpnt->request_bufflen;
 
 #ifdef BELT_AND_BRACES
                /*
@@ -98,6 +99,7 @@ static inline void init_SCp(struct scsi_cmnd *SCpnt)
        } else {
                SCpnt->SCp.ptr = (unsigned char *)SCpnt->request_buffer;
                SCpnt->SCp.this_residual = SCpnt->request_bufflen;
+               SCpnt->SCp.phase = SCpnt->request_bufflen;
        }
 
        /*
index 98ec861853280672d0828342184c73025dc555cc..c129a0e8e8070166144e2cf9f8a1fe3003d19766 100644 (file)
@@ -1196,7 +1196,7 @@ static void serial8250_enable_ms(struct uart_port *port)
 }
 
 static void
-receive_chars(struct uart_8250_port *up, int *status)
+receive_chars(struct uart_8250_port *up, unsigned int *status)
 {
        struct tty_struct *tty = up->port.info->tty;
        unsigned char ch, lsr = *status;
index 587d87b9eb3cebede48fa55362b56ccd8339e16d..d31721f2744d69db038b69b7c0f2a9e143cc362d 100644 (file)
@@ -170,8 +170,7 @@ static void dz_enable_ms(struct uart_port *port)
  * This routine deals with inputs from any lines.
  * ------------------------------------------------------------
  */
-static inline void dz_receive_chars(struct dz_port *dport_in,
-                                   struct pt_regs *regs)
+static inline void dz_receive_chars(struct dz_port *dport_in)
 {
        struct dz_port *dport;
        struct tty_struct *tty = NULL;
@@ -226,7 +225,7 @@ static inline void dz_receive_chars(struct dz_port *dport_in,
                        break;
                }
 
-               if (uart_handle_sysrq_char(&dport->port, ch, regs))
+               if (uart_handle_sysrq_char(&dport->port, ch))
                        continue;
 
                if ((status & dport->port.ignore_status_mask) == 0) {
@@ -332,7 +331,7 @@ static irqreturn_t dz_interrupt(int irq, void *dev)
        status = dz_in(dport, DZ_CSR);
 
        if ((status & (DZ_RDONE | DZ_RIE)) == (DZ_RDONE | DZ_RIE))
-               dz_receive_chars(dport, regs);
+               dz_receive_chars(dport);
 
        if ((status & (DZ_TRDY | DZ_TIE)) == (DZ_TRDY | DZ_TIE))
                dz_transmit_chars(dport);
index 08430961a89513885688a5197dadbfa24361d79c..99af084c7cecdfadc5f32205c05cc97daec48eda 100644 (file)
@@ -425,15 +425,13 @@ irqreturn_t mcfrs_interrupt(int irq, void *dev_id)
  * -------------------------------------------------------------------
  */
 
-static void mcfrs_offintr(void *private)
+static void mcfrs_offintr(struct work_struct *work)
 {
-       struct mcf_serial       *info = (struct mcf_serial *) private;
-       struct tty_struct       *tty;
+       struct mcf_serial *info = container_of(work, struct mcf_serial, tqueue);
+       struct tty_struct *tty = info->tty;
        
-       tty = info->tty;
-       if (!tty)
-               return;
-       tty_wakeup(tty);
+       if (tty)
+               tty_wakeup(tty);
 }
 
 
@@ -497,16 +495,13 @@ static void mcfrs_timer(void)
  *     do_serial_hangup() -> tty->hangup() -> mcfrs_hangup()
  * 
  */
-static void do_serial_hangup(void *private)
+static void do_serial_hangup(struct work_struct *work)
 {
-       struct mcf_serial       *info = (struct mcf_serial *) private;
-       struct tty_struct       *tty;
+       struct mcf_serial *info = container_of(work, struct mcf_serial, tqueue_hangup);
+       struct tty_struct *tty = info->tty;
        
-       tty = info->tty;
-       if (!tty)
-               return;
-
-       tty_hangup(tty);
+       if (tty)
+               tty_hangup(tty);
 }
 
 static int startup(struct mcf_serial * info)
@@ -857,7 +852,7 @@ static void mcfrs_throttle(struct tty_struct * tty)
 #ifdef SERIAL_DEBUG_THROTTLE
        char    buf[64];
        
-       printk("throttle %s: %d....\n", _tty_name(tty, buf),
+       printk("throttle %s: %d....\n", tty_name(tty, buf),
               tty->ldisc.chars_in_buffer(tty));
 #endif
 
@@ -876,7 +871,7 @@ static void mcfrs_unthrottle(struct tty_struct * tty)
 #ifdef SERIAL_DEBUG_THROTTLE
        char    buf[64];
        
-       printk("unthrottle %s: %d....\n", _tty_name(tty, buf),
+       printk("unthrottle %s: %d....\n", tty_name(tty, buf),
               tty->ldisc.chars_in_buffer(tty));
 #endif
 
@@ -1541,8 +1536,8 @@ static void mcfrs_irqinit(struct mcf_serial *info)
                 * External Pin Mask Setting & Enable External Pin for Interface
                 * mrcbis@aliceposta.it
                 */
-               unsigned short *serpin_enable_mask;
-               serpin_enable_mask = (MCF_IPSBAR + MCF_GPIO_PAR_UART);
+               u16 *serpin_enable_mask;
+               serpin_enable_mask = (u16 *) (MCF_IPSBAR + MCF_GPIO_PAR_UART);
                if (info->line == 0)
                        *serpin_enable_mask |= UART0_ENABLE_MASK;
                else if (info->line == 1)
@@ -1551,6 +1546,13 @@ static void mcfrs_irqinit(struct mcf_serial *info)
                        *serpin_enable_mask |= UART2_ENABLE_MASK;
        }
 #endif
+#if defined(CONFIG_M528x)
+       /* make sure PUAPAR is set for UART0 and UART1 */
+       if (info->line < 2) {
+               volatile unsigned char *portp = (volatile unsigned char *) (MCF_MBAR + MCF5282_GPIO_PUAPAR);
+               *portp |= (0x03 << (info->line * 2));
+       }
+#endif
 #elif defined(CONFIG_M520x)
        volatile unsigned char *icrp, *uartp;
        volatile unsigned long *imrp;
@@ -1783,8 +1785,8 @@ mcfrs_init(void)
                info->event = 0;
                info->count = 0;
                info->blocked_open = 0;
-               INIT_WORK(&info->tqueue, mcfrs_offintr, info);
-               INIT_WORK(&info->tqueue_hangup, do_serial_hangup, info);
+               INIT_WORK(&info->tqueue, mcfrs_offintr);
+               INIT_WORK(&info->tqueue_hangup, do_serial_hangup);
                init_waitqueue_head(&info->open_wait);
                init_waitqueue_head(&info->close_wait);
 
index ccb8fa1800a58e0b8a9f1fdf1b32b40d1e225831..83211013deb87603e3f764106509e4454afad569 100644 (file)
 
 #define MUX_NR 256
 static unsigned int port_cnt __read_mostly;
-static struct uart_port mux_ports[MUX_NR];
+struct mux_port {
+       struct uart_port port;
+       int enabled;
+};
+static struct mux_port mux_ports[MUX_NR];
 
 static struct uart_driver mux_driver = {
        .owner = THIS_MODULE,
@@ -66,7 +70,36 @@ static struct timer_list mux_timer;
 
 #define UART_PUT_CHAR(p, c) __raw_writel((c), (p)->membase + IO_DATA_REG_OFFSET)
 #define UART_GET_FIFO_CNT(p) __raw_readl((p)->membase + IO_DCOUNT_REG_OFFSET)
-#define GET_MUX_PORTS(iodc_data) ((((iodc_data)[4] & 0xf0) >> 4) * 8) + 8
+
+/**
+ * get_mux_port_count - Get the number of available ports on the Mux.
+ * @dev: The parisc device.
+ *
+ * This function is used to determine the number of ports the Mux
+ * supports.  The IODC data reports the number of ports the Mux
+ * can support, but there are cases where not all the Mux ports
+ * are connected.  This function can override the IODC and
+ * return the true port count.
+ */
+static int __init get_mux_port_count(struct parisc_device *dev)
+{
+       int status;
+       u8 iodc_data[32];
+       unsigned long bytecnt;
+
+       /* If this is the built-in Mux for the K-Class (Eole CAP/MUX),
+        * we only need to allocate resources for 1 port since the
+        * other 7 ports are not connected.
+        */
+       if(dev->id.hversion == 0x15)
+               return 1;
+
+       status = pdc_iodc_read(&bytecnt, dev->hpa.start, 0, iodc_data, 32);
+       BUG_ON(status != PDC_OK);
+
+       /* Return the number of ports specified in the iodc data. */
+       return ((((iodc_data)[4] & 0xf0) >> 4) * 8) + 8;
+}
 
 /**
  * mux_tx_empty - Check if the transmitter fifo is empty.
@@ -250,7 +283,7 @@ static void mux_read(struct uart_port *port)
  */
 static int mux_startup(struct uart_port *port)
 {
-       mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY);
+       mux_ports[port->line].enabled = 1;
        return 0;
 }
 
@@ -262,6 +295,7 @@ static int mux_startup(struct uart_port *port)
  */
 static void mux_shutdown(struct uart_port *port)
 {
+       mux_ports[port->line].enabled = 0;
 }
 
 /**
@@ -319,7 +353,7 @@ static int mux_request_port(struct uart_port *port)
  * @port: Ptr to the uart_port.
  * @type: Bitmask of required configurations.
  *
- * Perform any autoconfiguration steps for the port.  This functino is
+ * Perform any autoconfiguration steps for the port.  This function is
  * called if the UPF_BOOT_AUTOCONF flag is specified for the port.
  * [Note: This is required for now because of a bug in the Serial core.
  *  rmk has already submitted a patch to linus, should be available for
@@ -357,11 +391,11 @@ static void mux_poll(unsigned long unused)
        int i;
 
        for(i = 0; i < port_cnt; ++i) {
-               if(!mux_ports[i].info)
+               if(!mux_ports[i].enabled)
                        continue;
 
-               mux_read(&mux_ports[i]);
-               mux_write(&mux_ports[i]);
+               mux_read(&mux_ports[i].port);
+               mux_write(&mux_ports[i].port);
        }
 
        mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY);
@@ -371,8 +405,17 @@ static void mux_poll(unsigned long unused)
 #ifdef CONFIG_SERIAL_MUX_CONSOLE
 static void mux_console_write(struct console *co, const char *s, unsigned count)
 {
-        while(count--)
-                pdc_iodc_putc(*s++);
+       /* Wait until the FIFO drains. */
+       while(UART_GET_FIFO_CNT(&mux_ports[0].port))
+               udelay(1);
+
+       while(count--) {
+               if(*s == '\n') {
+                       UART_PUT_CHAR(&mux_ports[0].port, '\r');
+               }
+               UART_PUT_CHAR(&mux_ports[0].port, *s++);
+       }
+
 }
 
 static int mux_console_setup(struct console *co, char *options)
@@ -428,19 +471,14 @@ static struct uart_ops mux_pops = {
  */
 static int __init mux_probe(struct parisc_device *dev)
 {
-       int i, status, ports;
-       u8 iodc_data[32];
-       unsigned long bytecnt;
-       struct uart_port *port;
+       int i, status;
 
-       status = pdc_iodc_read(&bytecnt, dev->hpa.start, 0, iodc_data, 32);
-       if(status != PDC_OK) {
-               printk(KERN_ERR "Serial mux: Unable to read IODC.\n");
-               return 1;
-       }
+       int port_count = get_mux_port_count(dev);
+       printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.6\n", port_count);
 
-       ports = GET_MUX_PORTS(iodc_data);
-       printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.3\n", ports);
+       dev_set_drvdata(&dev->dev, (void *)(long)port_count);
+       request_mem_region(dev->hpa.start + MUX_OFFSET,
+                           port_count * MUX_LINE_OFFSET, "Mux");
 
        if(!port_cnt) {
                mux_driver.cons = MUX_CONSOLE;
@@ -450,13 +488,10 @@ static int __init mux_probe(struct parisc_device *dev)
                        printk(KERN_ERR "Serial mux: Unable to register driver.\n");
                        return 1;
                }
-
-               init_timer(&mux_timer);
-               mux_timer.function = mux_poll;
        }
 
-       for(i = 0; i < ports; ++i, ++port_cnt) {
-               port = &mux_ports[port_cnt];
+       for(i = 0; i < port_count; ++i, ++port_cnt) {
+               struct uart_port *port = &mux_ports[port_cnt].port;
                port->iobase    = 0;
                port->mapbase   = dev->hpa.start + MUX_OFFSET +
                                                (i * MUX_LINE_OFFSET);
@@ -477,27 +512,73 @@ static int __init mux_probe(struct parisc_device *dev)
                 */
                port->timeout   = HZ / 50;
                spin_lock_init(&port->lock);
+
                status = uart_add_one_port(&mux_driver, port);
                BUG_ON(status);
        }
 
-#ifdef CONFIG_SERIAL_MUX_CONSOLE
-        register_console(&mux_console);
-#endif
        return 0;
 }
 
+static int __devexit mux_remove(struct parisc_device *dev)
+{
+       int i, j;
+       int port_count = (long)dev_get_drvdata(&dev->dev);
+
+       /* Find Port 0 for this card in the mux_ports list. */
+       for(i = 0; i < port_cnt; ++i) {
+               if(mux_ports[i].port.mapbase == dev->hpa.start + MUX_OFFSET)
+                       break;
+       }
+       BUG_ON(i + port_count > port_cnt);
+
+       /* Release the resources associated with each port on the device. */
+       for(j = 0; j < port_count; ++j, ++i) {
+               struct uart_port *port = &mux_ports[i].port;
+
+               uart_remove_one_port(&mux_driver, port);
+               if(port->membase)
+                       iounmap(port->membase);
+       }
+
+       release_mem_region(dev->hpa.start + MUX_OFFSET, port_count * MUX_LINE_OFFSET);
+       return 0;
+}
+
+/* Hack.  This idea was taken from the 8250_gsc.c on how to properly order
+ * the serial port detection in the proper order.   The idea is we always
+ * want the builtin mux to be detected before addin mux cards, so we
+ * specifically probe for the builtin mux cards first.
+ *
+ * This table only contains the parisc_device_id of known builtin mux
+ * devices.  All other mux cards will be detected by the generic mux_tbl.
+ */
+static struct parisc_device_id builtin_mux_tbl[] = {
+       { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, 0x15, 0x0000D }, /* All K-class */
+       { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, 0x44, 0x0000D }, /* E35, E45, and E55 */
+       { 0, }
+};
+
 static struct parisc_device_id mux_tbl[] = {
        { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0000D },
        { 0, }
 };
 
+MODULE_DEVICE_TABLE(parisc, builtin_mux_tbl);
 MODULE_DEVICE_TABLE(parisc, mux_tbl);
 
+static struct parisc_driver builtin_serial_mux_driver = {
+       .name =         "builtin_serial_mux",
+       .id_table =     builtin_mux_tbl,
+       .probe =        mux_probe,
+       .remove =       __devexit_p(mux_remove),
+};
+
 static struct parisc_driver serial_mux_driver = {
        .name =         "serial_mux",
        .id_table =     mux_tbl,
        .probe =        mux_probe,
+       .remove =       __devexit_p(mux_remove),
 };
 
 /**
@@ -507,7 +588,21 @@ static struct parisc_driver serial_mux_driver = {
  */
 static int __init mux_init(void)
 {
-       return register_parisc_driver(&serial_mux_driver);
+       register_parisc_driver(&builtin_serial_mux_driver);
+       register_parisc_driver(&serial_mux_driver);
+
+       if(port_cnt > 0) {
+               /* Start the Mux timer */
+               init_timer(&mux_timer);
+               mux_timer.function = mux_poll;
+               mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY);
+
+#ifdef CONFIG_SERIAL_MUX_CONSOLE
+               register_console(&mux_console);
+#endif
+       }
+
+       return 0;
 }
 
 /**
@@ -517,14 +612,16 @@ static int __init mux_init(void)
  */
 static void __exit mux_exit(void)
 {
-       int i;
-
-       for (i = 0; i < port_cnt; i++) {
-               uart_remove_one_port(&mux_driver, &mux_ports[i]);
-               if (mux_ports[i].membase)
-                       iounmap(mux_ports[i].membase);
+       /* Delete the Mux timer. */
+       if(port_cnt > 0) {
+               del_timer(&mux_timer);
+#ifdef CONFIG_SERIAL_MUX_CONSOLE
+               unregister_console(&mux_console);
+#endif
        }
 
+       unregister_parisc_driver(&builtin_serial_mux_driver);
+       unregister_parisc_driver(&serial_mux_driver);
        uart_unregister_driver(&mux_driver);
 }
 
index f4440d3293106a9d7930fe3b9a55e10e755dbb78..509ace7e6881a84cf88f0329247aea4a308add43 100644 (file)
@@ -38,6 +38,8 @@
  *             Fix some spin_locks.
  *             Do not call uart_add_one_port for absent ports.
  *     1.07    Use CONFIG_SERIAL_TXX9_NR_UARTS.  Cleanup.
+ *     1.08    Use platform_device.
+ *             Fix and cleanup suspend/resume/initialization codes.
  */
 
 #if defined(CONFIG_SERIAL_TXX9_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
@@ -50,7 +52,7 @@
 #include <linux/console.h>
 #include <linux/sysrq.h>
 #include <linux/delay.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
 #include <linux/pci.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
@@ -60,7 +62,7 @@
 
 #include <asm/io.h>
 
-static char *serial_version = "1.07";
+static char *serial_version = "1.08";
 static char *serial_name = "TX39/49 Serial driver";
 
 #define PASS_LIMIT     256
@@ -94,12 +96,7 @@ static char *serial_name = "TX39/49 Serial driver";
 
 struct uart_txx9_port {
        struct uart_port        port;
-
-       /*
-        * We provide a per-port pm hook.
-        */
-       void                    (*pm)(struct uart_port *port,
-                                     unsigned int state, unsigned int old);
+       /* No additional info for now */
 };
 
 #define TXX9_REGION_SIZE       0x24
@@ -277,6 +274,31 @@ static void serial_txx9_enable_ms(struct uart_port *port)
        /* TXX9-SIO can not control DTR... */
 }
 
+static void serial_txx9_initialize(struct uart_port *port)
+{
+       struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+       unsigned int tmout = 10000;
+
+       sio_out(up, TXX9_SIFCR, TXX9_SIFCR_SWRST);
+       /* TX4925 BUG WORKAROUND.  Accessing SIOC register
+        * immediately after soft reset causes bus error. */
+       mmiowb();
+       udelay(1);
+       while ((sio_in(up, TXX9_SIFCR) & TXX9_SIFCR_SWRST) && --tmout)
+               udelay(1);
+       /* TX Int by FIFO Empty, RX Int by Receiving 1 char. */
+       sio_set(up, TXX9_SIFCR,
+               TXX9_SIFCR_TDIL_MAX | TXX9_SIFCR_RDIL_1);
+       /* initial settings */
+       sio_out(up, TXX9_SILCR,
+               TXX9_SILCR_UMODE_8BIT | TXX9_SILCR_USBL_1BIT |
+               ((up->port.flags & UPF_TXX9_USE_SCLK) ?
+                TXX9_SILCR_SCS_SCLK_BG : TXX9_SILCR_SCS_IMCLK_BG));
+       sio_quot_set(up, uart_get_divisor(port, 9600));
+       sio_out(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSTL_MAX /* 15 */);
+       sio_out(up, TXX9_SIDICR, 0);
+}
+
 static inline void
 receive_chars(struct uart_txx9_port *up, unsigned int *status)
 {
@@ -657,9 +679,8 @@ static void
 serial_txx9_pm(struct uart_port *port, unsigned int state,
              unsigned int oldstate)
 {
-       struct uart_txx9_port *up = (struct uart_txx9_port *)port;
-       if (up->pm)
-               up->pm(port, state, oldstate);
+       if (state == 0)
+               serial_txx9_initialize(port);
 }
 
 static int serial_txx9_request_resource(struct uart_txx9_port *up)
@@ -732,7 +753,6 @@ static int serial_txx9_request_port(struct uart_port *port)
 static void serial_txx9_config_port(struct uart_port *port, int uflags)
 {
        struct uart_txx9_port *up = (struct uart_txx9_port *)port;
-       unsigned long flags;
        int ret;
 
        /*
@@ -749,30 +769,7 @@ static void serial_txx9_config_port(struct uart_port *port, int uflags)
        if (up->port.line == up->port.cons->index)
                return;
 #endif
-       spin_lock_irqsave(&up->port.lock, flags);
-       /*
-        * Reset the UART.
-        */
-       sio_out(up, TXX9_SIFCR, TXX9_SIFCR_SWRST);
-#ifdef CONFIG_CPU_TX49XX
-       /* TX4925 BUG WORKAROUND.  Accessing SIOC register
-        * immediately after soft reset causes bus error. */
-       iob();
-       udelay(1);
-#endif
-       while (sio_in(up, TXX9_SIFCR) & TXX9_SIFCR_SWRST)
-               ;
-       /* TX Int by FIFO Empty, RX Int by Receiving 1 char. */
-       sio_set(up, TXX9_SIFCR,
-               TXX9_SIFCR_TDIL_MAX | TXX9_SIFCR_RDIL_1);
-       /* initial settings */
-       sio_out(up, TXX9_SILCR,
-               TXX9_SILCR_UMODE_8BIT | TXX9_SILCR_USBL_1BIT |
-               ((up->port.flags & UPF_TXX9_USE_SCLK) ?
-                TXX9_SILCR_SCS_SCLK_BG : TXX9_SILCR_SCS_IMCLK_BG));
-       sio_quot_set(up, uart_get_divisor(port, 9600));
-       sio_out(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSTL_MAX /* 15 */);
-       spin_unlock_irqrestore(&up->port.lock, flags);
+       serial_txx9_initialize(port);
 }
 
 static int
@@ -818,7 +815,8 @@ static struct uart_ops serial_txx9_pops = {
 
 static struct uart_txx9_port serial_txx9_ports[UART_NR];
 
-static void __init serial_txx9_register_ports(struct uart_driver *drv)
+static void __init serial_txx9_register_ports(struct uart_driver *drv,
+                                             struct device *dev)
 {
        int i;
 
@@ -827,6 +825,7 @@ static void __init serial_txx9_register_ports(struct uart_driver *drv)
 
                up->port.line = i;
                up->port.ops = &serial_txx9_pops;
+               up->port.dev = dev;
                if (up->port.iobase || up->port.mapbase)
                        uart_add_one_port(drv, &up->port);
        }
@@ -898,7 +897,7 @@ serial_txx9_console_write(struct console *co, const char *s, unsigned int count)
        sio_out(up, TXX9_SIDICR, ier);
 }
 
-static int serial_txx9_console_setup(struct console *co, char *options)
+static int __init serial_txx9_console_setup(struct console *co, char *options)
 {
        struct uart_port *port;
        struct uart_txx9_port *up;
@@ -919,17 +918,7 @@ static int serial_txx9_console_setup(struct console *co, char *options)
        if (!port->ops)
                return -ENODEV;
 
-       /*
-        *      Disable UART interrupts, set DTR and RTS high
-        *      and set speed.
-        */
-       sio_out(up, TXX9_SIDICR, 0);
-       /* initial settings */
-       sio_out(up, TXX9_SILCR,
-               TXX9_SILCR_UMODE_8BIT | TXX9_SILCR_USBL_1BIT |
-               ((port->flags & UPF_TXX9_USE_SCLK) ?
-                TXX9_SILCR_SCS_SCLK_BG : TXX9_SILCR_SCS_IMCLK_BG));
-       sio_out(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSTL_MAX /* 15 */);
+       serial_txx9_initialize(&up->port);
 
        if (options)
                uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -981,31 +970,6 @@ int __init early_serial_txx9_setup(struct uart_port *port)
        return 0;
 }
 
-#ifdef ENABLE_SERIAL_TXX9_PCI
-#ifdef CONFIG_PM
-/**
- *     serial_txx9_suspend_port - suspend one serial port
- *     @line:  serial line number
- *
- *     Suspend one serial port.
- */
-static void serial_txx9_suspend_port(int line)
-{
-       uart_suspend_port(&serial_txx9_reg, &serial_txx9_ports[line].port);
-}
-
-/**
- *     serial_txx9_resume_port - resume one serial port
- *     @line:  serial line number
- *
- *     Resume one serial port.
- */
-static void serial_txx9_resume_port(int line)
-{
-       uart_resume_port(&serial_txx9_reg, &serial_txx9_ports[line].port);
-}
-#endif
-
 static DEFINE_MUTEX(serial_txx9_mutex);
 
 /**
@@ -1028,8 +992,18 @@ static int __devinit serial_txx9_register_port(struct uart_port *port)
        mutex_lock(&serial_txx9_mutex);
        for (i = 0; i < UART_NR; i++) {
                uart = &serial_txx9_ports[i];
-               if (!(uart->port.iobase || uart->port.mapbase))
+               if (uart_match_port(&uart->port, port)) {
+                       uart_remove_one_port(&serial_txx9_reg, &uart->port);
                        break;
+               }
+       }
+       if (i == UART_NR) {
+               /* Find unused port */
+               for (i = 0; i < UART_NR; i++) {
+                       uart = &serial_txx9_ports[i];
+                       if (!(uart->port.iobase || uart->port.mapbase))
+                               break;
+               }
        }
        if (i < UART_NR) {
                uart->port.iobase = port->iobase;
@@ -1071,6 +1045,95 @@ static void __devexit serial_txx9_unregister_port(int line)
        mutex_unlock(&serial_txx9_mutex);
 }
 
+/*
+ * Register a set of serial devices attached to a platform device.
+ */
+static int __devinit serial_txx9_probe(struct platform_device *dev)
+{
+       struct uart_port *p = dev->dev.platform_data;
+       struct uart_port port;
+       int ret, i;
+
+       memset(&port, 0, sizeof(struct uart_port));
+       for (i = 0; p && p->uartclk != 0; p++, i++) {
+               port.iobase     = p->iobase;
+               port.membase    = p->membase;
+               port.irq        = p->irq;
+               port.uartclk    = p->uartclk;
+               port.iotype     = p->iotype;
+               port.flags      = p->flags;
+               port.mapbase    = p->mapbase;
+               port.dev        = &dev->dev;
+               ret = serial_txx9_register_port(&port);
+               if (ret < 0) {
+                       dev_err(&dev->dev, "unable to register port at index %d "
+                               "(IO%x MEM%lx IRQ%d): %d\n", i,
+                               p->iobase, p->mapbase, p->irq, ret);
+               }
+       }
+       return 0;
+}
+
+/*
+ * Remove serial ports registered against a platform device.
+ */
+static int __devexit serial_txx9_remove(struct platform_device *dev)
+{
+       int i;
+
+       for (i = 0; i < UART_NR; i++) {
+               struct uart_txx9_port *up = &serial_txx9_ports[i];
+
+               if (up->port.dev == &dev->dev)
+                       serial_txx9_unregister_port(i);
+       }
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int serial_txx9_suspend(struct platform_device *dev, pm_message_t state)
+{
+       int i;
+
+       for (i = 0; i < UART_NR; i++) {
+               struct uart_txx9_port *up = &serial_txx9_ports[i];
+
+               if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
+                       uart_suspend_port(&serial_txx9_reg, &up->port);
+       }
+
+       return 0;
+}
+
+static int serial_txx9_resume(struct platform_device *dev)
+{
+       int i;
+
+       for (i = 0; i < UART_NR; i++) {
+               struct uart_txx9_port *up = &serial_txx9_ports[i];
+
+               if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
+                       uart_resume_port(&serial_txx9_reg, &up->port);
+       }
+
+       return 0;
+}
+#endif
+
+static struct platform_driver serial_txx9_plat_driver = {
+       .probe          = serial_txx9_probe,
+       .remove         = __devexit_p(serial_txx9_remove),
+#ifdef CONFIG_PM
+       .suspend        = serial_txx9_suspend,
+       .resume         = serial_txx9_resume,
+#endif
+       .driver         = {
+               .name   = "serial_txx9",
+               .owner  = THIS_MODULE,
+       },
+};
+
+#ifdef ENABLE_SERIAL_TXX9_PCI
 /*
  * Probe one serial board.  Unfortunately, there is no rhyme nor reason
  * to the arrangement of serial ports on a PCI card.
@@ -1097,20 +1160,22 @@ pciserial_txx9_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
        line = serial_txx9_register_port(&port);
        if (line < 0) {
                printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), line);
+               pci_disable_device(dev);
+               return line;
        }
-       pci_set_drvdata(dev, (void *)(long)line);
+       pci_set_drvdata(dev, &serial_txx9_ports[line]);
 
        return 0;
 }
 
 static void __devexit pciserial_txx9_remove_one(struct pci_dev *dev)
 {
-       int line = (int)(long)pci_get_drvdata(dev);
+       struct uart_txx9_port *up = pci_get_drvdata(dev);
 
        pci_set_drvdata(dev, NULL);
 
-       if (line) {
-               serial_txx9_unregister_port(line);
+       if (up) {
+               serial_txx9_unregister_port(up->port.line);
                pci_disable_device(dev);
        }
 }
@@ -1118,10 +1183,10 @@ static void __devexit pciserial_txx9_remove_one(struct pci_dev *dev)
 #ifdef CONFIG_PM
 static int pciserial_txx9_suspend_one(struct pci_dev *dev, pm_message_t state)
 {
-       int line = (int)(long)pci_get_drvdata(dev);
+       struct uart_txx9_port *up = pci_get_drvdata(dev);
 
-       if (line)
-               serial_txx9_suspend_port(line);
+       if (up)
+               uart_suspend_port(&serial_txx9_reg, &up->port);
        pci_save_state(dev);
        pci_set_power_state(dev, pci_choose_state(dev, state));
        return 0;
@@ -1129,15 +1194,12 @@ static int pciserial_txx9_suspend_one(struct pci_dev *dev, pm_message_t state)
 
 static int pciserial_txx9_resume_one(struct pci_dev *dev)
 {
-       int line = (int)(long)pci_get_drvdata(dev);
+       struct uart_txx9_port *up = pci_get_drvdata(dev);
 
        pci_set_power_state(dev, PCI_D0);
        pci_restore_state(dev);
-
-       if (line) {
-               pci_enable_device(dev);
-               serial_txx9_resume_port(line);
-       }
+       if (up)
+               uart_resume_port(&serial_txx9_reg, &up->port);
        return 0;
 }
 #endif
@@ -1161,6 +1223,8 @@ static struct pci_driver serial_txx9_pci_driver = {
 MODULE_DEVICE_TABLE(pci, serial_txx9_pci_tbl);
 #endif /* ENABLE_SERIAL_TXX9_PCI */
 
+static struct platform_device *serial_txx9_plat_devs;
+
 static int __init serial_txx9_init(void)
 {
        int ret;
@@ -1168,13 +1232,39 @@ static int __init serial_txx9_init(void)
        printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
 
        ret = uart_register_driver(&serial_txx9_reg);
-       if (ret >= 0) {
-               serial_txx9_register_ports(&serial_txx9_reg);
+       if (ret)
+               goto out;
+
+       serial_txx9_plat_devs = platform_device_alloc("serial_txx9", -1);
+       if (!serial_txx9_plat_devs) {
+               ret = -ENOMEM;
+               goto unreg_uart_drv;
+       }
+
+       ret = platform_device_add(serial_txx9_plat_devs);
+       if (ret)
+               goto put_dev;
+
+       serial_txx9_register_ports(&serial_txx9_reg,
+                                  &serial_txx9_plat_devs->dev);
+
+       ret = platform_driver_register(&serial_txx9_plat_driver);
+       if (ret)
+               goto del_dev;
 
 #ifdef ENABLE_SERIAL_TXX9_PCI
-               ret = pci_register_driver(&serial_txx9_pci_driver);
+       ret = pci_register_driver(&serial_txx9_pci_driver);
 #endif
-       }
+       if (ret == 0)
+               goto out;
+
+ del_dev:
+       platform_device_del(serial_txx9_plat_devs);
+ put_dev:
+       platform_device_put(serial_txx9_plat_devs);
+ unreg_uart_drv:
+       uart_unregister_driver(&serial_txx9_reg);
+ out:
        return ret;
 }
 
@@ -1185,6 +1275,8 @@ static void __exit serial_txx9_exit(void)
 #ifdef ENABLE_SERIAL_TXX9_PCI
        pci_unregister_driver(&serial_txx9_pci_driver);
 #endif
+       platform_driver_unregister(&serial_txx9_plat_driver);
+       platform_device_unregister(serial_txx9_plat_devs);
        for (i = 0; i < UART_NR; i++) {
                struct uart_txx9_port *up = &serial_txx9_ports[i];
                if (up->port.iobase || up->port.mapbase)
index 253ceb895ca7bcf9a10b77b50e0493044aa30a32..a27e9e92cb5eed49811fe974ec50b3939ba39f53 100644 (file)
@@ -635,25 +635,6 @@ static irqreturn_t sn_sal_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-/**
- * sn_sal_connect_interrupt - Request interrupt, handled by sn_sal_interrupt
- * @port: Our sn_cons_port (which contains the uart port)
- *
- * returns the console irq if interrupt is successfully registered, else 0
- *
- */
-static int sn_sal_connect_interrupt(struct sn_cons_port *port)
-{
-       if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt,
-                       IRQF_DISABLED | IRQF_SHARED,
-                       "SAL console driver", port) >= 0) {
-               return SGI_UART_VECTOR;
-       }
-
-       printk(KERN_INFO "sn_console: console proceeding in polled mode\n");
-       return 0;
-}
-
 /**
  * sn_sal_timer_poll - this function handles polled console mode
  * @data: A pointer to our sn_cons_port (which contains the uart port)
@@ -746,30 +727,31 @@ static void __init sn_sal_switch_to_asynch(struct sn_cons_port *port)
  * mode.  We were previously in asynch/polling mode (using init_timer).
  *
  * We attempt to switch to interrupt mode here by calling
- * sn_sal_connect_interrupt.  If that works out, we enable receive interrupts.
+ * request_irq.  If that works out, we enable receive interrupts.
  */
 static void __init sn_sal_switch_to_interrupts(struct sn_cons_port *port)
 {
-       int irq;
        unsigned long flags;
 
-       if (!port)
-               return;
-
-       DPRINTF("sn_console: switching to interrupt driven console\n");
-
-       spin_lock_irqsave(&port->sc_port.lock, flags);
+       if (port) {
+               DPRINTF("sn_console: switching to interrupt driven console\n");
 
-       irq = sn_sal_connect_interrupt(port);
+               if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt,
+                               IRQF_DISABLED | IRQF_SHARED,
+                               "SAL console driver", port) >= 0) {
+                       spin_lock_irqsave(&port->sc_port.lock, flags);
+                       port->sc_port.irq = SGI_UART_VECTOR;
+                       port->sc_ops = &intr_ops;
 
-       if (irq) {
-               port->sc_port.irq = irq;
-               port->sc_ops = &intr_ops;
-
-               /* turn on receive interrupts */
-               ia64_sn_console_intr_enable(SAL_CONSOLE_INTR_RECV);
+                       /* turn on receive interrupts */
+                       ia64_sn_console_intr_enable(SAL_CONSOLE_INTR_RECV);
+                       spin_unlock_irqrestore(&port->sc_port.lock, flags);
+               }
+               else {
+                       printk(KERN_INFO
+                           "sn_console: console proceeding in polled mode\n");
+               }
        }
-       spin_unlock_irqrestore(&port->sc_port.lock, flags);
 }
 
 /*
index c2a9fef58edcc3e9d29235233aa24c7a83a63ca9..6fa260d1a9be06607be15658bcbc3b7a452b18e8 100644 (file)
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
 
+#ifdef CONFIG_ARCH_AT91
+#include <asm/arch/cpu.h>
+#endif
+
 #include "atmel_spi.h"
 
 /*
@@ -491,7 +495,7 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
        return 0;
 }
 
-static void atmel_spi_cleanup(const struct spi_device *spi)
+static void atmel_spi_cleanup(struct spi_device *spi)
 {
        if (spi->controller_state)
                gpio_free((unsigned int)spi->controller_data);
index 366af4959a0f27a70c4066d7d72a53da0269e7e7..96f62b2df300d26fce75823fa257e01a5e03f42b 100644 (file)
@@ -459,7 +459,7 @@ static int uwire_setup(struct spi_device *spi)
        return uwire_setup_transfer(spi, NULL);
 }
 
-static void uwire_cleanup(const struct spi_device *spi)
+static void uwire_cleanup(struct spi_device *spi)
 {
        kfree(spi->controller_state);
 }
index 6ccf8a12a21dd8f9e6d00e1c2c70bd8cdc6f877f..51daa212c6b799fd769ca82ef6f57bef96a933e3 100644 (file)
@@ -1361,10 +1361,9 @@ err_first_setup:
        return status;
 }
 
-static void cleanup(const struct spi_device *spi)
+static void cleanup(struct spi_device *spi)
 {
-       struct chip_data *chip = spi_get_ctldata((struct spi_device *)spi);
-       kfree(chip);
+       kfree(spi_get_ctldata(spi));
 }
 
 static int init_queue(struct driver_data *drv_data)
index eda53ed04cbc9cbefc3569762a5ce965c669a243..611ac22b7cdc2c404e69c07d8dfbcd4e73b1db7c 100644 (file)
@@ -73,6 +73,19 @@ static u32 s3c2410_spigpio_txrx_mode1(struct spi_device *spi,
        return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits);
 }
 
+static u32 s3c2410_spigpio_txrx_mode2(struct spi_device *spi,
+                                     unsigned nsecs, u32 word, u8 bits)
+{
+       return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits);
+}
+
+static u32 s3c2410_spigpio_txrx_mode3(struct spi_device *spi,
+                                     unsigned nsecs, u32 word, u8 bits)
+{
+       return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits);
+}
+
+
 static void s3c2410_spigpio_chipselect(struct spi_device *dev, int value)
 {
        struct s3c2410_spigpio *sg = spidev_to_sg(dev);
@@ -108,6 +121,8 @@ static int s3c2410_spigpio_probe(struct platform_device *dev)
 
        sp->bitbang.txrx_word[SPI_MODE_0] = s3c2410_spigpio_txrx_mode0;
        sp->bitbang.txrx_word[SPI_MODE_1] = s3c2410_spigpio_txrx_mode1;
+       sp->bitbang.txrx_word[SPI_MODE_2] = s3c2410_spigpio_txrx_mode2;
+       sp->bitbang.txrx_word[SPI_MODE_3] = s3c2410_spigpio_txrx_mode3;
 
        /* set state of spi pins */
        s3c2410_gpio_setpin(sp->info->pin_clk, 0);
index d38a25f36ea5839557b0328cd72940962d2d0dda..31ae661e586ad21731b58092146277fe0e0c99bb 100644 (file)
@@ -332,9 +332,9 @@ static void acm_rx_tasklet(unsigned long _acm)
        if (!ACM_READY(acm))
                return;
 
-       spin_lock(&acm->throttle_lock);
+       spin_lock_irqsave(&acm->throttle_lock, flags);
        throttled = acm->throttle;
-       spin_unlock(&acm->throttle_lock);
+       spin_unlock_irqrestore(&acm->throttle_lock, flags);
        if (throttled)
                return;
 
@@ -352,9 +352,9 @@ next_buffer:
        dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size);
 
        tty_buffer_request_room(tty, buf->size);
-       spin_lock(&acm->throttle_lock);
+       spin_lock_irqsave(&acm->throttle_lock, flags);
        throttled = acm->throttle;
-       spin_unlock(&acm->throttle_lock);
+       spin_unlock_irqrestore(&acm->throttle_lock, flags);
        if (!throttled)
                tty_insert_flip_string(tty, buf->base, buf->size);
        tty_flip_buffer_push(tty);
index 34e9bac319b4e5af731727e5da58907f28612a61..b6078706fb939d7f1d3aeb9466f6498f8857f366 100644 (file)
@@ -4,7 +4,7 @@
 
 usbcore-objs   := usb.o hub.o hcd.o urb.o message.o driver.o \
                        config.o file.o buffer.o sysfs.o endpoint.o \
-                       devio.o notify.o generic.o
+                       devio.o notify.o generic.o quirks.o
 
 ifeq ($(CONFIG_PCI),y)
        usbcore-objs    += hcd-pci.o
index 274f14f1633e8f348baff7c4ff8f138b3b2a803c..36e7a843bf9181fce7cb78bdca76584abe61a3e9 100644 (file)
@@ -912,7 +912,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
        struct async *as;
        struct usb_ctrlrequest *dr = NULL;
        unsigned int u, totlen, isofrmlen;
-       int ret, interval = 0, ifnum = -1;
+       int ret, ifnum = -1;
 
        if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK|
                           URB_NO_FSBR|URB_ZERO_PACKET))
@@ -992,7 +992,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
                if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
                                != USB_ENDPOINT_XFER_ISOC)
                        return -EINVAL;
-               interval = 1 << min (15, ep->desc.bInterval - 1);
                isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb->number_of_packets;
                if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
                        return -ENOMEM;
@@ -1021,10 +1020,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
                if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
                                != USB_ENDPOINT_XFER_INT)
                        return -EINVAL;
-               if (ps->dev->speed == USB_SPEED_HIGH)
-                       interval = 1 << min (15, ep->desc.bInterval - 1);
-               else
-                       interval = ep->desc.bInterval;
                if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
                        return -EINVAL;
                if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length))
@@ -1053,7 +1048,11 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
        as->urb->setup_packet = (unsigned char*)dr;
        as->urb->start_frame = uurb->start_frame;
        as->urb->number_of_packets = uurb->number_of_packets;
-       as->urb->interval = interval;
+       if (uurb->type == USBDEVFS_URB_TYPE_ISO ||
+                       ps->dev->speed == USB_SPEED_HIGH)
+               as->urb->interval = 1 << min(15, ep->desc.bInterval - 1);
+       else
+               as->urb->interval = ep->desc.bInterval;
         as->urb->context = as;
         as->urb->complete = async_completed;
        for (totlen = u = 0; u < uurb->number_of_packets; u++) {
index 2aded261f42c3acb5ffdd8a605a6c36b70049a6e..9e3e943f313c55dc3479be6b96f4ffbc58c988d2 100644 (file)
@@ -366,19 +366,8 @@ void usb_driver_release_interface(struct usb_driver *driver,
 EXPORT_SYMBOL(usb_driver_release_interface);
 
 /* returns 0 if no match, 1 if match */
-int usb_match_one_id(struct usb_interface *interface,
-                    const struct usb_device_id *id)
+int usb_match_device(struct usb_device *dev, const struct usb_device_id *id)
 {
-       struct usb_host_interface *intf;
-       struct usb_device *dev;
-
-       /* proc_connectinfo in devio.c may call us with id == NULL. */
-       if (id == NULL)
-               return 0;
-
-       intf = interface->cur_altsetting;
-       dev = interface_to_usbdev(interface);
-
        if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
            id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
                return 0;
@@ -409,6 +398,26 @@ int usb_match_one_id(struct usb_interface *interface,
            (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
                return 0;
 
+       return 1;
+}
+
+/* returns 0 if no match, 1 if match */
+int usb_match_one_id(struct usb_interface *interface,
+                    const struct usb_device_id *id)
+{
+       struct usb_host_interface *intf;
+       struct usb_device *dev;
+
+       /* proc_connectinfo in devio.c may call us with id == NULL. */
+       if (id == NULL)
+               return 0;
+
+       intf = interface->cur_altsetting;
+       dev = interface_to_usbdev(interface);
+
+       if (!usb_match_device(dev, id))
+               return 0;
+
        /* The interface class, subclass, and protocol should never be
         * checked for a match if the device class is Vendor Specific,
         * unless the match record specifies the Vendor ID. */
@@ -954,12 +963,16 @@ static int autosuspend_check(struct usb_device *udev)
        int                     i;
        struct usb_interface    *intf;
 
-       /* For autosuspend, fail fast if anything is in use.
-        * Also fail if any interfaces require remote wakeup but it
-        * isn't available. */
+       /* For autosuspend, fail fast if anything is in use or autosuspend
+        * is disabled.  Also fail if any interfaces require remote wakeup
+        * but it isn't available.
+        */
        udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
        if (udev->pm_usage_cnt > 0)
                return -EBUSY;
+       if (!udev->autosuspend_delay)
+               return -EPERM;
+
        if (udev->actconfig) {
                for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
                        intf = udev->actconfig->interface[i];
@@ -982,7 +995,7 @@ static int autosuspend_check(struct usb_device *udev)
 
 #define autosuspend_check(udev)                0
 
-#endif
+#endif /* CONFIG_USB_SUSPEND */
 
 /**
  * usb_suspend_both - suspend a USB device and its interfaces
@@ -1177,7 +1190,7 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt)
                        udev->pm_usage_cnt -= inc_usage_cnt;
        } else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
                queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
-                               USB_AUTOSUSPEND_DELAY);
+                               udev->autosuspend_delay);
        usb_pm_unlock(udev);
        return status;
 }
@@ -1211,6 +1224,26 @@ void usb_autosuspend_device(struct usb_device *udev)
        //              __FUNCTION__, udev->pm_usage_cnt);
 }
 
+/**
+ * usb_try_autosuspend_device - attempt an autosuspend of a USB device and its interfaces
+ * @udev: the usb_device to autosuspend
+ *
+ * This routine should be called when a core subsystem thinks @udev may
+ * be ready to autosuspend.
+ *
+ * @udev's usage counter left unchanged.  If it or any of the usage counters
+ * for an active interface is greater than 0, or autosuspend is not allowed
+ * for any other reason, no autosuspend request will be queued.
+ *
+ * This routine can run only in process context.
+ */
+void usb_try_autosuspend_device(struct usb_device *udev)
+{
+       usb_autopm_do_device(udev, 0);
+       // dev_dbg(&udev->dev, "%s: cnt %d\n",
+       //              __FUNCTION__, udev->pm_usage_cnt);
+}
+
 /**
  * usb_autoresume_device - immediately autoresume a USB device and its interfaces
  * @udev: the usb_device to autoresume
@@ -1261,7 +1294,7 @@ static int usb_autopm_do_interface(struct usb_interface *intf,
                                intf->pm_usage_cnt -= inc_usage_cnt;
                } else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
                        queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
-                                       USB_AUTOSUSPEND_DELAY);
+                                       udev->autosuspend_delay);
        }
        usb_pm_unlock(udev);
        return status;
index 50c0db15304aef513c30262b585b41db670c567e..b89a98e613235ea715154f347a50763fb81b4e78 100644 (file)
@@ -1281,11 +1281,8 @@ int usb_new_device(struct usb_device *udev)
 {
        int err;
 
-       /* Lock ourself into memory in order to keep a probe sequence
-        * sleeping in a new thread from allowing us to be unloaded.
-        */
-       if (!try_module_get(THIS_MODULE))
-               return -EINVAL;
+       /* Determine quirks */
+       usb_detect_quirks(udev);
 
        err = usb_get_configuration(udev);
        if (err < 0) {
@@ -1387,7 +1384,6 @@ int usb_new_device(struct usb_device *udev)
                usb_autoresume_device(udev->parent);
 
 exit:
-       module_put(THIS_MODULE);
        return err;
 
 fail:
@@ -2440,7 +2436,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
 
        if (portchange & USB_PORT_STAT_C_CONNECTION) {
                status = hub_port_debounce(hub, port1);
-               if (status < 0) {
+               if (status < 0 && printk_ratelimit()) {
                        dev_err (hub_dev,
                                "connect-debounce failed, port %d disabled\n",
                                port1);
index 74edaea5665d58367f6f62e48cec2d4a2b63313e..217a3d6d0a06dedc020129e5d0444e5b1ed8dda2 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/timer.h>
 #include <linux/ctype.h>
 #include <linux/device.h>
+#include <linux/usb/quirks.h>
 #include <asm/byteorder.h>
 #include <asm/scatterlist.h>
 
@@ -220,10 +221,15 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
 
        if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
                        USB_ENDPOINT_XFER_INT) {
+               int interval;
+
+               if (usb_dev->speed == USB_SPEED_HIGH)
+                       interval = 1 << min(15, ep->desc.bInterval - 1);
+               else
+                       interval = ep->desc.bInterval;
                pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
                usb_fill_int_urb(urb, usb_dev, pipe, data, len,
-                               usb_api_blocking_completion, NULL,
-                               ep->desc.bInterval);
+                               usb_api_blocking_completion, NULL, interval);
        } else
                usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
                                usb_api_blocking_completion, NULL);
@@ -685,7 +691,10 @@ static int usb_string_sub(struct usb_device *dev, unsigned int langid,
 
        /* Try to read the string descriptor by asking for the maximum
         * possible number of bytes */
-       rc = usb_get_string(dev, langid, index, buf, 255);
+       if (dev->quirks & USB_QUIRK_STRING_FETCH_255)
+               rc = -EIO;
+       else
+               rc = usb_get_string(dev, langid, index, buf, 255);
 
        /* If that failed try to read the descriptor length, then
         * ask for just that many bytes */
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
new file mode 100644 (file)
index 0000000..0e5c646
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * USB device quirk handling logic and table
+ *
+ * Copyright (c) 2007 Oliver Neukum
+ * Copyright (c) 2007 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, version 2.
+ *
+ *
+ */
+
+#include <linux/usb.h>
+#include <linux/usb/quirks.h>
+#include "usb.h"
+
+/* List of quirky USB devices.  Please keep this list ordered by:
+ *     1) Vendor ID
+ *     2) Product ID
+ *     3) Class ID
+ *
+ * as we want specific devices to be overridden first, and only after that, any
+ * class specific quirks.
+ *
+ * Right now the logic aborts if it finds a valid device in the table, we might
+ * want to change that in the future if it turns out that a whole class of
+ * devices is broken...
+ */
+static const struct usb_device_id usb_quirk_list[] = {
+       /* HP 5300/5370C scanner */
+       { USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 },
+
+       /* Elsa MicroLink 56k (V.250) */
+       { USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+
+       { }  /* terminating entry must be last */
+};
+
+static void usb_autosuspend_quirk(struct usb_device *udev)
+{
+#ifdef CONFIG_USB_SUSPEND
+       /* disable autosuspend, but allow the user to re-enable it via sysfs */
+       udev->autosuspend_delay = 0;
+#endif
+}
+
+static const struct usb_device_id *find_id(struct usb_device *udev)
+{
+       const struct usb_device_id *id = usb_quirk_list;
+
+       for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass ||
+                       id->driver_info; id++) {
+               if (usb_match_device(udev, id))
+                       return id;
+       }
+       return NULL;
+}
+
+/*
+ * Detect any quirks the device has, and do any housekeeping for it if needed.
+ */
+void usb_detect_quirks(struct usb_device *udev)
+{
+       const struct usb_device_id *id = usb_quirk_list;
+
+       id = find_id(udev);
+       if (id)
+               udev->quirks = (u32)(id->driver_info);
+       if (udev->quirks)
+               dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
+                               udev->quirks);
+
+       /* do any special quirk handling here if needed */
+       if (udev->quirks & USB_QUIRK_NO_AUTOSUSPEND)
+               usb_autosuspend_quirk(udev);
+}
index 0edfbafd702cced2fcda7638f2002be4c055fb52..311d5df80386c91174e6614e79ea5e337c09d9a6 100644 (file)
@@ -148,6 +148,75 @@ show_maxchild(struct device *dev, struct device_attribute *attr, char *buf)
 }
 static DEVICE_ATTR(maxchild, S_IRUGO, show_maxchild, NULL);
 
+static ssize_t
+show_quirks(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct usb_device *udev;
+
+       udev = to_usb_device(dev);
+       return sprintf(buf, "0x%x\n", udev->quirks);
+}
+static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL);
+
+#ifdef CONFIG_USB_SUSPEND
+
+static ssize_t
+show_autosuspend(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct usb_device *udev = to_usb_device(dev);
+
+       return sprintf(buf, "%u\n", udev->autosuspend_delay / HZ);
+}
+
+static ssize_t
+set_autosuspend(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       struct usb_device *udev = to_usb_device(dev);
+       unsigned value, old;
+
+       if (sscanf(buf, "%u", &value) != 1 || value >= INT_MAX/HZ)
+               return -EINVAL;
+       value *= HZ;
+
+       old = udev->autosuspend_delay;
+       udev->autosuspend_delay = value;
+       if (value > 0 && old == 0)
+               usb_try_autosuspend_device(udev);
+
+       return count;
+}
+
+static DEVICE_ATTR(autosuspend, S_IRUGO | S_IWUSR,
+               show_autosuspend, set_autosuspend);
+
+static char power_group[] = "power";
+
+static int add_power_attributes(struct device *dev)
+{
+       int rc = 0;
+
+       if (is_usb_device(dev))
+               rc = sysfs_add_file_to_group(&dev->kobj,
+                               &dev_attr_autosuspend.attr,
+                               power_group);
+       return rc;
+}
+
+static void remove_power_attributes(struct device *dev)
+{
+       sysfs_remove_file_from_group(&dev->kobj,
+                       &dev_attr_autosuspend.attr,
+                       power_group);
+}
+
+#else
+
+#define add_power_attributes(dev)      0
+#define remove_power_attributes(dev)   do {} while (0)
+
+#endif /* CONFIG_USB_SUSPEND */
+
 /* Descriptor fields */
 #define usb_descriptor_attr_le16(field, format_string)                 \
 static ssize_t                                                         \
@@ -204,6 +273,7 @@ static struct attribute *dev_attrs[] = {
        &dev_attr_devnum.attr,
        &dev_attr_version.attr,
        &dev_attr_maxchild.attr,
+       &dev_attr_quirks.attr,
        NULL,
 };
 static struct attribute_group dev_attr_grp = {
@@ -219,6 +289,10 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
        if (retval)
                return retval;
 
+       retval = add_power_attributes(dev);
+       if (retval)
+               goto error;
+
        if (udev->manufacturer) {
                retval = device_create_file(dev, &dev_attr_manufacturer);
                if (retval)
@@ -239,10 +313,7 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
                goto error;
        return 0;
 error:
-       usb_remove_ep_files(&udev->ep0);
-       device_remove_file(dev, &dev_attr_manufacturer);
-       device_remove_file(dev, &dev_attr_product);
-       device_remove_file(dev, &dev_attr_serial);
+       usb_remove_sysfs_dev_files(udev);
        return retval;
 }
 
@@ -251,14 +322,11 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
        struct device *dev = &udev->dev;
 
        usb_remove_ep_files(&udev->ep0);
+       device_remove_file(dev, &dev_attr_manufacturer);
+       device_remove_file(dev, &dev_attr_product);
+       device_remove_file(dev, &dev_attr_serial);
+       remove_power_attributes(dev);
        sysfs_remove_group(&dev->kobj, &dev_attr_grp);
-
-       if (udev->manufacturer)
-               device_remove_file(dev, &dev_attr_manufacturer);
-       if (udev->product)
-               device_remove_file(dev, &dev_attr_product);
-       if (udev->serial)
-               device_remove_file(dev, &dev_attr_serial);
 }
 
 /* Interface fields */
@@ -362,33 +430,28 @@ static inline void usb_remove_intf_ep_files(struct usb_interface *intf)
 
 int usb_create_sysfs_intf_files(struct usb_interface *intf)
 {
+       struct device *dev = &intf->dev;
        struct usb_device *udev = interface_to_usbdev(intf);
        struct usb_host_interface *alt = intf->cur_altsetting;
        int retval;
 
-       retval = sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
+       retval = sysfs_create_group(&dev->kobj, &intf_attr_grp);
        if (retval)
-               goto error;
+               return retval;
 
        if (alt->string == NULL)
                alt->string = usb_cache_string(udev, alt->desc.iInterface);
        if (alt->string)
-               retval = device_create_file(&intf->dev, &dev_attr_interface);
+               retval = device_create_file(dev, &dev_attr_interface);
        usb_create_intf_ep_files(intf, udev);
        return 0;
-error:
-       if (alt->string)
-               device_remove_file(&intf->dev, &dev_attr_interface);
-       sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
-       usb_remove_intf_ep_files(intf);
-       return retval;
 }
 
 void usb_remove_sysfs_intf_files(struct usb_interface *intf)
 {
-       usb_remove_intf_ep_files(intf);
-       sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
+       struct device *dev = &intf->dev;
 
-       if (intf->cur_altsetting->string)
-               device_remove_file(&intf->dev, &dev_attr_interface);
+       usb_remove_intf_ep_files(intf);
+       device_remove_file(dev, &dev_attr_interface);
+       sysfs_remove_group(&dev->kobj, &intf_attr_grp);
 }
index 3db721cd557a61eed125e2eba770389b28bc6d8a..54b42ce311c1887acf51ce225d91f9adfada78b8 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/string.h>
 #include <linux/bitops.h>
 #include <linux/slab.h>
@@ -50,6 +51,16 @@ static int nousb;    /* Disable USB when built into kernel image */
 
 struct workqueue_struct *ksuspend_usb_wq;      /* For autosuspend */
 
+#ifdef CONFIG_USB_SUSPEND
+static int usb_autosuspend_delay = 2;          /* Default delay value,
+                                                * in seconds */
+module_param_named(autosuspend, usb_autosuspend_delay, uint, 0644);
+MODULE_PARM_DESC(autosuspend, "default autosuspend delay");
+
+#else
+#define usb_autosuspend_delay          0
+#endif
+
 
 /**
  * usb_ifnum_to_if - get the interface object with a given interface number
@@ -306,6 +317,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
 #ifdef CONFIG_PM
        mutex_init(&dev->pm_mutex);
        INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work);
+       dev->autosuspend_delay = usb_autosuspend_delay * HZ;
 #endif
        return dev;
 }
index 17830a81be141743e06f5ac837ff0747ab314652..08b5a04e3755883652036d5f4f12f56240de9b62 100644 (file)
@@ -13,6 +13,7 @@ extern void usb_disable_interface (struct usb_device *dev,
                struct usb_interface *intf);
 extern void usb_release_interface_cache(struct kref *ref);
 extern void usb_disable_device (struct usb_device *dev, int skip_ep0);
+extern void usb_detect_quirks(struct usb_device *udev);
 
 extern int usb_get_device_descriptor(struct usb_device *dev,
                unsigned int size);
@@ -21,6 +22,8 @@ extern int usb_set_configuration(struct usb_device *dev, int configuration);
 
 extern void usb_kick_khubd(struct usb_device *dev);
 extern void usb_resume_root_hub(struct usb_device *dev);
+extern int usb_match_device(struct usb_device *dev,
+                           const struct usb_device_id *id);
 
 extern int  usb_hub_init(void);
 extern void usb_hub_cleanup(void);
@@ -62,14 +65,14 @@ static inline void usb_pm_unlock(struct usb_device *udev) {}
 
 #ifdef CONFIG_USB_SUSPEND
 
-#define USB_AUTOSUSPEND_DELAY  (HZ*2)
-
 extern void usb_autosuspend_device(struct usb_device *udev);
+extern void usb_try_autosuspend_device(struct usb_device *udev);
 extern int usb_autoresume_device(struct usb_device *udev);
 
 #else
 
-#define usb_autosuspend_device(udev)   do {} while (0)
+#define usb_autosuspend_device(udev)           do {} while (0)
+#define usb_try_autosuspend_device(udev)       do {} while (0)
 static inline int usb_autoresume_device(struct usb_device *udev)
 {
        return 0;
index a4677802fb208dde66c4be9cd85500acfa9074e1..2a6e3163d944765b9addcca1d8520c066327c7f0 100644 (file)
@@ -1835,7 +1835,7 @@ static int at91udc_resume(struct platform_device *pdev)
 #define        at91udc_resume  NULL
 #endif
 
-static struct platform_driver at91_udc = {
+static struct platform_driver at91_udc_driver = {
        .remove         = __exit_p(at91udc_remove),
        .shutdown       = at91udc_shutdown,
        .suspend        = at91udc_suspend,
@@ -1848,13 +1848,13 @@ static struct platform_driver at91_udc = {
 
 static int __init udc_init_module(void)
 {
-       return platform_driver_probe(&at91_udc, at91udc_probe);
+       return platform_driver_probe(&at91_udc_driver, at91udc_probe);
 }
 module_init(udc_init_module);
 
 static void __exit udc_exit_module(void)
 {
-       platform_driver_unregister(&at91_udc);
+       platform_driver_unregister(&at91_udc_driver);
 }
 module_exit(udc_exit_module);
 
index 7b3a326b57ab55e7099675857f91a2aeb409be74..65c91d3735de9ca439b5b36d5c71877aac7e25f4 100644 (file)
@@ -297,27 +297,6 @@ goku_free_request(struct usb_ep *_ep, struct usb_request *_req)
 
 /*-------------------------------------------------------------------------*/
 
-#undef USE_KMALLOC
-
-/* many common platforms have dma-coherent caches, which means that it's
- * safe to use kmalloc() memory for all i/o buffers without using any
- * cache flushing calls.  (unless you're trying to share cache lines
- * between dma and non-dma activities, which is a slow idea in any case.)
- *
- * other platforms need more care, with 2.6 having a moderately general
- * solution except for the common "buffer is smaller than a page" case.
- */
-#if    defined(CONFIG_X86)
-#define USE_KMALLOC
-
-#elif  defined(CONFIG_MIPS) && !defined(CONFIG_DMA_NONCOHERENT)
-#define USE_KMALLOC
-
-#elif  defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE)
-#define USE_KMALLOC
-
-#endif
-
 /* allocating buffers this way eliminates dma mapping overhead, which
  * on some platforms will mean eliminating a per-io buffer copy.  with
  * some kinds of system caches, further tweaks may still be needed.
@@ -334,11 +313,6 @@ goku_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
                return NULL;
        *dma = DMA_ADDR_INVALID;
 
-#if    defined(USE_KMALLOC)
-       retval = kmalloc(bytes, gfp_flags);
-       if (retval)
-               *dma = virt_to_phys(retval);
-#else
        if (ep->dma) {
                /* the main problem with this call is that it wastes memory
                 * on typical 1/N page allocations: it allocates 1-N pages.
@@ -348,7 +322,6 @@ goku_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
                                bytes, dma, gfp_flags);
        } else
                retval = kmalloc(bytes, gfp_flags);
-#endif
        return retval;
 }
 
@@ -356,7 +329,6 @@ static void
 goku_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma, unsigned bytes)
 {
        /* free memory into the right allocator */
-#ifndef        USE_KMALLOC
        if (dma != DMA_ADDR_INVALID) {
                struct goku_ep  *ep;
 
@@ -365,7 +337,6 @@ goku_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma, unsigned bytes)
                        return;
                dma_free_coherent(&ep->dev->pdev->dev, bytes, buf, dma);
        } else
-#endif
                kfree (buf);
 }
 
index 34296e79edcf0dee4a9d97733570a98f10394e44..188c74a95216860cb1740243211b94ef013cbddd 100644 (file)
@@ -553,6 +553,7 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb)
 {
        struct kiocb_priv       *priv = iocb->private;
        ssize_t                 len, total;
+       void                    *to_copy;
        int                     i;
 
        /* we "retry" to get the right mm context for this: */
@@ -560,10 +561,11 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb)
        /* copy stuff into user buffers */
        total = priv->actual;
        len = 0;
+       to_copy = priv->buf;
        for (i=0; i < priv->nr_segs; i++) {
                ssize_t this = min((ssize_t)(priv->iv[i].iov_len), total);
 
-               if (copy_to_user(priv->iv[i].iov_base, priv->buf, this)) {
+               if (copy_to_user(priv->iv[i].iov_base, to_copy, this)) {
                        if (len == 0)
                                len = -EFAULT;
                        break;
@@ -571,6 +573,7 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb)
 
                total -= this;
                len += this;
+               to_copy += this;
                if (total == 0)
                        break;
        }
index f01890dc87515493393dcbf1ea05a8dd0dcd418f..571f3ebb70ab705fd95545853dda4a359c463ea4 100644 (file)
@@ -2616,7 +2616,7 @@ lubbock_fail0:
                if (retval != 0) {
                        printk(KERN_ERR "%s: can't get irq %i, err %d\n",
                                driver_name, vbus_irq, retval);
-                       free_irq(IRQ_USB, dev);
+                       free_irq(irq, dev);
                        return -EBUSY;
                }
        }
index 9af529d22b3e609ee8af02b5fa9fc5c03021f13a..1813b7cac294db103f01271406cb2d550c2195c0 100644 (file)
@@ -653,8 +653,7 @@ static int ehci_hub_control (
        if (status & ~0xffff)   /* only if wPortChange is interesting */
 #endif
                dbg_port (ehci, "GetStatus", wIndex + 1, temp);
-               // we "know" this alignment is good, caller used kmalloc()...
-               *((__le32 *) buf) = cpu_to_le32 (status);
+               put_unaligned(cpu_to_le32 (status), (__le32 *) buf);
                break;
        case SetHubFeature:
                switch (wValue) {
index 5d6c06bc4524f10c1356583aedfad58396ecb66c..8d24d3dc0a6186173980988e010184b763e6c646 100644 (file)
@@ -196,7 +196,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
                struct uhci_td *td = list_entry(urbp->td_list.next,
                                struct uhci_td, list);
 
-               if (cpu_to_le32(td->dma_handle) != (element & ~UHCI_PTR_BITS))
+               if (element != LINK_TO_TD(td))
                        out += sprintf(out, "%*s Element != First TD\n",
                                        space, "");
                i = nurbs = 0;
@@ -220,16 +220,6 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
        return out - buf;
 }
 
-static const char * const qh_names[] = {
-  "skel_unlink_qh", "skel_iso_qh",
-  "skel_int128_qh", "skel_int64_qh",
-  "skel_int32_qh", "skel_int16_qh",
-  "skel_int8_qh", "skel_int4_qh",
-  "skel_int2_qh", "skel_int1_qh",
-  "skel_ls_control_qh", "skel_fs_control_qh",
-  "skel_bulk_qh", "skel_term_qh"
-};
-
 static int uhci_show_sc(int port, unsigned short status, char *buf, int len)
 {
        char *out = buf;
@@ -352,6 +342,12 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
        struct uhci_td *td;
        struct list_head *tmp, *head;
        int nframes, nerrs;
+       __le32 link;
+
+       static const char * const qh_names[] = {
+               "unlink", "iso", "int128", "int64", "int32", "int16",
+               "int8", "int4", "int2", "async", "term"
+       };
 
        out += uhci_show_root_hub_state(uhci, out, len - (out - buf));
        out += sprintf(out, "HC status\n");
@@ -374,7 +370,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
        nframes = 10;
        nerrs = 0;
        for (i = 0; i < UHCI_NUMFRAMES; ++i) {
-               __le32 link, qh_dma;
+               __le32 qh_dma;
 
                j = 0;
                td = uhci->frame_cpu[i];
@@ -393,7 +389,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
                do {
                        td = list_entry(tmp, struct uhci_td, fl_list);
                        tmp = tmp->next;
-                       if (cpu_to_le32(td->dma_handle) != link) {
+                       if (link != LINK_TO_TD(td)) {
                                if (nframes > 0)
                                        out += sprintf(out, "    link does "
                                                "not match list entry!\n");
@@ -430,23 +426,21 @@ check_link:
 
        for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
                int cnt = 0;
+               __le32 fsbr_link = 0;
 
                qh = uhci->skelqh[i];
-               out += sprintf(out, "- %s\n", qh_names[i]); \
+               out += sprintf(out, "- skel_%s_qh\n", qh_names[i]); \
                out += uhci_show_qh(qh, out, len - (out - buf), 4);
 
                /* Last QH is the Terminating QH, it's different */
-               if (i == UHCI_NUM_SKELQH - 1) {
-                       if (qh->link != UHCI_PTR_TERM)
-                               out += sprintf(out, "    bandwidth reclamation on!\n");
-
-                       if (qh_element(qh) != cpu_to_le32(uhci->term_td->dma_handle))
+               if (i == SKEL_TERM) {
+                       if (qh_element(qh) != LINK_TO_TD(uhci->term_td))
                                out += sprintf(out, "    skel_term_qh element is not set to term_td!\n");
-
+                       if (link == LINK_TO_QH(uhci->skel_term_qh))
+                               goto check_qh_link;
                        continue;
                }
 
-               j = (i < 9) ? 9 : i+1;          /* Next skeleton */
                head = &qh->node;
                tmp = head->next;
 
@@ -456,15 +450,26 @@ check_link:
                        if (++cnt <= 10)
                                out += uhci_show_qh(qh, out,
                                                len - (out - buf), 4);
+                       if (!fsbr_link && qh->skel >= SKEL_FSBR)
+                               fsbr_link = LINK_TO_QH(qh);
                }
                if ((cnt -= 10) > 0)
                        out += sprintf(out, "    Skipped %d QHs\n", cnt);
 
-               if (i > 1 && i < UHCI_NUM_SKELQH - 1) {
-                       if (qh->link !=
-                           (cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH))
-                               out += sprintf(out, "    last QH not linked to next skeleton!\n");
-               }
+               link = UHCI_PTR_TERM;
+               if (i <= SKEL_ISO)
+                       ;
+               else if (i < SKEL_ASYNC)
+                       link = LINK_TO_QH(uhci->skel_async_qh);
+               else if (!uhci->fsbr_is_on)
+                       ;
+               else if (fsbr_link)
+                       link = fsbr_link;
+               else
+                       link = LINK_TO_QH(uhci->skel_term_qh);
+check_qh_link:
+               if (qh->link != link)
+                       out += sprintf(out, "    last QH not linked to next skeleton!\n");
        }
 
        return out - buf;
index ded4df30a63131f85e36096bfffca16237c36215..44da4334f1d63aa066b848dadaf0a9929f0bc98d 100644 (file)
@@ -13,7 +13,7 @@
  * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
  *               support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
  * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
- * (C) Copyright 2004-2006 Alan Stern, stern@rowland.harvard.edu
+ * (C) Copyright 2004-2007 Alan Stern, stern@rowland.harvard.edu
  *
  * Intel documents this fairly well, and as far as I know there
  * are no royalties or anything like that, but even so there are
@@ -107,16 +107,16 @@ static __le32 uhci_frame_skel_link(struct uhci_hcd *uhci, int frame)
         * interrupt QHs, which will help spread out bandwidth utilization.
         *
         * ffs (Find First bit Set) does exactly what we need:
-        * 1,3,5,...  => ffs = 0 => use skel_int2_qh = skelqh[8],
-        * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc.
+        * 1,3,5,...  => ffs = 0 => use period-2 QH = skelqh[8],
+        * 2,6,10,... => ffs = 1 => use period-4 QH = skelqh[7], etc.
         * ffs >= 7 => not on any high-period queue, so use
-        *      skel_int1_qh = skelqh[9].
+        *      period-1 QH = skelqh[9].
         * Add in UHCI_NUMFRAMES to insure at least one bit is set.
         */
        skelnum = 8 - (int) __ffs(frame | UHCI_NUMFRAMES);
        if (skelnum <= 1)
                skelnum = 9;
-       return UHCI_PTR_QH | cpu_to_le32(uhci->skelqh[skelnum]->dma_handle);
+       return LINK_TO_QH(uhci->skelqh[skelnum]);
 }
 
 #include "uhci-debug.c"
@@ -540,16 +540,18 @@ static void uhci_shutdown(struct pci_dev *pdev)
  *
  * The hardware doesn't really know any difference
  * in the queues, but the order does matter for the
- * protocols higher up. The order is:
+ * protocols higher up.  The order in which the queues
+ * are encountered by the hardware is:
  *
- *  - any isochronous events handled before any
+ *  - All isochronous events are handled before any
  *    of the queues. We don't do that here, because
  *    we'll create the actual TD entries on demand.
- *  - The first queue is the interrupt queue.
- *  - The second queue is the control queue, split into low- and full-speed
- *  - The third queue is bulk queue.
- *  - The fourth queue is the bandwidth reclamation queue, which loops back
- *    to the full-speed control queue.
+ *  - The first queue is the high-period interrupt queue.
+ *  - The second queue is the period-1 interrupt and async
+ *    (low-speed control, full-speed control, then bulk) queue.
+ *  - The third queue is the terminating bandwidth reclamation queue,
+ *    which contains no members, loops back to itself, and is present
+ *    only when FSBR is on and there are no full-speed control or bulk QHs.
  */
 static int uhci_start(struct usb_hcd *hcd)
 {
@@ -626,34 +628,18 @@ static int uhci_start(struct usb_hcd *hcd)
        }
 
        /*
-        * 8 Interrupt queues; link all higher int queues to int1,
-        * then link int1 to control and control to bulk
+        * 8 Interrupt queues; link all higher int queues to int1 = async
         */
-       uhci->skel_int128_qh->link =
-                       uhci->skel_int64_qh->link =
-                       uhci->skel_int32_qh->link =
-                       uhci->skel_int16_qh->link =
-                       uhci->skel_int8_qh->link =
-                       uhci->skel_int4_qh->link =
-                       uhci->skel_int2_qh->link = UHCI_PTR_QH |
-                       cpu_to_le32(uhci->skel_int1_qh->dma_handle);
-
-       uhci->skel_int1_qh->link = UHCI_PTR_QH |
-                       cpu_to_le32(uhci->skel_ls_control_qh->dma_handle);
-       uhci->skel_ls_control_qh->link = UHCI_PTR_QH |
-                       cpu_to_le32(uhci->skel_fs_control_qh->dma_handle);
-       uhci->skel_fs_control_qh->link = UHCI_PTR_QH |
-                       cpu_to_le32(uhci->skel_bulk_qh->dma_handle);
-       uhci->skel_bulk_qh->link = UHCI_PTR_QH |
-                       cpu_to_le32(uhci->skel_term_qh->dma_handle);
+       for (i = SKEL_ISO + 1; i < SKEL_ASYNC; ++i)
+               uhci->skelqh[i]->link = LINK_TO_QH(uhci->skel_async_qh);
+       uhci->skel_async_qh->link = uhci->skel_term_qh->link = UHCI_PTR_TERM;
 
        /* This dummy TD is to work around a bug in Intel PIIX controllers */
        uhci_fill_td(uhci->term_td, 0, uhci_explen(0) |
-               (0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0);
-       uhci->term_td->link = cpu_to_le32(uhci->term_td->dma_handle);
-
-       uhci->skel_term_qh->link = UHCI_PTR_TERM;
-       uhci->skel_term_qh->element = cpu_to_le32(uhci->term_td->dma_handle);
+                       (0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0);
+       uhci->term_td->link = UHCI_PTR_TERM;
+       uhci->skel_async_qh->element = uhci->skel_term_qh->element =
+                       LINK_TO_TD(uhci->term_td);
 
        /*
         * Fill the frame list: make all entries point to the proper
index 74469b5bcb61a3e8af29b14ffcaf7b1ce6cd47f1..1b3d23406ac414005636d93212d2783968f8d17a 100644 (file)
@@ -129,11 +129,12 @@ struct uhci_qh {
        __le32 element;                 /* Queue element (TD) pointer */
 
        /* Software fields */
+       dma_addr_t dma_handle;
+
        struct list_head node;          /* Node in the list of QHs */
        struct usb_host_endpoint *hep;  /* Endpoint information */
        struct usb_device *udev;
        struct list_head queue;         /* Queue of urbps for this QH */
-       struct uhci_qh *skel;           /* Skeleton for this QH */
        struct uhci_td *dummy_td;       /* Dummy TD to end the queue */
        struct uhci_td *post_td;        /* Last TD completed */
 
@@ -149,8 +150,7 @@ struct uhci_qh {
 
        int state;                      /* QH_STATE_xxx; see above */
        int type;                       /* Queue type (control, bulk, etc) */
-
-       dma_addr_t dma_handle;
+       int skel;                       /* Skeleton queue number */
 
        unsigned int initial_toggle:1;  /* Endpoint's current toggle value */
        unsigned int needs_fixup:1;     /* Must fix the TD toggle values */
@@ -171,6 +171,8 @@ static inline __le32 qh_element(struct uhci_qh *qh) {
        return element;
 }
 
+#define LINK_TO_QH(qh)         (UHCI_PTR_QH | cpu_to_le32((qh)->dma_handle))
+
 
 /*
  *     Transfer Descriptors
@@ -264,6 +266,8 @@ static inline u32 td_status(struct uhci_td *td) {
        return le32_to_cpu(status);
 }
 
+#define LINK_TO_TD(td)         (cpu_to_le32((td)->dma_handle))
+
 
 /*
  *     Skeleton Queue Headers
@@ -272,12 +276,13 @@ static inline u32 td_status(struct uhci_td *td) {
 /*
  * The UHCI driver uses QHs with Interrupt, Control and Bulk URBs for
  * automatic queuing. To make it easy to insert entries into the schedule,
- * we have a skeleton of QHs for each predefined Interrupt latency,
- * low-speed control, full-speed control, bulk, and terminating QH
- * (see explanation for the terminating QH below).
+ * we have a skeleton of QHs for each predefined Interrupt latency.
+ * Asynchronous QHs (low-speed control, full-speed control, and bulk)
+ * go onto the period-1 interrupt list, since they all get accessed on
+ * every frame.
  *
- * When we want to add a new QH, we add it to the end of the list for the
- * skeleton QH.  For instance, the schedule list can look like this:
+ * When we want to add a new QH, we add it to the list starting from the
+ * appropriate skeleton QH.  For instance, the schedule can look like this:
  *
  * skel int128 QH
  * dev 1 interrupt QH
@@ -285,50 +290,47 @@ static inline u32 td_status(struct uhci_td *td) {
  * skel int64 QH
  * skel int32 QH
  * ...
- * skel int1 QH
- * skel low-speed control QH
- * dev 5 control QH
- * skel full-speed control QH
- * skel bulk QH
+ * skel int1 + async QH
+ * dev 5 low-speed control QH
  * dev 1 bulk QH
  * dev 2 bulk QH
- * skel terminating QH
  *
- * The terminating QH is used for 2 reasons:
- * - To place a terminating TD which is used to workaround a PIIX bug
- *   (see Intel errata for explanation), and
- * - To loop back to the full-speed control queue for full-speed bandwidth
- *   reclamation.
+ * There is a special terminating QH used to keep full-speed bandwidth
+ * reclamation active when no full-speed control or bulk QHs are linked
+ * into the schedule.  It has an inactive TD (to work around a PIIX bug,
+ * see the Intel errata) and it points back to itself.
  *
- * There's a special skeleton QH for Isochronous QHs.  It never appears
- * on the schedule, and Isochronous TDs go on the schedule before the
+ * There's a special skeleton QH for Isochronous QHs which never appears
+ * on the schedule Isochronous TDs go on the schedule before the
  * the skeleton QHs.  The hardware accesses them directly rather than
  * through their QH, which is used only for bookkeeping purposes.
  * While the UHCI spec doesn't forbid the use of QHs for Isochronous,
  * it doesn't use them either.  And the spec says that queues never
  * advance on an error completion status, which makes them totally
  * unsuitable for Isochronous transfers.
+ *
+ * There's also a special skeleton QH used for QHs which are in the process
+ * of unlinking and so may still be in use by the hardware.  It too never
+ * appears on the schedule.
  */
 
-#define UHCI_NUM_SKELQH                14
-#define skel_unlink_qh         skelqh[0]
-#define skel_iso_qh            skelqh[1]
-#define skel_int128_qh         skelqh[2]
-#define skel_int64_qh          skelqh[3]
-#define skel_int32_qh          skelqh[4]
-#define skel_int16_qh          skelqh[5]
-#define skel_int8_qh           skelqh[6]
-#define skel_int4_qh           skelqh[7]
-#define skel_int2_qh           skelqh[8]
-#define skel_int1_qh           skelqh[9]
-#define skel_ls_control_qh     skelqh[10]
-#define skel_fs_control_qh     skelqh[11]
-#define skel_bulk_qh           skelqh[12]
-#define skel_term_qh           skelqh[13]
-
-/* Find the skelqh entry corresponding to an interval exponent */
-#define UHCI_SKEL_INDEX(exponent)      (9 - exponent)
-
+#define UHCI_NUM_SKELQH                11
+#define SKEL_UNLINK            0
+#define skel_unlink_qh         skelqh[SKEL_UNLINK]
+#define SKEL_ISO               1
+#define skel_iso_qh            skelqh[SKEL_ISO]
+       /* int128, int64, ..., int1 = 2, 3, ..., 9 */
+#define SKEL_INDEX(exponent)   (9 - exponent)
+#define SKEL_ASYNC             9
+#define skel_async_qh          skelqh[SKEL_ASYNC]
+#define SKEL_TERM              10
+#define skel_term_qh           skelqh[SKEL_TERM]
+
+/* The following entries refer to sublists of skel_async_qh */
+#define SKEL_LS_CONTROL                20
+#define SKEL_FS_CONTROL                21
+#define SKEL_FSBR              SKEL_FS_CONTROL
+#define SKEL_BULK              22
 
 /*
  *     The UHCI controller and root hub
index bacc25c53ba3318c3626f1043ffb878706c85a69..8e4427aebb142e00d79b83e4624697b8d746ce33 100644 (file)
@@ -33,6 +33,9 @@ static __u8 root_hub_hub_des[] =
 /* status change bits:  nonzero writes will clear */
 #define RWC_BITS       (USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC)
 
+/* suspend/resume bits: port suspended or port resuming */
+#define SUSPEND_BITS   (USBPORTSC_SUSP | USBPORTSC_RD)
+
 /* A port that either is connected or has a changed-bit set will prevent
  * us from AUTO_STOPPING.
  */
@@ -96,8 +99,8 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
        int status;
        int i;
 
-       if (inw(port_addr) & (USBPORTSC_SUSP | USBPORTSC_RD)) {
-               CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD);
+       if (inw(port_addr) & SUSPEND_BITS) {
+               CLR_RH_PORTSTAT(SUSPEND_BITS);
                if (test_bit(port, &uhci->resuming_ports))
                        set_bit(port, &uhci->port_c_suspend);
 
@@ -107,7 +110,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
                 * Experiments show that some controllers take longer, so
                 * we'll poll for completion. */
                for (i = 0; i < 10; ++i) {
-                       if (!(inw(port_addr) & USBPORTSC_RD))
+                       if (!(inw(port_addr) & SUSPEND_BITS))
                                break;
                        udelay(1);
                }
@@ -289,7 +292,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        wPortStatus |= USB_PORT_STAT_CONNECTION;
                if (status & USBPORTSC_PE) {
                        wPortStatus |= USB_PORT_STAT_ENABLE;
-                       if (status & (USBPORTSC_SUSP | USBPORTSC_RD))
+                       if (status & SUSPEND_BITS)
                                wPortStatus |= USB_PORT_STAT_SUSPEND;
                }
                if (status & USBPORTSC_OC)
index 68e66b33e7269bfd1ba3972aadaee6e64b09bd79..f4ebdb3e488f59ad23d17ae7fc2a301b2aae0e9c 100644 (file)
@@ -13,7 +13,7 @@
  * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
  *               support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
  * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
- * (C) Copyright 2004-2006 Alan Stern, stern@rowland.harvard.edu
+ * (C) Copyright 2004-2007 Alan Stern, stern@rowland.harvard.edu
  */
 
 
@@ -45,15 +45,43 @@ static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci)
  */
 static void uhci_fsbr_on(struct uhci_hcd *uhci)
 {
+       struct uhci_qh *fsbr_qh, *lqh, *tqh;
+
        uhci->fsbr_is_on = 1;
-       uhci->skel_term_qh->link = cpu_to_le32(
-                       uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH;
+       lqh = list_entry(uhci->skel_async_qh->node.prev,
+                       struct uhci_qh, node);
+
+       /* Find the first FSBR QH.  Linear search through the list is
+        * acceptable because normally FSBR gets turned on as soon as
+        * one QH needs it. */
+       fsbr_qh = NULL;
+       list_for_each_entry_reverse(tqh, &uhci->skel_async_qh->node, node) {
+               if (tqh->skel < SKEL_FSBR)
+                       break;
+               fsbr_qh = tqh;
+       }
+
+       /* No FSBR QH means we must insert the terminating skeleton QH */
+       if (!fsbr_qh) {
+               uhci->skel_term_qh->link = LINK_TO_QH(uhci->skel_term_qh);
+               wmb();
+               lqh->link = uhci->skel_term_qh->link;
+
+       /* Otherwise loop the last QH to the first FSBR QH */
+       } else
+               lqh->link = LINK_TO_QH(fsbr_qh);
 }
 
 static void uhci_fsbr_off(struct uhci_hcd *uhci)
 {
+       struct uhci_qh *lqh;
+
        uhci->fsbr_is_on = 0;
-       uhci->skel_term_qh->link = UHCI_PTR_TERM;
+       lqh = list_entry(uhci->skel_async_qh->node.prev,
+                       struct uhci_qh, node);
+
+       /* End the async list normally and unlink the terminating QH */
+       lqh->link = uhci->skel_term_qh->link = UHCI_PTR_TERM;
 }
 
 static void uhci_add_fsbr(struct uhci_hcd *uhci, struct urb *urb)
@@ -158,11 +186,11 @@ static inline void uhci_insert_td_in_frame_list(struct uhci_hcd *uhci,
 
                td->link = ltd->link;
                wmb();
-               ltd->link = cpu_to_le32(td->dma_handle);
+               ltd->link = LINK_TO_TD(td);
        } else {
                td->link = uhci->frame[framenum];
                wmb();
-               uhci->frame[framenum] = cpu_to_le32(td->dma_handle);
+               uhci->frame[framenum] = LINK_TO_TD(td);
                uhci->frame_cpu[framenum] = td;
        }
 }
@@ -184,7 +212,7 @@ static inline void uhci_remove_td_from_frame_list(struct uhci_hcd *uhci,
                        struct uhci_td *ntd;
 
                        ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list);
-                       uhci->frame[td->frame] = cpu_to_le32(ntd->dma_handle);
+                       uhci->frame[td->frame] = LINK_TO_TD(ntd);
                        uhci->frame_cpu[td->frame] = ntd;
                }
        } else {
@@ -405,12 +433,81 @@ static void uhci_fixup_toggles(struct uhci_qh *qh, int skip_first)
 }
 
 /*
- * Put a QH on the schedule in both hardware and software
+ * Link an Isochronous QH into its skeleton's list
  */
-static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+static inline void link_iso(struct uhci_hcd *uhci, struct uhci_qh *qh)
+{
+       list_add_tail(&qh->node, &uhci->skel_iso_qh->node);
+
+       /* Isochronous QHs aren't linked by the hardware */
+}
+
+/*
+ * Link a high-period interrupt QH into the schedule at the end of its
+ * skeleton's list
+ */
+static void link_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh)
 {
        struct uhci_qh *pqh;
 
+       list_add_tail(&qh->node, &uhci->skelqh[qh->skel]->node);
+
+       pqh = list_entry(qh->node.prev, struct uhci_qh, node);
+       qh->link = pqh->link;
+       wmb();
+       pqh->link = LINK_TO_QH(qh);
+}
+
+/*
+ * Link a period-1 interrupt or async QH into the schedule at the
+ * correct spot in the async skeleton's list, and update the FSBR link
+ */
+static void link_async(struct uhci_hcd *uhci, struct uhci_qh *qh)
+{
+       struct uhci_qh *pqh, *lqh;
+       __le32 link_to_new_qh;
+       __le32 *extra_link = &link_to_new_qh;
+
+       /* Find the predecessor QH for our new one and insert it in the list.
+        * The list of QHs is expected to be short, so linear search won't
+        * take too long. */
+       list_for_each_entry_reverse(pqh, &uhci->skel_async_qh->node, node) {
+               if (pqh->skel <= qh->skel)
+                       break;
+       }
+       list_add(&qh->node, &pqh->node);
+       qh->link = pqh->link;
+
+       link_to_new_qh = LINK_TO_QH(qh);
+
+       /* If this is now the first FSBR QH, take special action */
+       if (uhci->fsbr_is_on && pqh->skel < SKEL_FSBR &&
+                       qh->skel >= SKEL_FSBR) {
+               lqh = list_entry(uhci->skel_async_qh->node.prev,
+                               struct uhci_qh, node);
+
+               /* If the new QH is also the last one, we must unlink
+                * the terminating skeleton QH and make the new QH point
+                * back to itself. */
+               if (qh == lqh) {
+                       qh->link = link_to_new_qh;
+                       extra_link = &uhci->skel_term_qh->link;
+
+               /* Otherwise the last QH must point to the new QH */
+               } else
+                       extra_link = &lqh->link;
+       }
+
+       /* Link it into the schedule */
+       wmb();
+       *extra_link = pqh->link = link_to_new_qh;
+}
+
+/*
+ * Put a QH on the schedule in both hardware and software
+ */
+static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+{
        WARN_ON(list_empty(&qh->queue));
 
        /* Set the element pointer if it isn't set already.
@@ -421,7 +518,7 @@ static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
                struct uhci_td *td = list_entry(urbp->td_list.next,
                                struct uhci_td, list);
 
-               qh->element = cpu_to_le32(td->dma_handle);
+               qh->element = LINK_TO_TD(td);
        }
 
        /* Treat the queue as if it has just advanced */
@@ -432,18 +529,64 @@ static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
                return;
        qh->state = QH_STATE_ACTIVE;
 
-       /* Move the QH from its old list to the end of the appropriate
+       /* Move the QH from its old list to the correct spot in the appropriate
         * skeleton's list */
        if (qh == uhci->next_qh)
                uhci->next_qh = list_entry(qh->node.next, struct uhci_qh,
                                node);
-       list_move_tail(&qh->node, &qh->skel->node);
+       list_del(&qh->node);
+
+       if (qh->skel == SKEL_ISO)
+               link_iso(uhci, qh);
+       else if (qh->skel < SKEL_ASYNC)
+               link_interrupt(uhci, qh);
+       else
+               link_async(uhci, qh);
+}
+
+/*
+ * Unlink a high-period interrupt QH from the schedule
+ */
+static void unlink_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh)
+{
+       struct uhci_qh *pqh;
 
-       /* Link it into the schedule */
        pqh = list_entry(qh->node.prev, struct uhci_qh, node);
-       qh->link = pqh->link;
-       wmb();
-       pqh->link = UHCI_PTR_QH | cpu_to_le32(qh->dma_handle);
+       pqh->link = qh->link;
+       mb();
+}
+
+/*
+ * Unlink a period-1 interrupt or async QH from the schedule
+ */
+static void unlink_async(struct uhci_hcd *uhci, struct uhci_qh *qh)
+{
+       struct uhci_qh *pqh, *lqh;
+       __le32 link_to_next_qh = qh->link;
+
+       pqh = list_entry(qh->node.prev, struct uhci_qh, node);
+
+       /* If this is the first FSBQ QH, take special action */
+       if (uhci->fsbr_is_on && pqh->skel < SKEL_FSBR &&
+                       qh->skel >= SKEL_FSBR) {
+               lqh = list_entry(uhci->skel_async_qh->node.prev,
+                               struct uhci_qh, node);
+
+               /* If this QH is also the last one, we must link in
+                * the terminating skeleton QH. */
+               if (qh == lqh) {
+                       link_to_next_qh = LINK_TO_QH(uhci->skel_term_qh);
+                       uhci->skel_term_qh->link = link_to_next_qh;
+                       wmb();
+                       qh->link = link_to_next_qh;
+
+               /* Otherwise the last QH must point to the new first FSBR QH */
+               } else
+                       lqh->link = link_to_next_qh;
+       }
+
+       pqh->link = link_to_next_qh;
+       mb();
 }
 
 /*
@@ -451,17 +594,18 @@ static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
  */
 static void uhci_unlink_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
 {
-       struct uhci_qh *pqh;
-
        if (qh->state == QH_STATE_UNLINKING)
                return;
        WARN_ON(qh->state != QH_STATE_ACTIVE || !qh->udev);
        qh->state = QH_STATE_UNLINKING;
 
        /* Unlink the QH from the schedule and record when we did it */
-       pqh = list_entry(qh->node.prev, struct uhci_qh, node);
-       pqh->link = qh->link;
-       mb();
+       if (qh->skel == SKEL_ISO)
+               ;
+       else if (qh->skel < SKEL_ASYNC)
+               unlink_interrupt(uhci, qh);
+       else
+               unlink_async(uhci, qh);
 
        uhci_get_current_frame_number(uhci);
        qh->unlink_frame = uhci->frame_number;
@@ -697,6 +841,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
        dma_addr_t data = urb->transfer_dma;
        __le32 *plink;
        struct urb_priv *urbp = urb->hcpriv;
+       int skel;
 
        /* The "pipe" thing contains the destination in bits 8--18 */
        destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
@@ -737,7 +882,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
                td = uhci_alloc_td(uhci);
                if (!td)
                        goto nomem;
-               *plink = cpu_to_le32(td->dma_handle);
+               *plink = LINK_TO_TD(td);
 
                /* Alternate Data0/1 (start with Data1) */
                destination ^= TD_TOKEN_TOGGLE;
@@ -757,7 +902,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
        td = uhci_alloc_td(uhci);
        if (!td)
                goto nomem;
-       *plink = cpu_to_le32(td->dma_handle);
+       *plink = LINK_TO_TD(td);
 
        /*
         * It's IN if the pipe is an output pipe or we're not expecting
@@ -784,7 +929,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
        td = uhci_alloc_td(uhci);
        if (!td)
                goto nomem;
-       *plink = cpu_to_le32(td->dma_handle);
+       *plink = LINK_TO_TD(td);
 
        uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0);
        wmb();
@@ -797,11 +942,13 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
         * isn't in the CONFIGURED state. */
        if (urb->dev->speed == USB_SPEED_LOW ||
                        urb->dev->state != USB_STATE_CONFIGURED)
-               qh->skel = uhci->skel_ls_control_qh;
+               skel = SKEL_LS_CONTROL;
        else {
-               qh->skel = uhci->skel_fs_control_qh;
+               skel = SKEL_FS_CONTROL;
                uhci_add_fsbr(uhci, urb);
        }
+       if (qh->state != QH_STATE_ACTIVE)
+               qh->skel = skel;
 
        urb->actual_length = -8;        /* Account for the SETUP packet */
        return 0;
@@ -860,7 +1007,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
                        td = uhci_alloc_td(uhci);
                        if (!td)
                                goto nomem;
-                       *plink = cpu_to_le32(td->dma_handle);
+                       *plink = LINK_TO_TD(td);
                }
                uhci_add_td_to_urbp(td, urbp);
                uhci_fill_td(td, status,
@@ -888,7 +1035,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
                td = uhci_alloc_td(uhci);
                if (!td)
                        goto nomem;
-               *plink = cpu_to_le32(td->dma_handle);
+               *plink = LINK_TO_TD(td);
 
                uhci_add_td_to_urbp(td, urbp);
                uhci_fill_td(td, status,
@@ -914,7 +1061,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
        td = uhci_alloc_td(uhci);
        if (!td)
                goto nomem;
-       *plink = cpu_to_le32(td->dma_handle);
+       *plink = LINK_TO_TD(td);
 
        uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0);
        wmb();
@@ -931,7 +1078,7 @@ nomem:
        return -ENOMEM;
 }
 
-static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb,
+static int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb,
                struct uhci_qh *qh)
 {
        int ret;
@@ -940,7 +1087,8 @@ static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb,
        if (urb->dev->speed == USB_SPEED_LOW)
                return -EINVAL;
 
-       qh->skel = uhci->skel_bulk_qh;
+       if (qh->state != QH_STATE_ACTIVE)
+               qh->skel = SKEL_BULK;
        ret = uhci_submit_common(uhci, urb, qh);
        if (ret == 0)
                uhci_add_fsbr(uhci, urb);
@@ -968,7 +1116,7 @@ static int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb,
                if (exponent < 0)
                        return -EINVAL;
                qh->period = 1 << exponent;
-               qh->skel = uhci->skelqh[UHCI_SKEL_INDEX(exponent)];
+               qh->skel = SKEL_INDEX(exponent);
 
                /* For now, interrupt phase is fixed by the layout
                 * of the QH lists. */
@@ -1005,7 +1153,7 @@ static int uhci_fixup_short_transfer(struct uhci_hcd *uhci,
                 * the queue at the status stage transaction, which is
                 * the last TD. */
                WARN_ON(list_empty(&urbp->td_list));
-               qh->element = cpu_to_le32(td->dma_handle);
+               qh->element = LINK_TO_TD(td);
                tmp = td->list.prev;
                ret = -EINPROGRESS;
 
@@ -1216,7 +1364,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
                qh->iso_status = 0;
        }
 
-       qh->skel = uhci->skel_iso_qh;
+       qh->skel = SKEL_ISO;
        if (!qh->bandwidth_reserved)
                uhci_reserve_bandwidth(uhci, qh);
        return 0;
@@ -1566,8 +1714,7 @@ static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh)
        if (time_after(jiffies, qh->advance_jiffies + QH_WAIT_TIMEOUT)) {
 
                /* Detect the Intel bug and work around it */
-               if (qh->post_td && qh_element(qh) ==
-                               cpu_to_le32(qh->post_td->dma_handle)) {
+               if (qh->post_td && qh_element(qh) == LINK_TO_TD(qh->post_td)) {
                        qh->element = qh->post_td->link;
                        qh->advance_jiffies = jiffies;
                        ret = 1;
index ef09952f20393aea387a031be84b45f3fcc6f99f..827a75a186ba6006f30819ca0d893fb0d076214a 100644 (file)
@@ -4,7 +4,7 @@
  *  Copyright (c) 1999 Andreas Gal
  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
- *  Copyright (c) 2006 Jiri Kosina
+ *  Copyright (c) 2006-2007 Jiri Kosina
  */
 
 /*
@@ -27,9 +27,6 @@
 #include <linux/input.h>
 #include <linux/wait.h>
 
-#undef DEBUG
-#undef DEBUG_DATA
-
 #include <linux/usb.h>
 
 #include <linux/hid.h>
@@ -689,10 +686,8 @@ void usbhid_init_reports(struct hid_device *hid)
 #define USB_DEVICE_ID_SMARTJOY_DUAL_PLUS 0x8802
 
 #define USB_VENDOR_ID_CODEMERCS                0x07c0
-#define USB_DEVICE_ID_CODEMERCS_IOW40  0x1500
-#define USB_DEVICE_ID_CODEMERCS_IOW24  0x1501
-#define USB_DEVICE_ID_CODEMERCS_IOW48  0x1502
-#define USB_DEVICE_ID_CODEMERCS_IOW28  0x1503
+#define USB_DEVICE_ID_CODEMERCS_IOW_FIRST      0x1500
+#define USB_DEVICE_ID_CODEMERCS_IOW_LAST       0x15ff
 
 #define USB_VENDOR_ID_DELORME          0x1163
 #define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
@@ -758,6 +753,8 @@ void usbhid_init_reports(struct hid_device *hid)
 
 #define USB_VENDOR_ID_LOGITECH         0x046d
 #define USB_DEVICE_ID_LOGITECH_USB_RECEIVER    0xc101
+#define USB_DEVICE_ID_LOGITECH_USB_RECEIVER_2  0xc517
+#define USB_DEVICE_ID_DINOVO_EDGE      0xc714
 
 #define USB_VENDOR_ID_IMATION          0x0718
 #define USB_DEVICE_ID_DISC_STAKKA      0xd000
@@ -778,6 +775,8 @@ static const struct hid_blacklist {
        unsigned quirks;
 } hid_blacklist[] = {
 
+       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES },
+
        { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20, HID_QUIRK_IGNORE },
@@ -788,10 +787,6 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW48, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE },
@@ -944,6 +939,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
 
        { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS },
+       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER_2, HID_QUIRK_LOGITECH_S510_DESCRIPTOR },
 
        { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
 
@@ -1041,6 +1037,22 @@ static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum)
        kfree(buf);
 }
 
+/*
+ * Logitech S510 keyboard sends in report #3 keys which are far
+ * above the logical maximum described in descriptor. This extends
+ * the original value of 0x28c of logical maximum to 0x104d
+ */
+static void hid_fixup_s510_descriptor(unsigned char *rdesc, int rsize)
+{
+       if (rsize >= 90 && rdesc[83] == 0x26
+                       && rdesc[84] == 0x8c
+                       && rdesc[85] == 0x02) {
+               info("Fixing up Logitech S510 report descriptor");
+               rdesc[84] = rdesc[89] = 0x4d;
+               rdesc[85] = rdesc[90] = 0x10;
+       }
+}
+
 static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 {
        struct usb_host_interface *interface = intf->cur_altsetting;
@@ -1052,9 +1064,14 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
        int n, len, insize = 0;
        struct usbhid_device *usbhid;
 
-        /* Ignore all Wacom devices */
-        if (le16_to_cpu(dev->descriptor.idVendor) == USB_VENDOR_ID_WACOM)
-                return NULL;
+       /* Ignore all Wacom devices */
+       if (le16_to_cpu(dev->descriptor.idVendor) == USB_VENDOR_ID_WACOM)
+               return NULL;
+       /* ignore all Code Mercenaries IOWarrior devices */
+       if (le16_to_cpu(dev->descriptor.idVendor) == USB_VENDOR_ID_CODEMERCS)
+               if (le16_to_cpu(dev->descriptor.idProduct) >= USB_DEVICE_ID_CODEMERCS_IOW_FIRST &&
+                   le16_to_cpu(dev->descriptor.idProduct) <= USB_DEVICE_ID_CODEMERCS_IOW_LAST)
+                       return NULL;
 
        for (n = 0; hid_blacklist[n].idVendor; n++)
                if ((hid_blacklist[n].idVendor == le16_to_cpu(dev->descriptor.idVendor)) &&
@@ -1109,7 +1126,10 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
        if ((quirks & HID_QUIRK_CYMOTION))
                hid_fixup_cymotion_descriptor(rdesc, rsize);
 
-#ifdef DEBUG_DATA
+       if (quirks & HID_QUIRK_LOGITECH_S510_DESCRIPTOR)
+               hid_fixup_s510_descriptor(rdesc, rsize);
+
+#ifdef CONFIG_HID_DEBUG
        printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
        for (n = 0; n < rsize; n++)
                printk(" %02x", (unsigned char) rdesc[n]);
@@ -1225,8 +1245,8 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
                         le16_to_cpu(dev->descriptor.idProduct));
 
        hid->bus = BUS_USB;
-       hid->vendor = dev->descriptor.idVendor;
-       hid->product = dev->descriptor.idProduct;
+       hid->vendor = le16_to_cpu(dev->descriptor.idVendor);
+       hid->product = le16_to_cpu(dev->descriptor.idProduct);
 
        usb_make_path(dev, hid->phys, sizeof(hid->phys));
        strlcat(hid->phys, "/input", sizeof(hid->phys));
index 8505824848f6b7995bc40bd1cab9ef1ad3038a9c..3749f4a235f9f9a064e89ac8fee83fbc82040d43 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/usb/input.h>
+#include <linux/hid.h>
 
 /*
  * Version Information
@@ -330,7 +331,8 @@ static void usb_kbd_disconnect(struct usb_interface *intf)
 }
 
 static struct usb_device_id usb_kbd_id_table [] = {
-       { USB_INTERFACE_INFO(3, 1, 1) },
+       { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
+               USB_INTERFACE_PROTOCOL_KEYBOARD) },
        { }                                             /* Terminating entry */
 };
 
index 64a33e420cfbabb3b6758f25353c67b4b02ee55e..692fd6087779a2a8b2c5a581122d860ee0a45595 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/usb/input.h>
+#include <linux/hid.h>
 
 /*
  * Version Information
@@ -213,7 +214,8 @@ static void usb_mouse_disconnect(struct usb_interface *intf)
 }
 
 static struct usb_device_id usb_mouse_id_table [] = {
-       { USB_INTERFACE_INFO(3, 1, 2) },
+       { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
+               USB_INTERFACE_PROTOCOL_MOUSE) },
        { }     /* Terminating entry */
 };
 
index 4142e36730fc7a359012a937def88fc8b7e299d6..4f3e9bc7177d236e9c1575111c0f9b4162d1c359 100644 (file)
@@ -163,7 +163,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
        }
 
        id = STYLUS_DEVICE_ID;
-       if (data[1] & 0x10) { /* in prox */
+       if (data[1] & 0x80) { /* in prox */
 
                switch ((data[1] >> 5) & 3) {
 
@@ -196,9 +196,6 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
                                        wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f);
                                break;
                }
-       }
-
-       if (data[1] & 0x90) {
                x = wacom_le16_to_cpu(&data[2]);
                y = wacom_le16_to_cpu(&data[4]);
                wacom_report_abs(wcombo, ABS_X, x);
@@ -210,19 +207,28 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
                        wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04);
                }
                wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */
-       }
-       else
-               wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
-
-       if (data[1] & 0x10)  /* only report prox-in when in area */
                wacom_report_key(wcombo, wacom->tool[0], 1);
-       if (!(data[1] & 0x90))  /* report prox-out when physically out */
+       } else if (!(data[1] & 0x90)) {
+               wacom_report_abs(wcombo, ABS_X, 0);
+               wacom_report_abs(wcombo, ABS_Y, 0);
+               if (wacom->tool[0] == BTN_TOOL_MOUSE) {
+                       wacom_report_key(wcombo, BTN_LEFT, 0);
+                       wacom_report_key(wcombo, BTN_RIGHT, 0);
+                       wacom_report_abs(wcombo, ABS_DISTANCE, 0);
+               } else {
+                       wacom_report_abs(wcombo, ABS_PRESSURE, 0);
+                       wacom_report_key(wcombo, BTN_TOUCH, 0);
+                       wacom_report_key(wcombo, BTN_STYLUS, 0);
+                       wacom_report_key(wcombo, BTN_STYLUS2, 0);
+               }
+               wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
                wacom_report_key(wcombo, wacom->tool[0], 0);
-       wacom_input_sync(wcombo);
+       }
 
        /* send pad data */
        if (wacom->features->type == WACOM_G4) {
-               if ( (wacom->serial[1] & 0xc0) != (data[7] & 0xf8) ) {
+               if (data[7] & 0xf8) {
+                       wacom_input_sync(wcombo); /* sync last event */
                        wacom->id[1] = 1;
                        wacom->serial[1] = (data[7] & 0xf8);
                        wacom_report_key(wcombo, BTN_0, (data[7] & 0x40));
@@ -230,10 +236,15 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
                        rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
                        wacom_report_rel(wcombo, REL_WHEEL, rw);
                        wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0);
+                       wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
                        wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
                } else if (wacom->id[1]) {
+                       wacom_input_sync(wcombo); /* sync last event */
                        wacom->id[1] = 0;
+                       wacom_report_key(wcombo, BTN_0, (data[7] & 0x40));
+                       wacom_report_key(wcombo, BTN_4, (data[7] & 0x80));
                        wacom_report_key(wcombo, BTN_TOOL_FINGER, 0);
+                       wacom_report_abs(wcombo, ABS_MISC, 0);
                        wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
                }
        }
@@ -304,28 +315,35 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo)
                        default: /* Unknown tool */
                                wacom->tool[idx] = BTN_TOOL_PEN;
                }
-               /* only large I3 support Lens Cursor */
-               if(!((wacom->tool[idx] == BTN_TOOL_LENS)
-                                && ((wacom->features->type == INTUOS3)
-                                || (wacom->features->type == INTUOS3S)))) {
-                       wacom_report_abs(wcombo, ABS_MISC, wacom->id[idx]); /* report tool id */
-                       wacom_report_key(wcombo, wacom->tool[idx], 1);
-                       wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
-                       return 2;
-               }
                return 1;
        }
 
        /* Exit report */
        if ((data[1] & 0xfe) == 0x80) {
-               if(!((wacom->tool[idx] == BTN_TOOL_LENS)
-                                && ((wacom->features->type == INTUOS3)
-                                || (wacom->features->type == INTUOS3S)))) {
-                       wacom_report_key(wcombo, wacom->tool[idx], 0);
-                       wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
-                       wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
-                       return 2;
+               wacom_report_abs(wcombo, ABS_X, 0);
+               wacom_report_abs(wcombo, ABS_Y, 0);
+               wacom_report_abs(wcombo, ABS_DISTANCE, 0);
+               if (wacom->tool[idx] >= BTN_TOOL_MOUSE) {
+                       wacom_report_key(wcombo, BTN_LEFT, 0);
+                       wacom_report_key(wcombo, BTN_MIDDLE, 0);
+                       wacom_report_key(wcombo, BTN_RIGHT, 0);
+                       wacom_report_key(wcombo, BTN_SIDE, 0);
+                       wacom_report_key(wcombo, BTN_EXTRA, 0);
+                       wacom_report_abs(wcombo, ABS_THROTTLE, 0);
+                       wacom_report_abs(wcombo, ABS_RZ, 0);
+               } else {
+                       wacom_report_abs(wcombo, ABS_PRESSURE, 0);
+                       wacom_report_abs(wcombo, ABS_TILT_X, 0);
+                       wacom_report_abs(wcombo, ABS_TILT_Y, 0);
+                       wacom_report_key(wcombo, BTN_STYLUS, 0);
+                       wacom_report_key(wcombo, BTN_STYLUS2, 0);
+                       wacom_report_key(wcombo, BTN_TOUCH, 0);
+                       wacom_report_abs(wcombo, ABS_WHEEL, 0);
                }
+               wacom_report_key(wcombo, wacom->tool[idx], 0);
+               wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
+               wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+               return 2;
        }
        return 0;
 }
@@ -394,6 +412,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
                        wacom_report_key(wcombo, wacom->tool[1], 1);
                else
                        wacom_report_key(wcombo, wacom->tool[1], 0);
+               wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
                wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xffffffff);
                 return 1;
        }
@@ -403,6 +422,12 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
        if (result)
                 return result-1;
 
+       /* Only large I3 and I1 & I2 support Lense Cursor */
+       if((wacom->tool[idx] == BTN_TOOL_LENS)
+                       && ((wacom->features->type == INTUOS3)
+                       || (wacom->features->type == INTUOS3S)))
+               return 0;
+
        /* Cintiq doesn't send data when RDY bit isn't set */
        if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40))
                  return 0;
@@ -554,11 +579,11 @@ static struct wacom_features wacom_features[] = {
        { "Wacom Volito2 4x5",   8,   5104,  3712,  511, 63, GRAPHIRE },
        { "Wacom Volito2 2x3",   8,   3248,  2320,  511, 63, GRAPHIRE },
        { "Wacom PenPartner2",   8,   3250,  2320,  255, 63, GRAPHIRE },
-       { "Wacom Intuos 4x5",   10,  12700, 10600, 1023, 63, INTUOS },
-       { "Wacom Intuos 6x8",   10,  20320, 16240, 1023, 63, INTUOS },
-       { "Wacom Intuos 9x12",  10,  30480, 24060, 1023, 63, INTUOS },
-       { "Wacom Intuos 12x12", 10,  30480, 31680, 1023, 63, INTUOS },
-       { "Wacom Intuos 12x18", 10,  45720, 31680, 1023, 63, INTUOS },
+       { "Wacom Intuos 4x5",   10,  12700, 10600, 1023, 31, INTUOS },
+       { "Wacom Intuos 6x8",   10,  20320, 16240, 1023, 31, INTUOS },
+       { "Wacom Intuos 9x12",  10,  30480, 24060, 1023, 31, INTUOS },
+       { "Wacom Intuos 12x12", 10,  30480, 31680, 1023, 31, INTUOS },
+       { "Wacom Intuos 12x18", 10,  45720, 31680, 1023, 31, INTUOS },
        { "Wacom PL400",         8,   5408,  4056,  255,  0, PL },
        { "Wacom PL500",         8,   6144,  4608,  255,  0, PL },
        { "Wacom PL600",         8,   6126,  4604,  255,  0, PL },
@@ -571,11 +596,11 @@ static struct wacom_features wacom_features[] = {
        { "Wacom DTF521",        8,   6282,  4762,  511,  0, PL },
        { "Wacom DTF720",        8,   6858,  5506,  511,  0, PL },
        { "Wacom Cintiq Partner",8,  20480, 15360,  511,  0, PTU },
-       { "Wacom Intuos2 4x5",   10, 12700, 10600, 1023, 63, INTUOS },
-       { "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 63, INTUOS },
-       { "Wacom Intuos2 9x12",  10, 30480, 24060, 1023, 63, INTUOS },
-       { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 63, INTUOS },
-       { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 63, INTUOS },
+       { "Wacom Intuos2 4x5",   10, 12700, 10600, 1023, 31, INTUOS },
+       { "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 31, INTUOS },
+       { "Wacom Intuos2 9x12",  10, 30480, 24060, 1023, 31, INTUOS },
+       { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 31, INTUOS },
+       { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 31, INTUOS },
        { "Wacom Intuos3 4x5",   10, 25400, 20320, 1023, 63, INTUOS3S },
        { "Wacom Intuos3 6x8",   10, 40640, 30480, 1023, 63, INTUOS3 },
        { "Wacom Intuos3 9x12",  10, 60960, 45720, 1023, 63, INTUOS3 },
@@ -584,7 +609,7 @@ static struct wacom_features wacom_features[] = {
        { "Wacom Intuos3 6x11",  10, 54204, 31750, 1023, 63, INTUOS3 },
        { "Wacom Intuos3 4x6",   10, 31496, 19685, 1023, 63, INTUOS3S },
        { "Wacom Cintiq 21UX",   10, 87200, 65600, 1023, 63, CINTIQ },
-       { "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 63, INTUOS },
+       { "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 31, INTUOS },
        { }
 };
 
index a1d9ce007970b12084c78c81e51cd0551541d3d1..a23022287248e12805f1250de2f0a41c3a079ae8 100644 (file)
@@ -12,6 +12,7 @@
 #define STYLUS_DEVICE_ID       0x02
 #define CURSOR_DEVICE_ID       0x06
 #define ERASER_DEVICE_ID       0x0A
+#define PAD_DEVICE_ID          0x0F
 
 enum {
        PENPARTNER = 0,
index 4907e8b8007087b37a3141135312acd43b2b4f90..9c7eb6144d02d3f8852a3c1abdb6a79a2f8a690a 100644 (file)
@@ -244,6 +244,20 @@ config USB_TRANCEVIBRATOR
          To compile this driver as a module, choose M here: the
          module will be called trancevibrator.
 
+config USB_IOWARRIOR
+       tristate "IO Warrior driver support"
+       depends on USB
+       help
+         Say Y here if you want to support the IO Warrior devices from Code
+         Mercenaries.  This includes support for the following devices:
+               IO Warrior 40
+               IO Warrior 24
+               IO Warrior 56
+               IO Warrior 24 Power Vampire
+
+         To compile this driver as a module, choose M here: the
+         module will be called iowarrior.
+
 config USB_TEST
        tristate "USB testing driver (DEVELOPMENT)"
        depends on USB && USB_DEVICEFS && EXPERIMENTAL
index dac2d5b715666492aa75d446d4b2acd16bcef067..b68e6b774f1add605b8bf5e89a930e07f1ca3ac2 100644 (file)
@@ -13,6 +13,7 @@ obj-$(CONFIG_USB_EMI26)               += emi26.o
 obj-$(CONFIG_USB_EMI62)                += emi62.o
 obj-$(CONFIG_USB_FTDI_ELAN)    += ftdi-elan.o
 obj-$(CONFIG_USB_IDMOUSE)      += idmouse.o
+obj-$(CONFIG_USB_IOWARRIOR)    += iowarrior.o
 obj-$(CONFIG_USB_LCD)          += usblcd.o
 obj-$(CONFIG_USB_LD)           += ldusb.o
 obj-$(CONFIG_USB_LED)          += usbled.o
index e573c8ba978545d164095dc634407daf4f859c2a..cf70c16f0e3f6981af7cd1b7946d9d91a712678e 100644 (file)
@@ -141,7 +141,7 @@ static int appledisplay_bl_update_status(struct backlight_device *bd)
        int retval;
 
        pdata->msgdata[0] = 0x10;
-       pdata->msgdata[1] = bd->props->brightness;
+       pdata->msgdata[1] = bd->props.brightness;
 
        retval = usb_control_msg(
                pdata->udev,
@@ -177,11 +177,9 @@ static int appledisplay_bl_get_brightness(struct backlight_device *bd)
                return pdata->msgdata[1];
 }
 
-static struct backlight_properties appledisplay_bl_data = {
-       .owner          = THIS_MODULE,
+static struct backlight_ops appledisplay_bl_data = {
        .get_brightness = appledisplay_bl_get_brightness,
        .update_status  = appledisplay_bl_update_status,
-       .max_brightness = 0xFF
 };
 
 static void appledisplay_work(struct work_struct *work)
@@ -190,11 +188,9 @@ static void appledisplay_work(struct work_struct *work)
                container_of(work, struct appledisplay, work.work);
        int retval;
 
-       up(&pdata->bd->sem);
        retval = appledisplay_bl_get_brightness(pdata->bd);
        if (retval >= 0)
-               pdata->bd->props->brightness = retval;
-       down(&pdata->bd->sem);
+               pdata->bd->props.brightness = retval;
 
        /* Poll again in about 125ms if there's still a button pressed */
        if (pdata->button_pressed)
@@ -288,10 +284,10 @@ static int appledisplay_probe(struct usb_interface *iface,
                goto error;
        }
 
+       pdata->bd->props.max_brightness = 0xff;
+
        /* Try to get brightness */
-       up(&pdata->bd->sem);
        brightness = appledisplay_bl_get_brightness(pdata->bd);
-       down(&pdata->bd->sem);
 
        if (brightness < 0) {
                retval = brightness;
@@ -300,9 +296,7 @@ static int appledisplay_probe(struct usb_interface *iface,
        }
 
        /* Set brightness in backlight device */
-       up(&pdata->bd->sem);
-       pdata->bd->props->brightness = brightness;
-       down(&pdata->bd->sem);
+       pdata->bd->props.brightness = brightness;
 
        /* save our data pointer in the interface device */
        usb_set_intfdata(iface, pdata);
index 0c1d66ddb8125fcc04461fd51be5cb4bac89778c..bc3327e3dd78a9e62897814203a3e4385a104ea0 100644 (file)
@@ -2905,17 +2905,31 @@ static int __init ftdi_elan_init(void)
 {
         int result;
         printk(KERN_INFO "driver %s built at %s on %s\n", ftdi_elan_driver.name,
-                 __TIME__, __DATE__);
+              __TIME__, __DATE__);
         init_MUTEX(&ftdi_module_lock);
         INIT_LIST_HEAD(&ftdi_static_list);
         status_queue = create_singlethread_workqueue("ftdi-status-control");
+       if (!status_queue)
+               goto err1;
         command_queue = create_singlethread_workqueue("ftdi-command-engine");
+       if (!command_queue)
+               goto err2;
         respond_queue = create_singlethread_workqueue("ftdi-respond-engine");
+       if (!respond_queue)
+               goto err3;
         result = usb_register(&ftdi_elan_driver);
         if (result)
                 printk(KERN_ERR "usb_register failed. Error number %d\n",
-                        result);
+                      result);
         return result;
+
+ err3:
+       destroy_workqueue(command_queue);
+ err2:
+       destroy_workqueue(status_queue);
+ err1:
+       printk(KERN_ERR "%s couldn't create workqueue\n", ftdi_elan_driver.name);
+       return -ENOMEM;
 }
 
 static void __exit ftdi_elan_exit(void)
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
new file mode 100644 (file)
index 0000000..d69665c
--- /dev/null
@@ -0,0 +1,925 @@
+/*
+ *  Native support for the I/O-Warrior USB devices
+ *
+ *  Copyright (c) 2003-2005  Code Mercenaries GmbH
+ *  written by Christian Lucht <lucht@codemercs.com>
+ *
+ *  based on
+
+ *  usb-skeleton.c by Greg Kroah-Hartman  <greg@kroah.com>
+ *  brlvger.c by Stephane Dalton  <sdalton@videotron.ca>
+ *           and St�hane Doyon   <s.doyon@videotron.ca>
+ *
+ *  Released under the GPLv2.
+ */
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/poll.h>
+#include <linux/version.h>
+#include <linux/usb/iowarrior.h>
+
+/* Version Information */
+#define DRIVER_VERSION "v0.4.0"
+#define DRIVER_AUTHOR "Christian Lucht <lucht@codemercs.com>"
+#define DRIVER_DESC "USB IO-Warrior driver (Linux 2.6.x)"
+
+#define USB_VENDOR_ID_CODEMERCS                1984
+/* low speed iowarrior */
+#define USB_DEVICE_ID_CODEMERCS_IOW40  0x1500
+#define USB_DEVICE_ID_CODEMERCS_IOW24  0x1501
+#define USB_DEVICE_ID_CODEMERCS_IOWPV1 0x1511
+#define USB_DEVICE_ID_CODEMERCS_IOWPV2 0x1512
+/* full speed iowarrior */
+#define USB_DEVICE_ID_CODEMERCS_IOW56  0x1503
+
+/* Get a minor range for your devices from the usb maintainer */
+#ifdef CONFIG_USB_DYNAMIC_MINORS
+#define IOWARRIOR_MINOR_BASE   0
+#else
+#define IOWARRIOR_MINOR_BASE   208     // SKELETON_MINOR_BASE 192 + 16, not offical yet
+#endif
+
+/* interrupt input queue size */
+#define MAX_INTERRUPT_BUFFER 16
+/*
+   maximum number of urbs that are submitted for writes at the same time,
+   this applies to the IOWarrior56 only!
+   IOWarrior24 and IOWarrior40 use synchronous usb_control_msg calls.
+*/
+#define MAX_WRITES_IN_FLIGHT 4
+
+/* Use our own dbg macro */
+#undef dbg
+#define dbg( format, arg... ) do { if( debug ) printk( KERN_DEBUG __FILE__ ": " format "\n" , ## arg ); } while ( 0 )
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+/* Module parameters */
+static int debug = 0;
+module_param(debug, bool, 0644);
+MODULE_PARM_DESC(debug, "debug=1 enables debugging messages");
+
+static struct usb_driver iowarrior_driver;
+
+/*--------------*/
+/*     data     */
+/*--------------*/
+
+/* Structure to hold all of our device specific stuff */
+struct iowarrior {
+       struct mutex mutex;                     /* locks this structure */
+       struct usb_device *udev;                /* save off the usb device pointer */
+       struct usb_interface *interface;        /* the interface for this device */
+       unsigned char minor;                    /* the starting minor number for this device */
+       struct usb_endpoint_descriptor *int_out_endpoint;       /* endpoint for reading (needed for IOW56 only) */
+       struct usb_endpoint_descriptor *int_in_endpoint;        /* endpoint for reading */
+       struct urb *int_in_urb;         /* the urb for reading data */
+       unsigned char *int_in_buffer;   /* buffer for data to be read */
+       unsigned char serial_number;    /* to detect lost packages */
+       unsigned char *read_queue;      /* size is MAX_INTERRUPT_BUFFER * packet size */
+       wait_queue_head_t read_wait;
+       wait_queue_head_t write_wait;   /* wait-queue for writing to the device */
+       atomic_t write_busy;            /* number of write-urbs submitted */
+       atomic_t read_idx;
+       atomic_t intr_idx;
+       spinlock_t intr_idx_lock;       /* protects intr_idx */
+       atomic_t overflow_flag;         /* signals an index 'rollover' */
+       int present;                    /* this is 1 as long as the device is connected */
+       int opened;                     /* this is 1 if the device is currently open */
+       char chip_serial[9];            /* the serial number string of the chip connected */
+       int report_size;                /* number of bytes in a report */
+       u16 product_id;
+};
+
+/*--------------*/
+/*    globals   */
+/*--------------*/
+/* prevent races between open() and disconnect() */
+static DECLARE_MUTEX(disconnect_sem);
+
+/*
+ *  USB spec identifies 5 second timeouts.
+ */
+#define GET_TIMEOUT 5
+#define USB_REQ_GET_REPORT  0x01
+//#if 0
+static int usb_get_report(struct usb_device *dev,
+                         struct usb_host_interface *inter, unsigned char type,
+                         unsigned char id, void *buf, int size)
+{
+       return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+                              USB_REQ_GET_REPORT,
+                              USB_DIR_IN | USB_TYPE_CLASS |
+                              USB_RECIP_INTERFACE, (type << 8) + id,
+                              inter->desc.bInterfaceNumber, buf, size,
+                              GET_TIMEOUT);
+}
+//#endif
+
+#define USB_REQ_SET_REPORT 0x09
+
+static int usb_set_report(struct usb_interface *intf, unsigned char type,
+                         unsigned char id, void *buf, int size)
+{
+       return usb_control_msg(interface_to_usbdev(intf),
+                              usb_sndctrlpipe(interface_to_usbdev(intf), 0),
+                              USB_REQ_SET_REPORT,
+                              USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+                              (type << 8) + id,
+                              intf->cur_altsetting->desc.bInterfaceNumber, buf,
+                              size, 1);
+}
+
+/*---------------------*/
+/* driver registration */
+/*---------------------*/
+/* table of devices that work with this driver */
+static struct usb_device_id iowarrior_ids[] = {
+       {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40)},
+       {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24)},
+       {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOWPV1)},
+       {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOWPV2)},
+       {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW56)},
+       {}                      /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, iowarrior_ids);
+
+/*
+ * USB callback handler for reading data
+ */
+static void iowarrior_callback(struct urb *urb)
+{
+       struct iowarrior *dev = (struct iowarrior *)urb->context;
+       int intr_idx;
+       int read_idx;
+       int aux_idx;
+       int offset;
+       int status;
+
+       switch (urb->status) {
+       case 0:
+               /* success */
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               return;
+       default:
+               goto exit;
+       }
+
+       spin_lock(&dev->intr_idx_lock);
+       intr_idx = atomic_read(&dev->intr_idx);
+       /* aux_idx become previous intr_idx */
+       aux_idx = (intr_idx == 0) ? (MAX_INTERRUPT_BUFFER - 1) : (intr_idx - 1);
+       read_idx = atomic_read(&dev->read_idx);
+
+       /* queue is not empty and it's interface 0 */
+       if ((intr_idx != read_idx)
+           && (dev->interface->cur_altsetting->desc.bInterfaceNumber == 0)) {
+               /* + 1 for serial number */
+               offset = aux_idx * (dev->report_size + 1);
+               if (!memcmp
+                   (dev->read_queue + offset, urb->transfer_buffer,
+                    dev->report_size)) {
+                       /* equal values on interface 0 will be ignored */
+                       spin_unlock(&dev->intr_idx_lock);
+                       goto exit;
+               }
+       }
+
+       /* aux_idx become next intr_idx */
+       aux_idx = (intr_idx == (MAX_INTERRUPT_BUFFER - 1)) ? 0 : (intr_idx + 1);
+       if (read_idx == aux_idx) {
+               /* queue full, dropping oldest input */
+               read_idx = (++read_idx == MAX_INTERRUPT_BUFFER) ? 0 : read_idx;
+               atomic_set(&dev->read_idx, read_idx);
+               atomic_set(&dev->overflow_flag, 1);
+       }
+
+       /* +1 for serial number */
+       offset = intr_idx * (dev->report_size + 1);
+       memcpy(dev->read_queue + offset, urb->transfer_buffer,
+              dev->report_size);
+       *(dev->read_queue + offset + (dev->report_size)) = dev->serial_number++;
+
+       atomic_set(&dev->intr_idx, aux_idx);
+       spin_unlock(&dev->intr_idx_lock);
+       /* tell the blocking read about the new data */
+       wake_up_interruptible(&dev->read_wait);
+
+exit:
+       status = usb_submit_urb(urb, GFP_ATOMIC);
+       if (status)
+               dev_err(&dev->interface->dev, "%s - usb_submit_urb failed with result %d",
+                       __FUNCTION__, status);
+
+}
+
+/*
+ * USB Callback handler for write-ops
+ */
+static void iowarrior_write_callback(struct urb *urb)
+{
+       struct iowarrior *dev;
+       dev = (struct iowarrior *)urb->context;
+       /* sync/async unlink faults aren't errors */
+       if (urb->status &&
+           !(urb->status == -ENOENT ||
+             urb->status == -ECONNRESET || urb->status == -ESHUTDOWN)) {
+               dbg("%s - nonzero write bulk status received: %d",
+                   __func__, urb->status);
+       }
+       /* free up our allocated buffer */
+       usb_buffer_free(urb->dev, urb->transfer_buffer_length,
+                       urb->transfer_buffer, urb->transfer_dma);
+       /* tell a waiting writer the interrupt-out-pipe is available again */
+       atomic_dec(&dev->write_busy);
+       wake_up_interruptible(&dev->write_wait);
+}
+
+/**
+ *     iowarrior_delete
+ */
+static inline void iowarrior_delete(struct iowarrior *dev)
+{
+       dbg("%s - minor %d", __func__, dev->minor);
+       kfree(dev->int_in_buffer);
+       usb_free_urb(dev->int_in_urb);
+       kfree(dev->read_queue);
+       kfree(dev);
+}
+
+/*---------------------*/
+/* fops implementation */
+/*---------------------*/
+
+static int read_index(struct iowarrior *dev)
+{
+       int intr_idx, read_idx;
+
+       read_idx = atomic_read(&dev->read_idx);
+       intr_idx = atomic_read(&dev->intr_idx);
+
+       return (read_idx == intr_idx ? -1 : read_idx);
+}
+
+/**
+ *  iowarrior_read
+ */
+static ssize_t iowarrior_read(struct file *file, char __user *buffer,
+                             size_t count, loff_t *ppos)
+{
+       struct iowarrior *dev;
+       int read_idx;
+       int offset;
+
+       dev = (struct iowarrior *)file->private_data;
+
+       /* verify that the device wasn't unplugged */
+       if (dev == NULL || !dev->present)
+               return -ENODEV;
+
+       dbg("%s - minor %d, count = %zd", __func__, dev->minor, count);
+
+       /* read count must be packet size (+ time stamp) */
+       if ((count != dev->report_size)
+           && (count != (dev->report_size + 1)))
+               return -EINVAL;
+
+       /* repeat until no buffer overrun in callback handler occur */
+       do {
+               atomic_set(&dev->overflow_flag, 0);
+               if ((read_idx = read_index(dev)) == -1) {
+                       /* queue emty */
+                       if (file->f_flags & O_NONBLOCK)
+                               return -EAGAIN;
+                       else {
+                               //next line will return when there is either new data, or the device is unplugged
+                               int r = wait_event_interruptible(dev->read_wait,
+                                                                (!dev->present
+                                                                 || (read_idx =
+                                                                     read_index
+                                                                     (dev)) !=
+                                                                 -1));
+                               if (r) {
+                                       //we were interrupted by a signal
+                                       return -ERESTART;
+                               }
+                               if (!dev->present) {
+                                       //The device was unplugged
+                                       return -ENODEV;
+                               }
+                               if (read_idx == -1) {
+                                       // Can this happen ???
+                                       return 0;
+                               }
+                       }
+               }
+
+               offset = read_idx * (dev->report_size + 1);
+               if (copy_to_user(buffer, dev->read_queue + offset, count)) {
+                       return -EFAULT;
+               }
+       } while (atomic_read(&dev->overflow_flag));
+
+       read_idx = ++read_idx == MAX_INTERRUPT_BUFFER ? 0 : read_idx;
+       atomic_set(&dev->read_idx, read_idx);
+       return count;
+}
+
+/*
+ * iowarrior_write
+ */
+static ssize_t iowarrior_write(struct file *file,
+                              const char __user *user_buffer,
+                              size_t count, loff_t *ppos)
+{
+       struct iowarrior *dev;
+       int retval = 0;
+       char *buf = NULL;       /* for IOW24 and IOW56 we need a buffer */
+       struct urb *int_out_urb = NULL;
+
+       dev = (struct iowarrior *)file->private_data;
+
+       mutex_lock(&dev->mutex);
+       /* verify that the device wasn't unplugged */
+       if (dev == NULL || !dev->present) {
+               retval = -ENODEV;
+               goto exit;
+       }
+       dbg("%s - minor %d, count = %zd", __func__, dev->minor, count);
+       /* if count is 0 we're already done */
+       if (count == 0) {
+               retval = 0;
+               goto exit;
+       }
+       /* We only accept full reports */
+       if (count != dev->report_size) {
+               retval = -EINVAL;
+               goto exit;
+       }
+       switch (dev->product_id) {
+       case USB_DEVICE_ID_CODEMERCS_IOW24:
+       case USB_DEVICE_ID_CODEMERCS_IOWPV1:
+       case USB_DEVICE_ID_CODEMERCS_IOWPV2:
+       case USB_DEVICE_ID_CODEMERCS_IOW40:
+               /* IOW24 and IOW40 use a synchronous call */
+               buf = kmalloc(8, GFP_KERNEL);   /* 8 bytes are enough for both products */
+               if (!buf) {
+                       retval = -ENOMEM;
+                       goto exit;
+               }
+               if (copy_from_user(buf, user_buffer, count)) {
+                       retval = -EFAULT;
+                       kfree(buf);
+                       goto exit;
+               }
+               retval = usb_set_report(dev->interface, 2, 0, buf, count);
+               kfree(buf);
+               goto exit;
+               break;
+       case USB_DEVICE_ID_CODEMERCS_IOW56:
+               /* The IOW56 uses asynchronous IO and more urbs */
+               if (atomic_read(&dev->write_busy) == MAX_WRITES_IN_FLIGHT) {
+                       /* Wait until we are below the limit for submitted urbs */
+                       if (file->f_flags & O_NONBLOCK) {
+                               retval = -EAGAIN;
+                               goto exit;
+                       } else {
+                               retval = wait_event_interruptible(dev->write_wait,
+                                                                 (!dev->present || (atomic_read (&dev-> write_busy) < MAX_WRITES_IN_FLIGHT)));
+                               if (retval) {
+                                       /* we were interrupted by a signal */
+                                       retval = -ERESTART;
+                                       goto exit;
+                               }
+                               if (!dev->present) {
+                                       /* The device was unplugged */
+                                       retval = -ENODEV;
+                                       goto exit;
+                               }
+                               if (!dev->opened) {
+                                       /* We were closed while waiting for an URB */
+                                       retval = -ENODEV;
+                                       goto exit;
+                               }
+                       }
+               }
+               atomic_inc(&dev->write_busy);
+               int_out_urb = usb_alloc_urb(0, GFP_KERNEL);
+               if (!int_out_urb) {
+                       retval = -ENOMEM;
+                       dbg("%s Unable to allocate urb ", __func__);
+                       goto error;
+               }
+               buf = usb_buffer_alloc(dev->udev, dev->report_size,
+                                      GFP_KERNEL, &int_out_urb->transfer_dma);
+               if (!buf) {
+                       retval = -ENOMEM;
+                       dbg("%s Unable to allocate buffer ", __func__);
+                       goto error;
+               }
+               usb_fill_int_urb(int_out_urb, dev->udev,
+                                usb_sndintpipe(dev->udev,
+                                               dev->int_out_endpoint->bEndpointAddress),
+                                buf, dev->report_size,
+                                iowarrior_write_callback, dev,
+                                dev->int_out_endpoint->bInterval);
+               int_out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+               if (copy_from_user(buf, user_buffer, count)) {
+                       retval = -EFAULT;
+                       goto error;
+               }
+               retval = usb_submit_urb(int_out_urb, GFP_KERNEL);
+               if (retval) {
+                       dbg("%s submit error %d for urb nr.%d", __func__,
+                           retval, atomic_read(&dev->write_busy));
+                       goto error;
+               }
+               /* submit was ok */
+               retval = count;
+               usb_free_urb(int_out_urb);
+               goto exit;
+               break;
+       default:
+               /* what do we have here ? An unsupported Product-ID ? */
+               dev_err(&dev->interface->dev, "%s - not supported for product=0x%x",
+                       __FUNCTION__, dev->product_id);
+               retval = -EFAULT;
+               goto exit;
+               break;
+       }
+error:
+       usb_buffer_free(dev->udev, dev->report_size, buf,
+                       int_out_urb->transfer_dma);
+       usb_free_urb(int_out_urb);
+       atomic_dec(&dev->write_busy);
+       wake_up_interruptible(&dev->write_wait);
+exit:
+       mutex_unlock(&dev->mutex);
+       return retval;
+}
+
+/**
+ *     iowarrior_ioctl
+ */
+static int iowarrior_ioctl(struct inode *inode, struct file *file,
+                          unsigned int cmd, unsigned long arg)
+{
+       struct iowarrior *dev = NULL;
+       __u8 *buffer;
+       __u8 __user *user_buffer;
+       int retval;
+       int io_res;             /* checks for bytes read/written and copy_to/from_user results */
+
+       dev = (struct iowarrior *)file->private_data;
+       if (dev == NULL) {
+               return -ENODEV;
+       }
+
+       buffer = kzalloc(dev->report_size, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
+
+       /* lock this object */
+       mutex_lock(&dev->mutex);
+
+       /* verify that the device wasn't unplugged */
+       if (!dev->present) {
+               mutex_unlock(&dev->mutex);
+               return -ENODEV;
+       }
+
+       dbg("%s - minor %d, cmd 0x%.4x, arg %ld", __func__, dev->minor, cmd,
+           arg);
+
+       retval = 0;
+       io_res = 0;
+       switch (cmd) {
+       case IOW_WRITE:
+               if (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW24 ||
+                   dev->product_id == USB_DEVICE_ID_CODEMERCS_IOWPV1 ||
+                   dev->product_id == USB_DEVICE_ID_CODEMERCS_IOWPV2 ||
+                   dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW40) {
+                       user_buffer = (__u8 __user *)arg;
+                       io_res = copy_from_user(buffer, user_buffer,
+                                               dev->report_size);
+                       if (io_res) {
+                               retval = -EFAULT;
+                       } else {
+                               io_res = usb_set_report(dev->interface, 2, 0,
+                                                       buffer,
+                                                       dev->report_size);
+                               if (io_res < 0)
+                                       retval = io_res;
+                       }
+               } else {
+                       retval = -EINVAL;
+                       dev_err(&dev->interface->dev,
+                               "ioctl 'IOW_WRITE' is not supported for product=0x%x.",
+                               dev->product_id);
+               }
+               break;
+       case IOW_READ:
+               user_buffer = (__u8 __user *)arg;
+               io_res = usb_get_report(dev->udev,
+                                       dev->interface->cur_altsetting, 1, 0,
+                                       buffer, dev->report_size);
+               if (io_res < 0)
+                       retval = io_res;
+               else {
+                       io_res = copy_to_user(user_buffer, buffer, dev->report_size);
+                       if (io_res < 0)
+                               retval = -EFAULT;
+               }
+               break;
+       case IOW_GETINFO:
+               {
+                       /* Report available information for the device */
+                       struct iowarrior_info info;
+                       /* needed for power consumption */
+                       struct usb_config_descriptor *cfg_descriptor = &dev->udev->actconfig->desc;
+
+                       /* directly from the descriptor */
+                       info.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
+                       info.product = dev->product_id;
+                       info.revision = le16_to_cpu(dev->udev->descriptor.bcdDevice);
+
+                       /* 0==UNKNOWN, 1==LOW(usb1.1) ,2=FULL(usb1.1), 3=HIGH(usb2.0) */
+                       info.speed = le16_to_cpu(dev->udev->speed);
+                       info.if_num = dev->interface->cur_altsetting->desc.bInterfaceNumber;
+                       info.report_size = dev->report_size;
+
+                       /* serial number string has been read earlier 8 chars or empty string */
+                       memcpy(info.serial, dev->chip_serial,
+                              sizeof(dev->chip_serial));
+                       if (cfg_descriptor == NULL) {
+                               info.power = -1;        /* no information available */
+                       } else {
+                               /* the MaxPower is stored in units of 2mA to make it fit into a byte-value */
+                               info.power = cfg_descriptor->bMaxPower * 2;
+                       }
+                       io_res = copy_to_user((struct iowarrior_info __user *)arg, &info,
+                                        sizeof(struct iowarrior_info));
+                       if (io_res < 0)
+                               retval = -EFAULT;
+                       break;
+               }
+       default:
+               /* return that we did not understand this ioctl call */
+               retval = -ENOTTY;
+               break;
+       }
+
+       /* unlock the device */
+       mutex_unlock(&dev->mutex);
+       return retval;
+}
+
+/**
+ *     iowarrior_open
+ */
+static int iowarrior_open(struct inode *inode, struct file *file)
+{
+       struct iowarrior *dev = NULL;
+       struct usb_interface *interface;
+       int subminor;
+       int retval = 0;
+
+       dbg("%s", __func__);
+
+       subminor = iminor(inode);
+
+       /* prevent disconnects */
+       down(&disconnect_sem);
+
+       interface = usb_find_interface(&iowarrior_driver, subminor);
+       if (!interface) {
+               err("%s - error, can't find device for minor %d", __FUNCTION__,
+                   subminor);
+               retval = -ENODEV;
+               goto out;
+       }
+
+       dev = usb_get_intfdata(interface);
+       if (!dev) {
+               retval = -ENODEV;
+               goto out;
+       }
+
+       /* Only one process can open each device, no sharing. */
+       if (dev->opened) {
+               retval = -EBUSY;
+               goto out;
+       }
+
+       /* setup interrupt handler for receiving values */
+       if ((retval = usb_submit_urb(dev->int_in_urb, GFP_KERNEL)) < 0) {
+               dev_err(&interface->dev, "Error %d while submitting URB\n", retval);
+               retval = -EFAULT;
+               goto out;
+       }
+       /* increment our usage count for the driver */
+       ++dev->opened;
+       /* save our object in the file's private structure */
+       file->private_data = dev;
+       retval = 0;
+
+out:
+       up(&disconnect_sem);
+       return retval;
+}
+
+/**
+ *     iowarrior_release
+ */
+static int iowarrior_release(struct inode *inode, struct file *file)
+{
+       struct iowarrior *dev;
+       int retval = 0;
+
+       dev = (struct iowarrior *)file->private_data;
+       if (dev == NULL) {
+               return -ENODEV;
+       }
+
+       dbg("%s - minor %d", __func__, dev->minor);
+
+       /* lock our device */
+       mutex_lock(&dev->mutex);
+
+       if (dev->opened <= 0) {
+               retval = -ENODEV;       /* close called more than once */
+               mutex_unlock(&dev->mutex);
+       } else {
+               dev->opened = 0;        /* we're closeing now */
+               retval = 0;
+               if (dev->present) {
+                       /*
+                          The device is still connected so we only shutdown
+                          pending read-/write-ops.
+                        */
+                       usb_kill_urb(dev->int_in_urb);
+                       wake_up_interruptible(&dev->read_wait);
+                       wake_up_interruptible(&dev->write_wait);
+                       mutex_unlock(&dev->mutex);
+               } else {
+                       /* The device was unplugged, cleanup resources */
+                       mutex_unlock(&dev->mutex);
+                       iowarrior_delete(dev);
+               }
+       }
+       return retval;
+}
+
+static unsigned iowarrior_poll(struct file *file, poll_table * wait)
+{
+       struct iowarrior *dev = file->private_data;
+       unsigned int mask = 0;
+
+       if (!dev->present)
+               return POLLERR | POLLHUP;
+
+       poll_wait(file, &dev->read_wait, wait);
+       poll_wait(file, &dev->write_wait, wait);
+
+       if (!dev->present)
+               return POLLERR | POLLHUP;
+
+       if (read_index(dev) != -1)
+               mask |= POLLIN | POLLRDNORM;
+
+       if (atomic_read(&dev->write_busy) < MAX_WRITES_IN_FLIGHT)
+               mask |= POLLOUT | POLLWRNORM;
+       return mask;
+}
+
+/*
+ * File operations needed when we register this driver.
+ * This assumes that this driver NEEDS file operations,
+ * of course, which means that the driver is expected
+ * to have a node in the /dev directory. If the USB
+ * device were for a network interface then the driver
+ * would use "struct net_driver" instead, and a serial
+ * device would use "struct tty_driver".
+ */
+static struct file_operations iowarrior_fops = {
+       .owner = THIS_MODULE,
+       .write = iowarrior_write,
+       .read = iowarrior_read,
+       .ioctl = iowarrior_ioctl,
+       .open = iowarrior_open,
+       .release = iowarrior_release,
+       .poll = iowarrior_poll,
+};
+
+/*
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with devfs and the driver core
+ */
+static struct usb_class_driver iowarrior_class = {
+       .name = "iowarrior%d",
+       .fops = &iowarrior_fops,
+       .minor_base = IOWARRIOR_MINOR_BASE,
+};
+
+/*---------------------------------*/
+/*  probe and disconnect functions */
+/*---------------------------------*/
+/**
+ *     iowarrior_probe
+ *
+ *     Called by the usb core when a new device is connected that it thinks
+ *     this driver might be interested in.
+ */
+static int iowarrior_probe(struct usb_interface *interface,
+                          const struct usb_device_id *id)
+{
+       struct usb_device *udev = interface_to_usbdev(interface);
+       struct iowarrior *dev = NULL;
+       struct usb_host_interface *iface_desc;
+       struct usb_endpoint_descriptor *endpoint;
+       int i;
+       int retval = -ENOMEM;
+       int idele = 0;
+
+       /* allocate memory for our device state and intialize it */
+       dev = kzalloc(sizeof(struct iowarrior), GFP_KERNEL);
+       if (dev == NULL) {
+               dev_err(&interface->dev, "Out of memory");
+               return retval;
+       }
+
+       mutex_init(&dev->mutex);
+
+       atomic_set(&dev->intr_idx, 0);
+       atomic_set(&dev->read_idx, 0);
+       spin_lock_init(&dev->intr_idx_lock);
+       atomic_set(&dev->overflow_flag, 0);
+       init_waitqueue_head(&dev->read_wait);
+       atomic_set(&dev->write_busy, 0);
+       init_waitqueue_head(&dev->write_wait);
+
+       dev->udev = udev;
+       dev->interface = interface;
+
+       iface_desc = interface->cur_altsetting;
+       dev->product_id = le16_to_cpu(udev->descriptor.idProduct);
+
+       /* set up the endpoint information */
+       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+               endpoint = &iface_desc->endpoint[i].desc;
+
+               if (usb_endpoint_is_int_in(endpoint))
+                       dev->int_in_endpoint = endpoint;
+               if (usb_endpoint_is_int_out(endpoint))
+                       /* this one will match for the IOWarrior56 only */
+                       dev->int_out_endpoint = endpoint;
+       }
+       /* we have to check the report_size often, so remember it in the endianess suitable for our machine */
+       dev->report_size = le16_to_cpu(dev->int_in_endpoint->wMaxPacketSize);
+       if ((dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) &&
+           (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56))
+               /* IOWarrior56 has wMaxPacketSize different from report size */
+               dev->report_size = 7;
+
+       /* create the urb and buffer for reading */
+       dev->int_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!dev->int_in_urb) {
+               dev_err(&interface->dev, "Couldn't allocate interrupt_in_urb\n");
+               goto error;
+       }
+       dev->int_in_buffer = kmalloc(dev->report_size, GFP_KERNEL);
+       if (!dev->int_in_buffer) {
+               dev_err(&interface->dev, "Couldn't allocate int_in_buffer\n");
+               goto error;
+       }
+       usb_fill_int_urb(dev->int_in_urb, dev->udev,
+                        usb_rcvintpipe(dev->udev,
+                                       dev->int_in_endpoint->bEndpointAddress),
+                        dev->int_in_buffer, dev->report_size,
+                        iowarrior_callback, dev,
+                        dev->int_in_endpoint->bInterval);
+       /* create an internal buffer for interrupt data from the device */
+       dev->read_queue =
+           kmalloc(((dev->report_size + 1) * MAX_INTERRUPT_BUFFER),
+                   GFP_KERNEL);
+       if (!dev->read_queue) {
+               dev_err(&interface->dev, "Couldn't allocate read_queue\n");
+               goto error;
+       }
+       /* Get the serial-number of the chip */
+       memset(dev->chip_serial, 0x00, sizeof(dev->chip_serial));
+       usb_string(udev, udev->descriptor.iSerialNumber, dev->chip_serial,
+                  sizeof(dev->chip_serial));
+       if (strlen(dev->chip_serial) != 8)
+               memset(dev->chip_serial, 0x00, sizeof(dev->chip_serial));
+
+       /* Set the idle timeout to 0, if this is interface 0 */
+       if (dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) {
+               idele = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                                       0x0A,
+                                       USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0,
+                                       0, NULL, 0, USB_CTRL_SET_TIMEOUT);
+               dbg("idele = %d", idele);
+       }
+       /* allow device read and ioctl */
+       dev->present = 1;
+
+       /* we can register the device now, as it is ready */
+       usb_set_intfdata(interface, dev);
+
+       retval = usb_register_dev(interface, &iowarrior_class);
+       if (retval) {
+               /* something prevented us from registering this driver */
+               dev_err(&interface->dev, "Not able to get a minor for this device.\n");
+               usb_set_intfdata(interface, NULL);
+               goto error;
+       }
+
+       dev->minor = interface->minor;
+
+       /* let the user know what node this device is now attached to */
+       dev_info(&interface->dev, "IOWarrior product=0x%x, serial=%s interface=%d "
+                "now attached to iowarrior%d\n", dev->product_id, dev->chip_serial,
+                iface_desc->desc.bInterfaceNumber, dev->minor - IOWARRIOR_MINOR_BASE);
+       return retval;
+
+error:
+       iowarrior_delete(dev);
+       return retval;
+}
+
+/**
+ *     iowarrior_disconnect
+ *
+ *     Called by the usb core when the device is removed from the system.
+ */
+static void iowarrior_disconnect(struct usb_interface *interface)
+{
+       struct iowarrior *dev;
+       int minor;
+
+       /* prevent races with open() */
+       down(&disconnect_sem);
+
+       dev = usb_get_intfdata(interface);
+       usb_set_intfdata(interface, NULL);
+
+       mutex_lock(&dev->mutex);
+
+       minor = dev->minor;
+
+       /* give back our minor */
+       usb_deregister_dev(interface, &iowarrior_class);
+
+       /* prevent device read, write and ioctl */
+       dev->present = 0;
+
+       mutex_unlock(&dev->mutex);
+
+       if (dev->opened) {
+               /* There is a process that holds a filedescriptor to the device ,
+                  so we only shutdown read-/write-ops going on.
+                  Deleting the device is postponed until close() was called.
+                */
+               usb_kill_urb(dev->int_in_urb);
+               wake_up_interruptible(&dev->read_wait);
+               wake_up_interruptible(&dev->write_wait);
+       } else {
+               /* no process is using the device, cleanup now */
+               iowarrior_delete(dev);
+       }
+       up(&disconnect_sem);
+
+       dev_info(&interface->dev, "I/O-Warror #%d now disconnected\n",
+                minor - IOWARRIOR_MINOR_BASE);
+}
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver iowarrior_driver = {
+       .name = "iowarrior",
+       .probe = iowarrior_probe,
+       .disconnect = iowarrior_disconnect,
+       .id_table = iowarrior_ids,
+};
+
+static int __init iowarrior_init(void)
+{
+       return usb_register(&iowarrior_driver);
+}
+
+static void __exit iowarrior_exit(void)
+{
+       usb_deregister(&iowarrior_driver);
+}
+
+module_init(iowarrior_init);
+module_exit(iowarrior_exit);
index c01dfe603672987cfe6f5038fbdb59993fe2776b..b2bedd974ac3bcd9018087d3f0c6ae80106fac77 100644 (file)
@@ -1165,7 +1165,7 @@ err_dev:
        return rc;
 }
 
-void __exit mon_bin_exit(void)
+void mon_bin_exit(void)
 {
        cdev_del(&mon_bin_cdev);
        unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR);
index d38a1279d9d9b071c0a9ddf0b078f094bf80a627..494ee3b9a22634afc9d7b724655a2e4450e848d8 100644 (file)
@@ -520,7 +520,7 @@ int __init mon_text_init(void)
        return 0;
 }
 
-void __exit mon_text_exit(void)
+void mon_text_exit(void)
 {
        debugfs_remove(mon_dir);
 }
index 4f949ce8a7f3b1c9617684e0e8919944827b526c..efdfd8993d9e2fc5b217ce498fbe48eed5d0d428 100644 (file)
@@ -57,9 +57,9 @@ void mon_text_del(struct mon_bus *mbus);
 // void mon_bin_add(struct mon_bus *);
 
 int __init mon_text_init(void);
-void __exit mon_text_exit(void);
+void mon_text_exit(void);
 int __init mon_bin_init(void);
-void __exit mon_bin_exit(void);
+void mon_bin_exit(void);
 
 /*
  * DMA interface.
index 0f3d7dbb537f43dca627e3544606562c5ff07e16..3de564b2314799b98a805d017f19ca2542db53e6 100644 (file)
@@ -186,6 +186,15 @@ config USB_NET_CDCETHER
          IEEE 802 "local assignment" bit is set in the address, a "usbX"
          name is used instead.
 
+config USB_NET_DM9601
+       tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices"
+       depends on USB_USBNET
+       select CRC32
+       select USB_USBNET_MII
+       help
+         This option adds support for Davicom DM9601 based USB 1.1
+         10/100 Ethernet adapters.
+
 config USB_NET_GL620A
        tristate "GeneSys GL620USB-A based cables"
        depends on USB_USBNET
index 7b51964de171416cc614c99c80b97f3494cdf841..595a539f83840ef7b7b05d4e825bc3f91d9c2eec 100644 (file)
@@ -8,6 +8,7 @@ obj-$(CONFIG_USB_PEGASUS)       += pegasus.o
 obj-$(CONFIG_USB_RTL8150)      += rtl8150.o
 obj-$(CONFIG_USB_NET_AX8817X)  += asix.o
 obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o
+obj-$(CONFIG_USB_NET_DM9601)   += dm9601.o
 obj-$(CONFIG_USB_NET_GL620A)   += gl620a.o
 obj-$(CONFIG_USB_NET_NET1080)  += net1080.o
 obj-$(CONFIG_USB_NET_PLUSB)    += plusb.o
index 7ef2e4b5e39bf986d559854458df5d6ea5bd5257..5808ea0824594adad543d4ac90fa13488c7903fb 100644 (file)
@@ -1395,9 +1395,9 @@ static const struct usb_device_id products [] = {
        USB_DEVICE (0x07b8, 0x420a),
        .driver_info =  (unsigned long) &hawking_uf200_info,
 }, {
-        // Billionton Systems, USB2AR
-        USB_DEVICE (0x08dd, 0x90ff),
-        .driver_info =  (unsigned long) &ax8817x_info,
+       // Billionton Systems, USB2AR
+       USB_DEVICE (0x08dd, 0x90ff),
+       .driver_info =  (unsigned long) &ax8817x_info,
 }, {
        // ATEN UC210T
        USB_DEVICE (0x0557, 0x2009),
@@ -1422,10 +1422,14 @@ static const struct usb_device_id       products [] = {
        // goodway corp usb gwusb2e
        USB_DEVICE (0x1631, 0x6200),
        .driver_info = (unsigned long) &ax8817x_info,
+}, {
+       // JVC MP-PRX1 Port Replicator
+       USB_DEVICE (0x04f1, 0x3008),
+       .driver_info = (unsigned long) &ax8817x_info,
 }, {
        // ASIX AX88772 10/100
-        USB_DEVICE (0x0b95, 0x7720),
-        .driver_info = (unsigned long) &ax88772_info,
+       USB_DEVICE (0x0b95, 0x7720),
+       .driver_info = (unsigned long) &ax88772_info,
 }, {
        // ASIX AX88178 10/100/1000
        USB_DEVICE (0x0b95, 0x1780),
diff --git a/drivers/usb/net/dm9601.c b/drivers/usb/net/dm9601.c
new file mode 100644 (file)
index 0000000..c0bc52b
--- /dev/null
@@ -0,0 +1,610 @@
+/*
+ * Davicom DM9601 USB 1.1 10/100Mbps ethernet devices
+ *
+ * Peter Korsgaard <jacmet@sunsite.dk>
+ *
+ * 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.
+ */
+
+//#define DEBUG
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/crc32.h>
+
+#include "usbnet.h"
+
+/* datasheet:
+ http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9601-DS-P01-930914.pdf
+*/
+
+/* control requests */
+#define DM_READ_REGS   0x00
+#define DM_WRITE_REGS  0x01
+#define DM_READ_MEMS   0x02
+#define DM_WRITE_REG   0x03
+#define DM_WRITE_MEMS  0x05
+#define DM_WRITE_MEM   0x07
+
+/* registers */
+#define DM_NET_CTRL    0x00
+#define DM_RX_CTRL     0x05
+#define DM_SHARED_CTRL 0x0b
+#define DM_SHARED_ADDR 0x0c
+#define DM_SHARED_DATA 0x0d    /* low + high */
+#define DM_PHY_ADDR    0x10    /* 6 bytes */
+#define DM_MCAST_ADDR  0x16    /* 8 bytes */
+#define DM_GPR_CTRL    0x1e
+#define DM_GPR_DATA    0x1f
+
+#define DM_MAX_MCAST   64
+#define DM_MCAST_SIZE  8
+#define DM_EEPROM_LEN  256
+#define DM_TX_OVERHEAD 2       /* 2 byte header */
+#define DM_RX_OVERHEAD 7       /* 3 byte header + 4 byte crc tail */
+#define DM_TIMEOUT     1000
+
+
+static int dm_read(struct usbnet *dev, u8 reg, u16 length, void *data)
+{
+       devdbg(dev, "dm_read() reg=0x%02x length=%d", reg, length);
+       return usb_control_msg(dev->udev,
+                              usb_rcvctrlpipe(dev->udev, 0),
+                              DM_READ_REGS,
+                              USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                              0, reg, data, length, USB_CTRL_SET_TIMEOUT);
+}
+
+static int dm_read_reg(struct usbnet *dev, u8 reg, u8 *value)
+{
+       return dm_read(dev, reg, 1, value);
+}
+
+static int dm_write(struct usbnet *dev, u8 reg, u16 length, void *data)
+{
+       devdbg(dev, "dm_write() reg=0x%02x, length=%d", reg, length);
+       return usb_control_msg(dev->udev,
+                              usb_sndctrlpipe(dev->udev, 0),
+                              DM_WRITE_REGS,
+                              USB_DIR_OUT | USB_TYPE_VENDOR |USB_RECIP_DEVICE,
+                              0, reg, data, length, USB_CTRL_SET_TIMEOUT);
+}
+
+static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value)
+{
+       devdbg(dev, "dm_write_reg() reg=0x%02x, value=0x%02x", reg, value);
+       return usb_control_msg(dev->udev,
+                              usb_sndctrlpipe(dev->udev, 0),
+                              DM_WRITE_REG,
+                              USB_DIR_OUT | USB_TYPE_VENDOR |USB_RECIP_DEVICE,
+                              value, reg, 0, 0, USB_CTRL_SET_TIMEOUT);
+}
+
+static void dm_write_async_callback(struct urb *urb)
+{
+       struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
+
+       if (urb->status < 0)
+               printk(KERN_DEBUG "dm_write_async_callback() failed with %d",
+                      urb->status);
+
+       kfree(req);
+       usb_free_urb(urb);
+}
+
+static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data)
+{
+       struct usb_ctrlrequest *req;
+       struct urb *urb;
+       int status;
+
+       devdbg(dev, "dm_write_async() reg=0x%02x length=%d", reg, length);
+
+       urb = usb_alloc_urb(0, GFP_ATOMIC);
+       if (!urb) {
+               deverr(dev, "Error allocating URB in dm_write_async!");
+               return;
+       }
+
+       req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
+       if (!req) {
+               deverr(dev, "Failed to allocate memory for control request");
+               usb_free_urb(urb);
+               return;
+       }
+
+       req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
+       req->bRequest = DM_WRITE_REGS;
+       req->wValue = 0;
+       req->wIndex = cpu_to_le16(reg);
+       req->wLength = cpu_to_le16(length);
+
+       usb_fill_control_urb(urb, dev->udev,
+                            usb_sndctrlpipe(dev->udev, 0),
+                            (void *)req, data, length,
+                            dm_write_async_callback, req);
+
+       status = usb_submit_urb(urb, GFP_ATOMIC);
+       if (status < 0) {
+               deverr(dev, "Error submitting the control message: status=%d",
+                      status);
+               kfree(req);
+               usb_free_urb(urb);
+       }
+}
+
+static void dm_write_reg_async(struct usbnet *dev, u8 reg, u8 value)
+{
+       struct usb_ctrlrequest *req;
+       struct urb *urb;
+       int status;
+
+       devdbg(dev, "dm_write_reg_async() reg=0x%02x value=0x%02x",
+              reg, value);
+
+       urb = usb_alloc_urb(0, GFP_ATOMIC);
+       if (!urb) {
+               deverr(dev, "Error allocating URB in dm_write_async!");
+               return;
+       }
+
+       req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
+       if (!req) {
+               deverr(dev, "Failed to allocate memory for control request");
+               usb_free_urb(urb);
+               return;
+       }
+
+       req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
+       req->bRequest = DM_WRITE_REG;
+       req->wValue = cpu_to_le16(value);
+       req->wIndex = cpu_to_le16(reg);
+       req->wLength = 0;
+
+       usb_fill_control_urb(urb, dev->udev,
+                            usb_sndctrlpipe(dev->udev, 0),
+                            (void *)req, 0, 0, dm_write_async_callback, req);
+
+       status = usb_submit_urb(urb, GFP_ATOMIC);
+       if (status < 0) {
+               deverr(dev, "Error submitting the control message: status=%d",
+                      status);
+               kfree(req);
+               usb_free_urb(urb);
+       }
+}
+
+static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, u16 *value)
+{
+       int ret, i;
+
+       mutex_lock(&dev->phy_mutex);
+
+       dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg);
+       dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0xc : 0x4);
+
+       for (i = 0; i < DM_TIMEOUT; i++) {
+               u8 tmp;
+
+               udelay(1);
+               ret = dm_read_reg(dev, DM_SHARED_CTRL, &tmp);
+               if (ret < 0)
+                       goto out;
+
+               /* ready */
+               if ((tmp & 1) == 0)
+                       break;
+       }
+
+       if (i == DM_TIMEOUT) {
+               deverr(dev, "%s read timed out!", phy ? "phy" : "eeprom");
+               ret = -EIO;
+               goto out;
+       }
+
+       dm_write_reg(dev, DM_SHARED_CTRL, 0x0);
+       ret = dm_read(dev, DM_SHARED_DATA, 2, value);
+
+       devdbg(dev, "read shared %d 0x%02x returned 0x%04x, %d",
+              phy, reg, *value, ret);
+
+ out:
+       mutex_unlock(&dev->phy_mutex);
+       return ret;
+}
+
+static int dm_write_shared_word(struct usbnet *dev, int phy, u8 reg, u16 value)
+{
+       int ret, i;
+
+       mutex_lock(&dev->phy_mutex);
+
+       ret = dm_write(dev, DM_SHARED_DATA, 2, &value);
+       if (ret < 0)
+               goto out;
+
+       dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg);
+       dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0x1c : 0x14);
+
+       for (i = 0; i < DM_TIMEOUT; i++) {
+               u8 tmp;
+
+               udelay(1);
+               ret = dm_read_reg(dev, DM_SHARED_CTRL, &tmp);
+               if (ret < 0)
+                       goto out;
+
+               /* ready */
+               if ((tmp & 1) == 0)
+                       break;
+       }
+
+       if (i == DM_TIMEOUT) {
+               deverr(dev, "%s write timed out!", phy ? "phy" : "eeprom");
+               ret = -EIO;
+               goto out;
+       }
+
+       dm_write_reg(dev, DM_SHARED_CTRL, 0x0);
+
+out:
+       mutex_unlock(&dev->phy_mutex);
+       return ret;
+}
+
+static int dm_read_eeprom_word(struct usbnet *dev, u8 offset, void *value)
+{
+       return dm_read_shared_word(dev, 0, offset, value);
+}
+
+
+
+static int dm9601_get_eeprom_len(struct net_device *dev)
+{
+       return DM_EEPROM_LEN;
+}
+
+static int dm9601_get_eeprom(struct net_device *net,
+                            struct ethtool_eeprom *eeprom, u8 * data)
+{
+       struct usbnet *dev = netdev_priv(net);
+       u16 *ebuf = (u16 *) data;
+       int i;
+
+       /* access is 16bit */
+       if ((eeprom->offset % 2) || (eeprom->len % 2))
+               return -EINVAL;
+
+       for (i = 0; i < eeprom->len / 2; i++) {
+               if (dm_read_eeprom_word(dev, eeprom->offset / 2 + i,
+                                       &ebuf[i]) < 0)
+                       return -EINVAL;
+       }
+       return 0;
+}
+
+static int dm9601_mdio_read(struct net_device *netdev, int phy_id, int loc)
+{
+       struct usbnet *dev = netdev_priv(netdev);
+
+       u16 res;
+
+       if (phy_id) {
+               devdbg(dev, "Only internal phy supported");
+               return 0;
+       }
+
+       dm_read_shared_word(dev, 1, loc, &res);
+
+       devdbg(dev,
+              "dm9601_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x",
+              phy_id, loc, le16_to_cpu(res));
+
+       return le16_to_cpu(res);
+}
+
+static void dm9601_mdio_write(struct net_device *netdev, int phy_id, int loc,
+                             int val)
+{
+       struct usbnet *dev = netdev_priv(netdev);
+       u16 res = cpu_to_le16(val);
+
+       if (phy_id) {
+               devdbg(dev, "Only internal phy supported");
+               return;
+       }
+
+       devdbg(dev,"dm9601_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x",
+              phy_id, loc, val);
+
+       dm_write_shared_word(dev, 1, loc, res);
+}
+
+static void dm9601_get_drvinfo(struct net_device *net,
+                              struct ethtool_drvinfo *info)
+{
+       /* Inherit standard device info */
+       usbnet_get_drvinfo(net, info);
+       info->eedump_len = DM_EEPROM_LEN;
+}
+
+static u32 dm9601_get_link(struct net_device *net)
+{
+       struct usbnet *dev = netdev_priv(net);
+
+       return mii_link_ok(&dev->mii);
+}
+
+static int dm9601_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
+{
+       struct usbnet *dev = netdev_priv(net);
+
+       return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
+}
+
+static struct ethtool_ops dm9601_ethtool_ops = {
+       .get_drvinfo    = dm9601_get_drvinfo,
+       .get_link       = dm9601_get_link,
+       .get_msglevel   = usbnet_get_msglevel,
+       .set_msglevel   = usbnet_set_msglevel,
+       .get_eeprom_len = dm9601_get_eeprom_len,
+       .get_eeprom     = dm9601_get_eeprom,
+       .get_settings   = usbnet_get_settings,
+       .set_settings   = usbnet_set_settings,
+       .nway_reset     = usbnet_nway_reset,
+};
+
+static void dm9601_set_multicast(struct net_device *net)
+{
+       struct usbnet *dev = netdev_priv(net);
+       /* We use the 20 byte dev->data for our 8 byte filter buffer
+        * to avoid allocating memory that is tricky to free later */
+       u8 *hashes = (u8 *) & dev->data;
+       u8 rx_ctl = 0x01;
+
+       memset(hashes, 0x00, DM_MCAST_SIZE);
+       hashes[DM_MCAST_SIZE - 1] |= 0x80;      /* broadcast address */
+
+       if (net->flags & IFF_PROMISC) {
+               rx_ctl |= 0x02;
+       } else if (net->flags & IFF_ALLMULTI || net->mc_count > DM_MAX_MCAST) {
+               rx_ctl |= 0x04;
+       } else if (net->mc_count) {
+               struct dev_mc_list *mc_list = net->mc_list;
+               int i;
+
+               for (i = 0; i < net->mc_count; i++) {
+                       u32 crc = ether_crc(ETH_ALEN, mc_list->dmi_addr) >> 26;
+                       hashes[crc >> 3] |= 1 << (crc & 0x7);
+               }
+       }
+
+       dm_write_async(dev, DM_MCAST_ADDR, DM_MCAST_SIZE, hashes);
+       dm_write_reg_async(dev, DM_RX_CTRL, rx_ctl);
+}
+
+static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+       int ret;
+
+       ret = usbnet_get_endpoints(dev, intf);
+       if (ret)
+               goto out;
+
+       dev->net->do_ioctl = dm9601_ioctl;
+       dev->net->set_multicast_list = dm9601_set_multicast;
+       dev->net->ethtool_ops = &dm9601_ethtool_ops;
+       dev->net->hard_header_len += DM_TX_OVERHEAD;
+       dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
+       dev->rx_urb_size = dev->net->mtu + DM_RX_OVERHEAD;
+
+       dev->mii.dev = dev->net;
+       dev->mii.mdio_read = dm9601_mdio_read;
+       dev->mii.mdio_write = dm9601_mdio_write;
+       dev->mii.phy_id_mask = 0x1f;
+       dev->mii.reg_num_mask = 0x1f;
+
+       /* reset */
+       ret = dm_write_reg(dev, DM_NET_CTRL, 1);
+       udelay(20);
+
+       /* read MAC */
+       ret = dm_read(dev, DM_PHY_ADDR, ETH_ALEN, dev->net->dev_addr);
+       if (ret < 0) {
+               printk(KERN_ERR "Error reading MAC address\n");
+               ret = -ENODEV;
+               goto out;
+       }
+
+
+       /* power up phy */
+       dm_write_reg(dev, DM_GPR_CTRL, 1);
+       dm_write_reg(dev, DM_GPR_DATA, 0);
+
+       /* receive broadcast packets */
+       dm9601_set_multicast(dev->net);
+
+       dm9601_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+       dm9601_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+                         ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
+       mii_nway_restart(&dev->mii);
+
+out:
+       return ret;
+}
+
+static int dm9601_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+       u8 status;
+       int len;
+
+       /* format:
+          b0: rx status
+          b1: packet length (incl crc) low
+          b2: packet length (incl crc) high
+          b3..n-4: packet data
+          bn-3..bn: ethernet crc
+        */
+
+       if (unlikely(skb->len < DM_RX_OVERHEAD)) {
+               dev_err(&dev->udev->dev, "unexpected tiny rx frame\n");
+               return 0;
+       }
+
+       status = skb->data[0];
+       len = (skb->data[1] | (skb->data[2] << 8)) - 4;
+
+       if (unlikely(status & 0xbf)) {
+               if (status & 0x01) dev->stats.rx_fifo_errors++;
+               if (status & 0x02) dev->stats.rx_crc_errors++;
+               if (status & 0x04) dev->stats.rx_frame_errors++;
+               if (status & 0x20) dev->stats.rx_missed_errors++;
+               if (status & 0x90) dev->stats.rx_length_errors++;
+               return 0;
+       }
+
+       skb_pull(skb, 3);
+       skb_trim(skb, len);
+
+       return 1;
+}
+
+static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
+                                      gfp_t flags)
+{
+       int len;
+
+       /* format:
+          b0: packet length low
+          b1: packet length high
+          b3..n: packet data
+       */
+
+       if (skb_headroom(skb) < DM_TX_OVERHEAD) {
+               struct sk_buff *skb2;
+
+               skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, 0, flags);
+               dev_kfree_skb_any(skb);
+               skb = skb2;
+               if (!skb)
+                       return NULL;
+       }
+
+       __skb_push(skb, DM_TX_OVERHEAD);
+
+       len = skb->len;
+       /* usbnet adds padding if length is a multiple of packet size
+          if so, adjust length value in header */
+       if ((len % dev->maxpacket) == 0)
+               len++;
+
+       skb->data[0] = len;
+       skb->data[1] = len >> 8;
+
+       return skb;
+}
+
+static void dm9601_status(struct usbnet *dev, struct urb *urb)
+{
+       int link;
+       u8 *buf;
+
+       /* format:
+          b0: net status
+          b1: tx status 1
+          b2: tx status 2
+          b3: rx status
+          b4: rx overflow
+          b5: rx count
+          b6: tx count
+          b7: gpr
+       */
+
+       if (urb->actual_length < 8)
+               return;
+
+       buf = urb->transfer_buffer;
+
+       link = !!(buf[0] & 0x40);
+       if (netif_carrier_ok(dev->net) != link) {
+               if (link) {
+                       netif_carrier_on(dev->net);
+                       usbnet_defer_kevent (dev, EVENT_LINK_RESET);
+               }
+               else
+                       netif_carrier_off(dev->net);
+               devdbg(dev, "Link Status is: %d", link);
+       }
+}
+
+static int dm9601_link_reset(struct usbnet *dev)
+{
+       struct ethtool_cmd ecmd;
+
+       mii_check_media(&dev->mii, 1, 1);
+       mii_ethtool_gset(&dev->mii, &ecmd);
+
+       devdbg(dev, "link_reset() speed: %d duplex: %d",
+              ecmd.speed, ecmd.duplex);
+
+       return 0;
+}
+
+static const struct driver_info dm9601_info = {
+       .description    = "Davicom DM9601 USB Ethernet",
+       .flags          = FLAG_ETHER,
+       .bind           = dm9601_bind,
+       .rx_fixup       = dm9601_rx_fixup,
+       .tx_fixup       = dm9601_tx_fixup,
+       .status         = dm9601_status,
+       .link_reset     = dm9601_link_reset,
+       .reset          = dm9601_link_reset,
+};
+
+static const struct usb_device_id products[] = {
+       {
+        USB_DEVICE(0x07aa, 0x9601),    /* Corega FEther USB-TXC */
+        .driver_info = (unsigned long)&dm9601_info,
+        },
+       {
+        USB_DEVICE(0x0a46, 0x9601),    /* Davicom USB-100 */
+        .driver_info = (unsigned long)&dm9601_info,
+        },
+       {},                     // END
+};
+
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver dm9601_driver = {
+       .name = "dm9601",
+       .id_table = products,
+       .probe = usbnet_probe,
+       .disconnect = usbnet_disconnect,
+       .suspend = usbnet_suspend,
+       .resume = usbnet_resume,
+};
+
+static int __init dm9601_init(void)
+{
+       return usb_register(&dm9601_driver);
+}
+
+static void __exit dm9601_exit(void)
+{
+       usb_deregister(&dm9601_driver);
+}
+
+module_init(dm9601_init);
+module_exit(dm9601_exit);
+
+MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
+MODULE_DESCRIPTION("Davicom DM9601 USB 1.1 ethernet devices");
+MODULE_LICENSE("GPL");
index 18816bf96a4d6152da19a062c5f21d3247eaca60..310a8b5f5906a6f54b226b5e2dddab2453d3f48f 100644 (file)
@@ -44,8 +44,43 @@ struct airprime_private {
        int outstanding_urbs;
        int throttled;
        struct urb *read_urbp[NUM_READ_URBS];
+
+       /* Settings for the port */
+       int rts_state;  /* Handshaking pins (outputs) */
+       int dtr_state;
+       int cts_state;  /* Handshaking pins (inputs) */
+       int dsr_state;
+       int dcd_state;
+       int ri_state;
 };
 
+static int airprime_send_setup(struct usb_serial_port *port)
+{
+       struct usb_serial *serial = port->serial;
+       struct airprime_private *priv;
+
+       dbg("%s", __FUNCTION__);
+
+       if (port->number != 0)
+               return 0;
+
+       priv = usb_get_serial_port_data(port);
+
+       if (port->tty) {
+               int val = 0;
+               if (priv->dtr_state)
+                       val |= 0x01;
+               if (priv->rts_state)
+                       val |= 0x02;
+
+               return usb_control_msg(serial->dev,
+                               usb_rcvctrlpipe(serial->dev, 0),
+                               0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
+       }
+
+       return 0;
+}
+
 static void airprime_read_bulk_callback(struct urb *urb)
 {
        struct usb_serial_port *port = urb->context;
@@ -118,6 +153,10 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
                usb_set_serial_port_data(port, priv);
        }
 
+       /* Set some sane defaults */
+       priv->rts_state = 1;
+       priv->dtr_state = 1;
+
        for (i = 0; i < NUM_READ_URBS; ++i) {
                buffer = kmalloc(buffer_size, GFP_KERNEL);
                if (!buffer) {
@@ -151,6 +190,9 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
                /* remember this urb so we can kill it when the port is closed */
                priv->read_urbp[i] = urb;
        }
+
+       airprime_send_setup(port);
+
        goto out;
 
  errout:
@@ -176,6 +218,11 @@ static void airprime_close(struct usb_serial_port *port, struct file * filp)
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
+       priv->rts_state = 0;
+       priv->dtr_state = 0;
+
+       airprime_send_setup(port);
+
        for (i = 0; i < NUM_READ_URBS; ++i) {
                usb_kill_urb (priv->read_urbp[i]);
                kfree (priv->read_urbp[i]->transfer_buffer);
index db623e754899859bc88e043a23ee593bdd3a14cf..d7d0ba986a80be0a79c38dcd6c4867321524e3ed 100644 (file)
@@ -63,6 +63,8 @@ static struct usb_device_id id_table [] = {
        { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
        { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */
        { USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */
+       { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */
+       { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */
        { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */
        { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */
        { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */
index 4695952b6470bd2fd8adc29366dafad35464cb51..1633a0fd48e82f54f838b2bcd702a7f96e578a60 100644 (file)
@@ -315,6 +315,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_232RL_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
@@ -420,6 +421,14 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_ELV_ALC8500_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_PYRAMID_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1000PC_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_IBS_US485_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_IBS_PICPRO_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_IBS_PCMCIA_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_IBS_PK1_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_IBS_RS232MON_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_IBS_APP70_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) },
        /*
         * These will probably use user-space drivers.  Uncomment them if
         * you need them or use the user-specified vendor/product module
@@ -459,6 +468,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FALCOM_VID, FALCOM_TWIST_PID) },
        { USB_DEVICE(FALCOM_VID, FALCOM_SAMBA_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_SUUNTO_SPORTS_PID) },
+       { USB_DEVICE(TTI_VID, TTI_QL355P_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) },
        { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) },
        { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) },
@@ -513,6 +523,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) },
        { USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) },
+       { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
        { },                                    /* Optional parameter entry */
        { }                                     /* Terminating entry */
 };
@@ -532,6 +543,7 @@ static const char *ftdi_chip_name[] = {
        [FT8U232AM] = "FT8U232AM",
        [FT232BM] = "FT232BM",
        [FT2232C] = "FT2232C",
+       [FT232RL] = "FT232RL",
 };
 
 
@@ -587,6 +599,8 @@ struct ftdi_private {
 static int  ftdi_sio_probe     (struct usb_serial *serial, const struct usb_device_id *id);
 static int  ftdi_sio_attach            (struct usb_serial *serial);
 static void ftdi_shutdown              (struct usb_serial *serial);
+static int  ftdi_sio_port_probe        (struct usb_serial_port *port);
+static int  ftdi_sio_port_remove       (struct usb_serial_port *port);
 static int  ftdi_open                  (struct usb_serial_port *port, struct file *filp);
 static void ftdi_close                 (struct usb_serial_port *port, struct file *filp);
 static int  ftdi_write                 (struct usb_serial_port *port, const unsigned char *buf, int count);
@@ -621,6 +635,8 @@ static struct usb_serial_driver ftdi_sio_device = {
        .num_bulk_out =         1,
        .num_ports =            1,
        .probe =                ftdi_sio_probe,
+       .port_probe =           ftdi_sio_port_probe,
+       .port_remove =          ftdi_sio_port_remove,
        .open =                 ftdi_open,
        .close =                ftdi_close,
        .throttle =             ftdi_throttle,
@@ -1023,11 +1039,10 @@ static ssize_t show_latency_timer(struct device *dev, struct device_attribute *a
 {
        struct usb_serial_port *port = to_usb_serial_port(dev);
        struct ftdi_private *priv = usb_get_serial_port_data(port);
-       struct usb_device *udev;
+       struct usb_device *udev = port->serial->dev;
        unsigned short latency = 0;
        int rv = 0;
 
-       udev = to_usb_device(dev);
 
        dbg("%s",__FUNCTION__);
 
@@ -1051,13 +1066,11 @@ static ssize_t store_latency_timer(struct device *dev, struct device_attribute *
 {
        struct usb_serial_port *port = to_usb_serial_port(dev);
        struct ftdi_private *priv = usb_get_serial_port_data(port);
-       struct usb_device *udev;
+       struct usb_device *udev = port->serial->dev;
        char buf[1];
        int v = simple_strtoul(valbuf, NULL, 10);
        int rv = 0;
 
-       udev = to_usb_device(dev);
-
        dbg("%s: setting latency timer = %i", __FUNCTION__, v);
 
        rv = usb_control_msg(udev,
@@ -1082,13 +1095,11 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att
 {
        struct usb_serial_port *port = to_usb_serial_port(dev);
        struct ftdi_private *priv = usb_get_serial_port_data(port);
-       struct usb_device *udev;
+       struct usb_device *udev = port->serial->dev;
        char buf[1];
        int v = simple_strtoul(valbuf, NULL, 10);
        int rv = 0;
 
-       udev = to_usb_device(dev);
-
        dbg("%s: setting event char = %i", __FUNCTION__, v);
 
        rv = usb_control_msg(udev,
@@ -1109,46 +1120,38 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att
 static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer);
 static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char);
 
-static int create_sysfs_attrs(struct usb_serial *serial)
+static int create_sysfs_attrs(struct usb_serial_port *port)
 {
-       struct ftdi_private *priv;
-       struct usb_device *udev;
+       struct ftdi_private *priv = usb_get_serial_port_data(port);
        int retval = 0;
 
        dbg("%s",__FUNCTION__);
 
-       priv = usb_get_serial_port_data(serial->port[0]);
-       udev = serial->dev;
-
        /* XXX I've no idea if the original SIO supports the event_char
         * sysfs parameter, so I'm playing it safe.  */
        if (priv->chip_type != SIO) {
                dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]);
-               retval = device_create_file(&udev->dev, &dev_attr_event_char);
+               retval = device_create_file(&port->dev, &dev_attr_event_char);
                if ((!retval) &&
                    (priv->chip_type == FT232BM || priv->chip_type == FT2232C)) {
-                       retval = device_create_file(&udev->dev,
+                       retval = device_create_file(&port->dev,
                                                    &dev_attr_latency_timer);
                }
        }
        return retval;
 }
 
-static void remove_sysfs_attrs(struct usb_serial *serial)
+static void remove_sysfs_attrs(struct usb_serial_port *port)
 {
-       struct ftdi_private *priv;
-       struct usb_device *udev;
+       struct ftdi_private *priv = usb_get_serial_port_data(port);
 
        dbg("%s",__FUNCTION__);
 
-       priv = usb_get_serial_port_data(serial->port[0]);
-       udev = serial->dev;
-
        /* XXX see create_sysfs_attrs */
        if (priv->chip_type != SIO) {
-               device_remove_file(&udev->dev, &dev_attr_event_char);
+               device_remove_file(&port->dev, &dev_attr_event_char);
                if (priv->chip_type == FT232BM || priv->chip_type == FT2232C) {
-                       device_remove_file(&udev->dev, &dev_attr_latency_timer);
+                       device_remove_file(&port->dev, &dev_attr_latency_timer);
                }
        }
 
@@ -1168,13 +1171,9 @@ static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id
        return (0);
 }
 
-/* attach subroutine */
-static int ftdi_sio_attach (struct usb_serial *serial)
+static int ftdi_sio_port_probe(struct usb_serial_port *port)
 {
-       struct usb_serial_port *port = serial->port[0];
        struct ftdi_private *priv;
-       struct ftdi_sio_quirk *quirk;
-       int retval;
 
        dbg("%s",__FUNCTION__);
 
@@ -1214,19 +1213,21 @@ static int ftdi_sio_attach (struct usb_serial *serial)
        kfree(port->bulk_out_buffer);
        port->bulk_out_buffer = NULL;
 
-       usb_set_serial_port_data(serial->port[0], priv);
+       usb_set_serial_port_data(port, priv);
 
-       ftdi_determine_type (serial->port[0]);
-       retval = create_sysfs_attrs(serial);
-       if (retval)
-               dev_err(&serial->dev->dev, "Error creating sysfs files, "
-                       "continuing\n");
+       ftdi_determine_type (port);
+       create_sysfs_attrs(port);
+       return 0;
+}
 
+/* attach subroutine */
+static int ftdi_sio_attach (struct usb_serial *serial)
+{
        /* Check for device requiring special set up. */
-       quirk = (struct ftdi_sio_quirk *)usb_get_serial_data(serial);
-       if (quirk && quirk->setup) {
+       struct ftdi_sio_quirk *quirk = usb_get_serial_data(serial);
+
+       if (quirk && quirk->setup)
                quirk->setup(serial);
-       }
 
        return 0;
 } /* ftdi_sio_attach */
@@ -1270,17 +1271,18 @@ static void ftdi_HE_TIRA1_setup (struct usb_serial *serial)
  *      calls __serial_close for each open of the port
  *      shutdown is called then (ie ftdi_shutdown)
  */
-
-
 static void ftdi_shutdown (struct usb_serial *serial)
-{ /* ftdi_shutdown */
+{
+       dbg("%s", __FUNCTION__);
+}
 
-       struct usb_serial_port *port = serial->port[0];
+static int ftdi_sio_port_remove(struct usb_serial_port *port)
+{
        struct ftdi_private *priv = usb_get_serial_port_data(port);
 
        dbg("%s", __FUNCTION__);
 
-       remove_sysfs_attrs(serial);
+       remove_sysfs_attrs(port);
 
        /* all open ports are closed at this point
          *    (by usbserial.c:__serial_close, which calls ftdi_close)
@@ -1290,8 +1292,9 @@ static void ftdi_shutdown (struct usb_serial *serial)
                usb_set_serial_port_data(port, NULL);
                kfree(priv);
        }
-} /* ftdi_shutdown */
 
+       return 0;
+}
 
 static int  ftdi_open (struct usb_serial_port *port, struct file *filp)
 { /* ftdi_open */
index 7eff1c03ba80b37ac41b010625eb10c8951eaca3..513cfe1b768b1383cb7e82f69890d9a64e270589 100644 (file)
@@ -27,6 +27,7 @@
 #define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */
 #define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */
 #define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
+#define FTDI_232RL_PID  0xFBFA  /* Product ID for FT232RL */
 #define FTDI_RELAIS_PID        0xFA10  /* Relais device from Rudolf Gugler */
 #define FTDI_NF_RIC_VID        0x0DCD  /* Vendor Id */
 #define FTDI_NF_RIC_PID        0x0001  /* Product Id */
  */
 #define FTDI_SUUNTO_SPORTS_PID 0xF680  /* Suunto Sports instrument */
 
+/*
+ * TTi (Thurlby Thandar Instruments)
+ */
+#define TTI_VID                        0x103E  /* Vendor Id */
+#define TTI_QL355P_PID         0x03E8  /* TTi QL355P power supply */
+
 /*
  * Definitions for B&B Electronics products.
  */
 #define FTDI_TACTRIX_OPENPORT_13S_PID  0xCC49  /* OpenPort 1.3 Subaru */
 #define FTDI_TACTRIX_OPENPORT_13U_PID  0xCC4A  /* OpenPort 1.3 Universal */
 
+/*
+ * Telldus Technologies
+ */
+#define TELLDUS_VID                    0x1781  /* Vendor ID */
+#define TELLDUS_TELLSTICK_PID          0x0C30  /* RF control dongle 433 MHz using FT232RL */
+
+/*
+ * IBS elektronik product ids
+ * Submitted by Thomas Schleusener
+ */
+#define FTDI_IBS_US485_PID     0xff38  /* IBS US485 (USB<-->RS422/485 interface) */
+#define FTDI_IBS_PICPRO_PID    0xff39  /* IBS PIC-Programmer */
+#define FTDI_IBS_PCMCIA_PID    0xff3a  /* IBS Card reader for PCMCIA SRAM-cards */
+#define FTDI_IBS_PK1_PID       0xff3b  /* IBS PK1 - Particel counter */
+#define FTDI_IBS_RS232MON_PID  0xff3c  /* IBS RS232 - Monitor */
+#define FTDI_IBS_APP70_PID     0xff3d  /* APP 70 (dust monitoring system) */
+#define FTDI_IBS_PEDO_PID      0xff3e  /* IBS PEDO-Modem (RF modem 868.35 MHz) */
+#define FTDI_IBS_PROD_PID      0xff3f  /* future device */
+
 /* Commands */
 #define FTDI_SIO_RESET                 0 /* Reset the port */
 #define FTDI_SIO_MODEM_CTRL    1 /* Set the modem control register */
@@ -614,6 +640,7 @@ typedef enum {
        FT8U232AM = 2,
        FT232BM = 3,
        FT2232C = 4,
+       FT232RL = 5,
 } ftdi_chip_type_t;
 
 typedef enum {
index a408184334ea9d829f7ecd3be632202c56cf0184..d16e2e1764adff84daae6697d5f7481dc6e77382 100644 (file)
@@ -247,6 +247,8 @@ static struct usb_device_id ipaq_id_table [] = {
        { USB_DEVICE(0x04AD, 0x0301) }, /* USB Sync 0301 */
        { USB_DEVICE(0x04AD, 0x0302) }, /* USB Sync 0302 */
        { USB_DEVICE(0x04AD, 0x0303) }, /* USB Sync 0303 */
+       { USB_DEVICE(0x04AD, 0x0306) }, /* GPS Pocket PC USB Sync */
+       { USB_DEVICE(0x04B7, 0x0531) }, /* MyGuide 7000 XL USB Sync */
        { USB_DEVICE(0x04C5, 0x1058) }, /* FUJITSU USB Sync */
        { USB_DEVICE(0x04C5, 0x1079) }, /* FUJITSU USB Sync */
        { USB_DEVICE(0x04DA, 0x2500) }, /* Panasonic USB Sync */
index 9963a8b758401aed14435230348c8f9a07e41fab..db92a7fb1f7cbbe9782aef280d46799c7e8d7490 100644 (file)
@@ -67,50 +67,95 @@ static int  option_tiocmset(struct usb_serial_port *port, struct file *file,
 static int  option_send_setup(struct usb_serial_port *port);
 
 /* Vendor and product IDs */
-#define OPTION_VENDOR_ID                0x0AF0
-#define HUAWEI_VENDOR_ID                0x12D1
-#define NOVATELWIRELESS_VENDOR_ID       0x1410
-#define ANYDATA_VENDOR_ID               0x16d5
-
-#define OPTION_PRODUCT_OLD              0x5000
-#define OPTION_PRODUCT_FUSION           0x6000
-#define OPTION_PRODUCT_FUSION2          0x6300
-#define OPTION_PRODUCT_COBRA            0x6500
-#define OPTION_PRODUCT_COBRA2           0x6600
-#define OPTION_PRODUCT_GTMAX36          0x6701
-#define HUAWEI_PRODUCT_E600             0x1001
-#define HUAWEI_PRODUCT_E220             0x1003
-#define NOVATELWIRELESS_PRODUCT_U740    0x1400
-#define ANYDATA_PRODUCT_ID              0x6501
+#define OPTION_VENDOR_ID                       0x0AF0
+#define OPTION_PRODUCT_COLT                    0x5000
+#define OPTION_PRODUCT_RICOLA                  0x6000
+#define OPTION_PRODUCT_RICOLA_LIGHT            0x6100
+#define OPTION_PRODUCT_RICOLA_QUAD             0x6200
+#define OPTION_PRODUCT_RICOLA_QUAD_LIGHT       0x6300
+#define OPTION_PRODUCT_RICOLA_NDIS             0x6050
+#define OPTION_PRODUCT_RICOLA_NDIS_LIGHT       0x6150
+#define OPTION_PRODUCT_RICOLA_NDIS_QUAD                0x6250
+#define OPTION_PRODUCT_RICOLA_NDIS_QUAD_LIGHT  0x6350
+#define OPTION_PRODUCT_COBRA                   0x6500
+#define OPTION_PRODUCT_COBRA_BUS               0x6501
+#define OPTION_PRODUCT_VIPER                   0x6600
+#define OPTION_PRODUCT_VIPER_BUS               0x6601
+#define OPTION_PRODUCT_GT_MAX_READY            0x6701
+#define OPTION_PRODUCT_GT_MAX                  0x6711
+#define OPTION_PRODUCT_FUJI_MODEM_LIGHT                0x6721
+#define OPTION_PRODUCT_FUJI_MODEM_GT           0x6741
+#define OPTION_PRODUCT_FUJI_MODEM_EX           0x6761
+#define OPTION_PRODUCT_FUJI_NETWORK_LIGHT      0x6731
+#define OPTION_PRODUCT_FUJI_NETWORK_GT         0x6751
+#define OPTION_PRODUCT_FUJI_NETWORK_EX         0x6771
+#define OPTION_PRODUCT_KOI_MODEM               0x6800
+#define OPTION_PRODUCT_KOI_NETWORK             0x6811
+#define OPTION_PRODUCT_SCORPION_MODEM          0x6901
+#define OPTION_PRODUCT_SCORPION_NETWORK                0x6911
+#define OPTION_PRODUCT_ETNA_MODEM              0x7001
+#define OPTION_PRODUCT_ETNA_NETWORK            0x7011
+#define OPTION_PRODUCT_ETNA_MODEM_LITE         0x7021
+#define OPTION_PRODUCT_ETNA_MODEM_GT           0x7041
+#define OPTION_PRODUCT_ETNA_MODEM_EX           0x7061
+#define OPTION_PRODUCT_ETNA_NETWORK_LITE       0x7031
+#define OPTION_PRODUCT_ETNA_NETWORK_GT         0x7051
+#define OPTION_PRODUCT_ETNA_NETWORK_EX         0x7071
+#define OPTION_PRODUCT_ETNA_KOI_MODEM          0x7100
+#define OPTION_PRODUCT_ETNA_KOI_NETWORK                0x7111
+
+#define HUAWEI_VENDOR_ID                       0x12D1
+#define HUAWEI_PRODUCT_E600                    0x1001
+#define HUAWEI_PRODUCT_E220                    0x1003
+
+#define NOVATELWIRELESS_VENDOR_ID              0x1410
+#define NOVATELWIRELESS_PRODUCT_U740           0x1400
+
+#define ANYDATA_VENDOR_ID                      0x16d5
+#define ANYDATA_PRODUCT_ID                     0x6501
 
 static struct usb_device_id option_ids[] = {
-       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) },
-       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) },
-       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_LIGHT) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_QUAD) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_QUAD_LIGHT) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS_LIGHT) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS_QUAD) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS_QUAD_LIGHT) },
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
-       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) },
-       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTMAX36) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA_BUS) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_VIPER) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_VIPER_BUS) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GT_MAX_READY) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GT_MAX) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_LIGHT) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_GT) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_EX) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_NETWORK_LIGHT) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_NETWORK_GT) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_NETWORK_EX) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_KOI_MODEM) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_KOI_NETWORK) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_SCORPION_MODEM) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_SCORPION_NETWORK) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_LITE) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_GT) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_EX) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_LITE) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_GT) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_EX) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_MODEM) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_NETWORK) },
        { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
        { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) },
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
        { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },
        { } /* Terminating entry */
 };
-
-static struct usb_device_id option_ids1[] = {
-       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) },
-       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) },
-       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
-       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
-       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) },
-       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTMAX36) },
-       { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
-       { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) },
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
-       { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },
-       { } /* Terminating entry */
-};
-
 MODULE_DEVICE_TABLE(usb, option_ids);
 
 static struct usb_driver option_driver = {
@@ -132,7 +177,7 @@ static struct usb_serial_driver option_1port_device = {
        },
        .description       = "GSM modem (1-port)",
        .usb_driver        = &option_driver,
-       .id_table          = option_ids1,
+       .id_table          = option_ids,
        .num_interrupt_in  = NUM_DONT_CARE,
        .num_bulk_in       = NUM_DONT_CARE,
        .num_bulk_out      = NUM_DONT_CARE,
index 6bf22a28adb823db701965aef720e74dfc6c54eb..8511352251f33ea3f551438913b9a778bf0158db 100644 (file)
@@ -99,9 +99,12 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po
                        continue;
 
                *minor = i;
+               j = 0;
                dbg("%s - minor base = %d", __FUNCTION__, *minor);
-               for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i)
+               for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) {
                        serial_table[i] = serial;
+                       serial->port[j++]->number = i;
+               }
                spin_unlock(&table_lock);
                return serial;
        }
@@ -135,11 +138,6 @@ static void destroy_serial(struct kref *kref)
 
        dbg("%s - %s", __FUNCTION__, serial->type->description);
 
-       serial->type->shutdown(serial);
-
-       /* return the minor range that this device had */
-       return_serial(serial);
-
        for (i = 0; i < serial->num_ports; ++i)
                serial->port[i]->open_count = 0;
 
@@ -150,6 +148,12 @@ static void destroy_serial(struct kref *kref)
                        serial->port[i] = NULL;
                }
 
+       if (serial->type->shutdown)
+               serial->type->shutdown(serial);
+
+       /* return the minor range that this device had */
+       return_serial(serial);
+
        /* If this is a "fake" port, we have to clean it up here, as it will
         * not get cleaned up in port_release() as it was never registered with
         * the driver core */
@@ -826,7 +830,6 @@ int usb_serial_probe(struct usb_interface *interface,
                        num_ports = type->num_ports;
        }
 
-       serial->minor = minor;
        serial->num_ports = num_ports;
        serial->num_bulk_in = num_bulk_in;
        serial->num_bulk_out = num_bulk_out;
@@ -847,7 +850,6 @@ int usb_serial_probe(struct usb_interface *interface,
                port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
                if (!port)
                        goto probe_error;
-               port->number = i + serial->minor;
                port->serial = serial;
                spin_lock_init(&port->lock);
                mutex_init(&port->mutex);
@@ -980,6 +982,7 @@ int usb_serial_probe(struct usb_interface *interface,
                dev_err(&interface->dev, "No more free serial devices\n");
                goto probe_error;
        }
+       serial->minor = minor;
 
        /* register all of the individual ports with the driver core */
        for (i = 0; i < num_ports; ++i) {
@@ -1034,9 +1037,6 @@ probe_error:
                kfree(port->interrupt_out_buffer);
        }
 
-       /* return the minor range that this device had */
-       return_serial (serial);
-
        /* free up any memory that we allocated */
        for (i = 0; i < serial->num_port_pointers; ++i)
                kfree(serial->port[i]);
index 9644a8ea4aa71adfe794abf9cc75bdae12122b98..2dd31e3f5107abaaa61cd8c1851f249a451bd02e 100644 (file)
@@ -146,6 +146,13 @@ UNUSUAL_DEV(  0x0420, 0x0001, 0x0100, 0x0100,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_IGNORE_RESIDUE ),
 
+/* Reported by Andrew Nayenko <relan@bk.ru> */
+UNUSUAL_DEV(  0x0421, 0x0019, 0x0592, 0x0592,
+               "Nokia",
+               "Nokia 6288",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_MAX_SECTORS_64 ),
+
 /* Reported by Mario Rettig <mariorettig@web.de> */
 UNUSUAL_DEV(  0x0421, 0x042e, 0x0100, 0x0100,
                "Nokia",
@@ -1395,16 +1402,6 @@ UNUSUAL_DEV(  0x1652, 0x6600, 0x0201, 0x0201,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_IGNORE_RESIDUE ),
 
-/* Reported by Thomas Baechler <thomas@archlinux.org>
- * Fixes I/O errors with Teac HD-35PU devices
- */
-
-UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201,
-               "Super Top",
-               "USB 2.0  IDE DEVICE",
-               US_SC_DEVICE, US_PR_DEVICE, NULL,
-               US_FL_IGNORE_RESIDUE),
-
 /* patch submitted by Davide Perini <perini.davide@dpsoftware.org>
  * and Renato Perini <rperini@email.it>
  */
index 7e7ec29782f124b0fb34fcd672064e7cfe8ccf67..8e898e3d861ea477153ce8f782230ede58e1292f 100644 (file)
@@ -55,7 +55,7 @@
 #include <linux/slab.h>
 #include <linux/kthread.h>
 #include <linux/mutex.h>
-#include <linux/utsrelease.h>
+#include <linux/utsname.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -547,7 +547,7 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id)
                                idesc->bInterfaceSubClass,
                                idesc->bInterfaceProtocol,
                                msgs[msg],
-                               UTS_RELEASE);
+                               utsname()->release);
        }
 
        return 0;
index 8874cf2fd279e1046d1ef473f4e2263e099029e0..7f5a59836818c6f1e227dfff3fff655b15f0d64d 100644 (file)
@@ -4,20 +4,7 @@
 
 menu "Graphics support"
 
-config FIRMWARE_EDID
-       bool "Enable firmware EDID"
-       default y
-       ---help---
-         This enables access to the EDID transferred from the firmware.
-        On the i386, this is from the Video BIOS. Enable this if DDC/I2C
-        transfers do not work for your driver and if you are using
-        nvidiafb, i810fb or savagefb.
-
-        In general, choosing Y for this option is safe.  If you
-        experience extremely long delays while booting before you get
-        something on your display, try setting this to N.  Matrox cards in
-        combination with certain motherboards and monitors are known to
-        suffer from this problem.
+source "drivers/video/backlight/Kconfig"
 
 config FB
        tristate "Support for frame buffer devices"
@@ -53,9 +40,27 @@ config FB
          (e.g. an accelerated X server) and that are not frame buffer
          device-aware may cause unexpected results. If unsure, say N.
 
+config FIRMWARE_EDID
+       bool "Enable firmware EDID"
+       depends on FB
+       default n
+       ---help---
+         This enables access to the EDID transferred from the firmware.
+        On the i386, this is from the Video BIOS. Enable this if DDC/I2C
+        transfers do not work for your driver and if you are using
+        nvidiafb, i810fb or savagefb.
+
+        In general, choosing Y for this option is safe.  If you
+        experience extremely long delays while booting before you get
+        something on your display, try setting this to N.  Matrox cards in
+        combination with certain motherboards and monitors are known to
+        suffer from this problem.
+
 config FB_DDC
        tristate
-       depends on FB && I2C && I2C_ALGOBIT
+       depends on FB
+       select I2C_ALGOBIT
+       select I2C
        default n
 
 config FB_CFB_FILLRECT
@@ -134,6 +139,9 @@ config FB_TILEBLITTING
         This is particularly important to one driver, matroxfb.  If
         unsure, say N.
 
+comment "Frambuffer hardware drivers"
+       depends on FB
+
 config FB_CIRRUS
        tristate "Cirrus Logic support"
        depends on FB && (ZORRO || PCI)
@@ -669,8 +677,7 @@ config FB_S1D13XXX
 config FB_NVIDIA
        tristate "nVidia Framebuffer Support"
        depends on FB && PCI
-       select I2C_ALGOBIT if FB_NVIDIA_I2C
-       select I2C if FB_NVIDIA_I2C
+       select FB_BACKLIGHT if FB_NVIDIA_BACKLIGHT
        select FB_MODE_HELPERS
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
@@ -688,6 +695,7 @@ config FB_NVIDIA
 config FB_NVIDIA_I2C
        bool "Enable DDC Support"
        depends on FB_NVIDIA
+       select FB_DDC
        help
          This enables I2C support for nVidia Chipsets.  This is used
          only for getting EDID information from the attached display
@@ -699,8 +707,7 @@ config FB_NVIDIA_I2C
 
 config FB_NVIDIA_BACKLIGHT
        bool "Support for backlight control"
-       depends on FB_NVIDIA && PMAC_BACKLIGHT
-       select FB_BACKLIGHT
+       depends on FB_NVIDIA
        default y
        help
          Say Y here if you want to control the backlight of your display.
@@ -708,9 +715,7 @@ config FB_NVIDIA_BACKLIGHT
 config FB_RIVA
        tristate "nVidia Riva support"
        depends on FB && PCI
-       select I2C_ALGOBIT if FB_RIVA_I2C
-       select I2C if FB_RIVA_I2C
-       select FB_DDC if FB_RIVA_I2C
+       select FB_BACKLIGHT if FB_RIVA_BACKLIGHT
        select FB_MODE_HELPERS
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
@@ -727,6 +732,7 @@ config FB_RIVA
 config FB_RIVA_I2C
        bool "Enable DDC Support"
        depends on FB_RIVA
+       select FB_DDC
        help
          This enables I2C support for nVidia Chipsets.  This is used
          only for getting EDID information from the attached display
@@ -747,8 +753,7 @@ config FB_RIVA_DEBUG
 
 config FB_RIVA_BACKLIGHT
        bool "Support for backlight control"
-       depends on FB_RIVA && PMAC_BACKLIGHT
-       select FB_BACKLIGHT
+       depends on FB_RIVA
        default y
        help
          Say Y here if you want to control the backlight of your display.
@@ -798,8 +803,6 @@ config FB_I810_GTF
 config FB_I810_I2C
        bool "Enable DDC Support"
        depends on FB_I810 && FB_I810_GTF
-       select I2C
-       select I2C_ALGOBIT
        select FB_DDC
        help
 
@@ -808,8 +811,6 @@ config FB_INTEL
        depends on FB && EXPERIMENTAL && PCI && X86
        select AGP
        select AGP_INTEL
-       select I2C_ALGOBIT if FB_INTEL_I2C
-       select I2C if FB_INTEL_I2C
        select FB_MODE_HELPERS
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
@@ -842,6 +843,7 @@ config FB_INTEL_DEBUG
 config FB_INTEL_I2C
        bool "DDC/I2C for Intel framebuffer support"
        depends on FB_INTEL
+       select FB_DDC
        default y
        help
          Say Y here if you want DDC/I2C support for your on-board Intel graphics.
@@ -920,8 +922,8 @@ config FB_MATROX_G
 
 config FB_MATROX_I2C
        tristate "Matrox I2C support"
-       depends on FB_MATROX && I2C
-       select I2C_ALGOBIT
+       depends on FB_MATROX
+       select FB_DDC
        ---help---
          This drivers creates I2C buses which are needed for accessing the
          DDC (I2C) bus present on all Matroxes, an I2C bus which
@@ -989,9 +991,7 @@ config FB_MATROX_MULTIHEAD
 config FB_RADEON
        tristate "ATI Radeon display support"
        depends on FB && PCI
-       select I2C_ALGOBIT if FB_RADEON_I2C
-       select I2C if FB_RADEON_I2C
-       select FB_DDC if FB_RADEON_I2C
+       select FB_BACKLIGHT if FB_RADEON_BACKLIGHT
        select FB_MODE_HELPERS
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
@@ -1015,14 +1015,14 @@ config FB_RADEON
 config FB_RADEON_I2C
        bool "DDC/I2C for ATI Radeon support"
        depends on FB_RADEON
+       select FB_DDC
        default y
        help
          Say Y here if you want DDC/I2C support for your Radeon board. 
 
 config FB_RADEON_BACKLIGHT
        bool "Support for backlight control"
-       depends on FB_RADEON && PMAC_BACKLIGHT
-       select FB_BACKLIGHT
+       depends on FB_RADEON
        default y
        help
          Say Y here if you want to control the backlight of your display.
@@ -1042,6 +1042,7 @@ config FB_ATY128
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
+       select FB_BACKLIGHT if FB_ATY128_BACKLIGHT
        select FB_MACMODES if PPC_PMAC
        help
          This driver supports graphics boards with the ATI Rage128 chips.
@@ -1053,8 +1054,7 @@ config FB_ATY128
 
 config FB_ATY128_BACKLIGHT
        bool "Support for backlight control"
-       depends on FB_ATY128 && PMAC_BACKLIGHT
-       select FB_BACKLIGHT
+       depends on FB_ATY128
        default y
        help
          Say Y here if you want to control the backlight of your display.
@@ -1065,6 +1065,7 @@ config FB_ATY
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
+       select FB_BACKLIGHT if FB_ATY_BACKLIGHT
        select FB_MACMODES if PPC
        help
          This driver supports graphics boards with the ATI Mach64 chips.
@@ -1103,8 +1104,7 @@ config FB_ATY_GX
 
 config FB_ATY_BACKLIGHT
        bool "Support for backlight control"
-       depends on FB_ATY && PMAC_BACKLIGHT
-       select FB_BACKLIGHT
+       depends on FB_ATY
        default y
        help
          Say Y here if you want to control the backlight of your display.
@@ -1123,9 +1123,6 @@ config FB_S3
 config FB_SAVAGE
        tristate "S3 Savage support"
        depends on FB && PCI && EXPERIMENTAL
-       select I2C_ALGOBIT if FB_SAVAGE_I2C
-       select I2C if FB_SAVAGE_I2C
-       select FB_DDC if FB_SAVAGE_I2C
        select FB_MODE_HELPERS
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
@@ -1142,6 +1139,7 @@ config FB_SAVAGE
 config FB_SAVAGE_I2C
        bool "Enable DDC2 Support"
        depends on FB_SAVAGE
+       select FB_DDC
        help
          This enables I2C support for S3 Savage Chipsets.  This is used
          only for getting EDID information from the attached display
@@ -1573,6 +1571,24 @@ config FB_S3C2410_DEBUG
          Turn on debugging messages. Note that you can set/unset at run time
          through sysfs
 
+config FB_SM501
+       tristate "Silicon Motion SM501 framebuffer support"
+       depends on FB && MFD_SM501
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       ---help---
+         Frame buffer driver for the CRT and LCD controllers in the Silicon
+         Motion SM501.
+
+         This driver is also available as a module ( = code which can be
+         inserted and removed from the running kernel whenever you want). The
+         module will be called sm501fb. If you want to compile it as a module,
+         say M here and read <file:Documentation/modules.txt>.
+
+         If unsure, say N.
+
+
 config FB_PNX4008_DUM
        tristate "Display Update Module support on Philips PNX4008 board"
        depends on FB && ARCH_PNX4008
@@ -1600,8 +1616,7 @@ config FB_IBM_GXT4500
 
 config FB_PS3
        bool "PS3 GPU framebuffer driver"
-       depends on FB && PPC_PS3
-       select PS3_PS3AV
+       depends on FB && PS3_PS3AV
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
@@ -1639,6 +1654,7 @@ config FB_VIRTUAL
          the vfb_enable=1 option.
 
          If unsure, say N.
+
 if VT
        source "drivers/video/console/Kconfig"
 endif
@@ -1647,9 +1663,5 @@ if FB || SGI_NEWPORT_CONSOLE
        source "drivers/video/logo/Kconfig"
 endif
 
-if SYSFS
-       source "drivers/video/backlight/Kconfig"
-endif
-
 endmenu
 
index 6801edff36d930ee4adc5163afa947bb8ec5b498..760305c8a8416736cb61d005bccf5459c8728e4f 100644 (file)
@@ -12,7 +12,7 @@ fb-objs                           := $(fb-y)
 
 obj-$(CONFIG_VT)                 += console/
 obj-$(CONFIG_LOGO)               += logo/
-obj-$(CONFIG_SYSFS)              += backlight/
+obj-y                            += backlight/
 
 obj-$(CONFIG_FB_CFB_FILLRECT)  += cfbfillrect.o
 obj-$(CONFIG_FB_CFB_COPYAREA)  += cfbcopyarea.o
@@ -98,6 +98,7 @@ obj-$(CONFIG_FB_PNX4008_DUM)    += pnx4008/
 obj-$(CONFIG_FB_PNX4008_DUM_RGB)  += pnx4008/
 obj-$(CONFIG_FB_IBM_GXT4500)     += gxt4500.o
 obj-$(CONFIG_FB_PS3)             += ps3fb.o
+obj-$(CONFIG_FB_SM501)            += sm501fb.o
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_VESA)             += vesafb.o
index 2e976ffcde0fa53a3977da6e05ed1f61884f99c3..e86d7e0c98254eaa3af3370e52d789b437a765c8 100644 (file)
@@ -357,6 +357,12 @@ static int default_lcd_on __devinitdata = 1;
 static int mtrr = 1;
 #endif
 
+#ifdef CONFIG_PMAC_BACKLIGHT
+static int backlight __devinitdata = 1;
+#else
+static int backlight __devinitdata = 0;
+#endif
+
 /* PLL constants */
 struct aty128_constants {
        u32 ref_clk;
@@ -1652,6 +1658,9 @@ static int __devinit aty128fb_setup(char *options)
                } else if (!strncmp(this_opt, "crt:", 4)) {
                        default_crt_on = simple_strtoul(this_opt+4, NULL, 0);
                        continue;
+               } else if (!strncmp(this_opt, "backlight:", 10)) {
+                       backlight = simple_strtoul(this_opt+10, NULL, 0);
+                       continue;
                }
 #ifdef CONFIG_MTRR
                if(!strncmp(this_opt, "nomtrr", 6)) {
@@ -1695,9 +1704,6 @@ static int __devinit aty128fb_setup(char *options)
 #ifdef CONFIG_FB_ATY128_BACKLIGHT
 #define MAX_LEVEL 0xFF
 
-static struct backlight_properties aty128_bl_data;
-
-/* Call with fb_info->bl_mutex held */
 static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
                int level)
 {
@@ -1705,6 +1711,7 @@ static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
        int atylevel;
 
        /* Get and convert the value */
+       /* No locking of bl_curve since we read a single value */
        atylevel = MAX_LEVEL -
                (info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL);
 
@@ -1724,19 +1731,18 @@ static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
 /* That one prevents proper CRT output with LCD off */
 #undef BACKLIGHT_DAC_OFF
 
-/* Call with fb_info->bl_mutex held */
-static int __aty128_bl_update_status(struct backlight_device *bd)
+static int aty128_bl_update_status(struct backlight_device *bd)
 {
        struct aty128fb_par *par = class_get_devdata(&bd->class_dev);
        unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL);
        int level;
 
-       if (bd->props->power != FB_BLANK_UNBLANK ||
-           bd->props->fb_blank != FB_BLANK_UNBLANK ||
+       if (bd->props.power != FB_BLANK_UNBLANK ||
+           bd->props.fb_blank != FB_BLANK_UNBLANK ||
            !par->lcd_on)
                level = 0;
        else
-               level = bd->props->brightness;
+               level = bd->props.brightness;
 
        reg |= LVDS_BL_MOD_EN | LVDS_BLON;
        if (level > 0) {
@@ -1778,43 +1784,22 @@ static int __aty128_bl_update_status(struct backlight_device *bd)
        return 0;
 }
 
-static int aty128_bl_update_status(struct backlight_device *bd)
-{
-       struct aty128fb_par *par = class_get_devdata(&bd->class_dev);
-       struct fb_info *info = pci_get_drvdata(par->pdev);
-       int ret;
-
-       mutex_lock(&info->bl_mutex);
-       ret = __aty128_bl_update_status(bd);
-       mutex_unlock(&info->bl_mutex);
-
-       return ret;
-}
-
 static int aty128_bl_get_brightness(struct backlight_device *bd)
 {
-       return bd->props->brightness;
+       return bd->props.brightness;
 }
 
-static struct backlight_properties aty128_bl_data = {
-       .owner          = THIS_MODULE,
+static struct backlight_ops aty128_bl_data = {
        .get_brightness = aty128_bl_get_brightness,
        .update_status  = aty128_bl_update_status,
-       .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
 };
 
 static void aty128_bl_set_power(struct fb_info *info, int power)
 {
-       mutex_lock(&info->bl_mutex);
-
        if (info->bl_dev) {
-               down(&info->bl_dev->sem);
-               info->bl_dev->props->power = power;
-               __aty128_bl_update_status(info->bl_dev);
-               up(&info->bl_dev->sem);
+               info->bl_dev->props.power = power;
+               backlight_update_status(info->bl_dev);
        }
-
-       mutex_unlock(&info->bl_mutex);
 }
 
 static void aty128_bl_init(struct aty128fb_par *par)
@@ -1841,25 +1826,15 @@ static void aty128_bl_init(struct aty128fb_par *par)
                goto error;
        }
 
-       mutex_lock(&info->bl_mutex);
        info->bl_dev = bd;
        fb_bl_default_curve(info, 0,
                 63 * FB_BACKLIGHT_MAX / MAX_LEVEL,
                219 * FB_BACKLIGHT_MAX / MAX_LEVEL);
-       mutex_unlock(&info->bl_mutex);
 
-       down(&bd->sem);
-       bd->props->brightness = aty128_bl_data.max_brightness;
-       bd->props->power = FB_BLANK_UNBLANK;
-       bd->props->update_status(bd);
-       up(&bd->sem);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-       mutex_lock(&pmac_backlight_mutex);
-       if (!pmac_backlight)
-               pmac_backlight = bd;
-       mutex_unlock(&pmac_backlight_mutex);
-#endif
+       bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+       bd->props.brightness = bd->props.max_brightness;
+       bd->props.power = FB_BLANK_UNBLANK;
+       backlight_update_status(bd);
 
        printk("aty128: Backlight initialized (%s)\n", name);
 
@@ -1869,31 +1844,10 @@ error:
        return;
 }
 
-static void aty128_bl_exit(struct aty128fb_par *par)
+static void aty128_bl_exit(struct backlight_device *bd)
 {
-       struct fb_info *info = pci_get_drvdata(par->pdev);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-       mutex_lock(&pmac_backlight_mutex);
-#endif
-
-       mutex_lock(&info->bl_mutex);
-       if (info->bl_dev) {
-#ifdef CONFIG_PMAC_BACKLIGHT
-               if (pmac_backlight == info->bl_dev)
-                       pmac_backlight = NULL;
-#endif
-
-               backlight_device_unregister(info->bl_dev);
-               info->bl_dev = NULL;
-
-               printk("aty128: Backlight unloaded\n");
-       }
-       mutex_unlock(&info->bl_mutex);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-       mutex_unlock(&pmac_backlight_mutex);
-#endif
+       backlight_device_unregister(bd);
+       printk("aty128: Backlight unloaded\n");
 }
 #endif /* CONFIG_FB_ATY128_BACKLIGHT */
 
@@ -2040,7 +1994,8 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i
        par->lock_blank = 0;
 
 #ifdef CONFIG_FB_ATY128_BACKLIGHT
-       aty128_bl_init(par);
+       if (backlight)
+               aty128_bl_init(par);
 #endif
 
        if (register_framebuffer(info) < 0)
@@ -2180,11 +2135,12 @@ static void __devexit aty128_remove(struct pci_dev *pdev)
 
        par = info->par;
 
+       unregister_framebuffer(info);
+
 #ifdef CONFIG_FB_ATY128_BACKLIGHT
-       aty128_bl_exit(par);
+       aty128_bl_exit(info->bl_dev);
 #endif
 
-       unregister_framebuffer(info);
 #ifdef CONFIG_MTRR
        if (par->mtrr.vram_valid)
                mtrr_del(par->mtrr.vram, info->fix.smem_start,
@@ -2214,11 +2170,6 @@ static int aty128fb_blank(int blank, struct fb_info *fb)
        if (par->lock_blank || par->asleep)
                return 0;
 
-#ifdef CONFIG_FB_ATY128_BACKLIGHT
-       if (machine_is(powermac) && blank)
-               aty128_bl_set_power(fb, FB_BLANK_POWERDOWN);
-#endif
-
        if (blank & FB_BLANK_VSYNC_SUSPEND)
                state |= 2;
        if (blank & FB_BLANK_HSYNC_SUSPEND)
@@ -2233,11 +2184,6 @@ static int aty128fb_blank(int blank, struct fb_info *fb)
                aty128_set_lcd_enable(par, par->lcd_on && !blank);
        }
 
-#ifdef CONFIG_FB_ATY128_BACKLIGHT
-       if (machine_is(powermac) && !blank)
-               aty128_bl_set_power(fb, FB_BLANK_UNBLANK);
-#endif
-
        return 0;
 }
 
index f72faff33c0ce2048ffd8f0831da661958a16b52..dc62f8e282b4ac9bfe3361ebd632bf9a288ac4ae 100644 (file)
@@ -284,7 +284,8 @@ static inline void aty_st_8(int regindex, u8 val, const struct atyfb_par *par)
 #endif
 }
 
-#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD)
+#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \
+defined (CONFIG_FB_ATY_GENERIC_LCD) || defined (CONFIG_FB_ATY_BACKLIGHT)
 extern void aty_st_lcd(int index, u32 val, const struct atyfb_par *par);
 extern u32 aty_ld_lcd(int index, const struct atyfb_par *par);
 #endif
index 301612cef3544ca4f3bc2b367af620ba6f83b801..d7627fc4f11ee82d094a763e8225a2e26172c974 100644 (file)
 #define PRINTKI(fmt, args...)  printk(KERN_INFO "atyfb: " fmt, ## args)
 #define PRINTKE(fmt, args...)   printk(KERN_ERR "atyfb: " fmt, ## args)
 
-#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD)
+#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \
+defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_FB_ATY_BACKLIGHT)
 static const u32 lt_lcd_regs[] = {
        CONFIG_PANEL_LG,
        LCD_GEN_CNTL_LG,
@@ -308,6 +309,12 @@ static int xclk;
 static int comp_sync __devinitdata = -1;
 static char *mode;
 
+#ifdef CONFIG_PMAC_BACKLIGHT
+static int backlight __devinitdata = 1;
+#else
+static int backlight __devinitdata = 0;
+#endif
+
 #ifdef CONFIG_PPC
 static int default_vmode __devinitdata = VMODE_CHOOSE;
 static int default_cmode __devinitdata = CMODE_CHOOSE;
@@ -2114,15 +2121,13 @@ static int atyfb_pci_resume(struct pci_dev *pdev)
 #ifdef CONFIG_FB_ATY_BACKLIGHT
 #define MAX_LEVEL 0xFF
 
-static struct backlight_properties aty_bl_data;
-
-/* Call with fb_info->bl_mutex held */
 static int aty_bl_get_level_brightness(struct atyfb_par *par, int level)
 {
        struct fb_info *info = pci_get_drvdata(par->pdev);
        int atylevel;
 
        /* Get and convert the value */
+       /* No locking of bl_curve since we read a single value */
        atylevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
 
        if (atylevel < 0)
@@ -2133,18 +2138,17 @@ static int aty_bl_get_level_brightness(struct atyfb_par *par, int level)
        return atylevel;
 }
 
-/* Call with fb_info->bl_mutex held */
-static int __aty_bl_update_status(struct backlight_device *bd)
+static int aty_bl_update_status(struct backlight_device *bd)
 {
        struct atyfb_par *par = class_get_devdata(&bd->class_dev);
        unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par);
        int level;
 
-       if (bd->props->power != FB_BLANK_UNBLANK ||
-           bd->props->fb_blank != FB_BLANK_UNBLANK)
+       if (bd->props.power != FB_BLANK_UNBLANK ||
+           bd->props.fb_blank != FB_BLANK_UNBLANK)
                level = 0;
        else
-               level = bd->props->brightness;
+               level = bd->props.brightness;
 
        reg |= (BLMOD_EN | BIASMOD_EN);
        if (level > 0) {
@@ -2159,45 +2163,16 @@ static int __aty_bl_update_status(struct backlight_device *bd)
        return 0;
 }
 
-static int aty_bl_update_status(struct backlight_device *bd)
-{
-       struct atyfb_par *par = class_get_devdata(&bd->class_dev);
-       struct fb_info *info = pci_get_drvdata(par->pdev);
-       int ret;
-
-       mutex_lock(&info->bl_mutex);
-       ret = __aty_bl_update_status(bd);
-       mutex_unlock(&info->bl_mutex);
-
-       return ret;
-}
-
 static int aty_bl_get_brightness(struct backlight_device *bd)
 {
-       return bd->props->brightness;
+       return bd->props.brightness;
 }
 
-static struct backlight_properties aty_bl_data = {
-       .owner    = THIS_MODULE,
+static struct backlight_ops aty_bl_data = {
        .get_brightness = aty_bl_get_brightness,
        .update_status  = aty_bl_update_status,
-       .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
 };
 
-static void aty_bl_set_power(struct fb_info *info, int power)
-{
-       mutex_lock(&info->bl_mutex);
-
-       if (info->bl_dev) {
-               down(&info->bl_dev->sem);
-               info->bl_dev->props->power = power;
-               __aty_bl_update_status(info->bl_dev);
-               up(&info->bl_dev->sem);
-       }
-
-       mutex_unlock(&info->bl_mutex);
-}
-
 static void aty_bl_init(struct atyfb_par *par)
 {
        struct fb_info *info = pci_get_drvdata(par->pdev);
@@ -2218,25 +2193,15 @@ static void aty_bl_init(struct atyfb_par *par)
                goto error;
        }
 
-       mutex_lock(&info->bl_mutex);
        info->bl_dev = bd;
        fb_bl_default_curve(info, 0,
                0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL,
                0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL);
-       mutex_unlock(&info->bl_mutex);
-
-       down(&bd->sem);
-       bd->props->brightness = aty_bl_data.max_brightness;
-       bd->props->power = FB_BLANK_UNBLANK;
-       bd->props->update_status(bd);
-       up(&bd->sem);
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-       mutex_lock(&pmac_backlight_mutex);
-       if (!pmac_backlight)
-               pmac_backlight = bd;
-       mutex_unlock(&pmac_backlight_mutex);
-#endif
+       bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+       bd->props.brightness = bd->props.max_brightness;
+       bd->props.power = FB_BLANK_UNBLANK;
+       backlight_update_status(bd);
 
        printk("aty: Backlight initialized (%s)\n", name);
 
@@ -2246,30 +2211,10 @@ error:
        return;
 }
 
-static void aty_bl_exit(struct atyfb_par *par)
+static void aty_bl_exit(struct backlight_device *bd)
 {
-       struct fb_info *info = pci_get_drvdata(par->pdev);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-       mutex_lock(&pmac_backlight_mutex);
-#endif
-
-       mutex_lock(&info->bl_mutex);
-       if (info->bl_dev) {
-#ifdef CONFIG_PMAC_BACKLIGHT
-               if (pmac_backlight == info->bl_dev)
-                       pmac_backlight = NULL;
-#endif
-
-               backlight_device_unregister(info->bl_dev);
-
-               printk("aty: Backlight unloaded\n");
-       }
-       mutex_unlock(&info->bl_mutex);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-       mutex_unlock(&pmac_backlight_mutex);
-#endif
+       backlight_device_unregister(bd);
+       printk("aty: Backlight unloaded\n");
 }
 
 #endif /* CONFIG_FB_ATY_BACKLIGHT */
@@ -2637,7 +2582,7 @@ static int __devinit aty_init(struct fb_info *info)
                           | (USE_F32KHZ | TRISTATE_MEM_EN), par);
        } else
 #endif
-       if (M64_HAS(MOBIL_BUS)) {
+       if (M64_HAS(MOBIL_BUS) && backlight) {
 #ifdef CONFIG_FB_ATY_BACKLIGHT
                aty_bl_init (par);
 #endif
@@ -2814,8 +2759,6 @@ static int atyfb_blank(int blank, struct fb_info *info)
                return 0;
 
 #ifdef CONFIG_FB_ATY_BACKLIGHT
-       if (machine_is(powermac) && blank > FB_BLANK_NORMAL)
-               aty_bl_set_power(info, FB_BLANK_POWERDOWN);
 #elif defined(CONFIG_FB_ATY_GENERIC_LCD)
        if (par->lcd_table && blank > FB_BLANK_NORMAL &&
            (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
@@ -2846,8 +2789,6 @@ static int atyfb_blank(int blank, struct fb_info *info)
        aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
 
 #ifdef CONFIG_FB_ATY_BACKLIGHT
-       if (machine_is(powermac) && blank <= FB_BLANK_NORMAL)
-               aty_bl_set_power(info, FB_BLANK_UNBLANK);
 #elif defined(CONFIG_FB_ATY_GENERIC_LCD)
        if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
            (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
@@ -3726,13 +3667,13 @@ static void __devexit atyfb_remove(struct fb_info *info)
        aty_set_crtc(par, &saved_crtc);
        par->pll_ops->set_pll(info, &saved_pll);
 
+       unregister_framebuffer(info);
+
 #ifdef CONFIG_FB_ATY_BACKLIGHT
        if (M64_HAS(MOBIL_BUS))
-               aty_bl_exit(par);
+               aty_bl_exit(info->bl_dev);
 #endif
 
-       unregister_framebuffer(info);
-
 #ifdef CONFIG_MTRR
        if (par->mtrr_reg >= 0) {
            mtrr_del(par->mtrr_reg, 0, 0);
@@ -3823,6 +3764,8 @@ static int __init atyfb_setup(char *options)
                        xclk = simple_strtoul(this_opt+5, NULL, 0);
                else if (!strncmp(this_opt, "comp_sync:", 10))
                        comp_sync = simple_strtoul(this_opt+10, NULL, 0);
+               else if (!strncmp(this_opt, "backlight:", 10))
+                       backlight = simple_strtoul(this_opt+10, NULL, 0);
 #ifdef CONFIG_PPC
                else if (!strncmp(this_opt, "vmode:", 6)) {
                        unsigned int vmode =
index f3b487b8710ba28725e1336b9fac6a2e0b1c7536..1fdcfdbf669b2a26f770af8d4b5816479f8f6f86 100644 (file)
@@ -598,7 +598,6 @@ static void aty_resume_pll_ct(const struct fb_info *info,
        struct atyfb_par *par = info->par;
 
        if (par->mclk_per != par->xclk_per) {
-               int i;
                /*
                * This disables the sclk, crashes the computer as reported:
                * aty_st_pll_ct(SPLL_CNTL2, 3, info);
@@ -614,7 +613,7 @@ static void aty_resume_pll_ct(const struct fb_info *info,
                 * helps for Rage Mobilities that sometimes crash when
                 * we switch to sclk. (Daniel Mantione, 13-05-2003)
                 */
-               for (i=0;i<=0x1ffff;i++);
+               udelay(500);
        }
 
        aty_st_pll_ct(PLL_REF_DIV, pll->ct.pll_ref_div, par);
index 3abfd4a380cc22c229520d3eaba7d728c0330001..0be25fa5540c8a938507bbdb7f3046e40c5973ff 100644 (file)
@@ -19,8 +19,6 @@
 
 #define MAX_RADEON_LEVEL 0xFF
 
-static struct backlight_properties radeon_bl_data;
-
 struct radeon_bl_privdata {
        struct radeonfb_info *rinfo;
        uint8_t negative;
@@ -29,17 +27,13 @@ struct radeon_bl_privdata {
 static int radeon_bl_get_level_brightness(struct radeon_bl_privdata *pdata,
                int level)
 {
-       struct fb_info *info = pdata->rinfo->info;
        int rlevel;
 
-       mutex_lock(&info->bl_mutex);
-
        /* Get and convert the value */
+       /* No locking of bl_curve since we read a single value */
        rlevel = pdata->rinfo->info->bl_curve[level] *
                 FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL;
 
-       mutex_unlock(&info->bl_mutex);
-
        if (rlevel < 0)
                rlevel = 0;
        else if (rlevel > MAX_RADEON_LEVEL)
@@ -65,11 +59,11 @@ static int radeon_bl_update_status(struct backlight_device *bd)
         * backlight. This provides some greater power saving and the display
         * is useless without backlight anyway.
         */
-        if (bd->props->power != FB_BLANK_UNBLANK ||
-           bd->props->fb_blank != FB_BLANK_UNBLANK)
+        if (bd->props.power != FB_BLANK_UNBLANK ||
+           bd->props.fb_blank != FB_BLANK_UNBLANK)
                level = 0;
        else
-               level = bd->props->brightness;
+               level = bd->props.brightness;
 
        del_timer_sync(&rinfo->lvds_timer);
        radeon_engine_idle();
@@ -130,14 +124,12 @@ static int radeon_bl_update_status(struct backlight_device *bd)
 
 static int radeon_bl_get_brightness(struct backlight_device *bd)
 {
-       return bd->props->brightness;
+       return bd->props.brightness;
 }
 
-static struct backlight_properties radeon_bl_data = {
-       .owner          = THIS_MODULE,
+static struct backlight_ops radeon_bl_data = {
        .get_brightness = radeon_bl_get_brightness,
        .update_status  = radeon_bl_update_status,
-       .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
 };
 
 void radeonfb_bl_init(struct radeonfb_info *rinfo)
@@ -188,25 +180,15 @@ void radeonfb_bl_init(struct radeonfb_info *rinfo)
                machine_is_compatible("PowerBook6,5");
 #endif
 
-       mutex_lock(&rinfo->info->bl_mutex);
        rinfo->info->bl_dev = bd;
        fb_bl_default_curve(rinfo->info, 0,
                 63 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL,
                217 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL);
-       mutex_unlock(&rinfo->info->bl_mutex);
 
-       down(&bd->sem);
-       bd->props->brightness = radeon_bl_data.max_brightness;
-       bd->props->power = FB_BLANK_UNBLANK;
-       bd->props->update_status(bd);
-       up(&bd->sem);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-       mutex_lock(&pmac_backlight_mutex);
-       if (!pmac_backlight)
-               pmac_backlight = bd;
-       mutex_unlock(&pmac_backlight_mutex);
-#endif
+       bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+       bd->props.brightness = bd->props.max_brightness;
+       bd->props.power = FB_BLANK_UNBLANK;
+       backlight_update_status(bd);
 
        printk("radeonfb: Backlight initialized (%s)\n", name);
 
@@ -219,29 +201,16 @@ error:
 
 void radeonfb_bl_exit(struct radeonfb_info *rinfo)
 {
-#ifdef CONFIG_PMAC_BACKLIGHT
-       mutex_lock(&pmac_backlight_mutex);
-#endif
+       struct backlight_device *bd = rinfo->info->bl_dev;
 
-       mutex_lock(&rinfo->info->bl_mutex);
-       if (rinfo->info->bl_dev) {
+       if (bd) {
                struct radeon_bl_privdata *pdata;
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-               if (pmac_backlight == rinfo->info->bl_dev)
-                       pmac_backlight = NULL;
-#endif
-
-               pdata = class_get_devdata(&rinfo->info->bl_dev->class_dev);
-               backlight_device_unregister(rinfo->info->bl_dev);
+               pdata = class_get_devdata(&bd->class_dev);
+               backlight_device_unregister(bd);
                kfree(pdata);
                rinfo->info->bl_dev = NULL;
 
                printk("radeonfb: Backlight unloaded\n");
        }
-       mutex_unlock(&rinfo->info->bl_mutex);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-       mutex_unlock(&pmac_backlight_mutex);
-#endif
 }
index 0ed577e7cc211e6dbdd7412644586a7f583554ec..1bf6f42eb400c8183defe6dee561ab3bf5db9a08 100644 (file)
@@ -268,6 +268,11 @@ static int nomtrr = 0;
 #endif
 static int force_sleep;
 static int ignore_devlist;
+#ifdef CONFIG_PMAC_BACKLIGHT
+static int backlight = 1;
+#else
+static int backlight = 0;
+#endif
 
 /*
  * prototypes
@@ -1026,8 +1031,7 @@ int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch)
                break;
        }
 
-       /* let fbcon do a soft blank for us */
-       return (blank == FB_BLANK_NORMAL) ? -EINVAL : 0;
+       return 0;
 }
 
 static int radeonfb_blank (int blank, struct fb_info *info)
@@ -2349,7 +2353,8 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
                                                 MTRR_TYPE_WRCOMB, 1);
 #endif
 
-       radeonfb_bl_init(rinfo);
+       if (backlight)
+               radeonfb_bl_init(rinfo);
 
        printk ("radeonfb (%s): %s\n", pci_name(rinfo->pdev), rinfo->name);
 
@@ -2393,7 +2398,6 @@ static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev)
         if (!rinfo)
                 return;
 
-       radeonfb_bl_exit(rinfo);
        radeonfb_pm_exit(rinfo);
 
        if (rinfo->mon1_EDID)
@@ -2420,6 +2424,8 @@ static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev)
 
         unregister_framebuffer(info);
 
+        radeonfb_bl_exit(rinfo);
+
         iounmap(rinfo->mmio_base);
         iounmap(rinfo->fb_base);
  
@@ -2469,6 +2475,8 @@ static int __init radeonfb_setup (char *options)
                        force_dfp = 1;
                } else if (!strncmp(this_opt, "panel_yres:", 11)) {
                        panel_yres = simple_strtoul((this_opt+11), NULL, 0);
+               } else if (!strncmp(this_opt, "backlight:", 10)) {
+                       backlight = simple_strtoul(this_opt+10, NULL, 0);
 #ifdef CONFIG_MTRR
                } else if (!strncmp(this_opt, "nomtrr", 6)) {
                        nomtrr = 1;
index 02f15297a021b1c7902137ee09bed8355e62f412..47d15b5d985a0ce3f124a7d83cf3a7e7a8fd82e5 100644 (file)
@@ -19,11 +19,6 @@ config BACKLIGHT_CLASS_DEVICE
          To have support for your specific LCD panel you will have to
          select the proper drivers which depend on this option.
 
-config BACKLIGHT_DEVICE
-       bool
-       depends on BACKLIGHT_CLASS_DEVICE
-       default y
-
 config LCD_CLASS_DEVICE
         tristate "Lowlevel LCD controls"
        depends on BACKLIGHT_LCD_SUPPORT
@@ -37,14 +32,9 @@ config LCD_CLASS_DEVICE
          To have support for your specific LCD panel you will have to
          select the proper drivers which depend on this option.
 
-config LCD_DEVICE
-       bool
-       depends on LCD_CLASS_DEVICE
-       default y
-
 config BACKLIGHT_CORGI
        tristate "Sharp Corgi Backlight Driver (SL Series)"
-       depends on BACKLIGHT_DEVICE && PXA_SHARPSL
+       depends on BACKLIGHT_CLASS_DEVICE && PXA_SHARPSL
        default y
        help
          If you have a Sharp Zaurus SL-C7xx, SL-Cxx00 or SL-6000x say y to enable the
@@ -52,7 +42,7 @@ config BACKLIGHT_CORGI
 
 config BACKLIGHT_LOCOMO
        tristate "Sharp LOCOMO LCD/Backlight Driver"
-       depends on BACKLIGHT_DEVICE && SHARP_LOCOMO
+       depends on BACKLIGHT_CLASS_DEVICE && SHARP_LOCOMO
        default y
        help
          If you have a Sharp Zaurus SL-5500 (Collie) or SL-5600 (Poodle) say y to
@@ -60,9 +50,16 @@ config BACKLIGHT_LOCOMO
 
 config BACKLIGHT_HP680
        tristate "HP Jornada 680 Backlight Driver"
-       depends on BACKLIGHT_DEVICE && SH_HP6XX
+       depends on BACKLIGHT_CLASS_DEVICE && SH_HP6XX
        default y
        help
          If you have a HP Jornada 680, say y to enable the
          backlight driver.
 
+config BACKLIGHT_PROGEAR
+       tristate "Frontpath ProGear Backlight Driver"
+       depends on BACKLIGHT_CLASS_DEVICE && PCI && X86
+       default n
+       help
+         If you have a Frontpath ProGear say Y to enable the
+         backlight driver.
index 65e5553fc849fed5bcbadb287640313bdfa09b97..0c3ce46f50949d17971d91dfa8b92f8441aa92a3 100644 (file)
@@ -5,3 +5,4 @@ obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
 obj-$(CONFIG_BACKLIGHT_CORGI)  += corgi_bl.o
 obj-$(CONFIG_BACKLIGHT_HP680)  += hp680_bl.o
 obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o
+obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o
index 9601bfe309ac2744c922a1f612eb4b6188e12aa0..c65e81ff3578fedb1ff1e00bde752f252f77a8e0 100644 (file)
@@ -14,6 +14,9 @@
 #include <linux/err.h>
 #include <linux/fb.h>
 
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
 
 #if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \
                           defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE))
@@ -28,19 +31,18 @@ static int fb_notifier_callback(struct notifier_block *self,
        struct fb_event *evdata = data;
 
        /* If we aren't interested in this event, skip it immediately ... */
-       if (event != FB_EVENT_BLANK)
+       if (event != FB_EVENT_BLANK && event != FB_EVENT_CONBLANK)
                return 0;
 
        bd = container_of(self, struct backlight_device, fb_notif);
-       down(&bd->sem);
-       if (bd->props)
-               if (!bd->props->check_fb ||
-                   bd->props->check_fb(evdata->info)) {
-                       bd->props->fb_blank = *(int *)evdata->data;
-                       if (likely(bd->props && bd->props->update_status))
-                               bd->props->update_status(bd);
+       mutex_lock(&bd->ops_lock);
+       if (bd->ops)
+               if (!bd->ops->check_fb ||
+                   bd->ops->check_fb(evdata->info)) {
+                       bd->props.fb_blank = *(int *)evdata->data;
+                       backlight_update_status(bd);
                }
-       up(&bd->sem);
+       mutex_unlock(&bd->ops_lock);
        return 0;
 }
 
@@ -69,15 +71,9 @@ static inline void backlight_unregister_fb(struct backlight_device *bd)
 
 static ssize_t backlight_show_power(struct class_device *cdev, char *buf)
 {
-       int rc = -ENXIO;
        struct backlight_device *bd = to_backlight_device(cdev);
 
-       down(&bd->sem);
-       if (likely(bd->props))
-               rc = sprintf(buf, "%d\n", bd->props->power);
-       up(&bd->sem);
-
-       return rc;
+       return sprintf(buf, "%d\n", bd->props.power);
 }
 
 static ssize_t backlight_store_power(struct class_device *cdev, const char *buf, size_t count)
@@ -93,30 +89,23 @@ static ssize_t backlight_store_power(struct class_device *cdev, const char *buf,
        if (size != count)
                return -EINVAL;
 
-       down(&bd->sem);
-       if (likely(bd->props)) {
+       mutex_lock(&bd->ops_lock);
+       if (bd->ops) {
                pr_debug("backlight: set power to %d\n", power);
-               bd->props->power = power;
-               if (likely(bd->props->update_status))
-                       bd->props->update_status(bd);
+               bd->props.power = power;
+               backlight_update_status(bd);
                rc = count;
        }
-       up(&bd->sem);
+       mutex_unlock(&bd->ops_lock);
 
        return rc;
 }
 
 static ssize_t backlight_show_brightness(struct class_device *cdev, char *buf)
 {
-       int rc = -ENXIO;
        struct backlight_device *bd = to_backlight_device(cdev);
 
-       down(&bd->sem);
-       if (likely(bd->props))
-               rc = sprintf(buf, "%d\n", bd->props->brightness);
-       up(&bd->sem);
-
-       return rc;
+       return sprintf(buf, "%d\n", bd->props.brightness);
 }
 
 static ssize_t backlight_store_brightness(struct class_device *cdev, const char *buf, size_t count)
@@ -132,35 +121,28 @@ static ssize_t backlight_store_brightness(struct class_device *cdev, const char
        if (size != count)
                return -EINVAL;
 
-       down(&bd->sem);
-       if (likely(bd->props)) {
-               if (brightness > bd->props->max_brightness)
+       mutex_lock(&bd->ops_lock);
+       if (bd->ops) {
+               if (brightness > bd->props.max_brightness)
                        rc = -EINVAL;
                else {
                        pr_debug("backlight: set brightness to %d\n",
                                 brightness);
-                       bd->props->brightness = brightness;
-                       if (likely(bd->props->update_status))
-                               bd->props->update_status(bd);
+                       bd->props.brightness = brightness;
+                       backlight_update_status(bd);
                        rc = count;
                }
        }
-       up(&bd->sem);
+       mutex_unlock(&bd->ops_lock);
 
        return rc;
 }
 
 static ssize_t backlight_show_max_brightness(struct class_device *cdev, char *buf)
 {
-       int rc = -ENXIO;
        struct backlight_device *bd = to_backlight_device(cdev);
 
-       down(&bd->sem);
-       if (likely(bd->props))
-               rc = sprintf(buf, "%d\n", bd->props->max_brightness);
-       up(&bd->sem);
-
-       return rc;
+       return sprintf(buf, "%d\n", bd->props.max_brightness);
 }
 
 static ssize_t backlight_show_actual_brightness(struct class_device *cdev,
@@ -169,10 +151,10 @@ static ssize_t backlight_show_actual_brightness(struct class_device *cdev,
        int rc = -ENXIO;
        struct backlight_device *bd = to_backlight_device(cdev);
 
-       down(&bd->sem);
-       if (likely(bd->props && bd->props->get_brightness))
-               rc = sprintf(buf, "%d\n", bd->props->get_brightness(bd));
-       up(&bd->sem);
+       mutex_lock(&bd->ops_lock);
+       if (bd->ops && bd->ops->get_brightness)
+               rc = sprintf(buf, "%d\n", bd->ops->get_brightness(bd));
+       mutex_unlock(&bd->ops_lock);
 
        return rc;
 }
@@ -211,7 +193,7 @@ static const struct class_device_attribute bl_class_device_attributes[] = {
  *   respective framebuffer device).
  * @devdata: an optional pointer to be stored in the class_device. The
  *   methods may retrieve it by using class_get_devdata(&bd->class_dev).
- * @bp: the backlight properties structure.
+ * @ops: the backlight operations structure.
  *
  * Creates and registers new backlight class_device. Returns either an
  * ERR_PTR() or a pointer to the newly allocated device.
@@ -219,39 +201,42 @@ static const struct class_device_attribute bl_class_device_attributes[] = {
 struct backlight_device *backlight_device_register(const char *name,
        struct device *dev,
        void *devdata,
-       struct backlight_properties *bp)
+       struct backlight_ops *ops)
 {
        int i, rc;
        struct backlight_device *new_bd;
 
        pr_debug("backlight_device_alloc: name=%s\n", name);
 
-       new_bd = kmalloc(sizeof(struct backlight_device), GFP_KERNEL);
-       if (unlikely(!new_bd))
+       new_bd = kzalloc(sizeof(struct backlight_device), GFP_KERNEL);
+       if (!new_bd)
                return ERR_PTR(-ENOMEM);
 
-       init_MUTEX(&new_bd->sem);
-       new_bd->props = bp;
-       memset(&new_bd->class_dev, 0, sizeof(new_bd->class_dev));
+       mutex_init(&new_bd->update_lock);
+       mutex_init(&new_bd->ops_lock);
+       new_bd->ops = ops;
        new_bd->class_dev.class = &backlight_class;
        new_bd->class_dev.dev = dev;
        strlcpy(new_bd->class_dev.class_id, name, KOBJ_NAME_LEN);
        class_set_devdata(&new_bd->class_dev, devdata);
 
        rc = class_device_register(&new_bd->class_dev);
-       if (unlikely(rc)) {
-error:         kfree(new_bd);
+       if (rc) {
+               kfree(new_bd);
                return ERR_PTR(rc);
        }
 
        rc = backlight_register_fb(new_bd);
-       if (unlikely(rc))
-               goto error;
+       if (rc) {
+               class_device_unregister(&new_bd->class_dev);
+               return ERR_PTR(rc);
+       }
+
 
        for (i = 0; i < ARRAY_SIZE(bl_class_device_attributes); i++) {
                rc = class_device_create_file(&new_bd->class_dev,
                                              &bl_class_device_attributes[i]);
-               if (unlikely(rc)) {
+               if (rc) {
                        while (--i >= 0)
                                class_device_remove_file(&new_bd->class_dev,
                                                         &bl_class_device_attributes[i]);
@@ -261,6 +246,13 @@ error:             kfree(new_bd);
                }
        }
 
+#ifdef CONFIG_PMAC_BACKLIGHT
+       mutex_lock(&pmac_backlight_mutex);
+       if (!pmac_backlight)
+               pmac_backlight = new_bd;
+       mutex_unlock(&pmac_backlight_mutex);
+#endif
+
        return new_bd;
 }
 EXPORT_SYMBOL(backlight_device_register);
@@ -280,13 +272,20 @@ void backlight_device_unregister(struct backlight_device *bd)
 
        pr_debug("backlight_device_unregister: name=%s\n", bd->class_dev.class_id);
 
+#ifdef CONFIG_PMAC_BACKLIGHT
+       mutex_lock(&pmac_backlight_mutex);
+       if (pmac_backlight == bd)
+               pmac_backlight = NULL;
+       mutex_unlock(&pmac_backlight_mutex);
+#endif
+
        for (i = 0; i < ARRAY_SIZE(bl_class_device_attributes); i++)
                class_device_remove_file(&bd->class_dev,
                                         &bl_class_device_attributes[i]);
 
-       down(&bd->sem);
-       bd->props = NULL;
-       up(&bd->sem);
+       mutex_lock(&bd->ops_lock);
+       bd->ops = NULL;
+       mutex_unlock(&bd->ops_lock);
 
        backlight_unregister_fb(bd);
 
index fde1d9518123b6b04a024184a023537379a7324f..ce00e18a4e5dac3b755284831685adb20a8560e3 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/hardware/sharpsl_pm.h>
 
 static int corgibl_intensity;
-static DEFINE_MUTEX(bl_mutex);
 static struct backlight_properties corgibl_data;
 static struct backlight_device *corgi_backlight_device;
 static struct corgibl_machinfo *bl_machinfo;
@@ -34,20 +33,18 @@ static unsigned long corgibl_flags;
 static int corgibl_send_intensity(struct backlight_device *bd)
 {
        void (*corgi_kick_batt)(void);
-       int intensity = bd->props->brightness;
+       int intensity = bd->props.brightness;
 
-       if (bd->props->power != FB_BLANK_UNBLANK)
+       if (bd->props.power != FB_BLANK_UNBLANK)
                intensity = 0;
-       if (bd->props->fb_blank != FB_BLANK_UNBLANK)
+       if (bd->props.fb_blank != FB_BLANK_UNBLANK)
                intensity = 0;
        if (corgibl_flags & CORGIBL_SUSPENDED)
                intensity = 0;
        if (corgibl_flags & CORGIBL_BATTLOW)
                intensity &= bl_machinfo->limit_mask;
 
-       mutex_lock(&bl_mutex);
        bl_machinfo->set_bl_intensity(intensity);
-       mutex_unlock(&bl_mutex);
 
        corgibl_intensity = intensity;
 
@@ -61,17 +58,21 @@ static int corgibl_send_intensity(struct backlight_device *bd)
 }
 
 #ifdef CONFIG_PM
-static int corgibl_suspend(struct platform_device *dev, pm_message_t state)
+static int corgibl_suspend(struct platform_device *pdev, pm_message_t state)
 {
+       struct backlight_device *bd = platform_get_drvdata(pdev);
+
        corgibl_flags |= CORGIBL_SUSPENDED;
-       corgibl_send_intensity(corgi_backlight_device);
+       backlight_update_status(bd);
        return 0;
 }
 
-static int corgibl_resume(struct platform_device *dev)
+static int corgibl_resume(struct platform_device *pdev)
 {
+       struct backlight_device *bd = platform_get_drvdata(pdev);
+
        corgibl_flags &= ~CORGIBL_SUSPENDED;
-       corgibl_send_intensity(corgi_backlight_device);
+       backlight_update_status(bd);
        return 0;
 }
 #else
@@ -84,12 +85,6 @@ static int corgibl_get_intensity(struct backlight_device *bd)
        return corgibl_intensity;
 }
 
-static int corgibl_set_intensity(struct backlight_device *bd)
-{
-       corgibl_send_intensity(corgi_backlight_device);
-       return 0;
-}
-
 /*
  * Called when the battery is low to limit the backlight intensity.
  * If limit==0 clear any limit, otherwise limit the intensity
@@ -100,15 +95,14 @@ void corgibl_limit_intensity(int limit)
                corgibl_flags |= CORGIBL_BATTLOW;
        else
                corgibl_flags &= ~CORGIBL_BATTLOW;
-       corgibl_send_intensity(corgi_backlight_device);
+       backlight_update_status(corgi_backlight_device);
 }
 EXPORT_SYMBOL(corgibl_limit_intensity);
 
 
-static struct backlight_properties corgibl_data = {
-       .owner          = THIS_MODULE,
+static struct backlight_ops corgibl_ops = {
        .get_brightness = corgibl_get_intensity,
-       .update_status  = corgibl_set_intensity,
+       .update_status  = corgibl_send_intensity,
 };
 
 static int corgibl_probe(struct platform_device *pdev)
@@ -116,30 +110,34 @@ static int corgibl_probe(struct platform_device *pdev)
        struct corgibl_machinfo *machinfo = pdev->dev.platform_data;
 
        bl_machinfo = machinfo;
-       corgibl_data.max_brightness = machinfo->max_intensity;
        if (!machinfo->limit_mask)
                machinfo->limit_mask = -1;
 
        corgi_backlight_device = backlight_device_register ("corgi-bl",
-               &pdev->dev, NULL, &corgibl_data);
+               &pdev->dev, NULL, &corgibl_ops);
        if (IS_ERR (corgi_backlight_device))
                return PTR_ERR (corgi_backlight_device);
 
-       corgibl_data.power = FB_BLANK_UNBLANK;
-       corgibl_data.brightness = machinfo->default_intensity;
-       corgibl_send_intensity(corgi_backlight_device);
+       platform_set_drvdata(pdev, corgi_backlight_device);
+
+       corgi_backlight_device->props.max_brightness = machinfo->max_intensity;
+       corgi_backlight_device->props.power = FB_BLANK_UNBLANK;
+       corgi_backlight_device->props.brightness = machinfo->default_intensity;
+       backlight_update_status(corgi_backlight_device);
 
        printk("Corgi Backlight Driver Initialized.\n");
        return 0;
 }
 
-static int corgibl_remove(struct platform_device *dev)
+static int corgibl_remove(struct platform_device *pdev)
 {
+       struct backlight_device *bd = platform_get_drvdata(pdev);
+
        corgibl_data.power = 0;
        corgibl_data.brightness = 0;
-       corgibl_send_intensity(corgi_backlight_device);
+       backlight_update_status(bd);
 
-       backlight_device_unregister(corgi_backlight_device);
+       backlight_device_unregister(bd);
 
        printk("Corgi Backlight Driver Unloaded\n");
        return 0;
index c07d8207fb549e1412b91a793f98e8b3d9719646..0899fccbd5709f203d10ecdd1c5b2b60215606cd 100644 (file)
 static int hp680bl_suspended;
 static int current_intensity = 0;
 static DEFINE_SPINLOCK(bl_lock);
-static struct backlight_device *hp680_backlight_device;
 
 static void hp680bl_send_intensity(struct backlight_device *bd)
 {
        unsigned long flags;
        u16 v;
-       int intensity = bd->props->brightness;
+       int intensity = bd->props.brightness;
 
-       if (bd->props->power != FB_BLANK_UNBLANK)
+       if (bd->props.power != FB_BLANK_UNBLANK)
                intensity = 0;
-       if (bd->props->fb_blank != FB_BLANK_UNBLANK)
+       if (bd->props.fb_blank != FB_BLANK_UNBLANK)
                intensity = 0;
        if (hp680bl_suspended)
                intensity = 0;
@@ -66,17 +65,21 @@ static void hp680bl_send_intensity(struct backlight_device *bd)
 
 
 #ifdef CONFIG_PM
-static int hp680bl_suspend(struct platform_device *dev, pm_message_t state)
+static int hp680bl_suspend(struct platform_device *pdev, pm_message_t state)
 {
+       struct backlight_device *bd = platform_get_drvdata(pdev);
+
        hp680bl_suspended = 1;
-       hp680bl_send_intensity(hp680_backlight_device);
+       hp680bl_send_intensity(bd);
        return 0;
 }
 
-static int hp680bl_resume(struct platform_device *dev)
+static int hp680bl_resume(struct platform_device *pdev)
 {
+       struct backlight_device *bd = platform_get_drvdata(pdev);
+
        hp680bl_suspended = 0;
-       hp680bl_send_intensity(hp680_backlight_device);
+       hp680bl_send_intensity(bd);
        return 0;
 }
 #else
@@ -95,33 +98,38 @@ static int hp680bl_get_intensity(struct backlight_device *bd)
        return current_intensity;
 }
 
-static struct backlight_properties hp680bl_data = {
-       .owner          = THIS_MODULE,
-       .max_brightness = HP680_MAX_INTENSITY,
+static struct backlight_ops hp680bl_ops = {
        .get_brightness = hp680bl_get_intensity,
        .update_status  = hp680bl_set_intensity,
 };
 
-static int __init hp680bl_probe(struct platform_device *dev)
+static int __init hp680bl_probe(struct platform_device *pdev)
 {
-       hp680_backlight_device = backlight_device_register ("hp680-bl",
-               &dev->dev, NULL, &hp680bl_data);
-       if (IS_ERR (hp680_backlight_device))
-               return PTR_ERR (hp680_backlight_device);
+       struct backlight_device *bd;
+
+       bd = backlight_device_register ("hp680-bl", &pdev->dev, NULL,
+                   &hp680bl_ops);
+       if (IS_ERR(bd))
+               return PTR_ERR(bd);
 
-       hp680_backlight_device->props->brightness = HP680_DEFAULT_INTENSITY;
-       hp680bl_send_intensity(hp680_backlight_device);
+       platform_set_drvdata(pdev, bd);
+
+       bd->props.max_brightness = HP680_MAX_INTENSITY;
+       bd->props.brightness = HP680_DEFAULT_INTENSITY;
+       hp680bl_send_intensity(bd);
 
        return 0;
 }
 
-static int hp680bl_remove(struct platform_device *dev)
+static int hp680bl_remove(struct platform_device *pdev)
 {
+       struct backlight_device *bd = platform_get_drvdata(pdev);
+
        hp680bl_data.brightness = 0;
        hp680bl_data.power = 0;
-       hp680bl_send_intensity(hp680_backlight_device);
+       hp680bl_send_intensity(bd);
 
-       backlight_device_unregister(hp680_backlight_device);
+       backlight_device_unregister(bd);
 
        return 0;
 }
index f6e041627edbb874419cc146ecd6df167fbe67c1..6ef8f0a7a137612deb25cbb3377f49e31e8aa93e 100644 (file)
@@ -31,11 +31,11 @@ static int fb_notifier_callback(struct notifier_block *self,
                return 0;
 
        ld = container_of(self, struct lcd_device, fb_notif);
-       down(&ld->sem);
-       if (ld->props)
-               if (!ld->props->check_fb || ld->props->check_fb(evdata->info))
-                       ld->props->set_power(ld, *(int *)evdata->data);
-       up(&ld->sem);
+       mutex_lock(&ld->ops_lock);
+       if (ld->ops)
+               if (!ld->ops->check_fb || ld->ops->check_fb(evdata->info))
+                       ld->ops->set_power(ld, *(int *)evdata->data);
+       mutex_unlock(&ld->ops_lock);
        return 0;
 }
 
@@ -66,12 +66,12 @@ static ssize_t lcd_show_power(struct class_device *cdev, char *buf)
        int rc;
        struct lcd_device *ld = to_lcd_device(cdev);
 
-       down(&ld->sem);
-       if (likely(ld->props && ld->props->get_power))
-               rc = sprintf(buf, "%d\n", ld->props->get_power(ld));
+       mutex_lock(&ld->ops_lock);
+       if (ld->ops && ld->ops->get_power)
+               rc = sprintf(buf, "%d\n", ld->ops->get_power(ld));
        else
                rc = -ENXIO;
-       up(&ld->sem);
+       mutex_unlock(&ld->ops_lock);
 
        return rc;
 }
@@ -89,13 +89,13 @@ static ssize_t lcd_store_power(struct class_device *cdev, const char *buf, size_
        if (size != count)
                return -EINVAL;
 
-       down(&ld->sem);
-       if (likely(ld->props && ld->props->set_power)) {
+       mutex_lock(&ld->ops_lock);
+       if (ld->ops && ld->ops->set_power) {
                pr_debug("lcd: set power to %d\n", power);
-               ld->props->set_power(ld, power);
+               ld->ops->set_power(ld, power);
                rc = count;
        }
-       up(&ld->sem);
+       mutex_unlock(&ld->ops_lock);
 
        return rc;
 }
@@ -105,10 +105,10 @@ static ssize_t lcd_show_contrast(struct class_device *cdev, char *buf)
        int rc = -ENXIO;
        struct lcd_device *ld = to_lcd_device(cdev);
 
-       down(&ld->sem);
-       if (likely(ld->props && ld->props->get_contrast))
-               rc = sprintf(buf, "%d\n", ld->props->get_contrast(ld));
-       up(&ld->sem);
+       mutex_lock(&ld->ops_lock);
+       if (ld->ops && ld->ops->get_contrast)
+               rc = sprintf(buf, "%d\n", ld->ops->get_contrast(ld));
+       mutex_unlock(&ld->ops_lock);
 
        return rc;
 }
@@ -126,28 +126,22 @@ static ssize_t lcd_store_contrast(struct class_device *cdev, const char *buf, si
        if (size != count)
                return -EINVAL;
 
-       down(&ld->sem);
-       if (likely(ld->props && ld->props->set_contrast)) {
+       mutex_lock(&ld->ops_lock);
+       if (ld->ops && ld->ops->set_contrast) {
                pr_debug("lcd: set contrast to %d\n", contrast);
-               ld->props->set_contrast(ld, contrast);
+               ld->ops->set_contrast(ld, contrast);
                rc = count;
        }
-       up(&ld->sem);
+       mutex_unlock(&ld->ops_lock);
 
        return rc;
 }
 
 static ssize_t lcd_show_max_contrast(struct class_device *cdev, char *buf)
 {
-       int rc = -ENXIO;
        struct lcd_device *ld = to_lcd_device(cdev);
 
-       down(&ld->sem);
-       if (likely(ld->props))
-               rc = sprintf(buf, "%d\n", ld->props->max_contrast);
-       up(&ld->sem);
-
-       return rc;
+       return sprintf(buf, "%d\n", ld->props.max_contrast);
 }
 
 static void lcd_class_release(struct class_device *dev)
@@ -180,45 +174,46 @@ static const struct class_device_attribute lcd_class_device_attributes[] = {
  *   respective framebuffer device).
  * @devdata: an optional pointer to be stored in the class_device. The
  *   methods may retrieve it by using class_get_devdata(ld->class_dev).
- * @lp: the lcd properties structure.
+ * @ops: the lcd operations structure.
  *
  * Creates and registers a new lcd class_device. Returns either an ERR_PTR()
  * or a pointer to the newly allocated device.
  */
 struct lcd_device *lcd_device_register(const char *name, void *devdata,
-                                      struct lcd_properties *lp)
+                                      struct lcd_ops *ops)
 {
        int i, rc;
        struct lcd_device *new_ld;
 
        pr_debug("lcd_device_register: name=%s\n", name);
 
-       new_ld = kmalloc(sizeof(struct lcd_device), GFP_KERNEL);
-       if (unlikely(!new_ld))
+       new_ld = kzalloc(sizeof(struct lcd_device), GFP_KERNEL);
+       if (!new_ld)
                return ERR_PTR(-ENOMEM);
 
-       init_MUTEX(&new_ld->sem);
-       new_ld->props = lp;
-       memset(&new_ld->class_dev, 0, sizeof(new_ld->class_dev));
+       mutex_init(&new_ld->ops_lock);
+       mutex_init(&new_ld->update_lock);
+       new_ld->ops = ops;
        new_ld->class_dev.class = &lcd_class;
        strlcpy(new_ld->class_dev.class_id, name, KOBJ_NAME_LEN);
        class_set_devdata(&new_ld->class_dev, devdata);
 
        rc = class_device_register(&new_ld->class_dev);
-       if (unlikely(rc)) {
-error:         kfree(new_ld);
+       if (rc) {
+               kfree(new_ld);
                return ERR_PTR(rc);
        }
 
        rc = lcd_register_fb(new_ld);
-
-       if (unlikely(rc))
-               goto error;
+       if (rc) {
+               class_device_unregister(&new_ld->class_dev);
+               return ERR_PTR(rc);
+       }
 
        for (i = 0; i < ARRAY_SIZE(lcd_class_device_attributes); i++) {
                rc = class_device_create_file(&new_ld->class_dev,
                                              &lcd_class_device_attributes[i]);
-               if (unlikely(rc)) {
+               if (rc) {
                        while (--i >= 0)
                                class_device_remove_file(&new_ld->class_dev,
                                                         &lcd_class_device_attributes[i]);
@@ -251,9 +246,9 @@ void lcd_device_unregister(struct lcd_device *ld)
                class_device_remove_file(&ld->class_dev,
                                         &lcd_class_device_attributes[i]);
 
-       down(&ld->sem);
-       ld->props = NULL;
-       up(&ld->sem);
+       mutex_lock(&ld->ops_lock);
+       ld->ops = NULL;
+       mutex_unlock(&ld->ops_lock);
        lcd_unregister_fb(ld);
        class_device_unregister(&ld->class_dev);
 }
index fc812d96c31dfc5fae102db6512afc9592b409da..d1312477813ee05bafbc95d15a8ead77619f28df 100644 (file)
@@ -112,11 +112,11 @@ static int current_intensity;
 
 static int locomolcd_set_intensity(struct backlight_device *bd)
 {
-       int intensity = bd->props->brightness;
+       int intensity = bd->props.brightness;
 
-       if (bd->props->power != FB_BLANK_UNBLANK)
+       if (bd->props.power != FB_BLANK_UNBLANK)
                intensity = 0;
-       if (bd->props->fb_blank != FB_BLANK_UNBLANK)
+       if (bd->props.fb_blank != FB_BLANK_UNBLANK)
                intensity = 0;
        if (locomolcd_flags & LOCOMOLCD_SUSPENDED)
                intensity = 0;
@@ -141,11 +141,9 @@ static int locomolcd_get_intensity(struct backlight_device *bd)
        return current_intensity;
 }
 
-static struct backlight_properties locomobl_data = {
-       .owner          = THIS_MODULE,
+static struct backlight_ops locomobl_data = {
        .get_brightness = locomolcd_get_intensity,
        .update_status  = locomolcd_set_intensity,
-       .max_brightness = 4,
 };
 
 #ifdef CONFIG_PM
@@ -190,7 +188,8 @@ static int locomolcd_probe(struct locomo_dev *ldev)
                return PTR_ERR (locomolcd_bl_device);
 
        /* Set up frontlight so that screen is readable */
-       locomobl_data.brightness = 2;
+       locomolcd_bl_device->props.max_brightness = 4,
+       locomolcd_bl_device->props.brightness = 2;
        locomolcd_set_intensity(locomolcd_bl_device);
 
        return 0;
diff --git a/drivers/video/backlight/progear_bl.c b/drivers/video/backlight/progear_bl.c
new file mode 100644 (file)
index 0000000..7022693
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ *  Backlight Driver for Frontpath ProGear HX1050+
+ *
+ *  Copyright (c) 2006 Marcin Juszkiewicz
+ *
+ *  Based on Progear LCD driver by M Schacht
+ *  <mschacht at alumni dot washington dot edu>
+ *
+ *  Based on Sharp's Corgi Backlight Driver
+ *  Based on Backlight Driver for HP Jornada 680
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+#include <linux/pci.h>
+#include <asm/uaccess.h>
+
+#define PMU_LPCR               0xB0
+#define SB_MPS1                0x61
+#define HW_LEVEL_MAX           0x77
+#define HW_LEVEL_MIN           0x4f
+
+static struct pci_dev *pmu_dev = NULL;
+static struct pci_dev *sb_dev = NULL;
+
+static int progearbl_set_intensity(struct backlight_device *bd)
+{
+       int intensity = bd->props.brightness;
+
+       if (bd->props.power != FB_BLANK_UNBLANK)
+               intensity = 0;
+       if (bd->props.fb_blank != FB_BLANK_UNBLANK)
+               intensity = 0;
+
+       pci_write_config_byte(pmu_dev, PMU_LPCR, intensity + HW_LEVEL_MIN);
+
+       return 0;
+}
+
+static int progearbl_get_intensity(struct backlight_device *bd)
+{
+       u8 intensity;
+       pci_read_config_byte(pmu_dev, PMU_LPCR, &intensity);
+
+       return intensity - HW_LEVEL_MIN;
+}
+
+static struct backlight_ops progearbl_ops = {
+       .get_brightness = progearbl_get_intensity,
+       .update_status = progearbl_set_intensity,
+};
+
+static int progearbl_probe(struct platform_device *pdev)
+{
+       u8 temp;
+       struct backlight_device *progear_backlight_device;
+
+       pmu_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, 0);
+       if (!pmu_dev) {
+               printk("ALI M7101 PMU not found.\n");
+               return -ENODEV;
+       }
+
+       sb_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, 0);
+       if (!sb_dev) {
+               printk("ALI 1533 SB not found.\n");
+               pci_dev_put(pmu_dev);
+               return -ENODEV;
+       }
+
+       /*     Set SB_MPS1 to enable brightness control. */
+       pci_read_config_byte(sb_dev, SB_MPS1, &temp);
+       pci_write_config_byte(sb_dev, SB_MPS1, temp | 0x20);
+
+       progear_backlight_device = backlight_device_register("progear-bl",
+                                                            &pdev->dev, NULL,
+                                                            &progearbl_ops);
+       if (IS_ERR(progear_backlight_device))
+               return PTR_ERR(progear_backlight_device);
+
+       platform_set_drvdata(pdev, progear_backlight_device);
+
+       progear_backlight_device->props.power = FB_BLANK_UNBLANK;
+       progear_backlight_device->props.brightness = HW_LEVEL_MAX - HW_LEVEL_MIN;
+       progear_backlight_device->props.max_brightness = HW_LEVEL_MAX - HW_LEVEL_MIN;
+       progearbl_set_intensity(progear_backlight_device);
+
+       return 0;
+}
+
+static int progearbl_remove(struct platform_device *pdev)
+{
+       struct backlight_device *bd = platform_get_drvdata(pdev);
+       backlight_device_unregister(bd);
+
+       return 0;
+}
+
+static struct platform_driver progearbl_driver = {
+       .probe = progearbl_probe,
+       .remove = progearbl_remove,
+       .driver = {
+                  .name = "progear-bl",
+                  },
+};
+
+static struct platform_device *progearbl_device;
+
+static int __init progearbl_init(void)
+{
+       int ret = platform_driver_register(&progearbl_driver);
+
+       if (!ret) {
+               progearbl_device = platform_device_alloc("progear-bl", -1);
+               if (!progearbl_device)
+                       return -ENOMEM;
+
+               ret = platform_device_add(progearbl_device);
+
+               if (ret) {
+                       platform_device_put(progearbl_device);
+                       platform_driver_unregister(&progearbl_driver);
+               }
+       }
+
+       return ret;
+}
+
+static void __exit progearbl_exit(void)
+{
+       pci_dev_put(pmu_dev);
+       pci_dev_put(sb_dev);
+
+       platform_device_unregister(progearbl_device);
+       platform_driver_unregister(&progearbl_driver);
+}
+
+module_init(progearbl_init);
+module_exit(progearbl_exit);
+
+MODULE_AUTHOR("Marcin Juszkiewicz <linux@hrw.one.pl>");
+MODULE_DESCRIPTION("ProGear Backlight Driver");
+MODULE_LICENSE("GPL");
index 73cb426bf2d7db5428ecb348da4b3fc112d2704c..af313bf1a2da04d7feccf9211e446c6f0303cfb7 100644 (file)
@@ -145,26 +145,6 @@ static int chipsfb_set_par(struct fb_info *info)
 
 static int chipsfb_blank(int blank, struct fb_info *info)
 {
-#ifdef CONFIG_PMAC_BACKLIGHT
-       mutex_lock(&pmac_backlight_mutex);
-
-       if (pmac_backlight) {
-               /* used to disable backlight only for blank > 1, but it seems
-                * useful at blank = 1 too (saves battery, extends backlight
-                * life)
-                */
-               down(&pmac_backlight->sem);
-               if (blank)
-                       pmac_backlight->props->power = FB_BLANK_POWERDOWN;
-               else
-                       pmac_backlight->props->power = FB_BLANK_UNBLANK;
-               pmac_backlight->props->update_status(pmac_backlight);
-               up(&pmac_backlight->sem);
-       }
-
-       mutex_unlock(&pmac_backlight_mutex);
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
        return 1;       /* get fb_blank to set the colormap to all black */
 }
 
@@ -415,10 +395,8 @@ chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
        /* turn on the backlight */
        mutex_lock(&pmac_backlight_mutex);
        if (pmac_backlight) {
-               down(&pmac_backlight->sem);
-               pmac_backlight->props->power = FB_BLANK_UNBLANK;
-               pmac_backlight->props->update_status(pmac_backlight);
-               up(&pmac_backlight->sem);
+               pmac_backlight->props.power = FB_BLANK_UNBLANK;
+               backlight_update_status(pmac_backlight);
        }
        mutex_unlock(&pmac_backlight_mutex);
 #endif /* CONFIG_PMAC_BACKLIGHT */
index be3f2c3f132c22d9f148da488aa9a9f5958ad32c..0429fd2cece09cff24a3e3f849a9894bac3056cb 100644 (file)
@@ -2233,6 +2233,8 @@ static int fbcon_switch(struct vc_data *vc)
 static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info,
                                int blank)
 {
+       struct fb_event event;
+
        if (blank) {
                unsigned short charmask = vc->vc_hi_font_mask ?
                        0x1ff : 0xff;
@@ -2243,6 +2245,11 @@ static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info,
                fbcon_clear(vc, 0, 0, vc->vc_rows, vc->vc_cols);
                vc->vc_video_erase_char = oldc;
        }
+
+
+       event.info = info;
+       event.data = &blank;
+       fb_notifier_call_chain(FB_EVENT_CONBLANK, &event);
 }
 
 static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
index 818fb09105f9885829a392e776a9baa8e548c492..40c80c8190e2f744dfc43e3f99fb08189a0c303e 100644 (file)
@@ -59,7 +59,7 @@ struct fb_info *framebuffer_alloc(size_t size, struct device *dev)
        info->device = dev;
 
 #ifdef CONFIG_FB_BACKLIGHT
-       mutex_init(&info->bl_mutex);
+       mutex_init(&info->bl_curve_mutex);
 #endif
 
        return info;
@@ -445,10 +445,10 @@ static ssize_t store_bl_curve(struct device *device,
        /* If there has been an error in the input data, we won't
         * reach this loop.
         */
-       mutex_lock(&fb_info->bl_mutex);
+       mutex_lock(&fb_info->bl_curve_mutex);
        for (i = 0; i < FB_BACKLIGHT_LEVELS; ++i)
                fb_info->bl_curve[i] = tmp_curve[i];
-       mutex_unlock(&fb_info->bl_mutex);
+       mutex_unlock(&fb_info->bl_curve_mutex);
 
        return count;
 }
@@ -466,7 +466,7 @@ static ssize_t show_bl_curve(struct device *device,
        if (!fb_info || !fb_info->bl_dev)
                return -ENODEV;
 
-       mutex_lock(&fb_info->bl_mutex);
+       mutex_lock(&fb_info->bl_curve_mutex);
        for (i = 0; i < FB_BACKLIGHT_LEVELS; i += 8)
                len += snprintf(&buf[len], PAGE_SIZE,
                                "%02x %02x %02x %02x %02x %02x %02x %02x\n",
@@ -478,7 +478,7 @@ static ssize_t show_bl_curve(struct device *device,
                                fb_info->bl_curve[i + 5],
                                fb_info->bl_curve[i + 6],
                                fb_info->bl_curve[i + 7]);
-       mutex_unlock(&fb_info->bl_mutex);
+       mutex_unlock(&fb_info->bl_curve_mutex);
 
        return len;
 }
@@ -552,6 +552,8 @@ void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max)
 {
        unsigned int i, flat, count, range = (max - min);
 
+       mutex_lock(&fb_info->bl_curve_mutex);
+
        fb_info->bl_curve[0] = off;
 
        for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat)
@@ -560,6 +562,8 @@ void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max)
        count = FB_BACKLIGHT_LEVELS * 15 / 16;
        for (i = 0; i < count; ++i)
                fb_info->bl_curve[flat + i] = min + (range * (i + 1) / count);
+
+       mutex_unlock(&fb_info->bl_curve_mutex);
 }
 EXPORT_SYMBOL_GPL(fb_bl_default_curve);
 #endif
index ab1b8fe34d6db9921d67ab966de098750df96d29..7e760197cf29a9932e6533641da3919fc597ca51 100644 (file)
@@ -142,7 +142,7 @@ static int hsync2     __devinitdata;
 static int vsync1     __devinitdata;
 static int vsync2     __devinitdata;
 static int xres       __devinitdata;
-static int yres       __devinitdata;
+static int yres;
 static int vyres      __devinitdata;
 static int sync       __devinitdata;
 static int extvga     __devinitdata;
index df934bd218994882e9dda27457ef8575890e274d..43f62d8ee41d8e3f0417c75757ffd1864e881bfb 100644 (file)
 #include <linux/backlight.h>
 #include <linux/fb.h>
 #include <linux/pci.h>
-#include "nv_local.h"
-#include "nv_type.h"
-#include "nv_proto.h"
 
 #ifdef CONFIG_PMAC_BACKLIGHT
 #include <asm/backlight.h>
-#include <asm/machdep.h>
 #endif
 
+#include "nv_local.h"
+#include "nv_type.h"
+#include "nv_proto.h"
+
 /* We do not have any information about which values are allowed, thus
  * we used safe values.
  */
@@ -28,9 +28,6 @@
 #define MAX_LEVEL 0x534
 #define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX)
 
-static struct backlight_properties nvidia_bl_data;
-
-/* Call with fb_info->bl_mutex held */
 static int nvidia_bl_get_level_brightness(struct nvidia_par *par,
                int level)
 {
@@ -38,6 +35,7 @@ static int nvidia_bl_get_level_brightness(struct nvidia_par *par,
        int nlevel;
 
        /* Get and convert the value */
+       /* No locking of bl_curve since we read a single value */
        nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP;
 
        if (nlevel < 0)
@@ -50,8 +48,7 @@ static int nvidia_bl_get_level_brightness(struct nvidia_par *par,
        return nlevel;
 }
 
-/* Call with fb_info->bl_mutex held */
-static int __nvidia_bl_update_status(struct backlight_device *bd)
+static int nvidia_bl_update_status(struct backlight_device *bd)
 {
        struct nvidia_par *par = class_get_devdata(&bd->class_dev);
        u32 tmp_pcrt, tmp_pmc, fpcontrol;
@@ -60,11 +57,11 @@ static int __nvidia_bl_update_status(struct backlight_device *bd)
        if (!par->FlatPanel)
                return 0;
 
-       if (bd->props->power != FB_BLANK_UNBLANK ||
-           bd->props->fb_blank != FB_BLANK_UNBLANK)
+       if (bd->props.power != FB_BLANK_UNBLANK ||
+           bd->props.fb_blank != FB_BLANK_UNBLANK)
                level = 0;
        else
-               level = bd->props->brightness;
+               level = bd->props.brightness;
 
        tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF;
        tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC;
@@ -85,45 +82,16 @@ static int __nvidia_bl_update_status(struct backlight_device *bd)
        return 0;
 }
 
-static int nvidia_bl_update_status(struct backlight_device *bd)
-{
-       struct nvidia_par *par = class_get_devdata(&bd->class_dev);
-       struct fb_info *info = pci_get_drvdata(par->pci_dev);
-       int ret;
-
-       mutex_lock(&info->bl_mutex);
-       ret = __nvidia_bl_update_status(bd);
-       mutex_unlock(&info->bl_mutex);
-
-       return ret;
-}
-
 static int nvidia_bl_get_brightness(struct backlight_device *bd)
 {
-       return bd->props->brightness;
+       return bd->props.brightness;
 }
 
-static struct backlight_properties nvidia_bl_data = {
-       .owner          = THIS_MODULE,
+static struct backlight_ops nvidia_bl_ops = {
        .get_brightness = nvidia_bl_get_brightness,
        .update_status  = nvidia_bl_update_status,
-       .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
 };
 
-void nvidia_bl_set_power(struct fb_info *info, int power)
-{
-       mutex_lock(&info->bl_mutex);
-
-       if (info->bl_dev) {
-               down(&info->bl_dev->sem);
-               info->bl_dev->props->power = power;
-               __nvidia_bl_update_status(info->bl_dev);
-               up(&info->bl_dev->sem);
-       }
-
-       mutex_unlock(&info->bl_mutex);
-}
-
 void nvidia_bl_init(struct nvidia_par *par)
 {
        struct fb_info *info = pci_get_drvdata(par->pci_dev);
@@ -141,32 +109,22 @@ void nvidia_bl_init(struct nvidia_par *par)
 
        snprintf(name, sizeof(name), "nvidiabl%d", info->node);
 
-       bd = backlight_device_register(name, info->dev, par, &nvidia_bl_data);
+       bd = backlight_device_register(name, info->dev, par, &nvidia_bl_ops);
        if (IS_ERR(bd)) {
                info->bl_dev = NULL;
                printk(KERN_WARNING "nvidia: Backlight registration failed\n");
                goto error;
        }
 
-       mutex_lock(&info->bl_mutex);
        info->bl_dev = bd;
        fb_bl_default_curve(info, 0,
                0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL,
                0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL);
-       mutex_unlock(&info->bl_mutex);
 
-       down(&bd->sem);
-       bd->props->brightness = nvidia_bl_data.max_brightness;
-       bd->props->power = FB_BLANK_UNBLANK;
-       bd->props->update_status(bd);
-       up(&bd->sem);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-       mutex_lock(&pmac_backlight_mutex);
-       if (!pmac_backlight)
-               pmac_backlight = bd;
-       mutex_unlock(&pmac_backlight_mutex);
-#endif
+       bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+       bd->props.brightness = bd->props.max_brightness;
+       bd->props.power = FB_BLANK_UNBLANK;
+       backlight_update_status(bd);
 
        printk("nvidia: Backlight initialized (%s)\n", name);
 
@@ -179,25 +137,8 @@ error:
 void nvidia_bl_exit(struct nvidia_par *par)
 {
        struct fb_info *info = pci_get_drvdata(par->pci_dev);
+       struct backlight_device *bd = info->bl_dev;
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-       mutex_lock(&pmac_backlight_mutex);
-#endif
-
-       mutex_lock(&info->bl_mutex);
-       if (info->bl_dev) {
-#ifdef CONFIG_PMAC_BACKLIGHT
-               if (pmac_backlight == info->bl_dev)
-                       pmac_backlight = NULL;
-#endif
-
-               backlight_device_unregister(info->bl_dev);
-
-               printk("nvidia: Backlight unloaded\n");
-       }
-       mutex_unlock(&info->bl_mutex);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-       mutex_unlock(&pmac_backlight_mutex);
-#endif
+       backlight_device_unregister(bd);
+       printk("nvidia: Backlight unloaded\n");
 }
index 43058d0cf5b7b86a47961dacd2da8a77708d89f1..ff5c410355ea46d9d853ecb3a7479c32a9d9cc66 100644 (file)
@@ -67,11 +67,9 @@ extern int nvidiafb_sync(struct fb_info *info);
 #ifdef CONFIG_FB_NVIDIA_BACKLIGHT
 extern void nvidia_bl_init(struct nvidia_par *par);
 extern void nvidia_bl_exit(struct nvidia_par *par);
-extern void nvidia_bl_set_power(struct fb_info *info, int power);
 #else
 static inline void nvidia_bl_init(struct nvidia_par *par) {}
 static inline void nvidia_bl_exit(struct nvidia_par *par) {}
-static inline void nvidia_bl_set_power(struct fb_info *info, int power) {}
 #endif
 
 #endif                         /* __NV_PROTO_H__ */
index 8e5b484db6498253fceaea43d818a13cbaa6970f..b97ec6901263ab02bef1fd4e77bb8c390b91f2f5 100644 (file)
@@ -83,6 +83,11 @@ static int bpp __devinitdata = 8;
 #ifdef CONFIG_MTRR
 static int nomtrr __devinitdata = 0;
 #endif
+#ifdef CONFIG_PMAC_BACKLIGHT
+static int backlight __devinitdata = 1;
+#else
+static int backlight __devinitdata = 0;
+#endif
 
 static char *mode_option __devinitdata = NULL;
 
@@ -938,8 +943,6 @@ static int nvidiafb_blank(int blank, struct fb_info *info)
        NVWriteSeq(par, 0x01, tmp);
        NVWriteCrtc(par, 0x1a, vesa);
 
-       nvidia_bl_set_power(info, blank);
-
        NVTRACE_LEAVE();
 
        return 0;
@@ -1313,7 +1316,10 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
        nvidia_save_vga(par, &par->SavedReg);
 
        pci_set_drvdata(pd, info);
-       nvidia_bl_init(par);
+
+       if (backlight)
+               nvidia_bl_init(par);
+
        if (register_framebuffer(info) < 0) {
                printk(KERN_ERR PFX "error registering nVidia framebuffer\n");
                goto err_out_iounmap_fb;
@@ -1352,9 +1358,10 @@ static void __devexit nvidiafb_remove(struct pci_dev *pd)
 
        NVTRACE_ENTER();
 
+       unregister_framebuffer(info);
+
        nvidia_bl_exit(par);
 
-       unregister_framebuffer(info);
 #ifdef CONFIG_MTRR
        if (par->mtrr.vram_valid)
                mtrr_del(par->mtrr.vram, info->fix.smem_start,
@@ -1409,6 +1416,8 @@ static int __devinit nvidiafb_setup(char *options)
                        paneltweak = simple_strtoul(this_opt+11, NULL, 0);
                } else if (!strncmp(this_opt, "vram:", 5)) {
                        vram = simple_strtoul(this_opt+5, NULL, 0);
+               } else if (!strncmp(this_opt, "backlight:", 10)) {
+                       backlight = simple_strtoul(this_opt+10, NULL, 0);
 #ifdef CONFIG_MTRR
                } else if (!strncmp(this_opt, "nomtrr", 6)) {
                        nomtrr = 1;
index f2e9b742c92fe812471d72b3a607039268d51145..1d1c7c624d7f04be2c854741fdac775e6674d7bf 100644 (file)
@@ -215,6 +215,11 @@ static int noaccel   __devinitdata = 0;
 #ifdef CONFIG_MTRR
 static int nomtrr __devinitdata = 0;
 #endif
+#ifdef CONFIG_PMAC_BACKLIGHT
+static int backlight __devinitdata = 1;
+#else
+static int backlight __devinitdata = 0;
+#endif
 
 static char *mode_option __devinitdata = NULL;
 static int  strictmode       = 0;
@@ -282,7 +287,6 @@ static const struct riva_regs reg_template = {
 
 static struct backlight_properties riva_bl_data;
 
-/* Call with fb_info->bl_mutex held */
 static int riva_bl_get_level_brightness(struct riva_par *par,
                int level)
 {
@@ -290,6 +294,7 @@ static int riva_bl_get_level_brightness(struct riva_par *par,
        int nlevel;
 
        /* Get and convert the value */
+       /* No locking on bl_curve since accessing a single value */
        nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP;
 
        if (nlevel < 0)
@@ -302,18 +307,17 @@ static int riva_bl_get_level_brightness(struct riva_par *par,
        return nlevel;
 }
 
-/* Call with fb_info->bl_mutex held */
-static int __riva_bl_update_status(struct backlight_device *bd)
+static int riva_bl_update_status(struct backlight_device *bd)
 {
        struct riva_par *par = class_get_devdata(&bd->class_dev);
        U032 tmp_pcrt, tmp_pmc;
        int level;
 
-       if (bd->props->power != FB_BLANK_UNBLANK ||
-           bd->props->fb_blank != FB_BLANK_UNBLANK)
+       if (bd->props.power != FB_BLANK_UNBLANK ||
+           bd->props.fb_blank != FB_BLANK_UNBLANK)
                level = 0;
        else
-               level = bd->props->brightness;
+               level = bd->props.brightness;
 
        tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF;
        tmp_pcrt = par->riva.PCRTC0[0x081C/4] & 0xFFFFFFFC;
@@ -328,45 +332,16 @@ static int __riva_bl_update_status(struct backlight_device *bd)
        return 0;
 }
 
-static int riva_bl_update_status(struct backlight_device *bd)
-{
-       struct riva_par *par = class_get_devdata(&bd->class_dev);
-       struct fb_info *info = pci_get_drvdata(par->pdev);
-       int ret;
-
-       mutex_lock(&info->bl_mutex);
-       ret = __riva_bl_update_status(bd);
-       mutex_unlock(&info->bl_mutex);
-
-       return ret;
-}
-
 static int riva_bl_get_brightness(struct backlight_device *bd)
 {
-       return bd->props->brightness;
+       return bd->props.brightness;
 }
 
-static struct backlight_properties riva_bl_data = {
-       .owner    = THIS_MODULE,
+static struct backlight_ops riva_bl_ops = {
        .get_brightness = riva_bl_get_brightness,
        .update_status  = riva_bl_update_status,
-       .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
 };
 
-static void riva_bl_set_power(struct fb_info *info, int power)
-{
-       mutex_lock(&info->bl_mutex);
-
-       if (info->bl_dev) {
-               down(&info->bl_dev->sem);
-               info->bl_dev->props->power = power;
-               __riva_bl_update_status(info->bl_dev);
-               up(&info->bl_dev->sem);
-       }
-
-       mutex_unlock(&info->bl_mutex);
-}
-
 static void riva_bl_init(struct riva_par *par)
 {
        struct fb_info *info = pci_get_drvdata(par->pdev);
@@ -384,32 +359,22 @@ static void riva_bl_init(struct riva_par *par)
 
        snprintf(name, sizeof(name), "rivabl%d", info->node);
 
-       bd = backlight_device_register(name, info->dev, par, &riva_bl_data);
+       bd = backlight_device_register(name, info->dev, par, &riva_bl_ops);
        if (IS_ERR(bd)) {
                info->bl_dev = NULL;
                printk(KERN_WARNING "riva: Backlight registration failed\n");
                goto error;
        }
 
-       mutex_lock(&info->bl_mutex);
        info->bl_dev = bd;
        fb_bl_default_curve(info, 0,
                MIN_LEVEL * FB_BACKLIGHT_MAX / MAX_LEVEL,
                FB_BACKLIGHT_MAX);
-       mutex_unlock(&info->bl_mutex);
 
-       down(&bd->sem);
-       bd->props->brightness = riva_bl_data.max_brightness;
-       bd->props->power = FB_BLANK_UNBLANK;
-       bd->props->update_status(bd);
-       up(&bd->sem);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-       mutex_lock(&pmac_backlight_mutex);
-       if (!pmac_backlight)
-               pmac_backlight = bd;
-       mutex_unlock(&pmac_backlight_mutex);
-#endif
+       bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+       bd->props.brightness = riva_bl_data.max_brightness;
+       bd->props.power = FB_BLANK_UNBLANK;
+       backlight_update_status(bd);
 
        printk("riva: Backlight initialized (%s)\n", name);
 
@@ -419,35 +384,16 @@ error:
        return;
 }
 
-static void riva_bl_exit(struct riva_par *par)
+static void riva_bl_exit(struct fb_info *info)
 {
-       struct fb_info *info = pci_get_drvdata(par->pdev);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-       mutex_lock(&pmac_backlight_mutex);
-#endif
-
-       mutex_lock(&info->bl_mutex);
-       if (info->bl_dev) {
-#ifdef CONFIG_PMAC_BACKLIGHT
-               if (pmac_backlight == info->bl_dev)
-                       pmac_backlight = NULL;
-#endif
-
-               backlight_device_unregister(info->bl_dev);
+       struct backlight_device *bd = info->bl_dev;
 
-               printk("riva: Backlight unloaded\n");
-       }
-       mutex_unlock(&info->bl_mutex);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-       mutex_unlock(&pmac_backlight_mutex);
-#endif
+       backlight_device_unregister(bd);
+       printk("riva: Backlight unloaded\n");
 }
 #else
 static inline void riva_bl_init(struct riva_par *par) {}
-static inline void riva_bl_exit(struct riva_par *par) {}
-static inline void riva_bl_set_power(struct fb_info *info, int power) {}
+static inline void riva_bl_exit(struct fb_info *info) {}
 #endif /* CONFIG_FB_RIVA_BACKLIGHT */
 
 /* ------------------------------------------------------------------------- *
@@ -1348,8 +1294,6 @@ static int rivafb_blank(int blank, struct fb_info *info)
        SEQout(par, 0x01, tmp);
        CRTCout(par, 0x1a, vesa);
 
-       riva_bl_set_power(info, blank);
-
        NVTRACE_LEAVE();
 
        return 0;
@@ -2120,7 +2064,10 @@ static int __devinit rivafb_probe(struct pci_dev *pd,
        info->monspecs.modedb = NULL;
 
        pci_set_drvdata(pd, info);
-       riva_bl_init(info->par);
+
+       if (backlight)
+               riva_bl_init(info->par);
+
        ret = register_framebuffer(info);
        if (ret < 0) {
                printk(KERN_ERR PFX
@@ -2166,14 +2113,15 @@ static void __exit rivafb_remove(struct pci_dev *pd)
        
        NVTRACE_ENTER();
 
-       riva_bl_exit(par);
-
 #ifdef CONFIG_FB_RIVA_I2C
        riva_delete_i2c_busses(par);
        kfree(par->EDID);
 #endif
 
        unregister_framebuffer(info);
+
+       riva_bl_exit(info);
+
 #ifdef CONFIG_MTRR
        if (par->mtrr.vram_valid)
                mtrr_del(par->mtrr.vram, info->fix.smem_start,
@@ -2217,6 +2165,8 @@ static int __init rivafb_setup(char *options)
                                forceCRTC = -1;
                } else if (!strncmp(this_opt, "flatpanel", 9)) {
                        flatpanel = 1;
+               } else if (!strncmp(this_opt, "backlight:", 10)) {
+                       backlight = simple_strtoul(this_opt+10, NULL, 0);
 #ifdef CONFIG_MTRR
                } else if (!strncmp(this_opt, "nomtrr", 6)) {
                        nomtrr = 1;
index 3162c37b1447f32223b7c79005263e1f325aa3f8..98919a6975f04b10ccec1219335dd60a2970d61e 100644 (file)
@@ -1134,11 +1134,11 @@ static int  __init s3fb_setup(char *options)
                if (!*opt)
                        continue;
 #ifdef CONFIG_MTRR
-               else if (!strcmp(opt, "mtrr:"))
+               else if (!strncmp(opt, "mtrr:", 5))
                        mtrr = simple_strtoul(opt + 5, NULL, 0);
 #endif
-               else if (!strcmp(opt, "fasttext:"))
-                       mtrr = simple_strtoul(opt + 9, NULL, 0);
+               else if (!strncmp(opt, "fasttext:", 9))
+                       fasttext = simple_strtoul(opt + 9, NULL, 0);
                else
                        mode = opt;
        }
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
new file mode 100644 (file)
index 0000000..0a44c44
--- /dev/null
@@ -0,0 +1,1786 @@
+/* linux/drivers/video/sm501fb.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *     Vincent Sanders <vince@simtec.co.uk>
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * 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.
+ *
+ * Framebuffer driver for the Silicon Motion SM501
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/wait.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/div64.h>
+
+#ifdef CONFIG_PM
+#include <linux/pm.h>
+#endif
+
+#include <linux/sm501.h>
+#include <linux/sm501-regs.h>
+
+#define NR_PALETTE     256
+
+enum sm501_controller {
+       HEAD_CRT        = 0,
+       HEAD_PANEL      = 1,
+};
+
+/* SM501 memory adress */
+struct sm501_mem {
+       unsigned long    size;
+       unsigned long    sm_addr;
+       void __iomem    *k_addr;
+};
+
+/* private data that is shared between all frambuffers* */
+struct sm501fb_info {
+       struct device           *dev;
+       struct fb_info          *fb[2];         /* fb info for both heads */
+       struct resource         *fbmem_res;     /* framebuffer resource */
+       struct resource         *regs_res;      /* registers resource */
+       struct sm501_platdata_fb *pdata;        /* our platform data */
+
+       int                      irq;
+       int                      swap_endian;   /* set to swap rgb=>bgr */
+       void __iomem            *regs;          /* remapped registers */
+       void __iomem            *fbmem;         /* remapped framebuffer */
+       size_t                   fbmem_len;     /* length of remapped region */
+};
+
+/* per-framebuffer private data */
+struct sm501fb_par {
+       u32                      pseudo_palette[16];
+
+       enum sm501_controller    head;
+       struct sm501_mem         cursor;
+       struct sm501_mem         screen;
+       struct fb_ops            ops;
+
+       void                    *store_fb;
+       void                    *store_cursor;
+       void __iomem            *cursor_regs;
+       struct sm501fb_info     *info;
+};
+
+/* Helper functions */
+
+static inline int h_total(struct fb_var_screeninfo *var)
+{
+       return var->xres + var->left_margin +
+               var->right_margin + var->hsync_len;
+}
+
+static inline int v_total(struct fb_var_screeninfo *var)
+{
+       return var->yres + var->upper_margin +
+               var->lower_margin + var->vsync_len;
+}
+
+/* sm501fb_sync_regs()
+ *
+ * This call is mainly for PCI bus systems where we need to
+ * ensure that any writes to the bus are completed before the
+ * next phase, or after completing a function.
+*/
+
+static inline void sm501fb_sync_regs(struct sm501fb_info *info)
+{
+       readl(info->regs);
+}
+
+/* sm501_alloc_mem
+ *
+ * This is an attempt to lay out memory for the two framebuffers and
+ * everything else
+ *
+ * |fbmem_res->start                                          fbmem_res->end|
+ * |                                                                         |
+ * |fb[0].fix.smem_start    |         |fb[1].fix.smem_start    |     2K      |
+ * |-> fb[0].fix.smem_len <-| spare   |-> fb[1].fix.smem_len <-|-> cursors <-|
+ *
+ * The "spare" space is for the 2d engine data
+ * the fixed is space for the cursors (2x1Kbyte)
+ *
+ * we need to allocate memory for the 2D acceleration engine
+ * command list and the data for the engine to deal with.
+ *
+ * - all allocations must be 128bit aligned
+ * - cursors are 64x64x2 bits (1Kbyte)
+ *
+ */
+
+#define SM501_MEMF_CURSOR              (1)
+#define SM501_MEMF_PANEL               (2)
+#define SM501_MEMF_CRT                 (4)
+#define SM501_MEMF_ACCEL               (8)
+
+static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem,
+                          unsigned int why, size_t size)
+{
+       unsigned int ptr = 0;
+
+       switch (why) {
+       case SM501_MEMF_CURSOR:
+               ptr = inf->fbmem_len - size;
+               inf->fbmem_len = ptr;
+               break;
+
+       case SM501_MEMF_PANEL:
+               ptr = inf->fbmem_len - size;
+               if (ptr < inf->fb[0]->fix.smem_len)
+                       return -ENOMEM;
+
+               break;
+
+       case SM501_MEMF_CRT:
+               ptr = 0;
+               break;
+
+       case SM501_MEMF_ACCEL:
+               ptr = inf->fb[0]->fix.smem_len;
+
+               if ((ptr + size) >
+                   (inf->fb[1]->fix.smem_start - inf->fbmem_res->start))
+                       return -ENOMEM;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       mem->size    = size;
+       mem->sm_addr = ptr;
+       mem->k_addr  = inf->fbmem + ptr;
+
+       dev_dbg(inf->dev, "%s: result %08lx, %p - %u, %zd\n",
+               __func__, mem->sm_addr, mem->k_addr, why, size);
+
+       return 0;
+}
+
+/* sm501fb_ps_to_hz
+ *
+ * Converts a period in picoseconds to Hz.
+ *
+ * Note, we try to keep this in Hz to minimise rounding with
+ * the limited PLL settings on the SM501.
+*/
+
+static unsigned long sm501fb_ps_to_hz(unsigned long psvalue)
+{
+       unsigned long long numerator=1000000000000ULL;
+
+       /* 10^12 / picosecond period gives frequency in Hz */
+       do_div(numerator, psvalue);
+       return (unsigned long)numerator;
+}
+
+/* sm501fb_hz_to_ps is identical to the oposite transform */
+
+#define sm501fb_hz_to_ps(x) sm501fb_ps_to_hz(x)
+
+/* sm501fb_setup_gamma
+ *
+ * Programs a linear 1.0 gamma ramp in case the gamma
+ * correction is enabled without programming anything else.
+*/
+
+static void sm501fb_setup_gamma(struct sm501fb_info *fbi,
+                               unsigned long palette)
+{
+       unsigned long value = 0;
+       int offset;
+
+       /* set gamma values */
+       for (offset = 0; offset < 256 * 4; offset += 4) {
+               writel(value, fbi->regs + palette + offset);
+               value += 0x010101;      /* Advance RGB by 1,1,1.*/
+       }
+}
+
+/* sm501fb_check_var
+ *
+ * check common variables for both panel and crt
+*/
+
+static int sm501fb_check_var(struct fb_var_screeninfo *var,
+                            struct fb_info *info)
+{
+       struct sm501fb_par  *par = info->par;
+       struct sm501fb_info *sm  = par->info;
+       unsigned long tmp;
+
+       /* check we can fit these values into the registers */
+
+       if (var->hsync_len > 255 || var->vsync_len > 255)
+               return -EINVAL;
+
+       if ((var->xres + var->right_margin) >= 4096)
+               return -EINVAL;
+
+       if ((var->yres + var->lower_margin) > 2048)
+               return -EINVAL;
+
+       /* hard limits of device */
+
+       if (h_total(var) > 4096 || v_total(var) > 2048)
+               return -EINVAL;
+
+       /* check our line length is going to be 128 bit aligned */
+
+       tmp = (var->xres * var->bits_per_pixel) / 8;
+       if ((tmp & 15) != 0)
+               return -EINVAL;
+
+       /* check the virtual size */
+
+       if (var->xres_virtual > 4096 || var->yres_virtual > 2048)
+               return -EINVAL;
+
+       /* can cope with 8,16 or 32bpp */
+
+       if (var->bits_per_pixel <= 8)
+               var->bits_per_pixel = 8;
+       else if (var->bits_per_pixel <= 16)
+               var->bits_per_pixel = 16;
+       else if (var->bits_per_pixel == 24)
+               var->bits_per_pixel = 32;
+
+       /* set r/g/b positions and validate bpp */
+       switch(var->bits_per_pixel) {
+       case 8:
+               var->red.length         = var->bits_per_pixel;
+               var->red.offset         = 0;
+               var->green.length       = var->bits_per_pixel;
+               var->green.offset       = 0;
+               var->blue.length        = var->bits_per_pixel;
+               var->blue.offset        = 0;
+               var->transp.length      = 0;
+
+               break;
+
+       case 16:
+               if (sm->pdata->flags & SM501_FBPD_SWAP_FB_ENDIAN) {
+                       var->red.offset         = 11;
+                       var->green.offset       = 5;
+                       var->blue.offset        = 0;
+               } else {
+                       var->blue.offset        = 11;
+                       var->green.offset       = 5;
+                       var->red.offset         = 0;
+               }
+
+               var->red.length         = 5;
+               var->green.length       = 6;
+               var->blue.length        = 5;
+               var->transp.length      = 0;
+               break;
+
+       case 32:
+               if (sm->pdata->flags & SM501_FBPD_SWAP_FB_ENDIAN) {
+                       var->transp.offset      = 0;
+                       var->red.offset         = 8;
+                       var->green.offset       = 16;
+                       var->blue.offset        = 24;
+               } else {
+                       var->transp.offset      = 24;
+                       var->red.offset         = 16;
+                       var->green.offset       = 8;
+                       var->blue.offset        = 0;
+               }
+
+               var->red.length         = 8;
+               var->green.length       = 8;
+               var->blue.length        = 8;
+               var->transp.length      = 0;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/*
+ * sm501fb_check_var_crt():
+ *
+ * check the parameters for the CRT head, and either bring them
+ * back into range, or return -EINVAL.
+*/
+
+static int sm501fb_check_var_crt(struct fb_var_screeninfo *var,
+                                struct fb_info *info)
+{
+       return sm501fb_check_var(var, info);
+}
+
+/* sm501fb_check_var_pnl():
+ *
+ * check the parameters for the CRT head, and either bring them
+ * back into range, or return -EINVAL.
+*/
+
+static int sm501fb_check_var_pnl(struct fb_var_screeninfo *var,
+                                struct fb_info *info)
+{
+       return sm501fb_check_var(var, info);
+}
+
+/* sm501fb_set_par_common
+ *
+ * set common registers for framebuffers
+*/
+
+static int sm501fb_set_par_common(struct fb_info *info,
+                                 struct fb_var_screeninfo *var)
+{
+       struct sm501fb_par  *par = info->par;
+       struct sm501fb_info *fbi = par->info;
+       unsigned long pixclock;      /* pixelclock in Hz */
+       unsigned long sm501pixclock; /* pixelclock the 501 can achive in Hz */
+       unsigned int mem_type;
+       unsigned int clock_type;
+       unsigned int head_addr;
+
+       dev_dbg(fbi->dev, "%s: %dx%d, bpp = %d, virtual %dx%d\n",
+               __func__, var->xres, var->yres, var->bits_per_pixel,
+               var->xres_virtual, var->yres_virtual);
+
+       switch (par->head) {
+       case HEAD_CRT:
+               mem_type = SM501_MEMF_CRT;
+               clock_type = SM501_CLOCK_V2XCLK;
+               head_addr = SM501_DC_CRT_FB_ADDR;
+               break;
+
+       case HEAD_PANEL:
+               mem_type = SM501_MEMF_PANEL;
+               clock_type = SM501_CLOCK_P2XCLK;
+               head_addr = SM501_DC_PANEL_FB_ADDR;
+               break;
+
+       default:
+               mem_type = 0;           /* stop compiler warnings */
+               head_addr = 0;
+               clock_type = 0;
+       }
+
+       switch (var->bits_per_pixel) {
+       case 8:
+               info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+               break;
+
+       case 16:
+               info->fix.visual = FB_VISUAL_DIRECTCOLOR;
+               break;
+
+       case 32:
+               info->fix.visual = FB_VISUAL_TRUECOLOR;
+               break;
+       }
+
+       /* allocate fb memory within 501 */
+       info->fix.line_length = (var->xres_virtual * var->bits_per_pixel)/8;
+       info->fix.smem_len    = info->fix.line_length * var->yres_virtual;
+
+       dev_dbg(fbi->dev, "%s: line length = %u\n", __func__,
+               info->fix.line_length);
+
+       if (sm501_alloc_mem(fbi, &par->screen, mem_type,
+                           info->fix.smem_len)) {
+               dev_err(fbi->dev, "no memory available\n");
+               return -ENOMEM;
+       }
+
+       info->fix.smem_start = fbi->fbmem_res->start + par->screen.sm_addr;
+
+       info->screen_base = fbi->fbmem + par->screen.sm_addr;
+       info->screen_size = info->fix.smem_len;
+
+       /* set start of framebuffer to the screen */
+
+       writel(par->screen.sm_addr | SM501_ADDR_FLIP, fbi->regs + head_addr);
+
+       /* program CRT clock  */
+
+       pixclock = sm501fb_ps_to_hz(var->pixclock);
+
+       sm501pixclock = sm501_set_clock(fbi->dev->parent, clock_type,
+                                       pixclock);
+
+       /* update fb layer with actual clock used */
+       var->pixclock = sm501fb_hz_to_ps(sm501pixclock);
+
+       dev_dbg(fbi->dev, "%s: pixclock(ps) = %u, pixclock(Hz)  = %lu, "
+              "sm501pixclock = %lu,  error = %ld%%\n",
+              __func__, var->pixclock, pixclock, sm501pixclock,
+              ((pixclock - sm501pixclock)*100)/pixclock);
+
+       return 0;
+}
+
+/* sm501fb_set_par_geometry
+ *
+ * set the geometry registers for specified framebuffer.
+*/
+
+static void sm501fb_set_par_geometry(struct fb_info *info,
+                                    struct fb_var_screeninfo *var)
+{
+       struct sm501fb_par  *par = info->par;
+       struct sm501fb_info *fbi = par->info;
+       void __iomem *base = fbi->regs;
+       unsigned long reg;
+
+       if (par->head == HEAD_CRT)
+               base += SM501_DC_CRT_H_TOT;
+       else
+               base += SM501_DC_PANEL_H_TOT;
+
+       /* set framebuffer width and display width */
+
+       reg = info->fix.line_length;
+       reg |= ((var->xres * var->bits_per_pixel)/8) << 16;
+
+       writel(reg, fbi->regs + (par->head == HEAD_CRT ?
+                   SM501_DC_CRT_FB_OFFSET :  SM501_DC_PANEL_FB_OFFSET));
+
+       /* program horizontal total */
+
+       reg  = (h_total(var) - 1) << 16;
+       reg |= (var->xres - 1);
+
+       writel(reg, base + SM501_OFF_DC_H_TOT);
+
+       /* program horizontal sync */
+
+       reg  = var->hsync_len << 16;
+       reg |= var->xres + var->right_margin - 1;
+
+       writel(reg, base + SM501_OFF_DC_H_SYNC);
+
+       /* program vertical total */
+
+       reg  = (v_total(var) - 1) << 16;
+       reg |= (var->yres - 1);
+
+       writel(reg, base + SM501_OFF_DC_V_TOT);
+
+       /* program vertical sync */
+       reg  = var->vsync_len << 16;
+       reg |= var->yres + var->lower_margin - 1;
+
+       writel(reg, base + SM501_OFF_DC_V_SYNC);
+}
+
+/* sm501fb_pan_crt
+ *
+ * pan the CRT display output within an virtual framebuffer
+*/
+
+static int sm501fb_pan_crt(struct fb_var_screeninfo *var,
+                          struct fb_info *info)
+{
+       struct sm501fb_par  *par = info->par;
+       struct sm501fb_info *fbi = par->info;
+       unsigned int bytes_pixel = var->bits_per_pixel / 8;
+       unsigned long reg;
+       unsigned long xoffs;
+
+       xoffs = var->xoffset * bytes_pixel;
+
+       reg = readl(fbi->regs + SM501_DC_CRT_CONTROL);
+
+       reg &= ~SM501_DC_CRT_CONTROL_PIXEL_MASK;
+       reg |= ((xoffs & 15) / bytes_pixel) << 4;
+       writel(reg, fbi->regs + SM501_DC_CRT_CONTROL);
+
+       reg = (par->screen.sm_addr + xoffs +
+              var->yoffset * info->fix.line_length);
+       writel(reg | SM501_ADDR_FLIP, fbi->regs + SM501_DC_CRT_FB_ADDR);
+
+       sm501fb_sync_regs(fbi);
+       return 0;
+}
+
+/* sm501fb_pan_pnl
+ *
+ * pan the panel display output within an virtual framebuffer
+*/
+
+static int sm501fb_pan_pnl(struct fb_var_screeninfo *var,
+                          struct fb_info *info)
+{
+       struct sm501fb_par  *par = info->par;
+       struct sm501fb_info *fbi = par->info;
+       unsigned long reg;
+
+       reg = var->xoffset | (var->xres_virtual << 16);
+       writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH);
+
+       reg = var->yoffset | (var->yres_virtual << 16);
+       writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT);
+
+       sm501fb_sync_regs(fbi);
+       return 0;
+}
+
+/* sm501fb_set_par_crt
+ *
+ * Set the CRT video mode from the fb_info structure
+*/
+
+static int sm501fb_set_par_crt(struct fb_info *info)
+{
+       struct sm501fb_par  *par = info->par;
+       struct sm501fb_info *fbi = par->info;
+       struct fb_var_screeninfo *var = &info->var;
+       unsigned long control;       /* control register */
+       int ret;
+
+       /* activate new configuration */
+
+       dev_dbg(fbi->dev, "%s(%p)\n", __func__, info);
+
+       /* enable CRT DAC - note 0 is on!*/
+       sm501_misc_control(fbi->dev->parent, 0, SM501_MISC_DAC_POWER);
+
+       control = readl(fbi->regs + SM501_DC_CRT_CONTROL);
+
+       control &= (SM501_DC_CRT_CONTROL_PIXEL_MASK |
+                   SM501_DC_CRT_CONTROL_GAMMA |
+                   SM501_DC_CRT_CONTROL_BLANK |
+                   SM501_DC_CRT_CONTROL_SEL |
+                   SM501_DC_CRT_CONTROL_CP |
+                   SM501_DC_CRT_CONTROL_TVP);
+
+       /* set the sync polarities before we check data source  */
+
+       if ((var->sync & FB_SYNC_HOR_HIGH_ACT) == 0)
+               control |= SM501_DC_CRT_CONTROL_HSP;
+
+       if ((var->sync & FB_SYNC_VERT_HIGH_ACT) == 0)
+               control |= SM501_DC_CRT_CONTROL_VSP;
+
+       if ((control & SM501_DC_CRT_CONTROL_SEL) == 0) {
+               /* the head is displaying panel data... */
+
+               sm501_alloc_mem(fbi, &par->screen, SM501_MEMF_CRT, 0);
+               goto out_update;
+       }
+
+       ret = sm501fb_set_par_common(info, var);
+       if (ret) {
+               dev_err(fbi->dev, "failed to set common parameters\n");
+               return ret;
+       }
+
+       sm501fb_pan_crt(var, info);
+       sm501fb_set_par_geometry(info, var);
+
+       control |= SM501_FIFO_3;        /* fill if >3 free slots */
+
+       switch(var->bits_per_pixel) {
+       case 8:
+               control |= SM501_DC_CRT_CONTROL_8BPP;
+               break;
+
+       case 16:
+               control |= SM501_DC_CRT_CONTROL_16BPP;
+               break;
+
+       case 32:
+               control |= SM501_DC_CRT_CONTROL_32BPP;
+               sm501fb_setup_gamma(fbi, SM501_DC_CRT_PALETTE);
+               break;
+
+       default:
+               BUG();
+       }
+
+       control |= SM501_DC_CRT_CONTROL_SEL;    /* CRT displays CRT data */
+       control |= SM501_DC_CRT_CONTROL_TE;     /* enable CRT timing */
+       control |= SM501_DC_CRT_CONTROL_ENABLE; /* enable CRT plane */
+
+ out_update:
+       dev_dbg(fbi->dev, "new control is %08lx\n", control);
+
+       writel(control, fbi->regs + SM501_DC_CRT_CONTROL);
+       sm501fb_sync_regs(fbi);
+
+       return 0;
+}
+
+static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
+{
+       unsigned long control;
+       void __iomem *ctrl_reg = fbi->regs + SM501_DC_PANEL_CONTROL;
+
+       control = readl(ctrl_reg);
+
+       if (to && (control & SM501_DC_PANEL_CONTROL_VDD) == 0) {
+               /* enable panel power */
+
+               control |= SM501_DC_PANEL_CONTROL_VDD;  /* FPVDDEN */
+               writel(control, ctrl_reg);
+               sm501fb_sync_regs(fbi);
+               mdelay(10);
+
+               control |= SM501_DC_PANEL_CONTROL_DATA; /* DATA */
+               writel(control, ctrl_reg);
+               sm501fb_sync_regs(fbi);
+               mdelay(10);
+
+               control |= SM501_DC_PANEL_CONTROL_BIAS; /* VBIASEN */
+               writel(control, ctrl_reg);
+               sm501fb_sync_regs(fbi);
+               mdelay(10);
+
+               control |= SM501_DC_PANEL_CONTROL_FPEN;
+               writel(control, ctrl_reg);
+
+       } else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) {
+               /* disable panel power */
+
+               control &= ~SM501_DC_PANEL_CONTROL_FPEN;
+               writel(control, ctrl_reg);
+               sm501fb_sync_regs(fbi);
+               mdelay(10);
+
+               control &= ~SM501_DC_PANEL_CONTROL_BIAS;
+               writel(control, ctrl_reg);
+               sm501fb_sync_regs(fbi);
+               mdelay(10);
+
+               control &= ~SM501_DC_PANEL_CONTROL_DATA;
+               writel(control, ctrl_reg);
+               sm501fb_sync_regs(fbi);
+               mdelay(10);
+
+               control &= ~SM501_DC_PANEL_CONTROL_VDD;
+               writel(control, ctrl_reg);
+               sm501fb_sync_regs(fbi);
+               mdelay(10);
+       }
+
+       sm501fb_sync_regs(fbi);
+}
+
+/* sm501fb_set_par_pnl
+ *
+ * Set the panel video mode from the fb_info structure
+*/
+
+static int sm501fb_set_par_pnl(struct fb_info *info)
+{
+       struct sm501fb_par  *par = info->par;
+       struct sm501fb_info *fbi = par->info;
+       struct fb_var_screeninfo *var = &info->var;
+       unsigned long control;
+       unsigned long reg;
+       int ret;
+
+       dev_dbg(fbi->dev, "%s(%p)\n", __func__, info);
+
+       /* activate this new configuration */
+
+       ret = sm501fb_set_par_common(info, var);
+       if (ret)
+               return ret;
+
+       sm501fb_pan_pnl(var, info);
+       sm501fb_set_par_geometry(info, var);
+
+       /* update control register */
+
+       control = readl(fbi->regs + SM501_DC_PANEL_CONTROL);
+       control &= (SM501_DC_PANEL_CONTROL_GAMMA |
+                   SM501_DC_PANEL_CONTROL_VDD  |
+                   SM501_DC_PANEL_CONTROL_DATA |
+                   SM501_DC_PANEL_CONTROL_BIAS |
+                   SM501_DC_PANEL_CONTROL_FPEN |
+                   SM501_DC_PANEL_CONTROL_CP |
+                   SM501_DC_PANEL_CONTROL_CK |
+                   SM501_DC_PANEL_CONTROL_HP |
+                   SM501_DC_PANEL_CONTROL_VP |
+                   SM501_DC_PANEL_CONTROL_HPD |
+                   SM501_DC_PANEL_CONTROL_VPD);
+
+       control |= SM501_FIFO_3;        /* fill if >3 free slots */
+
+       switch(var->bits_per_pixel) {
+       case 8:
+               control |= SM501_DC_PANEL_CONTROL_8BPP;
+               break;
+
+       case 16:
+               control |= SM501_DC_PANEL_CONTROL_16BPP;
+               break;
+
+       case 32:
+               control |= SM501_DC_PANEL_CONTROL_32BPP;
+               sm501fb_setup_gamma(fbi, SM501_DC_PANEL_PALETTE);
+               break;
+
+       default:
+               BUG();
+       }
+
+       writel(0x0, fbi->regs + SM501_DC_PANEL_PANNING_CONTROL);
+
+       /* panel plane top left and bottom right location */
+
+       writel(0x00, fbi->regs + SM501_DC_PANEL_TL_LOC);
+
+       reg  = var->xres - 1;
+       reg |= (var->yres - 1) << 16;
+
+       writel(reg, fbi->regs + SM501_DC_PANEL_BR_LOC);
+
+       /* program panel control register */
+
+       control |= SM501_DC_PANEL_CONTROL_TE;   /* enable PANEL timing */
+       control |= SM501_DC_PANEL_CONTROL_EN;   /* enable PANEL gfx plane */
+
+       if ((var->sync & FB_SYNC_HOR_HIGH_ACT) == 0)
+               control |= SM501_DC_PANEL_CONTROL_HSP;
+
+       if ((var->sync & FB_SYNC_VERT_HIGH_ACT) == 0)
+               control |= SM501_DC_PANEL_CONTROL_VSP;
+
+       writel(control, fbi->regs + SM501_DC_PANEL_CONTROL);
+       sm501fb_sync_regs(fbi);
+
+       /* power the panel up */
+       sm501fb_panel_power(fbi, 1);
+       return 0;
+}
+
+
+/* chan_to_field
+ *
+ * convert a colour value into a field position
+ *
+ * from pxafb.c
+*/
+
+static inline unsigned int chan_to_field(unsigned int chan,
+                                        struct fb_bitfield *bf)
+{
+       chan &= 0xffff;
+       chan >>= 16 - bf->length;
+       return chan << bf->offset;
+}
+
+/* sm501fb_setcolreg
+ *
+ * set the colour mapping for modes that support palettised data
+*/
+
+static int sm501fb_setcolreg(unsigned regno,
+                            unsigned red, unsigned green, unsigned blue,
+                            unsigned transp, struct fb_info *info)
+{
+       struct sm501fb_par  *par = info->par;
+       struct sm501fb_info *fbi = par->info;
+       void __iomem *base = fbi->regs;
+       unsigned int val;
+
+       if (par->head == HEAD_CRT)
+               base += SM501_DC_CRT_PALETTE;
+       else
+               base += SM501_DC_PANEL_PALETTE;
+
+       switch (info->fix.visual) {
+       case FB_VISUAL_TRUECOLOR:
+               /* true-colour, use pseuo-palette */
+
+               if (regno < 16) {
+                       u32 *pal = par->pseudo_palette;
+
+                       val  = chan_to_field(red,   &info->var.red);
+                       val |= chan_to_field(green, &info->var.green);
+                       val |= chan_to_field(blue,  &info->var.blue);
+
+                       pal[regno] = val;
+               }
+               break;
+
+       case FB_VISUAL_PSEUDOCOLOR:
+               if (regno < 256) {
+                       val = (red >> 8) << 16;
+                       val |= (green >> 8) << 8;
+                       val |= blue >> 8;
+
+                       writel(val, base + (regno * 4));
+               }
+
+               break;
+
+       default:
+               return 1;   /* unknown type */
+       }
+
+       return 0;
+}
+
+/* sm501fb_blank_pnl
+ *
+ * Blank or un-blank the panel interface
+*/
+
+static int sm501fb_blank_pnl(int blank_mode, struct fb_info *info)
+{
+       struct sm501fb_par  *par = info->par;
+       struct sm501fb_info *fbi = par->info;
+
+       dev_dbg(fbi->dev, "%s(mode=%d, %p)\n", __func__, blank_mode, info);
+
+       switch (blank_mode) {
+       case FB_BLANK_POWERDOWN:
+               sm501fb_panel_power(fbi, 0);
+               break;
+
+       case FB_BLANK_UNBLANK:
+               sm501fb_panel_power(fbi, 1);
+               break;
+
+       case FB_BLANK_NORMAL:
+       case FB_BLANK_VSYNC_SUSPEND:
+       case FB_BLANK_HSYNC_SUSPEND:
+       default:
+               return 1;
+       }
+
+       return 0;
+}
+
+/* sm501fb_blank_crt
+ *
+ * Blank or un-blank the crt interface
+*/
+
+static int sm501fb_blank_crt(int blank_mode, struct fb_info *info)
+{
+       struct sm501fb_par  *par = info->par;
+       struct sm501fb_info *fbi = par->info;
+       unsigned long ctrl;
+
+       dev_dbg(fbi->dev, "%s(mode=%d, %p)\n", __func__, blank_mode, info);
+
+       ctrl = readl(fbi->regs + SM501_DC_CRT_CONTROL);
+
+       switch (blank_mode) {
+       case FB_BLANK_POWERDOWN:
+               ctrl &= ~SM501_DC_CRT_CONTROL_ENABLE;
+               sm501_misc_control(fbi->dev->parent, SM501_MISC_DAC_POWER, 0);
+
+       case FB_BLANK_NORMAL:
+               ctrl |= SM501_DC_CRT_CONTROL_BLANK;
+               break;
+
+       case FB_BLANK_UNBLANK:
+               ctrl &= ~SM501_DC_CRT_CONTROL_BLANK;
+               ctrl |=  SM501_DC_CRT_CONTROL_ENABLE;
+               sm501_misc_control(fbi->dev->parent, 0, SM501_MISC_DAC_POWER);
+               break;
+
+       case FB_BLANK_VSYNC_SUSPEND:
+       case FB_BLANK_HSYNC_SUSPEND:
+       default:
+               return 1;
+
+       }
+
+       writel(ctrl, fbi->regs + SM501_DC_CRT_CONTROL);
+       sm501fb_sync_regs(fbi);
+
+       return 0;
+}
+
+/* sm501fb_cursor
+ *
+ * set or change the hardware cursor parameters
+*/
+
+static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+       struct sm501fb_par  *par = info->par;
+       struct sm501fb_info *fbi = par->info;
+       void __iomem *base = fbi->regs;
+       unsigned long hwc_addr;
+       unsigned long fg, bg;
+
+       dev_dbg(fbi->dev, "%s(%p,%p)\n", __func__, info, cursor);
+
+       if (par->head == HEAD_CRT)
+               base += SM501_DC_CRT_HWC_BASE;
+       else
+               base += SM501_DC_PANEL_HWC_BASE;
+
+       /* check not being asked to exceed capabilities */
+
+       if (cursor->image.width > 64)
+               return -EINVAL;
+
+       if (cursor->image.height > 64)
+               return -EINVAL;
+
+       if (cursor->image.depth > 1)
+               return -EINVAL;
+
+       hwc_addr = readl(base + SM501_OFF_HWC_ADDR);
+
+       if (cursor->enable)
+               writel(hwc_addr | SM501_HWC_EN, base + SM501_OFF_HWC_ADDR);
+       else
+               writel(hwc_addr & ~SM501_HWC_EN, base + SM501_OFF_HWC_ADDR);
+
+       /* set data */
+       if (cursor->set & FB_CUR_SETPOS) {
+               unsigned int x = cursor->image.dx;
+               unsigned int y = cursor->image.dy;
+
+               if (x >= 2048 || y >= 2048 )
+                       return -EINVAL;
+
+               dev_dbg(fbi->dev, "set position %d,%d\n", x, y);
+
+               //y += cursor->image.height;
+
+               writel(x | (y << 16), base + SM501_OFF_HWC_LOC);
+       }
+
+       if (cursor->set & FB_CUR_SETCMAP) {
+               unsigned int bg_col = cursor->image.bg_color;
+               unsigned int fg_col = cursor->image.fg_color;
+
+               dev_dbg(fbi->dev, "%s: update cmap (%08x,%08x)\n",
+                       __func__, bg_col, fg_col);
+
+               bg = ((info->cmap.red[bg_col] & 0xF8) << 8) |
+                       ((info->cmap.green[bg_col] & 0xFC) << 3) |
+                       ((info->cmap.blue[bg_col] & 0xF8) >> 3);
+
+               fg = ((info->cmap.red[fg_col] & 0xF8) << 8) |
+                       ((info->cmap.green[fg_col] & 0xFC) << 3) |
+                       ((info->cmap.blue[fg_col] & 0xF8) >> 3);
+
+               dev_dbg(fbi->dev, "fgcol %08x, bgcol %08x\n", fg, bg);
+
+               writel(bg, base + SM501_OFF_HWC_COLOR_1_2);
+               writel(fg, base + SM501_OFF_HWC_COLOR_3);
+       }
+
+       if (cursor->set & FB_CUR_SETSIZE ||
+           cursor->set & (FB_CUR_SETIMAGE | FB_CUR_SETSHAPE)) {
+               /* SM501 cursor is a two bpp 64x64 bitmap this routine
+                * clears it to transparent then combines the cursor
+                * shape plane with the colour plane to set the
+                * cursor */
+               int x, y;
+               const unsigned char *pcol = cursor->image.data;
+               const unsigned char *pmsk = cursor->mask;
+               void __iomem   *dst = par->cursor.k_addr;
+               unsigned char  dcol = 0;
+               unsigned char  dmsk = 0;
+               unsigned int   op;
+
+               dev_dbg(fbi->dev, "%s: setting shape (%d,%d)\n",
+                       __func__, cursor->image.width, cursor->image.height);
+
+               for (op = 0; op < (64*64*2)/8; op+=4)
+                       writel(0x0, dst + op);
+
+               for (y = 0; y < cursor->image.height; y++) {
+                       for (x = 0; x < cursor->image.width; x++) {
+                               if ((x % 8) == 0) {
+                                       dcol = *pcol++;
+                                       dmsk = *pmsk++;
+                               } else {
+                                       dcol >>= 1;
+                                       dmsk >>= 1;
+                               }
+
+                               if (dmsk & 1) {
+                                       op = (dcol & 1) ? 1 : 3;
+                                       op <<= ((x % 4) * 2);
+
+                                       op |= readb(dst + (x / 4));
+                                       writeb(op, dst + (x / 4));
+                               }
+                       }
+                       dst += (64*2)/8;
+               }
+       }
+
+       sm501fb_sync_regs(fbi); /* ensure cursor data flushed */
+       return 0;
+}
+
+/* sm501fb_crtsrc_show
+ *
+ * device attribute code to show where the crt output is sourced from
+*/
+
+static ssize_t sm501fb_crtsrc_show(struct device *dev,
+                              struct device_attribute *attr, char *buf)
+{
+       struct sm501fb_info *info = dev_get_drvdata(dev);
+       unsigned long ctrl;
+
+       ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+       ctrl &= SM501_DC_CRT_CONTROL_SEL;
+
+       return snprintf(buf, PAGE_SIZE, "%s\n", ctrl ? "crt" : "panel");
+}
+
+/* sm501fb_crtsrc_show
+ *
+ * device attribute code to set where the crt output is sourced from
+*/
+
+static ssize_t sm501fb_crtsrc_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t len)
+{
+       struct sm501fb_info *info = dev_get_drvdata(dev);
+       enum sm501_controller head;
+       unsigned long ctrl;
+
+       if (len < 1)
+               return -EINVAL;
+
+       if (strnicmp(buf, "crt", 3) == 0)
+               head = HEAD_CRT;
+       else if (strnicmp(buf, "panel", 5) == 0)
+               head = HEAD_PANEL;
+       else
+               return -EINVAL;
+
+       dev_info(dev, "setting crt source to head %d\n", head);
+
+       ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+
+       if (head == HEAD_CRT) {
+               ctrl |= SM501_DC_CRT_CONTROL_SEL;
+               ctrl |= SM501_DC_CRT_CONTROL_ENABLE;
+               ctrl |= SM501_DC_CRT_CONTROL_TE;
+       } else {
+               ctrl &= ~SM501_DC_CRT_CONTROL_SEL;
+               ctrl &= ~SM501_DC_CRT_CONTROL_ENABLE;
+               ctrl &= ~SM501_DC_CRT_CONTROL_TE;
+       }
+
+       writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
+       sm501fb_sync_regs(info);
+
+       return len;
+}
+
+/* Prepare the device_attr for registration with sysfs later */
+static DEVICE_ATTR(crt_src, 0666, sm501fb_crtsrc_show, sm501fb_crtsrc_store);
+
+/* sm501fb_show_regs
+ *
+ * show the primary sm501 registers
+*/
+static int sm501fb_show_regs(struct sm501fb_info *info, char *ptr,
+                            unsigned int start, unsigned int len)
+{
+       void __iomem *mem = info->regs;
+       char *buf = ptr;
+       unsigned int reg;
+
+       for (reg = start; reg < (len + start); reg += 4)
+               ptr += sprintf(ptr, "%08x = %08x\n", reg, readl(mem + reg));
+
+       return ptr - buf;
+}
+
+/* sm501fb_debug_show_crt
+ *
+ * show the crt control and cursor registers
+*/
+
+static ssize_t sm501fb_debug_show_crt(struct device *dev,
+                                 struct device_attribute *attr, char *buf)
+{
+       struct sm501fb_info *info = dev_get_drvdata(dev);
+       char *ptr = buf;
+
+       ptr += sm501fb_show_regs(info, ptr, SM501_DC_CRT_CONTROL, 0x40);
+       ptr += sm501fb_show_regs(info, ptr, SM501_DC_CRT_HWC_BASE, 0x10);
+
+       return ptr - buf;
+}
+
+static DEVICE_ATTR(fbregs_crt, 0444, sm501fb_debug_show_crt, NULL);
+
+/* sm501fb_debug_show_pnl
+ *
+ * show the panel control and cursor registers
+*/
+
+static ssize_t sm501fb_debug_show_pnl(struct device *dev,
+                                 struct device_attribute *attr, char *buf)
+{
+       struct sm501fb_info *info = dev_get_drvdata(dev);
+       char *ptr = buf;
+
+       ptr += sm501fb_show_regs(info, ptr, 0x0, 0x40);
+       ptr += sm501fb_show_regs(info, ptr, SM501_DC_PANEL_HWC_BASE, 0x10);
+
+       return ptr - buf;
+}
+
+static DEVICE_ATTR(fbregs_pnl, 0444, sm501fb_debug_show_pnl, NULL);
+
+/* framebuffer ops */
+
+static struct fb_ops sm501fb_ops_crt = {
+       .owner          = THIS_MODULE,
+       .fb_check_var   = sm501fb_check_var_crt,
+       .fb_set_par     = sm501fb_set_par_crt,
+       .fb_blank       = sm501fb_blank_crt,
+       .fb_setcolreg   = sm501fb_setcolreg,
+       .fb_pan_display = sm501fb_pan_crt,
+       .fb_cursor      = sm501fb_cursor,
+       .fb_fillrect    = cfb_fillrect,
+       .fb_copyarea    = cfb_copyarea,
+       .fb_imageblit   = cfb_imageblit,
+};
+
+static struct fb_ops sm501fb_ops_pnl = {
+       .owner          = THIS_MODULE,
+       .fb_check_var   = sm501fb_check_var_pnl,
+       .fb_set_par     = sm501fb_set_par_pnl,
+       .fb_pan_display = sm501fb_pan_pnl,
+       .fb_blank       = sm501fb_blank_pnl,
+       .fb_setcolreg   = sm501fb_setcolreg,
+       .fb_cursor      = sm501fb_cursor,
+       .fb_fillrect    = cfb_fillrect,
+       .fb_copyarea    = cfb_copyarea,
+       .fb_imageblit   = cfb_imageblit,
+};
+
+/* sm501fb_info_alloc
+ *
+ * creates and initialises an sm501fb_info structure
+*/
+
+static struct sm501fb_info *sm501fb_info_alloc(struct fb_info *fbinfo_crt,
+                                              struct fb_info *fbinfo_pnl)
+{
+       struct sm501fb_info *info;
+       struct sm501fb_par  *par;
+
+       info = kzalloc(sizeof(struct sm501fb_info), GFP_KERNEL);
+       if (info) {
+               /* set the references back */
+
+               par = fbinfo_crt->par;
+               par->info = info;
+               par->head = HEAD_CRT;
+               fbinfo_crt->pseudo_palette = &par->pseudo_palette;
+
+               par = fbinfo_pnl->par;
+               par->info = info;
+               par->head = HEAD_PANEL;
+               fbinfo_pnl->pseudo_palette = &par->pseudo_palette;
+
+               /* store the two fbs into our info */
+               info->fb[HEAD_CRT] = fbinfo_crt;
+               info->fb[HEAD_PANEL] = fbinfo_pnl;
+       }
+
+       return info;
+}
+
+/* sm501_init_cursor
+ *
+ * initialise hw cursor parameters
+*/
+
+static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base)
+{
+       struct sm501fb_par *par = fbi->par;
+       struct sm501fb_info *info = par->info;
+       int ret;
+
+       par->cursor_regs = info->regs + reg_base;
+
+       ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024);
+       if (ret < 0)
+               return ret;
+
+       /* initialise the colour registers */
+
+       writel(par->cursor.sm_addr, par->cursor_regs + SM501_OFF_HWC_ADDR);
+
+       writel(0x00, par->cursor_regs + SM501_OFF_HWC_LOC);
+       writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_1_2);
+       writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_3);
+       sm501fb_sync_regs(info);
+
+       return 0;
+}
+
+/* sm501fb_info_start
+ *
+ * fills the par structure claiming resources and remapping etc.
+*/
+
+static int sm501fb_start(struct sm501fb_info *info,
+                        struct platform_device *pdev)
+{
+       struct resource *res;
+       struct device *dev;
+       int ret;
+
+       info->dev = dev = &pdev->dev;
+       platform_set_drvdata(pdev, info);
+
+       info->irq = ret = platform_get_irq(pdev, 0);
+       if (ret < 0) {
+               /* we currently do not use the IRQ */
+               dev_warn(dev, "no irq for device\n");
+       }
+
+       /* allocate, reserve and remap resources for registers */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(dev, "no resource definition for registers\n");
+               ret = -ENOENT;
+               goto err_release;
+       }
+
+       info->regs_res = request_mem_region(res->start,
+                                           res->end - res->start,
+                                           pdev->name);
+
+       if (info->regs_res == NULL) {
+               dev_err(dev, "cannot claim registers\n");
+               ret = -ENXIO;
+               goto err_release;
+       }
+
+       info->regs = ioremap(res->start, (res->end - res->start)+1);
+       if (info->regs == NULL) {
+               dev_err(dev, "cannot remap registers\n");
+               ret = -ENXIO;
+               goto err_regs_res;
+       }
+
+       /* allocate, reserve resources for framebuffer */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+       if (res == NULL) {
+               dev_err(dev, "no memory resource defined\n");
+               ret = -ENXIO;
+               goto err_regs_map;
+       }
+
+       info->fbmem_res = request_mem_region(res->start,
+                                            (res->end - res->start)+1,
+                                            pdev->name);
+       if (info->fbmem_res == NULL) {
+               dev_err(dev, "cannot claim framebuffer\n");
+               ret = -ENXIO;
+               goto err_regs_map;
+       }
+
+       info->fbmem = ioremap(res->start, (res->end - res->start)+1);
+       if (info->fbmem == NULL) {
+               dev_err(dev, "cannot remap framebuffer\n");
+               goto err_mem_res;
+       }
+
+       info->fbmem_len = (res->end - res->start)+1;
+
+       /* enable display controller */
+       sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1);
+
+       /* setup cursors */
+
+       sm501_init_cursor(info->fb[HEAD_CRT], SM501_DC_CRT_HWC_ADDR);
+       sm501_init_cursor(info->fb[HEAD_PANEL], SM501_DC_PANEL_HWC_ADDR);
+
+       return 0; /* everything is setup */
+
+ err_mem_res:
+       release_resource(info->fbmem_res);
+       kfree(info->fbmem_res);
+
+ err_regs_map:
+       iounmap(info->regs);
+
+ err_regs_res:
+       release_resource(info->regs_res);
+       kfree(info->regs_res);
+
+ err_release:
+       return ret;
+}
+
+static void sm501fb_stop(struct sm501fb_info *info)
+{
+       /* disable display controller */
+       sm501_unit_power(info->dev->parent, SM501_GATE_DISPLAY, 0);
+
+       iounmap(info->fbmem);
+       release_resource(info->fbmem_res);
+       kfree(info->fbmem_res);
+
+       iounmap(info->regs);
+       release_resource(info->regs_res);
+       kfree(info->regs_res);
+}
+
+static void sm501fb_info_release(struct sm501fb_info *info)
+{
+       kfree(info);
+}
+
+static int sm501fb_init_fb(struct fb_info *fb,
+                          enum sm501_controller head,
+                          const char *fbname)
+{
+       struct sm501_platdata_fbsub *pd;
+       struct sm501fb_par *par = fb->par;
+       struct sm501fb_info *info = par->info;
+       unsigned long ctrl;
+       unsigned int enable;
+       int ret;
+
+       switch (head) {
+       case HEAD_CRT:
+               pd = info->pdata->fb_crt;
+               ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+               enable = (ctrl & SM501_DC_CRT_CONTROL_ENABLE) ? 1 : 0;
+
+               /* ensure we set the correct source register */
+               if (info->pdata->fb_route != SM501_FB_CRT_PANEL) {
+                       ctrl |= SM501_DC_CRT_CONTROL_SEL;
+                       writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
+               }
+
+               break;
+
+       case HEAD_PANEL:
+               pd = info->pdata->fb_pnl;
+               ctrl = readl(info->regs + SM501_DC_PANEL_CONTROL);
+               enable = (ctrl & SM501_DC_PANEL_CONTROL_EN) ? 1 : 0;
+               break;
+
+       default:
+               pd = NULL;              /* stop compiler warnings */
+               ctrl = 0;
+               enable = 0;
+               BUG();
+       }
+
+       dev_info(info->dev, "fb %s %sabled at start\n",
+                fbname, enable ? "en" : "dis");
+
+       /* check to see if our routing allows this */
+
+       if (head == HEAD_CRT && info->pdata->fb_route == SM501_FB_CRT_PANEL) {
+               ctrl &= ~SM501_DC_CRT_CONTROL_SEL;
+               writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
+               enable = 0;
+       }
+
+       strlcpy(fb->fix.id, fbname, sizeof(fb->fix.id));
+
+       memcpy(&par->ops,
+              (head == HEAD_CRT) ? &sm501fb_ops_crt : &sm501fb_ops_pnl,
+              sizeof(struct fb_ops));
+
+       /* update ops dependant on what we've been passed */
+
+       if ((pd->flags & SM501FB_FLAG_USE_HWCURSOR) == 0)
+               par->ops.fb_cursor = NULL;
+
+       fb->fbops = &par->ops;
+       fb->flags = FBINFO_FLAG_DEFAULT |
+               FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
+
+       /* fixed data */
+
+       fb->fix.type            = FB_TYPE_PACKED_PIXELS;
+       fb->fix.type_aux        = 0;
+       fb->fix.xpanstep        = 1;
+       fb->fix.ypanstep        = 1;
+       fb->fix.ywrapstep       = 0;
+       fb->fix.accel           = FB_ACCEL_NONE;
+
+       /* screenmode */
+
+       fb->var.nonstd          = 0;
+       fb->var.activate        = FB_ACTIVATE_NOW;
+       fb->var.accel_flags     = 0;
+       fb->var.vmode           = FB_VMODE_NONINTERLACED;
+       fb->var.bits_per_pixel  = 16;
+
+       if (enable && (pd->flags & SM501FB_FLAG_USE_INIT_MODE) && 0) {
+               /* TODO read the mode from the current display */
+
+       } else {
+               if (pd->def_mode) {
+                       dev_info(info->dev, "using supplied mode\n");
+                       fb_videomode_to_var(&fb->var, pd->def_mode);
+
+                       fb->var.bits_per_pixel = pd->def_bpp ? pd->def_bpp : 8;
+                       fb->var.xres_virtual = fb->var.xres;
+                       fb->var.yres_virtual = fb->var.yres;
+               } else {
+                       ret = fb_find_mode(&fb->var, fb,
+                                          NULL, NULL, 0, NULL, 8);
+
+                       if (ret == 0 || ret == 4) {
+                               dev_err(info->dev,
+                                       "failed to get initial mode\n");
+                               return -EINVAL;
+                       }
+               }
+       }
+
+       /* initialise and set the palette */
+       fb_alloc_cmap(&fb->cmap, NR_PALETTE, 0);
+       fb_set_cmap(&fb->cmap, fb);
+
+       ret = (fb->fbops->fb_check_var)(&fb->var, fb);
+       if (ret)
+               dev_err(info->dev, "check_var() failed on initial setup?\n");
+
+       /* ensure we've activated our new configuration */
+       (fb->fbops->fb_set_par)(fb);
+
+       return 0;
+}
+
+/* default platform data if none is supplied (ie, PCI device) */
+
+static struct sm501_platdata_fbsub sm501fb_pdata_crt = {
+       .flags          = (SM501FB_FLAG_USE_INIT_MODE |
+                          SM501FB_FLAG_USE_HWCURSOR |
+                          SM501FB_FLAG_USE_HWACCEL |
+                          SM501FB_FLAG_DISABLE_AT_EXIT),
+
+};
+
+static struct sm501_platdata_fbsub sm501fb_pdata_pnl = {
+       .flags          = (SM501FB_FLAG_USE_INIT_MODE |
+                          SM501FB_FLAG_USE_HWCURSOR |
+                          SM501FB_FLAG_USE_HWACCEL |
+                          SM501FB_FLAG_DISABLE_AT_EXIT),
+};
+
+static struct sm501_platdata_fb sm501fb_def_pdata = {
+       .fb_route               = SM501_FB_OWN,
+       .fb_crt                 = &sm501fb_pdata_crt,
+       .fb_pnl                 = &sm501fb_pdata_pnl,
+};
+
+static char driver_name_crt[] = "sm501fb-crt";
+static char driver_name_pnl[] = "sm501fb-panel";
+
+static int __init sm501fb_probe(struct platform_device *pdev)
+{
+       struct sm501fb_info *info;
+       struct device       *dev = &pdev->dev;
+       struct fb_info      *fbinfo_crt;
+       struct fb_info      *fbinfo_pnl;
+       int                  ret;
+
+       /* allocate our framebuffers */
+
+       fbinfo_crt = framebuffer_alloc(sizeof(struct sm501fb_par), dev);
+       if (fbinfo_crt == NULL) {
+               dev_err(dev, "cannot allocate crt framebuffer\n");
+               return -ENOMEM;
+       }
+
+       fbinfo_pnl = framebuffer_alloc(sizeof(struct sm501fb_par), dev);
+       if (fbinfo_pnl == NULL) {
+               dev_err(dev, "cannot allocate panel framebuffer\n");
+               ret = -ENOMEM;
+               goto fbinfo_crt_alloc_fail;
+       }
+
+       info = sm501fb_info_alloc(fbinfo_crt, fbinfo_pnl);
+       if (info == NULL) {
+               dev_err(dev, "cannot allocate par\n");
+               ret = -ENOMEM;
+               goto sm501fb_alloc_fail;
+       }
+
+       if (dev->parent->platform_data) {
+               struct sm501_platdata *pd = dev->parent->platform_data;
+               info->pdata = pd->fb;
+       }
+
+       if (info->pdata == NULL) {
+               dev_info(dev, "using default configuration data\n");
+               info->pdata = &sm501fb_def_pdata;
+       }
+
+       /* start the framebuffers */
+
+       ret = sm501fb_start(info, pdev);
+       if (ret) {
+               dev_err(dev, "cannot initialise SM501\n");
+               goto sm501fb_start_fail;
+       }
+
+       /* CRT framebuffer setup */
+
+       ret = sm501fb_init_fb(fbinfo_crt, HEAD_CRT, driver_name_crt);
+       if (ret) {
+               dev_err(dev, "cannot initialise CRT fb\n");
+               goto sm501fb_start_fail;
+       }
+
+       /* Panel framebuffer setup */
+
+       ret = sm501fb_init_fb(fbinfo_pnl, HEAD_PANEL, driver_name_pnl);
+       if (ret) {
+               dev_err(dev, "cannot initialise Panel fb\n");
+               goto sm501fb_start_fail;
+       }
+
+       /* register framebuffers */
+
+       ret = register_framebuffer(fbinfo_crt);
+       if (ret < 0) {
+               dev_err(dev, "failed to register CRT fb (%d)\n", ret);
+               goto register_crt_fail;
+       }
+
+       ret = register_framebuffer(fbinfo_pnl);
+       if (ret < 0) {
+               dev_err(dev, "failed to register panel fb (%d)\n", ret);
+               goto register_pnl_fail;
+       }
+
+       dev_info(dev, "fb%d: %s frame buffer device\n",
+                fbinfo_crt->node, fbinfo_crt->fix.id);
+
+       dev_info(dev, "fb%d: %s frame buffer device\n",
+              fbinfo_pnl->node, fbinfo_pnl->fix.id);
+
+       /* create device files */
+
+       ret = device_create_file(dev, &dev_attr_crt_src);
+       if (ret)
+               goto crtsrc_fail;
+
+       ret = device_create_file(dev, &dev_attr_fbregs_pnl);
+       if (ret)
+               goto fbregs_pnl_fail;
+
+       ret = device_create_file(dev, &dev_attr_fbregs_crt);
+       if (ret)
+               goto fbregs_crt_fail;
+
+       /* we registered, return ok */
+       return 0;
+
+ fbregs_crt_fail:
+       device_remove_file(dev, &dev_attr_fbregs_pnl);
+
+ fbregs_pnl_fail:
+       device_remove_file(dev, &dev_attr_crt_src);
+
+ crtsrc_fail:
+       unregister_framebuffer(fbinfo_pnl);
+
+ register_pnl_fail:
+       unregister_framebuffer(fbinfo_crt);
+
+ register_crt_fail:
+       sm501fb_stop(info);
+
+ sm501fb_start_fail:
+       sm501fb_info_release(info);
+
+ sm501fb_alloc_fail:
+       framebuffer_release(fbinfo_pnl);
+
+ fbinfo_crt_alloc_fail:
+       framebuffer_release(fbinfo_crt);
+
+       return ret;
+}
+
+
+/*
+ *  Cleanup
+ */
+static int sm501fb_remove(struct platform_device *pdev)
+{
+       struct sm501fb_info *info = platform_get_drvdata(pdev);
+       struct fb_info     *fbinfo_crt = info->fb[0];
+       struct fb_info     *fbinfo_pnl = info->fb[1];
+
+       device_remove_file(&pdev->dev, &dev_attr_fbregs_crt);
+       device_remove_file(&pdev->dev, &dev_attr_fbregs_pnl);
+       device_remove_file(&pdev->dev, &dev_attr_crt_src);
+
+       unregister_framebuffer(fbinfo_crt);
+       unregister_framebuffer(fbinfo_pnl);
+
+       sm501fb_stop(info);
+       sm501fb_info_release(info);
+
+       framebuffer_release(fbinfo_pnl);
+       framebuffer_release(fbinfo_crt);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int sm501fb_suspend_fb(struct sm501fb_info *info,
+                             enum sm501_controller head)
+{
+       struct fb_info *fbi = info->fb[head];
+       struct sm501fb_par *par = fbi->par;
+
+       if (par->screen.size == 0)
+               return 0;
+
+       /* backup copies in case chip is powered down over suspend */
+
+       par->store_fb = vmalloc(par->screen.size);
+       if (par->store_fb == NULL) {
+               dev_err(info->dev, "no memory to store screen\n");
+               return -ENOMEM;
+       }
+
+       par->store_cursor = vmalloc(par->cursor.size);
+       if (par->store_cursor == NULL) {
+               dev_err(info->dev, "no memory to store cursor\n");
+               goto err_nocursor;
+       }
+
+       memcpy_fromio(par->store_fb, par->screen.k_addr, par->screen.size);
+       memcpy_fromio(par->store_cursor, par->cursor.k_addr, par->cursor.size);
+
+       /* blank the relevant interface to ensure unit power minimised */
+       (par->ops.fb_blank)(FB_BLANK_POWERDOWN, fbi);
+
+       return 0;
+
+ err_nocursor:
+       vfree(par->store_fb);
+
+       return -ENOMEM;
+
+}
+
+static void sm501fb_resume_fb(struct sm501fb_info *info,
+                             enum sm501_controller head)
+{
+       struct fb_info *fbi = info->fb[head];
+       struct sm501fb_par *par = fbi->par;
+
+       if (par->screen.size == 0)
+               return;
+
+       /* re-activate the configuration */
+
+       (par->ops.fb_set_par)(fbi);
+
+       /* restore the data */
+
+       memcpy_toio(par->screen.k_addr, par->store_fb, par->screen.size);
+       memcpy_toio(par->cursor.k_addr, par->store_cursor, par->cursor.size);
+
+       vfree(par->store_fb);
+       vfree(par->store_cursor);
+}
+
+
+/* suspend and resume support */
+
+static int sm501fb_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct sm501fb_info *info = platform_get_drvdata(pdev);
+
+       sm501fb_suspend_fb(info, HEAD_CRT);
+       sm501fb_suspend_fb(info, HEAD_PANEL);
+
+       /* turn off the clocks, in case the device is not powered down */
+       sm501_unit_power(info->dev->parent, SM501_GATE_DISPLAY, 0);
+
+       return 0;
+}
+
+static int sm501fb_resume(struct platform_device *pdev)
+{
+       struct sm501fb_info *info = platform_get_drvdata(pdev);
+
+       sm501_unit_power(info->dev->parent, SM501_GATE_DISPLAY, 1);
+
+       sm501fb_resume_fb(info, HEAD_CRT);
+       sm501fb_resume_fb(info, HEAD_PANEL);
+
+       return 0;
+}
+
+#else
+#define sm501fb_suspend NULL
+#define sm501fb_resume  NULL
+#endif
+
+static struct platform_driver sm501fb_driver = {
+       .probe          = sm501fb_probe,
+       .remove         = sm501fb_remove,
+       .suspend        = sm501fb_suspend,
+       .resume         = sm501fb_resume,
+       .driver         = {
+               .name   = "sm501-fb",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __devinit sm501fb_init(void)
+{
+       return platform_driver_register(&sm501fb_driver);
+}
+
+static void __exit sm501fb_cleanup(void)
+{
+       platform_driver_unregister(&sm501fb_driver);
+}
+
+module_init(sm501fb_init);
+module_exit(sm501fb_cleanup);
+
+MODULE_AUTHOR("Ben Dooks, Vincent Sanders");
+MODULE_DESCRIPTION("SM501 Framebuffer driver");
+MODULE_LICENSE("GPL v2");
index 7db2d287e9f39576c1d18d595988ddc87eb51843..232c694936836f123cecb5f5ab670ffed2d69657 100644 (file)
@@ -171,6 +171,7 @@ extern unsigned long                 affs_parent_ino(struct inode *dir);
 extern struct inode            *affs_new_inode(struct inode *dir);
 extern int                      affs_notify_change(struct dentry *dentry, struct iattr *attr);
 extern void                     affs_put_inode(struct inode *inode);
+extern void                     affs_drop_inode(struct inode *inode);
 extern void                     affs_delete_inode(struct inode *inode);
 extern void                     affs_clear_inode(struct inode *inode);
 extern void                     affs_read_inode(struct inode *inode);
index fce6848a4641a91a4d5341e69f0106ec99d02e36..c5b9d73c084a821dc669d781ddd8c2bc08a4b68e 100644 (file)
@@ -243,12 +243,17 @@ affs_put_inode(struct inode *inode)
 {
        pr_debug("AFFS: put_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink);
        affs_free_prealloc(inode);
-       if (atomic_read(&inode->i_count) == 1) {
-               mutex_lock(&inode->i_mutex);
-               if (inode->i_size != AFFS_I(inode)->mmu_private)
-                       affs_truncate(inode);
-               mutex_unlock(&inode->i_mutex);
-       }
+}
+
+void
+affs_drop_inode(struct inode *inode)
+{
+       mutex_lock(&inode->i_mutex);
+       if (inode->i_size != AFFS_I(inode)->mmu_private)
+               affs_truncate(inode);
+       mutex_unlock(&inode->i_mutex);
+
+       generic_drop_inode(inode);
 }
 
 void
index a324045d8554aed593fd2947c4eaa76ff5b79f7f..c3986a1911b0227e331b03cc2e4018aca282131f 100644 (file)
@@ -118,6 +118,7 @@ static const struct super_operations affs_sops = {
        .read_inode     = affs_read_inode,
        .write_inode    = affs_write_inode,
        .put_inode      = affs_put_inode,
+       .drop_inode     = affs_drop_inode,
        .delete_inode   = affs_delete_inode,
        .clear_inode    = affs_clear_inode,
        .put_super      = affs_put_super,
index 6b4cec3f272ff091a893e85e0ee927459422ef22..d85f42fa92060003b7000f3e686a5070e3da908e 100644 (file)
@@ -52,6 +52,8 @@ struct autofs_info {
 
        int             flags;
 
+       struct list_head rehash;
+
        struct autofs_sb_info *sbi;
        unsigned long last_used;
        atomic_t count;
@@ -110,6 +112,8 @@ struct autofs_sb_info {
        struct mutex wq_mutex;
        spinlock_t fs_lock;
        struct autofs_wait_queue *queues; /* Wait queue pointer */
+       spinlock_t rehash_lock;
+       struct list_head rehash_list;
 };
 
 static inline struct autofs_sb_info *autofs4_sbi(struct super_block *sb)
index 5e458e096ef6a6d845a60158c987b3422f41d2a7..26063dc84a2a623da272a92a5c323058eb63ebb2 100644 (file)
@@ -48,6 +48,8 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino,
        ino->dentry = NULL;
        ino->size = 0;
 
+       INIT_LIST_HEAD(&ino->rehash);
+
        ino->last_used = jiffies;
        atomic_set(&ino->count, 0);
 
@@ -158,14 +160,13 @@ void autofs4_kill_sb(struct super_block *sb)
        if (!sbi)
                goto out_kill_sb;
 
-       sb->s_fs_info = NULL;
-
-       if ( !sbi->catatonic )
+       if (!sbi->catatonic)
                autofs4_catatonic_mode(sbi); /* Free wait queues, close pipe */
 
        /* Clean up and release dangling references */
        autofs4_force_release(sbi);
 
+       sb->s_fs_info = NULL;
        kfree(sbi);
 
 out_kill_sb:
@@ -336,6 +337,8 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
        mutex_init(&sbi->wq_mutex);
        spin_lock_init(&sbi->fs_lock);
        sbi->queues = NULL;
+       spin_lock_init(&sbi->rehash_lock);
+       INIT_LIST_HEAD(&sbi->rehash_list);
        s->s_blocksize = 1024;
        s->s_blocksize_bits = 10;
        s->s_magic = AUTOFS_SUPER_MAGIC;
index 47fee96c21828de22ad5b5c78acfd8bf0e16c611..b4631046867e30a92e2bf5b866d9bc8a05e0c375 100644 (file)
@@ -263,7 +263,7 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags)
                 */
                status = d_invalidate(dentry);
                if (status != -EBUSY)
-                       return -ENOENT;
+                       return -EAGAIN;
        }
 
        DPRINTK("dentry=%p %.*s ino=%p",
@@ -413,7 +413,16 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
                 */
                status = try_to_fill_dentry(dentry, flags);
                if (status == 0)
-                               return 1;
+                       return 1;
+
+               /*
+                * A status of EAGAIN here means that the dentry has gone
+                * away while waiting for an expire to complete. If we are
+                * racing with expire lookup will wait for it so this must
+                * be a revalidate and we need to send it to lookup.
+                */
+               if (status == -EAGAIN)
+                       return 0;
 
                return status;
        }
@@ -459,9 +468,18 @@ void autofs4_dentry_release(struct dentry *de)
        de->d_fsdata = NULL;
 
        if (inf) {
+               struct autofs_sb_info *sbi = autofs4_sbi(de->d_sb);
+
                inf->dentry = NULL;
                inf->inode = NULL;
 
+               if (sbi) {
+                       spin_lock(&sbi->rehash_lock);
+                       if (!list_empty(&inf->rehash))
+                               list_del(&inf->rehash);
+                       spin_unlock(&sbi->rehash_lock);
+               }
+
                autofs4_free_ino(inf);
        }
 }
@@ -478,10 +496,80 @@ static struct dentry_operations autofs4_dentry_operations = {
        .d_release      = autofs4_dentry_release,
 };
 
+static struct dentry *autofs4_lookup_unhashed(struct autofs_sb_info *sbi, struct dentry *parent, struct qstr *name)
+{
+       unsigned int len = name->len;
+       unsigned int hash = name->hash;
+       const unsigned char *str = name->name;
+       struct list_head *p, *head;
+
+       spin_lock(&dcache_lock);
+       spin_lock(&sbi->rehash_lock);
+       head = &sbi->rehash_list;
+       list_for_each(p, head) {
+               struct autofs_info *ino;
+               struct dentry *dentry;
+               struct qstr *qstr;
+
+               ino = list_entry(p, struct autofs_info, rehash);
+               dentry = ino->dentry;
+
+               spin_lock(&dentry->d_lock);
+
+               /* Bad luck, we've already been dentry_iput */
+               if (!dentry->d_inode)
+                       goto next;
+
+               qstr = &dentry->d_name;
+
+               if (dentry->d_name.hash != hash)
+                       goto next;
+               if (dentry->d_parent != parent)
+                       goto next;
+
+               if (qstr->len != len)
+                       goto next;
+               if (memcmp(qstr->name, str, len))
+                       goto next;
+
+               if (d_unhashed(dentry)) {
+                       struct autofs_info *ino = autofs4_dentry_ino(dentry);
+                       struct inode *inode = dentry->d_inode;
+
+                       list_del_init(&ino->rehash);
+                       dget(dentry);
+                       /*
+                        * Make the rehashed dentry negative so the VFS
+                        * behaves as it should.
+                        */
+                       if (inode) {
+                               dentry->d_inode = NULL;
+                               list_del_init(&dentry->d_alias);
+                               spin_unlock(&dentry->d_lock);
+                               spin_unlock(&sbi->rehash_lock);
+                               spin_unlock(&dcache_lock);
+                               iput(inode);
+                               return dentry;
+                       }
+                       spin_unlock(&dentry->d_lock);
+                       spin_unlock(&sbi->rehash_lock);
+                       spin_unlock(&dcache_lock);
+                       return dentry;
+               }
+next:
+               spin_unlock(&dentry->d_lock);
+       }
+       spin_unlock(&sbi->rehash_lock);
+       spin_unlock(&dcache_lock);
+
+       return NULL;
+}
+
 /* Lookups in the root directory */
 static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
        struct autofs_sb_info *sbi;
+       struct dentry *unhashed;
        int oz_mode;
 
        DPRINTK("name = %.*s",
@@ -497,25 +585,46 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
        DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d",
                 current->pid, process_group(current), sbi->catatonic, oz_mode);
 
-       /*
-        * Mark the dentry incomplete, but add it. This is needed so
-        * that the VFS layer knows about the dentry, and we can count
-        * on catching any lookups through the revalidate.
-        *
-        * Let all the hard work be done by the revalidate function that
-        * needs to be able to do this anyway..
-        *
-        * We need to do this before we release the directory semaphore.
-        */
-       dentry->d_op = &autofs4_root_dentry_operations;
+       unhashed = autofs4_lookup_unhashed(sbi, dentry->d_parent, &dentry->d_name);
+       if (!unhashed) {
+               /*
+                * Mark the dentry incomplete, but add it. This is needed so
+                * that the VFS layer knows about the dentry, and we can count
+                * on catching any lookups through the revalidate.
+                *
+                * Let all the hard work be done by the revalidate function that
+                * needs to be able to do this anyway..
+                *
+                * We need to do this before we release the directory semaphore.
+                */
+               dentry->d_op = &autofs4_root_dentry_operations;
+
+               dentry->d_fsdata = NULL;
+               d_add(dentry, NULL);
+       } else {
+               struct autofs_info *ino = autofs4_dentry_ino(unhashed);
+               DPRINTK("rehash %p with %p", dentry, unhashed);
+               /*
+                * If we are racing with expire the request might not
+                * be quite complete but the directory has been removed
+                * so it must have been successful, so just wait for it.
+                */
+               if (ino && (ino->flags & AUTOFS_INF_EXPIRING)) {
+                       DPRINTK("wait for incomplete expire %p name=%.*s",
+                               unhashed, unhashed->d_name.len,
+                               unhashed->d_name.name);
+                       autofs4_wait(sbi, unhashed, NFY_NONE);
+                       DPRINTK("request completed");
+               }
+               d_rehash(unhashed);
+               dentry = unhashed;
+       }
 
        if (!oz_mode) {
                spin_lock(&dentry->d_lock);
                dentry->d_flags |= DCACHE_AUTOFS_PENDING;
                spin_unlock(&dentry->d_lock);
        }
-       dentry->d_fsdata = NULL;
-       d_add(dentry, NULL);
 
        if (dentry->d_op && dentry->d_op->d_revalidate) {
                mutex_unlock(&dir->i_mutex);
@@ -534,6 +643,8 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
                        if (sigismember (sigset, SIGKILL) ||
                            sigismember (sigset, SIGQUIT) ||
                            sigismember (sigset, SIGINT)) {
+                           if (unhashed)
+                               dput(unhashed);
                            return ERR_PTR(-ERESTARTNOINTR);
                        }
                }
@@ -544,12 +655,33 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
 
        /*
         * If this dentry is unhashed, then we shouldn't honour this
-        * lookup even if the dentry is positive.  Returning ENOENT here
-        * doesn't do the right thing for all system calls, but it should
-        * be OK for the operations we permit from an autofs.
+        * lookup.  Returning ENOENT here doesn't do the right thing
+        * for all system calls, but it should be OK for the operations
+        * we permit from an autofs.
         */
-       if (dentry->d_inode && d_unhashed(dentry))
-               return ERR_PTR(-ENOENT);
+       if (dentry->d_inode && d_unhashed(dentry)) {
+               /*
+                * A user space application can (and has done in the past)
+                * remove and re-create this directory during the callback.
+                * This can leave us with an unhashed dentry, but a
+                * successful mount!  So we need to perform another
+                * cached lookup in case the dentry now exists.
+                */
+               struct dentry *parent = dentry->d_parent;
+               struct dentry *new = d_lookup(parent, &dentry->d_name);
+               if (new != NULL)
+                       dentry = new;
+               else
+                       dentry = ERR_PTR(-ENOENT);
+
+               if (unhashed)
+                       dput(unhashed);
+
+               return dentry;
+       }
+
+       if (unhashed)
+               return dentry;
 
        return NULL;
 }
@@ -611,9 +743,10 @@ static int autofs4_dir_symlink(struct inode *dir,
  * Normal filesystems would do a "d_delete()" to tell the VFS dcache
  * that the file no longer exists. However, doing that means that the
  * VFS layer can turn the dentry into a negative dentry.  We don't want
- * this, because since the unlink is probably the result of an expire.
- * We simply d_drop it, which allows the dentry lookup to remount it
- * if necessary.
+ * this, because the unlink is probably the result of an expire.
+ * We simply d_drop it and add it to a rehash candidates list in the
+ * super block, which allows the dentry lookup to reuse it retaining
+ * the flags, such as expire in progress, in case we're racing with expire.
  *
  * If a process is blocked on the dentry waiting for the expire to finish,
  * it will invalidate the dentry and try to mount with a new one.
@@ -642,7 +775,14 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
 
        dir->i_mtime = CURRENT_TIME;
 
-       d_drop(dentry);
+       spin_lock(&dcache_lock);
+       spin_lock(&sbi->rehash_lock);
+       list_add(&ino->rehash, &sbi->rehash_list);
+       spin_unlock(&sbi->rehash_lock);
+       spin_lock(&dentry->d_lock);
+       __d_drop(dentry);
+       spin_unlock(&dentry->d_lock);
+       spin_unlock(&dcache_lock);
 
        return 0;
 }
@@ -653,6 +793,9 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
        struct autofs_info *ino = autofs4_dentry_ino(dentry);
        struct autofs_info *p_ino;
        
+       DPRINTK("dentry %p, removing %.*s",
+               dentry, dentry->d_name.len, dentry->d_name.name);
+
        if (!autofs4_oz_mode(sbi))
                return -EACCES;
 
@@ -661,6 +804,9 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
                spin_unlock(&dcache_lock);
                return -ENOTEMPTY;
        }
+       spin_lock(&sbi->rehash_lock);
+       list_add(&ino->rehash, &sbi->rehash_list);
+       spin_unlock(&sbi->rehash_lock);
        spin_lock(&dentry->d_lock);
        __d_drop(dentry);
        spin_unlock(&dentry->d_lock);
index 1e4a539f4417c3c94a38c844c6a419dea606d709..0d041a9cb348efe59dd71e1d8079e10ae86fa11b 100644 (file)
@@ -84,7 +84,11 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
                                 struct autofs_wait_queue *wq,
                                 int type)
 {
-       union autofs_packet_union pkt;
+       union {
+               struct autofs_packet_hdr hdr;
+               union autofs_packet_union v4_pkt;
+               union autofs_v5_packet_union v5_pkt;
+       } pkt;
        size_t pktsz;
 
        DPRINTK("wait id = 0x%08lx, name = %.*s, type=%d",
@@ -98,7 +102,7 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
        /* Kernel protocol v4 missing and expire packets */
        case autofs_ptype_missing:
        {
-               struct autofs_packet_missing *mp = &pkt.missing;
+               struct autofs_packet_missing *mp = &pkt.v4_pkt.missing;
 
                pktsz = sizeof(*mp);
 
@@ -110,7 +114,7 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
        }
        case autofs_ptype_expire_multi:
        {
-               struct autofs_packet_expire_multi *ep = &pkt.expire_multi;
+               struct autofs_packet_expire_multi *ep = &pkt.v4_pkt.expire_multi;
 
                pktsz = sizeof(*ep);
 
@@ -129,7 +133,7 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
        case autofs_ptype_missing_direct:
        case autofs_ptype_expire_direct:
        {
-               struct autofs_v5_packet *packet = &pkt.v5_packet;
+               struct autofs_v5_packet *packet = &pkt.v5_pkt.v5_packet;
 
                pktsz = sizeof(*packet);
 
index 0c59b703e9d56f8b104f4ad556e235db904573ac..575076c018f4789c3c5f313f56b7b09674604baf 100644 (file)
@@ -1101,6 +1101,13 @@ static int __blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags,
                        int for_part);
 static int __blkdev_put(struct block_device *bdev, int for_part);
 
+/*
+ * bd_mutex locking:
+ *
+ *  mutex_lock(part->bd_mutex)
+ *    mutex_lock_nested(whole->bd_mutex, 1)
+ */
+
 static int do_open(struct block_device *bdev, struct file *file, int for_part)
 {
        struct module *owner = NULL;
index f99c509697cd7b11865b6d40f8abda1bd349d7a1..1d0852fa728bd851969e93a9f9cfcf4fea6010bc 100644 (file)
@@ -1743,7 +1743,6 @@ recover:
        SetPageError(page);
        BUG_ON(PageWriteback(page));
        set_page_writeback(page);
-       unlock_page(page);
        do {
                struct buffer_head *next = bh->b_this_page;
                if (buffer_async_write(bh)) {
@@ -1753,6 +1752,7 @@ recover:
                }
                bh = next;
        } while (bh != head);
+       unlock_page(page);
        goto done;
 }
 
@@ -2248,7 +2248,6 @@ int nobh_prepare_write(struct page *page, unsigned from, unsigned to,
        int i;
        int ret = 0;
        int is_mapped_to_disk = 1;
-       int dirtied_it = 0;
 
        if (PageMappedToDisk(page))
                return 0;
@@ -2285,14 +2284,10 @@ int nobh_prepare_write(struct page *page, unsigned from, unsigned to,
                        continue;
                if (buffer_new(&map_bh) || !buffer_mapped(&map_bh)) {
                        kaddr = kmap_atomic(page, KM_USER0);
-                       if (block_start < from) {
+                       if (block_start < from)
                                memset(kaddr+block_start, 0, from-block_start);
-                               dirtied_it = 1;
-                       }
-                       if (block_end > to) {
+                       if (block_end > to)
                                memset(kaddr + to, 0, block_end - to);
-                               dirtied_it = 1;
-                       }
                        flush_dcache_page(page);
                        kunmap_atomic(kaddr, KM_USER0);
                        continue;
@@ -2347,17 +2342,6 @@ int nobh_prepare_write(struct page *page, unsigned from, unsigned to,
 
        if (is_mapped_to_disk)
                SetPageMappedToDisk(page);
-       SetPageUptodate(page);
-
-       /*
-        * Setting the page dirty here isn't necessary for the prepare_write
-        * function - commit_write will do that.  But if/when this function is
-        * used within the pagefault handler to ensure that all mmapped pages
-        * have backing space in the filesystem, we will need to dirty the page
-        * if its contents were altered.
-        */
-       if (dirtied_it)
-               set_page_dirty(page);
 
        return 0;
 
@@ -2381,12 +2365,17 @@ failed:
 }
 EXPORT_SYMBOL(nobh_prepare_write);
 
+/*
+ * Make sure any changes to nobh_commit_write() are reflected in
+ * nobh_truncate_page(), since it doesn't call commit_write().
+ */
 int nobh_commit_write(struct file *file, struct page *page,
                unsigned from, unsigned to)
 {
        struct inode *inode = page->mapping->host;
        loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
 
+       SetPageUptodate(page);
        set_page_dirty(page);
        if (pos > inode->i_size) {
                i_size_write(inode, pos);
@@ -2481,6 +2470,11 @@ int nobh_truncate_page(struct address_space *mapping, loff_t from)
                memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
                flush_dcache_page(page);
                kunmap_atomic(kaddr, KM_USER0);
+               /*
+                * It would be more correct to call aops->commit_write()
+                * here, but this is more efficient.
+                */
+               SetPageUptodate(page);
                set_page_dirty(page);
        }
        unlock_page(page);
index e6194e2b9bb9cbf39c9c85f23d346d55716293a1..78ced721554d8f855f3254ac052e15d8b248d47d 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <linux/init.h>
 #include <linux/fs.h>
+#include <linux/kdev_t.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 
@@ -108,12 +109,7 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor,
        /* temporary */
        if (major == 0) {
                for (i = ARRAY_SIZE(chrdevs)-1; i > 0; i--) {
-                       /*
-                        * Disallow the LANANA-assigned LOCAL/EXPERIMENTAL
-                        * majors
-                        */
-                       if ((60 <= i && i <= 63) || (120 <= i && i <= 127) ||
-                                       (240 <= i && i <= 254))
+                       if (is_lanana_major(i))
                                continue;
                        if (chrdevs[i] == NULL)
                                break;
index 5fe13593b57faec72a1c9211de31b31f667ae759..6247628bdaed896cf09485c2a50f66edb5c40d5b 100644 (file)
@@ -1,3 +1,10 @@
+Verison 1.48
+------------
+Fix mtime bouncing around from local idea of last write times to remote time.
+Fix hang (in i_size_read) when simultaneous size update of same remote file
+on smp system corrupts sequence number. Do not reread unnecessarily partial page
+(which we are about to overwrite anyway) when writing out file opened rw.
+
 Version 1.47
 ------------
 Fix oops in list_del during mount caused by unaligned string.
index a26f26ed5a17e78bb5caf31732be07d21e172a5f..6ecd9d6ba3f3734a572ee757faf1773190069d35 100644 (file)
@@ -3,4 +3,4 @@
 #
 obj-$(CONFIG_CIFS) += cifs.o
 
-cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o sess.o
+cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o sess.o export.o
index 68372946dc92ba07e9ff6b0fe0a47126e2d99e8e..d7b9c27c942d97a041f40186fa4a5c68e2b15ce7 100644 (file)
@@ -18,7 +18,9 @@ better)
 
 d) Kerberos/SPNEGO session setup support - (started)
 
-e) NTLMv2 authentication (mostly implemented)
+e) NTLMv2 authentication (mostly implemented - double check
+that NTLMv2 signing works, also need to cleanup now unneeded SessSetup code in
+fs/cifs/connect.c)
 
 f) MD5-HMAC signing SMB PDUs when SPNEGO style SessionSetup 
 used (Kerberos or NTLMSSP). Signing alreadyimplemented for NTLM
@@ -88,11 +90,12 @@ w) Finish up the dos time conversion routines needed to return old server
 time to the client (default time, of now or time 0 is used now for these 
 very old servers)
 
-x) Add support for OS/2 (LANMAN 1.2 and LANMAN2.1 based SMB servers)
+x) In support for OS/2 (LANMAN 1.2 and LANMAN2.1 based SMB servers) 
+need to add ability to set time to server (utimes command)
 
 y) Finish testing of Windows 9x/Windows ME server support (started).
 
-KNOWN BUGS (updated April 29, 2005)
+KNOWN BUGS (updated February 26, 2007)
 ====================================
 See http://bugzilla.samba.org - search on product "CifsVFS" for
 current bug list.
@@ -107,11 +110,6 @@ but recognizes them
 succeed but still return access denied (appears to be Windows 
 server not cifs client problem) and has not been reproduced recently.
 NTFS partitions do not have this problem.
-4) debug connectathon lock test case 10 which fails against
-Samba (may be unmappable due to POSIX to Windows lock model
-differences but worth investigating).  Also debug Samba to 
-see why lock test case 7 takes longer to complete to Samba
-than to Windows.
 
 Misc testing to do
 ==================
@@ -119,7 +117,7 @@ Misc testing to do
 types. Try nested symlinks (8 deep). Return max path name in stat -f information
 
 2) Modify file portion of ltp so it can run against a mounted network
-share and run it against cifs vfs.
+share and run it against cifs vfs in automated fashion.
 
 3) Additional performance testing and optimization using iozone and similar - 
 there are some easy changes that can be done to parallelize sequential writes,
index e8287c4c6eb33c416c56ea6ac41e3cccd3ae31d1..faba4d69fe91fbcd12279c3683d88a03d479830a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/cifsfs.c
  *
- *   Copyright (C) International Business Machines  Corp., 2002,2004
+ *   Copyright (C) International Business Machines  Corp., 2002,2007
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   Common Internet FileSystem (CIFS) client
 
 #ifdef CONFIG_CIFS_QUOTA
 static struct quotactl_ops cifs_quotactl_ops;
-#endif
+#endif /* QUOTA */
+
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+extern struct export_operations cifs_export_ops;
+#endif /* EXPERIMENTAL */
 
 int cifsFYI = 0;
 int cifsERROR = 1;
@@ -62,8 +66,8 @@ unsigned int extended_security = CIFSSEC_DEF;
 unsigned int sign_CIFS_PDUs = 1;
 extern struct task_struct * oplockThread; /* remove sparse warning */
 struct task_struct * oplockThread = NULL;
-extern struct task_struct * dnotifyThread; /* remove sparse warning */
-struct task_struct * dnotifyThread = NULL;
+/* extern struct task_struct * dnotifyThread; remove sparse warning */
+static struct task_struct * dnotifyThread = NULL;
 static const struct super_operations cifs_super_ops;
 unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
 module_param(CIFSMaxBufSize, int, 0);
@@ -91,8 +95,9 @@ cifs_read_super(struct super_block *sb, void *data,
        struct inode *inode;
        struct cifs_sb_info *cifs_sb;
        int rc = 0;
-
-       sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */
+       
+       /* BB should we make this contingent on mount parm? */
+       sb->s_flags |= MS_NODIRATIME | MS_NOATIME;
        sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info),GFP_KERNEL);
        cifs_sb = CIFS_SB(sb);
        if(cifs_sb == NULL)
@@ -109,6 +114,10 @@ cifs_read_super(struct super_block *sb, void *data,
 
        sb->s_magic = CIFS_MAGIC_NUMBER;
        sb->s_op = &cifs_super_ops;
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+       if(experimEnabled != 0)
+               sb->s_export_op = &cifs_export_ops;
+#endif /* EXPERIMENTAL */      
 /*     if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
            sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
 #ifdef CONFIG_CIFS_QUOTA
@@ -258,7 +267,10 @@ cifs_alloc_inode(struct super_block *sb)
        cifs_inode->clientCanCacheRead = FALSE;
        cifs_inode->clientCanCacheAll = FALSE;
        cifs_inode->vfs_inode.i_blkbits = 14;  /* 2**14 = CIFS_MAX_MSGSIZE */
-       cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;
+       
+       /* Can not set i_flags here - they get immediately overwritten
+          to zero by the VFS */
+/*     cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;*/
        INIT_LIST_HEAD(&cifs_inode->openFileList);
        return &cifs_inode->vfs_inode;
 }
@@ -283,6 +295,7 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
 
        if (cifs_sb) {
                if (cifs_sb->tcon) {
+/* BB add prepath to mount options displayed */
                        seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName);
                        if (cifs_sb->tcon->ses) {
                                if (cifs_sb->tcon->ses->userName)
index c97c08eb481a38b926a63f039b27ad57068c2b78..2c2c384894d872cf10d31919d68023f160263151 100644 (file)
@@ -38,8 +38,8 @@ extern const struct address_space_operations cifs_addr_ops_smallbuf;
 /* Functions related to super block operations */
 /* extern const struct super_operations cifs_super_ops;*/
 extern void cifs_read_inode(struct inode *);
-extern void cifs_delete_inode(struct inode *);
-/* extern void cifs_write_inode(struct inode *); *//* BB not needed yet */
+/*extern void cifs_delete_inode(struct inode *);*/  /* BB not needed yet */
+/* extern void cifs_write_inode(struct inode *); */ /* BB not needed yet */
 
 /* Functions related to inodes */
 extern const struct inode_operations cifs_dir_inode_ops;
index 74d3ccbb103bfdbaf82b56cb03272ceebf9c022e..e4de8eba47807ff604559adda4bd170349a5d7c3 100644 (file)
@@ -525,15 +525,17 @@ require use of the stronger protocol */
  */
 GLOBAL_EXTERN struct smbUidInfo *GlobalUidList[UID_HASH];
 
-GLOBAL_EXTERN struct list_head GlobalServerList; /* BB not implemented yet */
+/* GLOBAL_EXTERN struct list_head GlobalServerList; BB not implemented yet */
 GLOBAL_EXTERN struct list_head GlobalSMBSessionList;
 GLOBAL_EXTERN struct list_head GlobalTreeConnectionList;
 GLOBAL_EXTERN rwlock_t GlobalSMBSeslock;  /* protects list inserts on 3 above */
 
 GLOBAL_EXTERN struct list_head GlobalOplock_Q;
 
-GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; /* Outstanding dir notify requests */
-GLOBAL_EXTERN struct list_head GlobalDnotifyRsp_Q;/* DirNotify response queue */
+/* Outstanding dir notify requests */
+GLOBAL_EXTERN struct list_head GlobalDnotifyReqList;
+/* DirNotify response queue */
+GLOBAL_EXTERN struct list_head GlobalDnotifyRsp_Q;
 
 /*
  * Global transaction id (XID) information
index 7d9505491b16e2a7fa83147b711fa9f53a0ec848..0efdf35aab2c53bd82ea110f7ec92f14051b1660 100644 (file)
 #define BAD_PROT 0xFFFF
 
 /* SMB command codes */
-/* Some commands have minimal (wct=0,bcc=0), or uninteresting, responses
- (ie which include no useful data other than the SMB error code itself).
- Knowing this helps avoid response buffer allocations and copy in some cases */
+/*
+ * Some commands have minimal (wct=0,bcc=0), or uninteresting, responses
+ * (ie which include no useful data other than the SMB error code itself).
+ * Knowing this helps avoid response buffer allocations and copy in some cases
+ */
 #define SMB_COM_CREATE_DIRECTORY      0x00 /* trivial response */
 #define SMB_COM_DELETE_DIRECTORY      0x01 /* trivial response */
 #define SMB_COM_CLOSE                 0x04 /* triv req/rsp, timestamp ignored */
  */
 #define CIFS_NO_HANDLE        0xFFFF
 
+#define NO_CHANGE_64          0xFFFFFFFFFFFFFFFFULL
+#define NO_CHANGE_32          0xFFFFFFFFUL
+
 /* IPC$ in ASCII */
 #define CIFS_IPC_RESOURCE "\x49\x50\x43\x24"
 
index 6148b82170c40a129b017e9ae4793148126525f1..32eb1acab6305f94acacb653de3da0b6f050af57 100644 (file)
@@ -43,7 +43,7 @@ extern void _FreeXid(unsigned int);
 #define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,(int)rc));}
 extern char *build_path_from_dentry(struct dentry *);
 extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
-extern void renew_parental_timestamps(struct dentry *direntry);
+/* extern void renew_parental_timestamps(struct dentry *direntry);*/
 extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
                        struct smb_hdr * /* input */ ,
                        struct smb_hdr * /* out */ ,
index 24364106b8f9d6883bc1dd6d29975bc22b50e5f8..48fc0c2ab0e5fb022e8b714cf561a55a521b1737 100644 (file)
@@ -4803,6 +4803,16 @@ setPermsRetry:
        pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
        pSMB->Reserved4 = 0;
        pSMB->hdr.smb_buf_length += byte_count;
+       /* Samba server ignores set of file size to zero due to bugs in some
+       older clients, but we should be precise - we use SetFileSize to
+       set file size and do not want to truncate file size to zero
+       accidently as happened on one Samba server beta by putting
+       zero instead of -1 here */ 
+       data_offset->EndOfFile = NO_CHANGE_64;
+       data_offset->NumOfBytes = NO_CHANGE_64;
+       data_offset->LastStatusChange = NO_CHANGE_64;
+       data_offset->LastAccessTime = NO_CHANGE_64;
+       data_offset->LastModificationTime = NO_CHANGE_64;
        data_offset->Uid = cpu_to_le64(uid);
        data_offset->Gid = cpu_to_le64(gid);
        /* better to leave device as zero when it is  */
index 66b825ade3e194b9176717275d29ce2731730c4f..3fad638d26d3b3f7806477da3d869f6559feeaff 100644 (file)
@@ -31,7 +31,7 @@
 #include "cifs_debug.h"
 #include "cifs_fs_sb.h"
 
-void
+static void
 renew_parental_timestamps(struct dentry *direntry)
 {
        /* BB check if there is a way to get the kernel to do this or if we really need this */
diff --git a/fs/cifs/export.c b/fs/cifs/export.c
new file mode 100644 (file)
index 0000000..1d71639
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ *   fs/cifs/export.c
+ *
+ *   Copyright (C) International Business Machines  Corp., 2007
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   Common Internet FileSystem (CIFS) client
+ * 
+ *   Operations related to support for exporting files via NFSD
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library 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 Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+ /* 
+  * See Documentation/filesystems/Exporting
+  * and examples in fs/exportfs
+  */
+
+#include <linux/fs.h>
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+static struct dentry *cifs_get_parent(struct dentry *dentry)
+{
+       /* BB need to add code here eventually to enable export via NFSD */
+       return ERR_PTR(-EACCES);
+}
+struct export_operations cifs_export_ops = {
+       .get_parent = cifs_get_parent,
+/*     Following five export operations are unneeded so far and can default */         
+/*     .get_dentry =
+       .get_name =
+       .find_exported_dentry =
+       .decode_fh = 
+       .encode_fs =  */
+ };
+#endif /* EXPERIMENTAL */
index 07ff9351e9ee71d5586f47827f92f1f9c1f7b4ff..2d3275bedb55b9a4667027404f5a811c5b0d5ef2 100644 (file)
@@ -879,18 +879,19 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
        cifs_stats_bytes_written(pTcon, total_written);
 
        /* since the write may have blocked check these pointers again */
-       if (file->f_path.dentry) {
-               if (file->f_path.dentry->d_inode) {
-                       struct inode *inode = file->f_path.dentry->d_inode;
-                       inode->i_ctime = inode->i_mtime =
-                               current_fs_time(inode->i_sb);
-                       if (total_written > 0) {
-                               if (*poffset > file->f_path.dentry->d_inode->i_size)
-                                       i_size_write(file->f_path.dentry->d_inode,
+       if ((file->f_path.dentry) && (file->f_path.dentry->d_inode)) {
+               struct inode *inode = file->f_path.dentry->d_inode;
+/* Do not update local mtime - server will set its actual value on write               
+ *             inode->i_ctime = inode->i_mtime = 
+ *                     current_fs_time(inode->i_sb);*/
+               if (total_written > 0) {
+                       spin_lock(&inode->i_lock);
+                       if (*poffset > file->f_path.dentry->d_inode->i_size)
+                               i_size_write(file->f_path.dentry->d_inode,
                                        *poffset);
-                       }
-                       mark_inode_dirty_sync(file->f_path.dentry->d_inode);
+                       spin_unlock(&inode->i_lock);
                }
+               mark_inode_dirty_sync(file->f_path.dentry->d_inode);    
        }
        FreeXid(xid);
        return total_written;
@@ -1012,17 +1013,18 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
        cifs_stats_bytes_written(pTcon, total_written);
 
        /* since the write may have blocked check these pointers again */
-       if (file->f_path.dentry) {
-               if (file->f_path.dentry->d_inode) {
-                       file->f_path.dentry->d_inode->i_ctime =
-                       file->f_path.dentry->d_inode->i_mtime = CURRENT_TIME;
-                       if (total_written > 0) {
-                               if (*poffset > file->f_path.dentry->d_inode->i_size)
-                                       i_size_write(file->f_path.dentry->d_inode,
-                                                    *poffset);
-                       }
-                       mark_inode_dirty_sync(file->f_path.dentry->d_inode);
+       if ((file->f_path.dentry) && (file->f_path.dentry->d_inode)) {
+/*BB We could make this contingent on superblock ATIME flag too */
+/*             file->f_path.dentry->d_inode->i_ctime =
+               file->f_path.dentry->d_inode->i_mtime = CURRENT_TIME;*/
+               if (total_written > 0) {
+                       spin_lock(&file->f_path.dentry->d_inode->i_lock);
+                       if (*poffset > file->f_path.dentry->d_inode->i_size)
+                               i_size_write(file->f_path.dentry->d_inode,
+                                            *poffset);
+                       spin_unlock(&file->f_path.dentry->d_inode->i_lock);
                }
+               mark_inode_dirty_sync(file->f_path.dentry->d_inode);
        }
        FreeXid(xid);
        return total_written;
@@ -1399,6 +1401,7 @@ static int cifs_commit_write(struct file *file, struct page *page,
        xid = GetXid();
        cFYI(1, ("commit write for page %p up to position %lld for %d", 
                 page, position, to));
+       spin_lock(&inode->i_lock);
        if (position > inode->i_size) {
                i_size_write(inode, position);
                /* if (file->private_data == NULL) {
@@ -1428,6 +1431,7 @@ static int cifs_commit_write(struct file *file, struct page *page,
                        cFYI(1, (" SetEOF (commit write) rc = %d", rc));
                } */
        }
+       spin_unlock(&inode->i_lock);
        if (!PageUptodate(page)) {
                position =  ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset;
                /* can not rely on (or let) writepage write this data */
@@ -1988,34 +1992,52 @@ static int cifs_prepare_write(struct file *file, struct page *page,
        unsigned from, unsigned to)
 {
        int rc = 0;
-        loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
+       loff_t i_size;
+       loff_t offset;
+
        cFYI(1, ("prepare write for page %p from %d to %d",page,from,to));
-       if (!PageUptodate(page)) {
-       /*      if (to - from != PAGE_CACHE_SIZE) {
-                       void *kaddr = kmap_atomic(page, KM_USER0);
+       if (PageUptodate(page))
+               return 0;
+
+       /* If we are writing a full page it will be up to date,
+          no need to read from the server */
+       if ((to == PAGE_CACHE_SIZE) && (from == 0)) {
+               SetPageUptodate(page);
+               return 0;
+       }
+
+       offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
+       i_size = i_size_read(page->mapping->host);
+
+       if ((offset >= i_size) ||
+           ((from == 0) && (offset + to) >= i_size)) {
+               /*
+                * We don't need to read data beyond the end of the file.
+                * zero it, and set the page uptodate
+                */
+               void *kaddr = kmap_atomic(page, KM_USER0);
+
+               if (from)
                        memset(kaddr, 0, from);
+               if (to < PAGE_CACHE_SIZE)
                        memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
-                       flush_dcache_page(page);
-                       kunmap_atomic(kaddr, KM_USER0);
-               } */
-               /* If we are writing a full page it will be up to date,
-                  no need to read from the server */
-               if ((to == PAGE_CACHE_SIZE) && (from == 0))
-                       SetPageUptodate(page);
-
+               flush_dcache_page(page);
+               kunmap_atomic(kaddr, KM_USER0);
+               SetPageUptodate(page);
+       } else if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
                /* might as well read a page, it is fast enough */
-               if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
-                       rc = cifs_readpage_worker(file, page, &offset);
-               } else {
-               /* should we try using another file handle if there is one -
-                  how would we lock it to prevent close of that handle
-                  racing with this read?
-                  In any case this will be written out by commit_write */
-               }
+               rc = cifs_readpage_worker(file, page, &offset);
+       } else {
+               /* we could try using another file handle if there is one -
+                  but how would we lock it to prevent close of that handle
+                  racing with this read? In any case
+                  this will be written out by commit_write so is fine */
        }
 
-       /* BB should we pass any errors back? 
-          e.g. if we do not have read access to the file */
+       /* we do not need to pass errors back 
+          e.g. if we do not have read access to the file 
+          because cifs_commit_write will do the right thing.  -- shaggy */
+
        return 0;
 }
 
index 3f5bc83dc3d1eabd97991f18a2cfaf53a0b8a5ba..86b9dbbd8441b487c7f496bc95394cf8494845ba 100644 (file)
@@ -90,6 +90,9 @@ int cifs_get_inode_info_unix(struct inode **pinode,
                                (*pinode)->i_ino =
                                        (unsigned long)findData.UniqueId;
                        } /* note ino incremented to unique num in new_inode */
+                       if(sb->s_flags & MS_NOATIME)
+                               (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
+                               
                        insert_inode_hash(*pinode);
                }
 
@@ -140,10 +143,10 @@ int cifs_get_inode_info_unix(struct inode **pinode,
                inode->i_gid = le64_to_cpu(findData.Gid);
                inode->i_nlink = le64_to_cpu(findData.Nlinks);
 
+               spin_lock(&inode->i_lock);
                if (is_size_safe_to_change(cifsInfo, end_of_file)) {
                /* can not safely change the file size here if the
                   client is writing to it due to potential races */
-
                        i_size_write(inode, end_of_file);
 
                /* blksize needs to be multiple of two. So safer to default to
@@ -159,6 +162,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
                /* for this calculation */
                        inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
                }
+               spin_unlock(&inode->i_lock);
 
                if (num_of_bytes < end_of_file)
                        cFYI(1, ("allocation size less than end of file"));
@@ -421,6 +425,8 @@ int cifs_get_inode_info(struct inode **pinode,
                                } else /* do we need cast or hash to ino? */
                                        (*pinode)->i_ino = inode_num;
                        } /* else ino incremented to unique num in new_inode*/
+                       if(sb->s_flags & MS_NOATIME)
+                               (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
                        insert_inode_hash(*pinode);
                }
                inode = *pinode;
@@ -491,6 +497,8 @@ int cifs_get_inode_info(struct inode **pinode,
                /* BB add code here -
                   validate if device or weird share or device type? */
                }
+               
+               spin_lock(&inode->i_lock);
                if (is_size_safe_to_change(cifsInfo, le64_to_cpu(pfindData->EndOfFile))) {
                        /* can not safely shrink the file size here if the
                           client is writing to it due to potential races */
@@ -501,6 +509,7 @@ int cifs_get_inode_info(struct inode **pinode,
                        inode->i_blocks = (512 - 1 + le64_to_cpu(
                                           pfindData->AllocationSize)) >> 9;
                }
+               spin_unlock(&inode->i_lock);
 
                inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
 
@@ -829,8 +838,10 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
 
        if (!rc) {
                drop_nlink(inode);
+               spin_lock(&direntry->d_inode->i_lock);
                i_size_write(direntry->d_inode,0);
                clear_nlink(direntry->d_inode);
+               spin_unlock(&direntry->d_inode->i_lock);
        }
 
        cifsInode = CIFS_I(direntry->d_inode);
@@ -1123,6 +1134,52 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from)
        return rc;
 }
 
+static int cifs_vmtruncate(struct inode * inode, loff_t offset)
+{
+       struct address_space *mapping = inode->i_mapping;
+       unsigned long limit;
+
+       spin_lock(&inode->i_lock);
+       if (inode->i_size < offset)
+               goto do_expand;
+       /*
+        * truncation of in-use swapfiles is disallowed - it would cause
+        * subsequent swapout to scribble on the now-freed blocks.
+        */
+       if (IS_SWAPFILE(inode)) {
+               spin_unlock(&inode->i_lock);
+               goto out_busy;
+       }
+       i_size_write(inode, offset);
+       spin_unlock(&inode->i_lock);
+       unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
+       truncate_inode_pages(mapping, offset);
+       goto out_truncate;
+
+do_expand:
+       limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
+       if (limit != RLIM_INFINITY && offset > limit) {
+               spin_unlock(&inode->i_lock);
+               goto out_sig;
+       }
+       if (offset > inode->i_sb->s_maxbytes) {
+               spin_unlock(&inode->i_lock);
+               goto out_big;
+       }
+       i_size_write(inode, offset);
+       spin_unlock(&inode->i_lock);
+out_truncate:
+       if (inode->i_op && inode->i_op->truncate)
+               inode->i_op->truncate(inode);
+       return 0;
+out_sig:
+       send_sig(SIGXFSZ, current, 0);
+out_big:
+       return -EFBIG;
+out_busy:
+       return -ETXTBSY;
+}
+
 int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
 {
        int xid;
@@ -1239,7 +1296,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
                   */
 
                if (rc == 0) {
-                       rc = vmtruncate(direntry->d_inode, attrs->ia_size);
+                       rc = cifs_vmtruncate(direntry->d_inode, attrs->ia_size);
                        cifs_truncate_page(direntry->d_inode->i_mapping,
                                           direntry->d_inode->i_size);
                } else 
@@ -1359,7 +1416,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
                and this check ensures that we are not being called from
                sys_utimes in which case we ought to fail the call back to
                the user when the server rejects the call */
-               if((rc) && (attrs->ia_valid &&
+               if((rc) && (attrs->ia_valid &
                         (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
                        rc = 0;
        }
@@ -1374,9 +1431,11 @@ cifs_setattr_exit:
        return rc;
 }
 
+#if 0
 void cifs_delete_inode(struct inode *inode)
 {
        cFYI(1, ("In cifs_delete_inode, inode = 0x%p", inode));
        /* may have to add back in if and when safe distributed caching of
           directories added e.g. via FindNotify */
 }
+#endif
index 8e259969354bced4024795fa7d6ffb0d42018db8..6baea85d726ed85489aa288753bdd0fc72434fcd 100644 (file)
@@ -77,7 +77,8 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
                cifsInode = CIFS_I(old_file->d_inode);
                if(rc == 0) {
                        old_file->d_inode->i_nlink++;
-                       old_file->d_inode->i_ctime = CURRENT_TIME;
+/* BB should we make this contingent on superblock flag NOATIME? */
+/*                     old_file->d_inode->i_ctime = CURRENT_TIME;*/
                        /* parent dir timestamps will update from srv
                        within a second, would it really be worth it
                        to set the parent dir cifs inode time to zero
index c6220bd271656055395e67dd94f2d9158f87b2d7..44cfb528797d73548fc8df8ac12eeb4a27063653 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Directory search handling
  * 
- *   Copyright (C) International Business Machines  Corp., 2004, 2005
+ *   Copyright (C) International Business Machines  Corp., 2004, 2007
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -83,6 +83,8 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
                                return rc;
                        rc = 1;
                }
+               if(file->f_path.dentry->d_sb->s_flags & MS_NOATIME)
+                       (*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME;
        } else {
                tmp_dentry = d_alloc(file->f_path.dentry, qstring);
                if(tmp_dentry == NULL) {
@@ -98,6 +100,8 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
                        tmp_dentry->d_op = &cifs_dentry_ops;
                if(*ptmp_inode == NULL)
                        return rc;
+               if(file->f_path.dentry->d_sb->s_flags & MS_NOATIME)
+                       (*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME;                       
                rc = 2;
        }
 
@@ -222,6 +226,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
                atomic_set(&cifsInfo->inUse, 1);
        }
 
+       spin_lock(&tmp_inode->i_lock);
        if (is_size_safe_to_change(cifsInfo, end_of_file)) {
                /* can not safely change the file size here if the 
                client is writing to it due to potential races */
@@ -231,6 +236,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
        /* for this calculation, even though the reported blocksize is larger */
                tmp_inode->i_blocks = (512 - 1 + allocation_size) >> 9;
        }
+       spin_unlock(&tmp_inode->i_lock);
 
        if (allocation_size < end_of_file)
                cFYI(1, ("May be sparse file, allocation less than file size"));
@@ -351,6 +357,7 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
        tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
        tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
 
+       spin_lock(&tmp_inode->i_lock);
        if (is_size_safe_to_change(cifsInfo, end_of_file)) {
                /* can not safely change the file size here if the 
                client is writing to it due to potential races */
@@ -360,6 +367,7 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
        /* for this calculation, not the real blocksize */
                tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
        }
+       spin_unlock(&tmp_inode->i_lock);
 
        if (S_ISREG(tmp_inode->i_mode)) {
                cFYI(1, ("File inode"));
index f80007eaebf4100c67224e4ffa524d2c6c517517..5f468459a1e294fb9f2ba30b2141bc5bc26eaab0 100644 (file)
@@ -499,7 +499,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
           due to last connection to this server being unmounted */
        if (signal_pending(current)) {
                /* if signal pending do not hold up user for full smb timeout
-               but we still give response a change to complete */
+               but we still give response a chance to complete */
                timeout = 2 * HZ;
        }   
 
@@ -587,7 +587,6 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
        }
 
 out:
-
        DeleteMidQEntry(midQ);
        atomic_dec(&ses->server->inFlight); 
        wake_up(&ses->server->request_q);
@@ -681,7 +680,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
           due to last connection to this server being unmounted */
        if (signal_pending(current)) {
                /* if signal pending do not hold up user for full smb timeout
-               but we still give response a change to complete */
+               but we still give response a chance to complete */
                timeout = 2 * HZ;
        }   
 
@@ -765,7 +764,6 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
        }
 
 out:
-
        DeleteMidQEntry(midQ);
        atomic_dec(&ses->server->inFlight); 
        wake_up(&ses->server->request_q);
index 0ec70e3cee0a6113e24b9282250dbcb950e144f1..040a8be38a4896af7334769a9cb26f852b5cc56a 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/highmem.h>
 #include <linux/poll.h>
 #include <linux/mm.h>
+#include <linux/eventpoll.h>
 
 #include <net/sock.h>          /* siocdevprivate_ioctl */
 
@@ -2235,3 +2236,102 @@ long asmlinkage compat_sys_nfsservctl(int cmd, void *notused, void *notused2)
        return sys_ni_syscall();
 }
 #endif
+
+#ifdef CONFIG_EPOLL
+
+#ifdef CONFIG_HAS_COMPAT_EPOLL_EVENT
+asmlinkage long compat_sys_epoll_ctl(int epfd, int op, int fd,
+                       struct compat_epoll_event __user *event)
+{
+       long err = 0;
+       struct compat_epoll_event user;
+       struct epoll_event __user *kernel = NULL;
+
+       if (event) {
+               if (copy_from_user(&user, event, sizeof(user)))
+                       return -EFAULT;
+               kernel = compat_alloc_user_space(sizeof(struct epoll_event));
+               err |= __put_user(user.events, &kernel->events);
+               err |= __put_user(user.data, &kernel->data);
+       }
+
+       return err ? err : sys_epoll_ctl(epfd, op, fd, kernel);
+}
+
+
+asmlinkage long compat_sys_epoll_wait(int epfd,
+                       struct compat_epoll_event __user *events,
+                       int maxevents, int timeout)
+{
+       long i, ret, err = 0;
+       struct epoll_event __user *kbuf;
+       struct epoll_event ev;
+
+       if ((maxevents <= 0) ||
+                       (maxevents > (INT_MAX / sizeof(struct epoll_event))))
+               return -EINVAL;
+       kbuf = compat_alloc_user_space(sizeof(struct epoll_event) * maxevents);
+       ret = sys_epoll_wait(epfd, kbuf, maxevents, timeout);
+       for (i = 0; i < ret; i++) {
+               err |= __get_user(ev.events, &kbuf[i].events);
+               err |= __get_user(ev.data, &kbuf[i].data);
+               err |= __put_user(ev.events, &events->events);
+               err |= __put_user_unaligned(ev.data, &events->data);
+               events++;
+       }
+
+       return err ? -EFAULT: ret;
+}
+#endif /* CONFIG_HAS_COMPAT_EPOLL_EVENT */
+
+#ifdef TIF_RESTORE_SIGMASK
+asmlinkage long compat_sys_epoll_pwait(int epfd,
+                       struct compat_epoll_event __user *events,
+                       int maxevents, int timeout,
+                       const compat_sigset_t __user *sigmask,
+                       compat_size_t sigsetsize)
+{
+       long err;
+       compat_sigset_t csigmask;
+       sigset_t ksigmask, sigsaved;
+
+       /*
+        * If the caller wants a certain signal mask to be set during the wait,
+        * we apply it here.
+        */
+       if (sigmask) {
+               if (sigsetsize != sizeof(compat_sigset_t))
+                       return -EINVAL;
+               if (copy_from_user(&csigmask, sigmask, sizeof(csigmask)))
+                       return -EFAULT;
+               sigset_from_compat(&ksigmask, &csigmask);
+               sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
+               sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+       }
+
+#ifdef CONFIG_HAS_COMPAT_EPOLL_EVENT
+       err = compat_sys_epoll_wait(epfd, events, maxevents, timeout);
+#else
+       err = sys_epoll_wait(epfd, events, maxevents, timeout);
+#endif
+
+       /*
+        * If we changed the signal mask, we need to restore the original one.
+        * In case we've got a signal while waiting, we do not restore the
+        * signal mask yet, and we allow do_signal() to deliver the signal on
+        * the way back to userspace, before the signal mask is restored.
+        */
+       if (sigmask) {
+               if (err == -EINTR) {
+                       memcpy(&current->saved_sigmask, &sigsaved,
+                              sizeof(sigsaved));
+                       set_thread_flag(TIF_RESTORE_SIGMASK);
+               } else
+                       sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+       }
+
+       return err;
+}
+#endif /* TIF_RESTORE_SIGMASK */
+
+#endif /* CONFIG_EPOLL */
index 40db61dc95f2550f09d592bcd2b2e751fca85291..3870150b83a479396eb6a179757d92c1a61baf2c 100644 (file)
@@ -22,6 +22,7 @@
 #include "lockspace.h"
 #include "lock.h"
 #include "lvb_table.h"
+#include "user.h"
 
 static const char *name_prefix="dlm";
 static struct miscdevice ctl_device;
index bd969adf70d72bd8cc5335e3f8a47e06c220be52..7a7d25d541e727cb4515acb771c3e077773c5a20 100644 (file)
@@ -205,6 +205,7 @@ int ecryptfs_open_lower_file(struct file **lower_file,
 {
        int rc = 0;
 
+       flags |= O_LARGEFILE;
        dget(lower_dentry);
        mntget(lower_mnt);
        *lower_file = dentry_open(lower_dentry, lower_mnt, flags);
index 9fa7e0b27a96ee57ae08187e17b6872b79d39fd4..1548be26b5e61060ee5c5eb440209bd98b850724 100644 (file)
@@ -38,7 +38,7 @@ static struct dentry *lock_parent(struct dentry *dentry)
        struct dentry *dir;
 
        dir = dget(dentry->d_parent);
-       mutex_lock(&(dir->d_inode->i_mutex));
+       mutex_lock_nested(&(dir->d_inode->i_mutex), I_MUTEX_PARENT);
        return dir;
 }
 
@@ -168,9 +168,9 @@ static int grow_file(struct dentry *ecryptfs_dentry, struct file *lower_file,
                goto out;
        }
        i_size_write(inode, 0);
-       ecryptfs_write_inode_size_to_metadata(lower_file, lower_inode, inode,
-                                             ecryptfs_dentry,
-                                             ECRYPTFS_LOWER_I_MUTEX_NOT_HELD);
+       rc = ecryptfs_write_inode_size_to_metadata(lower_file, lower_inode,
+                       inode, ecryptfs_dentry,
+                       ECRYPTFS_LOWER_I_MUTEX_NOT_HELD);
        ecryptfs_inode_to_private(inode)->crypt_stat.flags |= ECRYPTFS_NEW_FILE;
 out:
        return rc;
@@ -200,9 +200,6 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry)
        inode = ecryptfs_dentry->d_inode;
        crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
        lower_flags = ((O_CREAT | O_TRUNC) & O_ACCMODE) | O_RDWR;
-#if BITS_PER_LONG != 32
-       lower_flags |= O_LARGEFILE;
-#endif
        lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry);
        /* Corresponding fput() at end of this function */
        if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry, lower_mnt,
index 80044d196fe06b7b82ae3c6dc0cacaddc3e1a2f6..fc4a3a22464182ebb80e130c2d2013e102905776 100644 (file)
@@ -484,18 +484,12 @@ static int ecryptfs_read_super(struct super_block *sb, const char *dev_name)
        struct vfsmount *lower_mnt;
 
        memset(&nd, 0, sizeof(struct nameidata));
-       rc = path_lookup(dev_name, LOOKUP_FOLLOW, &nd);
+       rc = path_lookup(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &nd);
        if (rc) {
                ecryptfs_printk(KERN_WARNING, "path_lookup() failed\n");
-               goto out_free;
+               goto out;
        }
        lower_root = nd.dentry;
-       if (!lower_root->d_inode) {
-               ecryptfs_printk(KERN_WARNING,
-                               "No directory to interpose on\n");
-               rc = -ENOENT;
-               goto out_free;
-       }
        lower_mnt = nd.mnt;
        ecryptfs_set_superblock_lower(sb, lower_root->d_sb);
        sb->s_maxbytes = lower_root->d_sb->s_maxbytes;
index 3a6f65c3f14fc2fb26aa77df1ba8f10cae7198b7..b731b09499cb8dcc996a87772b1090bd34484a83 100644 (file)
@@ -238,7 +238,6 @@ int ecryptfs_do_readpage(struct file *file, struct page *page,
        lower_page_data = kmap_atomic(lower_page, KM_USER1);
        memcpy(page_data, lower_page_data, PAGE_CACHE_SIZE);
        kunmap_atomic(lower_page_data, KM_USER1);
-       flush_dcache_page(lower_page);
        kunmap_atomic(page_data, KM_USER0);
        flush_dcache_page(page);
        rc = 0;
@@ -422,9 +421,11 @@ out:
        return rc;
 }
 
-static void ecryptfs_release_lower_page(struct page *lower_page)
+static
+void ecryptfs_release_lower_page(struct page *lower_page, int page_locked)
 {
-       unlock_page(lower_page);
+       if (page_locked)
+               unlock_page(lower_page);
        page_cache_release(lower_page);
 }
 
@@ -445,6 +446,7 @@ static int ecryptfs_write_inode_size_to_header(struct file *lower_file,
        const struct address_space_operations *lower_a_ops;
        u64 file_size;
 
+retry:
        header_page = grab_cache_page(lower_inode->i_mapping, 0);
        if (!header_page) {
                ecryptfs_printk(KERN_ERR, "grab_cache_page for "
@@ -454,6 +456,14 @@ static int ecryptfs_write_inode_size_to_header(struct file *lower_file,
        }
        lower_a_ops = lower_inode->i_mapping->a_ops;
        rc = lower_a_ops->prepare_write(lower_file, header_page, 0, 8);
+       if (rc) {
+               if (rc == AOP_TRUNCATED_PAGE) {
+                       ecryptfs_release_lower_page(header_page, 0);
+                       goto retry;
+               } else
+                       ecryptfs_release_lower_page(header_page, 1);
+               goto out;
+       }
        file_size = (u64)i_size_read(inode);
        ecryptfs_printk(KERN_DEBUG, "Writing size: [0x%.16x]\n", file_size);
        file_size = cpu_to_be64(file_size);
@@ -465,7 +475,11 @@ static int ecryptfs_write_inode_size_to_header(struct file *lower_file,
        if (rc < 0)
                ecryptfs_printk(KERN_ERR, "Error commiting header page "
                                "write\n");
-       ecryptfs_release_lower_page(header_page);
+       if (rc == AOP_TRUNCATED_PAGE) {
+               ecryptfs_release_lower_page(header_page, 0);
+               goto retry;
+       } else
+               ecryptfs_release_lower_page(header_page, 1);
        lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
        mark_inode_dirty_sync(inode);
 out:
@@ -491,7 +505,8 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *lower_inode,
                goto out;
        }
        lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
-       if (!lower_dentry->d_inode->i_op->getxattr) {
+       if (!lower_dentry->d_inode->i_op->getxattr ||
+                       !lower_dentry->d_inode->i_op->setxattr) {
                printk(KERN_WARNING
                       "No support for setting xattr in lower filesystem\n");
                rc = -ENOSYS;
@@ -553,6 +568,7 @@ int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode,
 {
        int rc = 0;
 
+retry:
        *lower_page = grab_cache_page(lower_inode->i_mapping, lower_page_index);
        if (!(*lower_page)) {
                rc = -EINVAL;
@@ -566,15 +582,18 @@ int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode,
                                                          byte_offset,
                                                          region_bytes);
        if (rc) {
-               ecryptfs_printk(KERN_ERR, "prepare_write for "
+               if (rc == AOP_TRUNCATED_PAGE) {
+                       ecryptfs_release_lower_page(*lower_page, 0);
+                       goto retry;
+               } else {
+                       ecryptfs_printk(KERN_ERR, "prepare_write for "
                                "lower_page_index = [0x%.16x] failed; rc = "
                                "[%d]\n", lower_page_index, rc);
+                       ecryptfs_release_lower_page(*lower_page, 1);
+                       (*lower_page) = NULL;
+               }
        }
 out:
-       if (rc && (*lower_page)) {
-               ecryptfs_release_lower_page(*lower_page);
-               (*lower_page) = NULL;
-       }
        return rc;
 }
 
@@ -588,16 +607,19 @@ ecryptfs_commit_lower_page(struct page *lower_page, struct inode *lower_inode,
                           struct file *lower_file, int byte_offset,
                           int region_size)
 {
+       int page_locked = 1;
        int rc = 0;
 
        rc = lower_inode->i_mapping->a_ops->commit_write(
                lower_file, lower_page, byte_offset, region_size);
+       if (rc == AOP_TRUNCATED_PAGE)
+               page_locked = 0;
        if (rc < 0) {
                ecryptfs_printk(KERN_ERR,
                                "Error committing write; rc = [%d]\n", rc);
        } else
                rc = 0;
-       ecryptfs_release_lower_page(lower_page);
+       ecryptfs_release_lower_page(lower_page, page_locked);
        return rc;
 }
 
index b1981d0e95ad624e42595e3aace23044716c7770..baf71dd721fa161adcb936735ba69355c79d9acb 100644 (file)
@@ -29,7 +29,7 @@
  * The file system contains group descriptors which are located after the
  * super block.  Each descriptor contains the number of the bitmap block and
  * the free blocks count in the block.  The descriptors are loaded in memory
- * when a file system is mounted (see ext2_read_super).
+ * when a file system is mounted (see ext2_fill_super).
  */
 
 
index 22161740ba295e7e1e650c571544cb9e6c2b5f3b..ca8aee6efe3720aefc617d9d8c8c1e9b49359359 100644 (file)
@@ -32,7 +32,7 @@
  * The file system contains group descriptors which are located after the
  * super block.  Each descriptor contains the number of the bitmap block and
  * the free blocks count in the block.  The descriptors are loaded in memory
- * when a file system is mounted (see ext3_read_super).
+ * when a file system is mounted (see ext3_fill_super).
  */
 
 
index 99857a400f4be217dcf92e5f16ac6c62783b62e2..12f7dda1232cb8b17749d6f3e87d6ea77a40bb0c 100644 (file)
@@ -475,8 +475,15 @@ ext3_xattr_release_block(handle_t *handle, struct inode *inode,
                         struct buffer_head *bh)
 {
        struct mb_cache_entry *ce = NULL;
+       int error = 0;
 
        ce = mb_cache_entry_get(ext3_xattr_cache, bh->b_bdev, bh->b_blocknr);
+       error = ext3_journal_get_write_access(handle, bh);
+       if (error)
+                goto out;
+
+       lock_buffer(bh);
+
        if (BHDR(bh)->h_refcount == cpu_to_le32(1)) {
                ea_bdebug(bh, "refcount now=0; freeing");
                if (ce)
@@ -485,21 +492,20 @@ ext3_xattr_release_block(handle_t *handle, struct inode *inode,
                get_bh(bh);
                ext3_forget(handle, 1, inode, bh, bh->b_blocknr);
        } else {
-               if (ext3_journal_get_write_access(handle, bh) == 0) {
-                       lock_buffer(bh);
-                       BHDR(bh)->h_refcount = cpu_to_le32(
+               BHDR(bh)->h_refcount = cpu_to_le32(
                                le32_to_cpu(BHDR(bh)->h_refcount) - 1);
-                       ext3_journal_dirty_metadata(handle, bh);
-                       if (IS_SYNC(inode))
-                               handle->h_sync = 1;
-                       DQUOT_FREE_BLOCK(inode, 1);
-                       unlock_buffer(bh);
-                       ea_bdebug(bh, "refcount now=%d; releasing",
-                                 le32_to_cpu(BHDR(bh)->h_refcount));
-               }
+               error = ext3_journal_dirty_metadata(handle, bh);
+               handle->h_sync = 1;
+               DQUOT_FREE_BLOCK(inode, 1);
+               ea_bdebug(bh, "refcount now=%d; releasing",
+                         le32_to_cpu(BHDR(bh)->h_refcount));
                if (ce)
                        mb_cache_entry_release(ce);
        }
+       unlock_buffer(bh);
+out:
+       ext3_std_error(inode->i_sb, error);
+       return;
 }
 
 struct ext3_xattr_info {
@@ -675,7 +681,7 @@ ext3_xattr_block_set(handle_t *handle, struct inode *inode,
        struct buffer_head *new_bh = NULL;
        struct ext3_xattr_search *s = &bs->s;
        struct mb_cache_entry *ce = NULL;
-       int error;
+       int error = 0;
 
 #define header(x) ((struct ext3_xattr_header *)(x))
 
@@ -684,16 +690,17 @@ ext3_xattr_block_set(handle_t *handle, struct inode *inode,
        if (s->base) {
                ce = mb_cache_entry_get(ext3_xattr_cache, bs->bh->b_bdev,
                                        bs->bh->b_blocknr);
+               error = ext3_journal_get_write_access(handle, bs->bh);
+               if (error)
+                       goto cleanup;
+               lock_buffer(bs->bh);
+
                if (header(s->base)->h_refcount == cpu_to_le32(1)) {
                        if (ce) {
                                mb_cache_entry_free(ce);
                                ce = NULL;
                        }
                        ea_bdebug(bs->bh, "modifying in-place");
-                       error = ext3_journal_get_write_access(handle, bs->bh);
-                       if (error)
-                               goto cleanup;
-                       lock_buffer(bs->bh);
                        error = ext3_xattr_set_entry(i, s);
                        if (!error) {
                                if (!IS_LAST_ENTRY(s->first))
@@ -713,6 +720,9 @@ ext3_xattr_block_set(handle_t *handle, struct inode *inode,
                } else {
                        int offset = (char *)s->here - bs->bh->b_data;
 
+                       unlock_buffer(bs->bh);
+                       journal_release_buffer(handle, bs->bh);
+
                        if (ce) {
                                mb_cache_entry_release(ce);
                                ce = NULL;
index c4dd1103ccf1033f70af475bbf26ff3a2c107cc8..8a23483ca8d0c3668e171bbc53c7a629a2403876 100644 (file)
@@ -50,7 +50,7 @@ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
  * The file system contains group descriptors which are located after the
  * super block.  Each descriptor contains the number of the bitmap block and
  * the free blocks count in the block.  The descriptors are loaded in memory
- * when a file system is mounted (see ext4_read_super).
+ * when a file system is mounted (see ext4_fill_super).
  */
 
 
index dc969c357aa1d4ef9e207054e506053b8efdc0c6..e832e96095b33c177e880db6370e1686153439f6 100644 (file)
@@ -475,8 +475,14 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode,
                         struct buffer_head *bh)
 {
        struct mb_cache_entry *ce = NULL;
+       int error = 0;
 
        ce = mb_cache_entry_get(ext4_xattr_cache, bh->b_bdev, bh->b_blocknr);
+       error = ext4_journal_get_write_access(handle, bh);
+       if (error)
+               goto out;
+
+       lock_buffer(bh);
        if (BHDR(bh)->h_refcount == cpu_to_le32(1)) {
                ea_bdebug(bh, "refcount now=0; freeing");
                if (ce)
@@ -485,21 +491,21 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode,
                get_bh(bh);
                ext4_forget(handle, 1, inode, bh, bh->b_blocknr);
        } else {
-               if (ext4_journal_get_write_access(handle, bh) == 0) {
-                       lock_buffer(bh);
-                       BHDR(bh)->h_refcount = cpu_to_le32(
+               BHDR(bh)->h_refcount = cpu_to_le32(
                                le32_to_cpu(BHDR(bh)->h_refcount) - 1);
-                       ext4_journal_dirty_metadata(handle, bh);
-                       if (IS_SYNC(inode))
-                               handle->h_sync = 1;
-                       DQUOT_FREE_BLOCK(inode, 1);
-                       unlock_buffer(bh);
-                       ea_bdebug(bh, "refcount now=%d; releasing",
-                                 le32_to_cpu(BHDR(bh)->h_refcount));
-               }
+               error = ext4_journal_dirty_metadata(handle, bh);
+               if (IS_SYNC(inode))
+                       handle->h_sync = 1;
+               DQUOT_FREE_BLOCK(inode, 1);
+               ea_bdebug(bh, "refcount now=%d; releasing",
+                         le32_to_cpu(BHDR(bh)->h_refcount));
                if (ce)
                        mb_cache_entry_release(ce);
        }
+       unlock_buffer(bh);
+out:
+       ext4_std_error(inode->i_sb, error);
+       return;
 }
 
 struct ext4_xattr_info {
@@ -675,7 +681,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
        struct buffer_head *new_bh = NULL;
        struct ext4_xattr_search *s = &bs->s;
        struct mb_cache_entry *ce = NULL;
-       int error;
+       int error = 0;
 
 #define header(x) ((struct ext4_xattr_header *)(x))
 
@@ -684,16 +690,17 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
        if (s->base) {
                ce = mb_cache_entry_get(ext4_xattr_cache, bs->bh->b_bdev,
                                        bs->bh->b_blocknr);
+               error = ext4_journal_get_write_access(handle, bs->bh);
+               if (error)
+                       goto cleanup;
+               lock_buffer(bs->bh);
+
                if (header(s->base)->h_refcount == cpu_to_le32(1)) {
                        if (ce) {
                                mb_cache_entry_free(ce);
                                ce = NULL;
                        }
                        ea_bdebug(bs->bh, "modifying in-place");
-                       error = ext4_journal_get_write_access(handle, bs->bh);
-                       if (error)
-                               goto cleanup;
-                       lock_buffer(bs->bh);
                        error = ext4_xattr_set_entry(i, s);
                        if (!error) {
                                if (!IS_LAST_ENTRY(s->first))
@@ -713,6 +720,8 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
                } else {
                        int offset = (char *)s->here - bs->bh->b_data;
 
+                       unlock_buffer(bs->bh);
+                       jbd2_journal_release_buffer(handle, bs->bh);
                        if (ce) {
                                mb_cache_entry_release(ce);
                                ce = NULL;
index 7610735442178f8081a50004ce45977a9e671994..9bfe607c892ec835161ee461e1cb1379d5133dc6 100644 (file)
@@ -173,10 +173,12 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb,
                 *
                 * But we must fill the remaining area or hole by nul for
                 * updating ->mmu_private.
+                *
+                * Return 0, and fallback to normal buffered write.
                 */
                loff_t size = offset + iov_length(iov, nr_segs);
                if (MSDOS_I(inode)->mmu_private < size)
-                       return -EINVAL;
+                       return 0;
        }
 
        /*
index 6618c1190252881f6aae8266d7303deec76398ae..12accb08fe02d3e701fa49e79d9e1a1c7519f495 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/list.h>
 #include <linux/lm_interface.h>
 #include <linux/wait.h>
+#include <linux/module.h>
 #include <linux/rwsem.h>
 #include <asm/uaccess.h>
 
@@ -953,9 +954,6 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret)
                spin_unlock(&gl->gl_spin);
        }
 
-       if (glops->go_drop_bh)
-               glops->go_drop_bh(gl);
-
        spin_lock(&gl->gl_spin);
        gl->gl_req_gh = NULL;
        gl->gl_req_bh = NULL;
index 46af553555135f362d47a957faeb0418d7f8a46f..39c8ae23bd9c04a8b47b0cec2a371a597b5a2450 100644 (file)
@@ -245,7 +245,6 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
 
        if (ip && S_ISREG(ip->i_inode.i_mode)) {
                truncate_inode_pages(ip->i_inode.i_mapping, 0);
-               gfs2_assert_withdraw(GFS2_SB(&ip->i_inode), !ip->i_inode.i_mapping->nrpages);
                clear_bit(GIF_PAGED, &ip->i_flags);
        }
 }
@@ -459,6 +458,8 @@ const struct gfs2_glock_operations gfs2_inode_glops = {
 };
 
 const struct gfs2_glock_operations gfs2_rgrp_glops = {
+       .go_xmote_th = meta_go_sync,
+       .go_drop_th = meta_go_sync,
        .go_inval = meta_go_inval,
        .go_demote_ok = rgrp_go_demote_ok,
        .go_lock = rgrp_go_lock,
index 12c80fd28db51d8f3b92fdebddcfee954bc926d5..49f0dbf40d8644a35da4f5b6e5978ecb886b94ba 100644 (file)
@@ -104,7 +104,6 @@ struct gfs2_glock_operations {
        void (*go_xmote_th) (struct gfs2_glock *gl);
        void (*go_xmote_bh) (struct gfs2_glock *gl);
        void (*go_drop_th) (struct gfs2_glock *gl);
-       void (*go_drop_bh) (struct gfs2_glock *gl);
        void (*go_inval) (struct gfs2_glock *gl, int flags);
        int (*go_demote_ok) (struct gfs2_glock *gl);
        int (*go_lock) (struct gfs2_holder *gh);
@@ -416,7 +415,6 @@ struct gfs2_tune {
        unsigned int gt_stall_secs; /* Detects trouble! */
        unsigned int gt_complain_secs;
        unsigned int gt_reclaim_limit; /* Max num of glocks in reclaim list */
-       unsigned int gt_entries_per_readdir;
        unsigned int gt_statfs_quantum;
        unsigned int gt_statfs_slow;
 };
index 0d6831a40565015da1af7f343544e25551bcaf57..df0b8b3018b934e72a30830b5a2936498c969be9 100644 (file)
@@ -43,7 +43,8 @@ static int iget_test(struct inode *inode, void *opaque)
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_inum_host *inum = opaque;
 
-       if (ip->i_num.no_addr == inum->no_addr)
+       if (ip->i_num.no_addr == inum->no_addr &&
+           inode->i_private != NULL)
                return 1;
 
        return 0;
@@ -61,13 +62,13 @@ static int iget_set(struct inode *inode, void *opaque)
 
 struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum_host *inum)
 {
-       return ilookup5(sb, (unsigned long)inum->no_formal_ino,
+       return ilookup5(sb, (unsigned long)inum->no_addr,
                        iget_test, inum);
 }
 
 static struct inode *gfs2_iget(struct super_block *sb, struct gfs2_inum_host *inum)
 {
-       return iget5_locked(sb, (unsigned long)inum->no_formal_ino,
+       return iget5_locked(sb, (unsigned long)inum->no_addr,
                     iget_test, iget_set, inum);
 }
 
index 56e33590b65661cec2bd8cdf8c375513d450c153..b3b7e8475359d0feae533b9f80f2229e1ae6993e 100644 (file)
@@ -266,9 +266,11 @@ skip_lock:
 out:
        return error;
 out_unlock:
-       if (error == GLR_TRYFAILED)
-               error = AOP_TRUNCATED_PAGE;
        unlock_page(page);
+       if (error == GLR_TRYFAILED) {
+               error = AOP_TRUNCATED_PAGE;
+               yield();
+       }
        if (do_unlock)
                gfs2_holder_uninit(&gh);
        goto out;
@@ -364,6 +366,7 @@ static int gfs2_prepare_write(struct file *file, struct page *page,
                if (error == GLR_TRYFAILED) {
                        unlock_page(page);
                        error = AOP_TRUNCATED_PAGE;
+                       yield();
                }
                goto out_uninit;
        }
index 1de05b63d43affea74c9c1ebf6d7da81de64d599..aad918337a469136778f32e5367c3fb586da82b2 100644 (file)
@@ -38,14 +38,11 @@ static struct dentry *gfs2_decode_fh(struct super_block *sb,
        struct gfs2_fh_obj fh_obj;
        struct gfs2_inum_host *this, parent;
 
-       if (fh_type != fh_len)
-               return NULL;
-
        this            = &fh_obj.this;
        fh_obj.imode    = DT_UNKNOWN;
        memset(&parent, 0, sizeof(struct gfs2_inum));
 
-       switch (fh_type) {
+       switch (fh_len) {
        case GFS2_LARGE_FH_SIZE:
                parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32;
                parent.no_formal_ino |= be32_to_cpu(fh[5]);
index ee80b8a5e7bc1ddfa0bb3136ae4f38240ef3ec8e..ee54cb6670832e841206377bf50dff0b50ed0474 100644 (file)
@@ -840,7 +840,7 @@ static struct super_block* get_gfs2_sb(const char *dev_name)
        }
 
        printk(KERN_WARNING "GFS2: Unrecognized block device or "
-              "mount point %s", dev_name);
+              "mount point %s\n", dev_name);
 
 free_nd:
        path_release(&nd);
index d0db881b55d2cf34231335d1c2848f1fd131af30..c186857e48a80a49433b81fe2f11986b58c188f7 100644 (file)
@@ -279,7 +279,7 @@ static int bh_get(struct gfs2_quota_data *qd)
                (bh->b_data + sizeof(struct gfs2_meta_header) +
                 offset * sizeof(struct gfs2_quota_change));
 
-       mutex_lock(&sdp->sd_quota_mutex);
+       mutex_unlock(&sdp->sd_quota_mutex);
 
        return 0;
 
index 70f424fcf1cdb8468c825367aead70c48a462254..4fdda974dc837e03d930091ba10fdef0adbe7c63 100644 (file)
@@ -76,7 +76,6 @@ void gfs2_tune_init(struct gfs2_tune *gt)
        gt->gt_stall_secs = 600;
        gt->gt_complain_secs = 10;
        gt->gt_reclaim_limit = 5000;
-       gt->gt_entries_per_readdir = 32;
        gt->gt_statfs_quantum = 30;
        gt->gt_statfs_slow = 0;
 }
index e965eb11d76fa4e92034ceb0bcba4e69f1f0271d..9baf69773ed119c2144bdb228ea592a715cec1f5 100644 (file)
@@ -47,7 +47,7 @@ struct dentry_operations hostfs_dentry_ops = {
 };
 
 /* Changed in hostfs_args before the kernel starts running */
-static char *root_ino = "/";
+static char *root_ino = "";
 static int append = 0;
 
 #define HOSTFS_SUPER_MAGIC 0x00c0ffee
@@ -947,15 +947,17 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
        sb->s_magic = HOSTFS_SUPER_MAGIC;
        sb->s_op = &hostfs_sbops;
 
-       if((data == NULL) || (*data == '\0'))
-               data = root_ino;
+       /* NULL is printed as <NULL> by sprintf: avoid that. */
+       if (data == NULL)
+               data = "";
 
        err = -ENOMEM;
-       name = kmalloc(strlen(data) + 1, GFP_KERNEL);
+       name = kmalloc(strlen(root_ino) + 1
+                       + strlen(data) + 1, GFP_KERNEL);
        if(name == NULL)
                goto out;
 
-       strcpy(name, data);
+       sprintf(name, "%s/%s", root_ino, data);
 
        root_inode = iget(sb, 0);
        if(root_inode == NULL)
@@ -966,6 +968,9 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
                goto out_put;
 
        HOSTFS_I(root_inode)->host_filename = name;
+       /* Avoid that in the error path, iput(root_inode) frees again name through
+        * hostfs_destroy_inode! */
+       name = NULL;
 
        err = -ENOMEM;
        sb->s_root = d_alloc_root(root_inode);
@@ -977,7 +982,7 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
                 /* No iput in this case because the dput does that for us */
                 dput(sb->s_root);
                 sb->s_root = NULL;
-               goto out_free;
+               goto out;
         }
 
        return(0);
index 6eb3daebd56354ca4973093c9d5966c7e148ae0a..888f236e54948a77fdfd26736a80a1ffd99a35f7 100644 (file)
@@ -99,7 +99,13 @@ static int jffs2_garbage_collect_thread(void *_c)
                if (try_to_freeze())
                        continue;
 
-               cond_resched();
+               /* This thread is purely an optimisation. But if it runs when
+                  other things could be running, it actually makes things a
+                  lot worse. Use yield() and put it at the back of the runqueue
+                  every time. Especially during boot, pulling an inode in
+                  with read_inode() is much preferable to having the GC thread
+                  get there first. */
+               yield();
 
                /* Put_super will send a SIGKILL and then wait on the sem.
                 */
diff --git a/fs/jffs2/comprtest.c b/fs/jffs2/comprtest.c
deleted file mode 100644 (file)
index f0fb8be..0000000
+++ /dev/null
@@ -1,307 +0,0 @@
-/* $Id: comprtest.c,v 1.6 2005/11/07 11:14:38 gleixner Exp $ */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/module.h>
-#include <asm/types.h>
-#if 0
-#define TESTDATA_LEN 512
-static unsigned char testdata[TESTDATA_LEN] = {
- 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x83, 0x04, 0x08, 0x34, 0x00, 0x00, 0x00,
- 0xb0, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x20, 0x00, 0x06, 0x00, 0x28, 0x00,
- 0x1e, 0x00, 0x1b, 0x00, 0x06, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x80, 0x04, 0x08,
- 0x34, 0x80, 0x04, 0x08, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0xf4, 0x80, 0x04, 0x08,
- 0xf4, 0x80, 0x04, 0x08, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x08,
- 0x00, 0x80, 0x04, 0x08, 0x0d, 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
- 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x10, 0x95, 0x04, 0x08,
- 0x10, 0x95, 0x04, 0x08, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x00, 0x10, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x58, 0x05, 0x00, 0x00, 0x58, 0x95, 0x04, 0x08,
- 0x58, 0x95, 0x04, 0x08, 0xa0, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x08, 0x81, 0x04, 0x08,
- 0x08, 0x81, 0x04, 0x08, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x2f, 0x6c, 0x69, 0x62, 0x2f, 0x6c, 0x64, 0x2d, 0x6c, 0x69, 0x6e, 0x75,
- 0x78, 0x2e, 0x73, 0x6f, 0x2e, 0x32, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x47, 0x4e, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00,
- 0x0c, 0x83, 0x04, 0x08, 0x81, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
- 0x1c, 0x83, 0x04, 0x08, 0xac, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00,
- 0x2c, 0x83, 0x04, 0x08, 0xdd, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
- 0x3c, 0x83, 0x04, 0x08, 0x2e, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
- 0x4c, 0x83, 0x04, 0x08, 0x7d, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
- 0x00, 0x85, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x67,
- 0x6d, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x5f, 0x00, 0x6c, 0x69, 0x62, 0x63,
- 0x2e, 0x73, 0x6f, 0x2e, 0x36, 0x00, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x00, 0x5f, 0x5f, 0x63};
-#else
-#define TESTDATA_LEN 3481
-static unsigned char testdata[TESTDATA_LEN] = {
- 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x22, 0x64, 0x62, 0x65, 0x6e, 0x63, 0x68,
- 0x2e, 0x68, 0x22, 0x0a, 0x0a, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x4d, 0x41, 0x58,
- 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x20, 0x31, 0x30, 0x30, 0x30, 0x0a, 0x0a, 0x73, 0x74, 0x61,
- 0x74, 0x69, 0x63, 0x20, 0x63, 0x68, 0x61, 0x72, 0x20, 0x62, 0x75, 0x66, 0x5b, 0x37, 0x30, 0x30,
- 0x30, 0x30, 0x5d, 0x3b, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x20,
- 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x61,
- 0x74, 0x69, 0x63, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x7b, 0x0a, 0x09, 0x69, 0x6e,
- 0x74, 0x20, 0x66, 0x64, 0x3b, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c,
- 0x65, 0x3b, 0x0a, 0x7d, 0x20, 0x66, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x4d, 0x41, 0x58, 0x5f,
- 0x46, 0x49, 0x4c, 0x45, 0x53, 0x5d, 0x3b, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f,
- 0x5f, 0x75, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x28, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x66, 0x6e,
- 0x61, 0x6d, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x75, 0x70, 0x70, 0x65, 0x72,
- 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x3b, 0x0a, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x75,
- 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x20, 0x21, 0x3d, 0x20,
- 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x28,
- 0x25, 0x64, 0x29, 0x20, 0x75, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x25, 0x73, 0x20, 0x66, 0x61,
- 0x69, 0x6c, 0x65, 0x64, 0x20, 0x28, 0x25, 0x73, 0x29, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09,
- 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75,
- 0x6e, 0x74, 0x2c, 0x20, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x65, 0x72,
- 0x72, 0x6f, 0x72, 0x28, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x29, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a,
- 0x7d, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x5f, 0x66,
- 0x69, 0x6c, 0x65, 0x28, 0x69, 0x6e, 0x74, 0x20, 0x66, 0x64, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20,
- 0x73, 0x69, 0x7a, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x73, 0x3b, 0x0a,
- 0x09, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x28, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x20, 0x7b, 0x0a,
- 0x09, 0x09, 0x73, 0x20, 0x3d, 0x20, 0x4d, 0x49, 0x4e, 0x28, 0x73, 0x69, 0x7a, 0x65, 0x6f, 0x66,
- 0x28, 0x62, 0x75, 0x66, 0x29, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x09,
- 0x77, 0x72, 0x69, 0x74, 0x65, 0x28, 0x66, 0x64, 0x2c, 0x20, 0x62, 0x75, 0x66, 0x2c, 0x20, 0x73,
- 0x29, 0x3b, 0x0a, 0x09, 0x09, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x2d, 0x3d, 0x20, 0x73, 0x3b, 0x0a,
- 0x09, 0x7d, 0x0a, 0x7d, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x6f, 0x70,
- 0x65, 0x6e, 0x28, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20,
- 0x69, 0x6e, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20,
- 0x73, 0x69, 0x7a, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x66, 0x64, 0x2c,
- 0x20, 0x69, 0x3b, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x3d,
- 0x20, 0x4f, 0x5f, 0x52, 0x44, 0x57, 0x52, 0x7c, 0x4f, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x3b,
- 0x0a, 0x09, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x73, 0x74, 0x61, 0x74, 0x20, 0x73, 0x74,
- 0x3b, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x63, 0x6f,
- 0x75, 0x6e, 0x74, 0x3b, 0x0a, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x75, 0x70, 0x70, 0x65, 0x72, 0x28,
- 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x3b, 0x0a, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x73, 0x69,
- 0x7a, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x7c,
- 0x3d, 0x20, 0x4f, 0x5f, 0x54, 0x52, 0x55, 0x4e, 0x43, 0x3b, 0x0a, 0x0a, 0x09, 0x66, 0x64, 0x20,
- 0x3d, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x66, 0x6c,
- 0x61, 0x67, 0x73, 0x2c, 0x20, 0x30, 0x36, 0x30, 0x30, 0x29, 0x3b, 0x0a, 0x09, 0x69, 0x66, 0x20,
- 0x28, 0x66, 0x64, 0x20, 0x3d, 0x3d, 0x20, 0x2d, 0x31, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70,
- 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x28, 0x25, 0x64, 0x29, 0x20, 0x6f, 0x70, 0x65, 0x6e,
- 0x20, 0x25, 0x73, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x68,
- 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x25, 0x64, 0x20, 0x28, 0x25, 0x73, 0x29, 0x5c, 0x6e, 0x22,
- 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65,
- 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x68,
- 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28,
- 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x29, 0x29, 0x3b, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72,
- 0x6e, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x66, 0x73, 0x74, 0x61, 0x74, 0x28, 0x66, 0x64, 0x2c,
- 0x20, 0x26, 0x73, 0x74, 0x29, 0x3b, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x73, 0x69, 0x7a, 0x65,
- 0x20, 0x3e, 0x20, 0x73, 0x74, 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x20, 0x7b,
- 0x0a, 0x23, 0x69, 0x66, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69,
- 0x6e, 0x74, 0x66, 0x28, 0x22, 0x28, 0x25, 0x64, 0x29, 0x20, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64,
- 0x69, 0x6e, 0x67, 0x20, 0x25, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x25, 0x64, 0x20, 0x66, 0x72, 0x6f,
- 0x6d, 0x20, 0x25, 0x64, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20, 0x66,
- 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2c, 0x20, 0x28, 0x69, 0x6e, 0x74,
- 0x29, 0x73, 0x74, 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x23, 0x65,
- 0x6e, 0x64, 0x69, 0x66, 0x0a, 0x09, 0x09, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x5f, 0x66, 0x69,
- 0x6c, 0x65, 0x28, 0x66, 0x64, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x2d, 0x20, 0x73, 0x74,
- 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x20, 0x65, 0x6c,
- 0x73, 0x65, 0x20, 0x69, 0x66, 0x20, 0x28, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x3c, 0x20, 0x73, 0x74,
- 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72,
- 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x69, 0x6e, 0x67,
- 0x20, 0x25, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x25, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x25,
- 0x64, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2c, 0x20, 0x28, 0x69, 0x6e,
- 0x74, 0x29, 0x73, 0x74, 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x09,
- 0x09, 0x66, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x28, 0x66, 0x64, 0x2c, 0x20, 0x73,
- 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x69,
- 0x3d, 0x30, 0x3b, 0x69, 0x3c, 0x4d, 0x41, 0x58, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x3b, 0x69,
- 0x2b, 0x2b, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x66, 0x74, 0x61, 0x62,
- 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x3d, 0x3d, 0x20,
- 0x30, 0x29, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x69, 0x66,
- 0x20, 0x28, 0x69, 0x20, 0x3d, 0x3d, 0x20, 0x4d, 0x41, 0x58, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53,
- 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x66, 0x69,
- 0x6c, 0x65, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x66, 0x6f,
- 0x72, 0x20, 0x25, 0x73, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x3b,
- 0x0a, 0x09, 0x09, 0x65, 0x78, 0x69, 0x74, 0x28, 0x31, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09,
- 0x66, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65,
- 0x20, 0x3d, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x3b, 0x0a, 0x09, 0x66, 0x74, 0x61, 0x62,
- 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x66, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x64, 0x3b, 0x0a, 0x09,
- 0x69, 0x66, 0x20, 0x28, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2b, 0x2b, 0x20, 0x25, 0x20, 0x31, 0x30,
- 0x30, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e,
- 0x74, 0x66, 0x28, 0x22, 0x2e, 0x22, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x7d, 0x0a, 0x0a, 0x76,
- 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x28, 0x69, 0x6e, 0x74,
- 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x7a,
- 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x29, 0x0a, 0x7b,
- 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x69, 0x3b, 0x0a, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x62,
- 0x75, 0x66, 0x5b, 0x30, 0x5d, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x6d, 0x65, 0x6d, 0x73,
- 0x65, 0x74, 0x28, 0x62, 0x75, 0x66, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x6f,
- 0x66, 0x28, 0x62, 0x75, 0x66, 0x29, 0x29, 0x3b, 0x0a, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28,
- 0x69, 0x3d, 0x30, 0x3b, 0x69, 0x3c, 0x4d, 0x41, 0x58, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x3b,
- 0x69, 0x2b, 0x2b, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x66, 0x74, 0x61,
- 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x3d, 0x3d,
- 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x29, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a,
- 0x09, 0x7d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x69, 0x20, 0x3d, 0x3d, 0x20, 0x4d, 0x41, 0x58,
- 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x29, 0x20, 0x7b, 0x0a, 0x23, 0x69, 0x66, 0x20, 0x31, 0x0a,
- 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x28, 0x25, 0x64, 0x29, 0x20, 0x64,
- 0x6f, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x3a, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20,
- 0x25, 0x64, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20,
- 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x25, 0x64, 0x20, 0x6f, 0x66, 0x73, 0x3d, 0x25, 0x64, 0x5c, 0x6e,
- 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e,
- 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x2c,
- 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2c, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x29, 0x3b, 0x0a,
- 0x23, 0x65, 0x6e, 0x64, 0x69, 0x66, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x3b,
- 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x6c, 0x73, 0x65, 0x65, 0x6b, 0x28, 0x66, 0x74, 0x61, 0x62, 0x6c,
- 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x66, 0x64, 0x2c, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c,
- 0x20, 0x53, 0x45, 0x45, 0x4b, 0x5f, 0x53, 0x45, 0x54, 0x29, 0x3b, 0x0a, 0x09, 0x69, 0x66, 0x20,
- 0x28, 0x77, 0x72, 0x69, 0x74, 0x65, 0x28, 0x66, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d,
- 0x2e, 0x66, 0x64, 0x2c, 0x20, 0x62, 0x75, 0x66, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x20,
- 0x21, 0x3d, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69,
- 0x6e, 0x74, 0x66, 0x28, 0x22, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65,
- 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x25, 0x64, 0x5c, 0x6e,
- 0x22, 0x2c, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x7d,
- 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x28, 0x69,
- 0x6e, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x73,
- 0x69, 0x7a, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x29,
- 0x0a, 0x7b, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x69, 0x3b, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20,
- 0x28, 0x69, 0x3d, 0x30, 0x3b, 0x69, 0x3c, 0x4d, 0x41, 0x58, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53,
- 0x3b, 0x69, 0x2b, 0x2b, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x66, 0x74,
- 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x3d,
- 0x3d, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x29, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b,
- 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x69, 0x20, 0x3d, 0x3d, 0x20, 0x4d, 0x41,
- 0x58, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69,
- 0x6e, 0x74, 0x66, 0x28, 0x22, 0x28, 0x25, 0x64, 0x29, 0x20, 0x64, 0x6f, 0x5f, 0x72, 0x65, 0x61,
- 0x64, 0x3a, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x25, 0x64, 0x20, 0x77, 0x61, 0x73,
- 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x25,
- 0x64, 0x20, 0x6f, 0x66, 0x73, 0x3d, 0x25, 0x64, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e,
- 0x74, 0x2c, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2c,
- 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x29, 0x3b, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75,
- 0x72, 0x6e, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x6c, 0x73, 0x65, 0x65, 0x6b, 0x28, 0x66, 0x74,
- 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x66, 0x64, 0x2c, 0x20, 0x6f, 0x66, 0x66, 0x73,
- 0x65, 0x74, 0x2c, 0x20, 0x53, 0x45, 0x45, 0x4b, 0x5f, 0x53, 0x45, 0x54, 0x29, 0x3b, 0x0a, 0x09,
- 0x72, 0x65, 0x61, 0x64, 0x28, 0x66, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x66,
- 0x64, 0x2c, 0x20, 0x62, 0x75, 0x66, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x7d,
- 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x28,
- 0x69, 0x6e, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x09, 0x69,
- 0x6e, 0x74, 0x20, 0x69, 0x3b, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x69, 0x3d, 0x30, 0x3b,
- 0x69, 0x3c, 0x4d, 0x41, 0x58, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x3b, 0x69, 0x2b, 0x2b, 0x29,
- 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x66, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b,
- 0x69, 0x5d, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x68, 0x61, 0x6e,
- 0x64, 0x6c, 0x65, 0x29, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09,
- 0x69, 0x66, 0x20, 0x28, 0x69, 0x20, 0x3d, 0x3d, 0x20, 0x4d, 0x41, 0x58, 0x5f, 0x46, 0x49, 0x4c,
- 0x45, 0x53, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22,
- 0x28, 0x25, 0x64, 0x29, 0x20, 0x64, 0x6f, 0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x3a, 0x20, 0x68,
- 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x25, 0x64, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x74,
- 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20,
- 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72,
- 0x6e, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x28, 0x66, 0x74, 0x61,
- 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x66, 0x64, 0x29, 0x3b, 0x0a, 0x09, 0x66, 0x74, 0x61,
- 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x3d, 0x20,
- 0x30, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x6d, 0x6b,
- 0x64, 0x69, 0x72, 0x28, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29,
- 0x0a, 0x7b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x75, 0x70, 0x70, 0x65, 0x72, 0x28, 0x66, 0x6e, 0x61,
- 0x6d, 0x65, 0x29, 0x3b, 0x0a, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x6d, 0x6b, 0x64, 0x69, 0x72,
- 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x30, 0x37, 0x30, 0x30, 0x29, 0x20, 0x21, 0x3d,
- 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x23, 0x69, 0x66, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x0a,
- 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x6d, 0x6b, 0x64, 0x69, 0x72, 0x20,
- 0x25, 0x73, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x28, 0x25, 0x73, 0x29, 0x5c, 0x6e,
- 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6e, 0x61,
- 0x6d, 0x65, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x65, 0x72, 0x72,
- 0x6e, 0x6f, 0x29, 0x29, 0x3b, 0x0a, 0x23, 0x65, 0x6e, 0x64, 0x69, 0x66, 0x0a, 0x09, 0x7d, 0x0a,
- 0x7d, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x72, 0x6d, 0x64, 0x69, 0x72,
- 0x28, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x0a, 0x7b, 0x0a,
- 0x09, 0x73, 0x74, 0x72, 0x75, 0x70, 0x70, 0x65, 0x72, 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29,
- 0x3b, 0x0a, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x72, 0x6d, 0x64, 0x69, 0x72, 0x28, 0x66, 0x6e,
- 0x61, 0x6d, 0x65, 0x29, 0x20, 0x21, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70,
- 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x72, 0x6d, 0x64, 0x69, 0x72, 0x20, 0x25, 0x73, 0x20,
- 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x28, 0x25, 0x73, 0x29, 0x5c, 0x6e, 0x22, 0x2c, 0x20,
- 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c,
- 0x20, 0x73, 0x74, 0x72, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x29,
- 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x7d, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f,
- 0x5f, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x6f, 0x6c,
- 0x64, 0x2c, 0x20, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x6e, 0x65, 0x77, 0x29, 0x0a, 0x7b, 0x0a,
- 0x09, 0x73, 0x74, 0x72, 0x75, 0x70, 0x70, 0x65, 0x72, 0x28, 0x6f, 0x6c, 0x64, 0x29, 0x3b, 0x0a,
- 0x09, 0x73, 0x74, 0x72, 0x75, 0x70, 0x70, 0x65, 0x72, 0x28, 0x6e, 0x65, 0x77, 0x29, 0x3b, 0x0a,
- 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x6f, 0x6c, 0x64,
- 0x2c, 0x20, 0x6e, 0x65, 0x77, 0x29, 0x20, 0x21, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x09,
- 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x20,
- 0x25, 0x73, 0x20, 0x25, 0x73, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x28, 0x25, 0x73,
- 0x29, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x6e, 0x65, 0x77, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x65, 0x72, 0x72,
- 0x6f, 0x72, 0x28, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x29, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x7d,
- 0x0a, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x28,
- 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74,
- 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74,
- 0x20, 0x73, 0x74, 0x61, 0x74, 0x20, 0x73, 0x74, 0x3b, 0x0a, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x75,
- 0x70, 0x70, 0x65, 0x72, 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x3b, 0x0a, 0x0a, 0x09, 0x69,
- 0x66, 0x20, 0x28, 0x73, 0x74, 0x61, 0x74, 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x26,
- 0x73, 0x74, 0x29, 0x20, 0x21, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72,
- 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x28, 0x25, 0x64, 0x29, 0x20, 0x64, 0x6f, 0x5f, 0x73, 0x74,
- 0x61, 0x74, 0x3a, 0x20, 0x25, 0x73, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x25, 0x64, 0x20, 0x25,
- 0x73, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20, 0x66, 0x6e, 0x61, 0x6d,
- 0x65, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x65, 0x72, 0x72, 0x6f,
- 0x72, 0x28, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x29, 0x29, 0x3b, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74,
- 0x75, 0x72, 0x6e, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x53, 0x5f, 0x49,
- 0x53, 0x44, 0x49, 0x52, 0x28, 0x73, 0x74, 0x2e, 0x73, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x29,
- 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x3b, 0x0a, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28,
- 0x73, 0x74, 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x21, 0x3d, 0x20, 0x73, 0x69,
- 0x7a, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22,
- 0x28, 0x25, 0x64, 0x29, 0x20, 0x64, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x3a, 0x20, 0x25, 0x73,
- 0x20, 0x77, 0x72, 0x6f, 0x6e, 0x67, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x25, 0x64, 0x20, 0x25,
- 0x64, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20, 0x66, 0x6e, 0x61, 0x6d,
- 0x65, 0x2c, 0x20, 0x28, 0x69, 0x6e, 0x74, 0x29, 0x73, 0x74, 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69,
- 0x7a, 0x65, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x7d, 0x0a,
- 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x28,
- 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74,
- 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x09, 0x64, 0x6f, 0x5f, 0x6f, 0x70, 0x65,
- 0x6e, 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x35, 0x30, 0x30, 0x30, 0x2c, 0x20, 0x73,
- 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x64, 0x6f, 0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x28,
- 0x35, 0x30, 0x30, 0x30, 0x29, 0x3b, 0x0a, 0x7d, 0x0a
-};
-#endif
-static unsigned char comprbuf[TESTDATA_LEN];
-static unsigned char decomprbuf[TESTDATA_LEN];
-
-int jffs2_decompress(unsigned char comprtype, unsigned char *cdata_in,
-                    unsigned char *data_out, uint32_t cdatalen, uint32_t datalen);
-unsigned char jffs2_compress(unsigned char *data_in, unsigned char *cpage_out,
-                            uint32_t *datalen, uint32_t *cdatalen);
-
-int init_module(void ) {
-       unsigned char comprtype;
-       uint32_t c, d;
-       int ret;
-
-       printk("Original data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
-              testdata[0],testdata[1],testdata[2],testdata[3],
-              testdata[4],testdata[5],testdata[6],testdata[7],
-              testdata[8],testdata[9],testdata[10],testdata[11],
-              testdata[12],testdata[13],testdata[14],testdata[15]);
-       d = TESTDATA_LEN;
-       c = TESTDATA_LEN;
-       comprtype = jffs2_compress(testdata, comprbuf, &d, &c);
-
-       printk("jffs2_compress used compression type %d. Compressed size %d, uncompressed size %d\n",
-              comprtype, c, d);
-       printk("Compressed data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
-              comprbuf[0],comprbuf[1],comprbuf[2],comprbuf[3],
-              comprbuf[4],comprbuf[5],comprbuf[6],comprbuf[7],
-              comprbuf[8],comprbuf[9],comprbuf[10],comprbuf[11],
-              comprbuf[12],comprbuf[13],comprbuf[14],comprbuf[15]);
-
-       ret = jffs2_decompress(comprtype, comprbuf, decomprbuf, c, d);
-       printk("jffs2_decompress returned %d\n", ret);
-       printk("Decompressed data:  %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
-              decomprbuf[0],decomprbuf[1],decomprbuf[2],decomprbuf[3],
-              decomprbuf[4],decomprbuf[5],decomprbuf[6],decomprbuf[7],
-              decomprbuf[8],decomprbuf[9],decomprbuf[10],decomprbuf[11],
-              decomprbuf[12],decomprbuf[13],decomprbuf[14],decomprbuf[15]);
-       if (memcmp(decomprbuf, testdata, d))
-               printk("Compression and decompression corrupted data\n");
-       else
-               printk("Compression good for %d bytes\n", d);
-       return 1;
-}
index 58a0b912e9d05ce5697ff1239711ead97671e152..717a48cf7df2aadbccde0432024dafde0e80a410 100644 (file)
@@ -373,7 +373,14 @@ free_out:
 static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, struct jffs2_unknown_node *un)
 {
        /* We don't mark unknown nodes as REF_UNCHECKED */
-       BUG_ON(ref_flags(ref) == REF_UNCHECKED);
+       if (ref_flags(ref) == REF_UNCHECKED) {
+               JFFS2_ERROR("REF_UNCHECKED but unknown node at %#08x\n",
+                           ref_offset(ref));
+               JFFS2_ERROR("Node is {%04x,%04x,%08x,%08x}. Please report this error.\n",
+                            je16_to_cpu(un->magic), je16_to_cpu(un->nodetype),
+                            je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc));
+               return 1;
+       }
 
        un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype));
 
@@ -576,6 +583,13 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
                        jffs2_mark_node_obsolete(c, ref);
                        goto cont;
                }
+               /* Due to poor choice of crc32 seed, an all-zero node will have a correct CRC */
+               if (!je32_to_cpu(node->u.hdr_crc) && !je16_to_cpu(node->u.nodetype) &&
+                   !je16_to_cpu(node->u.magic) && !je32_to_cpu(node->u.totlen)) {
+                       JFFS2_NOTICE("All zero node header at %#08x.\n", ref_offset(ref));
+                       jffs2_mark_node_obsolete(c, ref);
+                       goto cont;
+               }
 
                switch (je16_to_cpu(node->u.nodetype)) {
 
index 31c1475d922aa2d3f4eb5c75841838f1100a385b..7fb45bd4915c5c1f1cbc8ffb71bd226f5a99b24b 100644 (file)
@@ -734,6 +734,15 @@ scan_more:
                        ofs += 4;
                        continue;
                }
+               /* Due to poor choice of crc32 seed, an all-zero node will have a correct CRC */
+               if (!je32_to_cpu(node->hdr_crc) && !je16_to_cpu(node->nodetype) &&
+                   !je16_to_cpu(node->magic) && !je32_to_cpu(node->totlen)) {
+                       noisy_printk(&noise, "jffs2_scan_eraseblock(): All zero node header at 0x%08x.\n", ofs);
+                       if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
+                               return err;
+                       ofs += 4;
+                       continue;
+               }
 
                if (ofs + je32_to_cpu(node->totlen) >
                    jeb->offset + c->sector_size) {
index de718e3a169296c6c6dc526743f2498762205ee8..4fac6dd539545f91ef33fae876737202b93d2f55 100644 (file)
@@ -238,7 +238,10 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
        jeb = &c->blocks[c->wbuf_ofs / c->sector_size];
 
        spin_lock(&c->erase_completion_lock);
-       jffs2_block_refile(c, jeb, REFILE_NOTEMPTY);
+       if (c->wbuf_ofs % c->mtd->erasesize)
+               jffs2_block_refile(c, jeb, REFILE_NOTEMPTY);
+       else
+               jffs2_block_refile(c, jeb, REFILE_ANYWAY);
        spin_unlock(&c->erase_completion_lock);
 
        BUG_ON(!ref_obsolete(jeb->last_node));
@@ -1087,7 +1090,7 @@ int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *
        if (!c->mtd->block_markbad)
                return 1; // What else can we do?
 
-       D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Marking bad block at %08x\n", bad_offset));
+       printk(KERN_WARNING "JFFS2: marking eraseblock at %08x\n as bad", bad_offset);
        ret = c->mtd->block_markbad(c->mtd, bad_offset);
 
        if (ret) {
index 6988a1082f5818e48fe4dd36d4aab07bc0016f50..03893acbfda479d15351fb5f45dc9b74b4cd6986 100644 (file)
@@ -1919,7 +1919,8 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
         * header ?
         */
        if (tlck->type & tlckTRUNCATE) {
-               pxd_t pxd;      /* truncated extent of xad */
+               /* This odd declaration suppresses a bogus gcc warning */
+               pxd_t pxd = pxd;        /* truncated extent of xad */
                int twm;
 
                /*
index 7d487047dbb8814ea1d5f0a01c9e30c630d9a322..d93842d3c0a0b66943a0491622e0793971d70de5 100644 (file)
@@ -190,6 +190,10 @@ const struct inode_operations simple_dir_inode_operations = {
        .lookup         = simple_lookup,
 };
 
+static const struct super_operations simple_super_operations = {
+       .statfs         = simple_statfs,
+};
+
 /*
  * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that
  * will never be mountable)
@@ -199,7 +203,6 @@ int get_sb_pseudo(struct file_system_type *fs_type, char *name,
        struct vfsmount *mnt)
 {
        struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
-       static const struct super_operations default_ops = {.statfs = simple_statfs};
        struct dentry *dentry;
        struct inode *root;
        struct qstr d_name = {.name = name, .len = strlen(name)};
@@ -212,7 +215,7 @@ int get_sb_pseudo(struct file_system_type *fs_type, char *name,
        s->s_blocksize = 1024;
        s->s_blocksize_bits = 10;
        s->s_magic = magic;
-       s->s_op = ops ? ops : &default_ops;
+       s->s_op = ops ? ops : &simple_super_operations;
        s->s_time_gran = 1;
        root = new_inode(s);
        if (!root)
@@ -335,17 +338,18 @@ int simple_prepare_write(struct file *file, struct page *page,
                        flush_dcache_page(page);
                        kunmap_atomic(kaddr, KM_USER0);
                }
-               SetPageUptodate(page);
        }
        return 0;
 }
 
 int simple_commit_write(struct file *file, struct page *page,
-                       unsigned offset, unsigned to)
+                       unsigned from, unsigned to)
 {
        struct inode *inode = page->mapping->host;
        loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
 
+       if (!PageUptodate(page))
+               SetPageUptodate(page);
        /*
         * No need to use i_size_read() here, the i_size
         * cannot change under us because we hold the i_mutex.
@@ -358,7 +362,6 @@ int simple_commit_write(struct file *file, struct page *page,
 
 int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files)
 {
-       static struct super_operations s_ops = {.statfs = simple_statfs};
        struct inode *inode;
        struct dentry *root;
        struct dentry *dentry;
@@ -367,7 +370,7 @@ int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files
        s->s_blocksize = PAGE_CACHE_SIZE;
        s->s_blocksize_bits = PAGE_CACHE_SHIFT;
        s->s_magic = magic;
-       s->s_op = &s_ops;
+       s->s_op = &simple_super_operations;
        s->s_time_gran = 1;
 
        inode = new_inode(s);
index 14939ddf74f16b0c2fed361fdfb06f685d4c05b6..7285c94956c4988cbf1fd06b2a01bd3b0216cd4e 100644 (file)
@@ -576,6 +576,12 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
        server->packet = vmalloc(NCP_PACKET_SIZE);
        if (server->packet == NULL)
                goto out_nls;
+       server->txbuf = vmalloc(NCP_PACKET_SIZE);
+       if (server->txbuf == NULL)
+               goto out_packet;
+       server->rxbuf = vmalloc(NCP_PACKET_SIZE);
+       if (server->rxbuf == NULL)
+               goto out_txbuf;
 
        sock->sk->sk_data_ready   = ncp_tcp_data_ready;
        sock->sk->sk_error_report = ncp_tcp_error_report;
@@ -597,7 +603,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
        error = ncp_connect(server);
        ncp_unlock_server(server);
        if (error < 0)
-               goto out_packet;
+               goto out_rxbuf;
        DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
 
        error = -EMSGSIZE;      /* -EREMOTESIDEINCOMPATIBLE */
@@ -666,8 +672,12 @@ out_disconnect:
        ncp_lock_server(server);
        ncp_disconnect(server);
        ncp_unlock_server(server);
-out_packet:
+out_rxbuf:
        ncp_stop_tasks(server);
+       vfree(server->rxbuf);
+out_txbuf:
+       vfree(server->txbuf);
+out_packet:
        vfree(server->packet);
 out_nls:
 #ifdef CONFIG_NCPFS_NLS
@@ -723,6 +733,8 @@ static void ncp_put_super(struct super_block *sb)
 
        kfree(server->priv.data);
        kfree(server->auth.object_name);
+       vfree(server->rxbuf);
+       vfree(server->txbuf);
        vfree(server->packet);
        sb->s_fs_info = NULL;
        kfree(server);
index e496d8b65e92d50141139cec9519353e0a953793..e37df8d5fe707968d0720de94b45c6a4bf5d8f2e 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/socket.h>
 #include <linux/fcntl.h>
 #include <linux/stat.h>
+#include <linux/string.h>
 #include <asm/uaccess.h>
 #include <linux/in.h>
 #include <linux/net.h>
@@ -55,10 +56,11 @@ static int _send(struct socket *sock, const void *buff, int len)
 struct ncp_request_reply {
        struct list_head req;
        wait_queue_head_t wq;
-       struct ncp_reply_header* reply_buf;
+       atomic_t refs;
+       unsigned char* reply_buf;
        size_t datalen;
        int result;
-       enum { RQ_DONE, RQ_INPROGRESS, RQ_QUEUED, RQ_IDLE } status;
+       enum { RQ_DONE, RQ_INPROGRESS, RQ_QUEUED, RQ_IDLE, RQ_ABANDONED } status;
        struct kvec* tx_ciov;
        size_t tx_totallen;
        size_t tx_iovlen;
@@ -67,6 +69,32 @@ struct ncp_request_reply {
        u_int32_t sign[6];
 };
 
+static inline struct ncp_request_reply* ncp_alloc_req(void)
+{
+       struct ncp_request_reply *req;
+
+       req = kmalloc(sizeof(struct ncp_request_reply), GFP_KERNEL);
+       if (!req)
+               return NULL;
+
+       init_waitqueue_head(&req->wq);
+       atomic_set(&req->refs, (1));
+       req->status = RQ_IDLE;
+
+       return req;
+}
+
+static void ncp_req_get(struct ncp_request_reply *req)
+{
+       atomic_inc(&req->refs);
+}
+
+static void ncp_req_put(struct ncp_request_reply *req)
+{
+       if (atomic_dec_and_test(&req->refs))
+               kfree(req);
+}
+
 void ncp_tcp_data_ready(struct sock *sk, int len)
 {
        struct ncp_server *server = sk->sk_user_data;
@@ -101,14 +129,17 @@ void ncpdgram_timeout_call(unsigned long v)
        schedule_work(&server->timeout_tq);
 }
 
-static inline void ncp_finish_request(struct ncp_request_reply *req, int result)
+static inline void ncp_finish_request(struct ncp_server *server, struct ncp_request_reply *req, int result)
 {
        req->result = result;
+       if (req->status != RQ_ABANDONED)
+               memcpy(req->reply_buf, server->rxbuf, req->datalen);
        req->status = RQ_DONE;
        wake_up_all(&req->wq);
+       ncp_req_put(req);
 }
 
-static void __abort_ncp_connection(struct ncp_server *server, struct ncp_request_reply *aborted, int err)
+static void __abort_ncp_connection(struct ncp_server *server)
 {
        struct ncp_request_reply *req;
 
@@ -118,31 +149,19 @@ static void __abort_ncp_connection(struct ncp_server *server, struct ncp_request
                req = list_entry(server->tx.requests.next, struct ncp_request_reply, req);
                
                list_del_init(&req->req);
-               if (req == aborted) {
-                       ncp_finish_request(req, err);
-               } else {
-                       ncp_finish_request(req, -EIO);
-               }
+               ncp_finish_request(server, req, -EIO);
        }
        req = server->rcv.creq;
        if (req) {
                server->rcv.creq = NULL;
-               if (req == aborted) {
-                       ncp_finish_request(req, err);
-               } else {
-                       ncp_finish_request(req, -EIO);
-               }
+               ncp_finish_request(server, req, -EIO);
                server->rcv.ptr = NULL;
                server->rcv.state = 0;
        }
        req = server->tx.creq;
        if (req) {
                server->tx.creq = NULL;
-               if (req == aborted) {
-                       ncp_finish_request(req, err);
-               } else {
-                       ncp_finish_request(req, -EIO);
-               }
+               ncp_finish_request(server, req, -EIO);
        }
 }
 
@@ -160,10 +179,12 @@ static inline void __ncp_abort_request(struct ncp_server *server, struct ncp_req
                        break;
                case RQ_QUEUED:
                        list_del_init(&req->req);
-                       ncp_finish_request(req, err);
+                       ncp_finish_request(server, req, err);
                        break;
                case RQ_INPROGRESS:
-                       __abort_ncp_connection(server, req, err);
+                       req->status = RQ_ABANDONED;
+                       break;
+               case RQ_ABANDONED:
                        break;
        }
 }
@@ -177,7 +198,7 @@ static inline void ncp_abort_request(struct ncp_server *server, struct ncp_reque
 
 static inline void __ncptcp_abort(struct ncp_server *server)
 {
-       __abort_ncp_connection(server, NULL, 0);
+       __abort_ncp_connection(server);
 }
 
 static int ncpdgram_send(struct socket *sock, struct ncp_request_reply *req)
@@ -294,6 +315,11 @@ static void ncptcp_start_request(struct ncp_server *server, struct ncp_request_r
 
 static inline void __ncp_start_request(struct ncp_server *server, struct ncp_request_reply *req)
 {
+       /* we copy the data so that we do not depend on the caller
+          staying alive */
+       memcpy(server->txbuf, req->tx_iov[1].iov_base, req->tx_iov[1].iov_len);
+       req->tx_iov[1].iov_base = server->txbuf;
+
        if (server->ncp_sock->type == SOCK_STREAM)
                ncptcp_start_request(server, req);
        else
@@ -308,6 +334,7 @@ static int ncp_add_request(struct ncp_server *server, struct ncp_request_reply *
                printk(KERN_ERR "ncpfs: tcp: Server died\n");
                return -EIO;
        }
+       ncp_req_get(req);
        if (server->tx.creq || server->rcv.creq) {
                req->status = RQ_QUEUED;
                list_add_tail(&req->req, &server->tx.requests);
@@ -409,7 +436,7 @@ void ncpdgram_rcv_proc(struct work_struct *work)
                                        server->timeout_last = NCP_MAX_RPC_TIMEOUT;
                                        mod_timer(&server->timeout_tm, jiffies + NCP_MAX_RPC_TIMEOUT);
                                } else if (reply.type == NCP_REPLY) {
-                                       result = _recv(sock, (void*)req->reply_buf, req->datalen, MSG_DONTWAIT);
+                                       result = _recv(sock, server->rxbuf, req->datalen, MSG_DONTWAIT);
 #ifdef CONFIG_NCPFS_PACKET_SIGNING
                                        if (result >= 0 && server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) {
                                                if (result < 8 + 8) {
@@ -419,7 +446,7 @@ void ncpdgram_rcv_proc(struct work_struct *work)
                                                        
                                                        result -= 8;
                                                        hdrl = sock->sk->sk_family == AF_INET ? 8 : 6;
-                                                       if (sign_verify_reply(server, ((char*)req->reply_buf) + hdrl, result - hdrl, cpu_to_le32(result), ((char*)req->reply_buf) + result)) {
+                                                       if (sign_verify_reply(server, server->rxbuf + hdrl, result - hdrl, cpu_to_le32(result), server->rxbuf + result)) {
                                                                printk(KERN_INFO "ncpfs: Signature violation\n");
                                                                result = -EIO;
                                                        }
@@ -428,7 +455,7 @@ void ncpdgram_rcv_proc(struct work_struct *work)
 #endif
                                        del_timer(&server->timeout_tm);
                                        server->rcv.creq = NULL;
-                                       ncp_finish_request(req, result);
+                                       ncp_finish_request(server, req, result);
                                        __ncp_next_request(server);
                                        mutex_unlock(&server->rcv.creq_mutex);
                                        continue;
@@ -478,12 +505,6 @@ void ncpdgram_timeout_proc(struct work_struct *work)
        mutex_unlock(&server->rcv.creq_mutex);
 }
 
-static inline void ncp_init_req(struct ncp_request_reply* req)
-{
-       init_waitqueue_head(&req->wq);
-       req->status = RQ_IDLE;
-}
-
 static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len)
 {
        int result;
@@ -601,8 +622,8 @@ skipdata:;
                                        goto skipdata;
                                }
                                req->datalen = datalen - 8;
-                               req->reply_buf->type = NCP_REPLY;
-                               server->rcv.ptr = (unsigned char*)(req->reply_buf) + 2;
+                               ((struct ncp_reply_header*)server->rxbuf)->type = NCP_REPLY;
+                               server->rcv.ptr = server->rxbuf + 2;
                                server->rcv.len = datalen - 10;
                                server->rcv.state = 1;
                                break;
@@ -615,12 +636,12 @@ skipdata:;
                        case 1:
                                req = server->rcv.creq;
                                if (req->tx_type != NCP_ALLOC_SLOT_REQUEST) {
-                                       if (req->reply_buf->sequence != server->sequence) {
+                                       if (((struct ncp_reply_header*)server->rxbuf)->sequence != server->sequence) {
                                                printk(KERN_ERR "ncpfs: tcp: Bad sequence number\n");
                                                __ncp_abort_request(server, req, -EIO);
                                                return -EIO;
                                        }
-                                       if ((req->reply_buf->conn_low | (req->reply_buf->conn_high << 8)) != server->connection) {
+                                       if ((((struct ncp_reply_header*)server->rxbuf)->conn_low | (((struct ncp_reply_header*)server->rxbuf)->conn_high << 8)) != server->connection) {
                                                printk(KERN_ERR "ncpfs: tcp: Connection number mismatch\n");
                                                __ncp_abort_request(server, req, -EIO);
                                                return -EIO;
@@ -628,14 +649,14 @@ skipdata:;
                                }
 #ifdef CONFIG_NCPFS_PACKET_SIGNING                             
                                if (server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) {
-                                       if (sign_verify_reply(server, (unsigned char*)(req->reply_buf) + 6, req->datalen - 6, cpu_to_be32(req->datalen + 16), &server->rcv.buf.type)) {
+                                       if (sign_verify_reply(server, server->rxbuf + 6, req->datalen - 6, cpu_to_be32(req->datalen + 16), &server->rcv.buf.type)) {
                                                printk(KERN_ERR "ncpfs: tcp: Signature violation\n");
                                                __ncp_abort_request(server, req, -EIO);
                                                return -EIO;
                                        }
                                }
 #endif                         
-                               ncp_finish_request(req, req->datalen);
+                               ncp_finish_request(server, req, req->datalen);
                        nextreq:;
                                __ncp_next_request(server);
                        case 2:
@@ -645,7 +666,7 @@ skipdata:;
                                server->rcv.state = 0;
                                break;
                        case 3:
-                               ncp_finish_request(server->rcv.creq, -EIO);
+                               ncp_finish_request(server, server->rcv.creq, -EIO);
                                goto nextreq;
                        case 5:
                                info_server(server, 0, server->unexpected_packet.data, server->unexpected_packet.len);
@@ -675,28 +696,39 @@ void ncp_tcp_tx_proc(struct work_struct *work)
 }
 
 static int do_ncp_rpc_call(struct ncp_server *server, int size,
-               struct ncp_reply_header* reply_buf, int max_reply_size)
+               unsigned char* reply_buf, int max_reply_size)
 {
        int result;
-       struct ncp_request_reply req;
-
-       ncp_init_req(&req);
-       req.reply_buf = reply_buf;
-       req.datalen = max_reply_size;
-       req.tx_iov[1].iov_base = server->packet;
-       req.tx_iov[1].iov_len = size;
-       req.tx_iovlen = 1;
-       req.tx_totallen = size;
-       req.tx_type = *(u_int16_t*)server->packet;
-
-       result = ncp_add_request(server, &req);
-       if (result < 0) {
-               return result;
-       }
-       if (wait_event_interruptible(req.wq, req.status == RQ_DONE)) {
-               ncp_abort_request(server, &req, -EIO);
+       struct ncp_request_reply *req;
+
+       req = ncp_alloc_req();
+       if (!req)
+               return -ENOMEM;
+
+       req->reply_buf = reply_buf;
+       req->datalen = max_reply_size;
+       req->tx_iov[1].iov_base = server->packet;
+       req->tx_iov[1].iov_len = size;
+       req->tx_iovlen = 1;
+       req->tx_totallen = size;
+       req->tx_type = *(u_int16_t*)server->packet;
+
+       result = ncp_add_request(server, req);
+       if (result < 0)
+               goto out;
+
+       if (wait_event_interruptible(req->wq, req->status == RQ_DONE)) {
+               ncp_abort_request(server, req, -EINTR);
+               result = -EINTR;
+               goto out;
        }
-       return req.result;
+
+       result = req->result;
+
+out:
+       ncp_req_put(req);
+
+       return result;
 }
 
 /*
@@ -751,11 +783,6 @@ static int ncp_do_request(struct ncp_server *server, int size,
 
        DDPRINTK("do_ncp_rpc_call returned %d\n", result);
 
-       if (result < 0) {
-               /* There was a problem with I/O, so the connections is
-                * no longer usable. */
-               ncp_invalidate_conn(server);
-       }
        return result;
 }
 
index 22d38ffc9ef0b892c65e8c380f6f6682bacb398a..e46d237b10f90c1d7f643244a7ffd1e44b40bbfe 100644 (file)
@@ -180,7 +180,7 @@ check_partition(struct gendisk *hd, struct block_device *bdev)
        }
        if (res > 0)
                return state;
-       if (!err)
+       if (err)
        /* The partition is unrecognized. So report I/O errors if there were any */
                res = err;
        if (!res)
index 4f5745af8c193809f37d9f2cfa78be383d42ef9c..01f7769da8e67bf7f7091f6ece8ca09b060b859f 100644 (file)
@@ -581,7 +581,7 @@ out_no_task:
 
 #ifndef mem_write
 /* This is a security hazard */
-static ssize_t mem_write(struct file * file, const char buf,
+static ssize_t mem_write(struct file * file, const char __user *buf,
                         size_t count, loff_t *ppos)
 {
        int copied;
index 8813990304fe58f8b12449b6f99471887f1920ee..85a668680f82af4e550b3b381cf7340419eb7d86 100644 (file)
@@ -431,6 +431,8 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent)
        new_parent_dentry = new_parent ?
                new_parent->dentry : sysfs_mount->mnt_sb->s_root;
 
+       if (old_parent_dentry->d_inode == new_parent_dentry->d_inode)
+               return 0;       /* nothing to move */
 again:
        mutex_lock(&old_parent_dentry->d_inode->i_mutex);
        if (!mutex_trylock(&new_parent_dentry->d_inode->i_mutex)) {
index 98b0910ad80c43795456d56bd061966499bf7fa7..8d4d839a9d887eb4a753da824e55a98542b26f21 100644 (file)
@@ -501,6 +501,30 @@ int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
 }
 
 
+/**
+ * sysfs_add_file_to_group - add an attribute file to a pre-existing group.
+ * @kobj: object we're acting for.
+ * @attr: attribute descriptor.
+ * @group: group name.
+ */
+int sysfs_add_file_to_group(struct kobject *kobj,
+               const struct attribute *attr, const char *group)
+{
+       struct dentry *dir;
+       int error;
+
+       dir = lookup_one_len(group, kobj->dentry, strlen(group));
+       if (IS_ERR(dir))
+               error = PTR_ERR(dir);
+       else {
+               error = sysfs_add_file(dir, attr, SYSFS_KOBJ_ATTR);
+               dput(dir);
+       }
+       return error;
+}
+EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
+
+
 /**
  * sysfs_update_file - update the modified timestamp on an object attribute.
  * @kobj: object we're acting for.
@@ -586,6 +610,26 @@ void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
 }
 
 
+/**
+ * sysfs_remove_file_from_group - remove an attribute file from a group.
+ * @kobj: object we're acting for.
+ * @attr: attribute descriptor.
+ * @group: group name.
+ */
+void sysfs_remove_file_from_group(struct kobject *kobj,
+               const struct attribute *attr, const char *group)
+{
+       struct dentry *dir;
+
+       dir = lookup_one_len(group, kobj->dentry, strlen(group));
+       if (!IS_ERR(dir)) {
+               sysfs_hash_and_remove(dir, attr->name);
+               dput(dir);
+       }
+}
+EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group);
+
+
 EXPORT_SYMBOL_GPL(sysfs_create_file);
 EXPORT_SYMBOL_GPL(sysfs_remove_file);
 EXPORT_SYMBOL_GPL(sysfs_update_file);
index dd1344b007f59baf3b0d5ba05fadecd83f8d0604..ccb7d722c55897a6105e93457b923e5b1b741c0d 100644 (file)
@@ -227,11 +227,8 @@ static inline void orphan_all_buffers(struct inode *node)
 
        mutex_lock_nested(&node->i_mutex, I_MUTEX_CHILD);
        if (node->i_private) {
-               list_for_each_entry(buf, &set->associates, associates) {
-                       down(&buf->sem);
+               list_for_each_entry(buf, &set->associates, associates)
                        buf->orphaned = 1;
-                       up(&buf->sem);
-               }
        }
        mutex_unlock(&node->i_mutex);
 }
index d976b0005549e9deb720352298550dfed644a839..a77c57e5a6d5d983116203656559911142251c87 100644 (file)
@@ -1,3 +1,14 @@
+struct sysfs_dirent {
+       atomic_t                s_count;
+       struct list_head        s_sibling;
+       struct list_head        s_children;
+       void                    * s_element;
+       int                     s_type;
+       umode_t                 s_mode;
+       struct dentry           * s_dentry;
+       struct iattr            * s_iattr;
+       atomic_t                s_event;
+};
 
 extern struct vfsmount * sysfs_mount;
 extern struct kmem_cache *sysfs_dir_cachep;
index 1a4103ca593c9e285c3c9740686b793bcf541737..2f2c40db562e36942fdeaeaf9341ed6d41625757 100644 (file)
@@ -900,7 +900,7 @@ static struct quotactl_ops xfs_quotactl_operations = {
        .set_xquota             = xfs_fs_setxquota,
 };
 
-STATIC struct file_system_type xfs_fs_type = {
+static struct file_system_type xfs_fs_type = {
        .owner                  = THIS_MODULE,
        .name                   = "xfs",
        .get_sb                 = xfs_fs_get_sb,
index 1eb3503bd16e1a78303a610eb4723422cde8988a..83fdf68f6b7c9c216a1d6bbfe6152089fa414785 100644 (file)
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
                mov     r4, #0xf8000000
                add     r4, r4, #0x00000500
index 76c8cccf73aa18bc6c10dcf82507f5b45078c31c..cc1d850a0788012574c2c44310245789a8b1fbb5 100644 (file)
        .macro  disable_fiq
        .endm
 
+       .macro  get_irqnr_preamble, base, tmp
+       .endm
+
+       .macro  arch_ret_to_user, tmp1, tmp2
+       .endm
+
        .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
        ldr     \base, =(AT91_VA_BASE_SYS + AT91_AIC)           @ base virtual address of AIC peripheral
        ldr     \irqnr, [\base, #(AT91_AIC_IVR - AT91_AIC)]     @ read IRQ vector register: de-asserts nIRQ to processor (and clears interrupt)
index eaaf1c12b75330c9d1fbf52a46df61e71e8ac069..28133e0154dd880fd0af57c9080663649adaf0ce 100644 (file)
@@ -31,7 +31,7 @@
 
 /*
  * Remap the peripherals from address 0xFFF78000 .. 0xFFFFFFFF
- * to 0xFEF78000 .. 0xFF000000.  (5444Kb)
+ * to 0xFEF78000 .. 0xFF000000.  (544Kb)
  */
 #define AT91_IO_PHYS_BASE      0xFFF78000
 #define AT91_IO_SIZE           (0xFFFFFFFF - AT91_IO_PHYS_BASE + 1)
index c9e5395e510614a50259c4cd5719d724f4320ad9..0cfb89b229d18da94b1595aa4d429b1d24a5f7ab 100644 (file)
@@ -1,3 +1,8 @@
 #include <asm/hardware.h>
 #include <asm/hardware/entry-macro-iomd.S>
+       .macro  get_irqnr_preamble, base, tmp
+       .endm
+
+       .macro  arch_ret_to_user, tmp1, tmp2
+       .endm
 
index de4481dd8ba0ebe6fbc21dc11f9c9bcf9e55ee52..cd8c5a0bc7bce6dfae9b8060b4347840a4b539d6 100644 (file)
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
 #if (INTSR2 - INTSR1) != (INTMR2 - INTMR1)
 #error INTSR stride != INTMR stride
 #endif
index b12ca04f998c657feaacb1cc5e0a680d16ed0e6f..aa23c5d6c69e4b4b31daf9ca1726f53daf10dcc6 100644 (file)
        .macro  disable_fiq
        .endm
 
+       .macro  get_irqnr_preamble, base, tmp
+       .endm
+
+       .macro  arch_ret_to_user, tmp1, tmp2
+       .endm
+
        .macro  get_irqnr_and_base, irqnr, stat, base, tmp
        mov     \base, #IRQ_STAT
        ldrb    \stat, [\base]                  @ get interrupts
index ce812d4f4a33687cdbd2deeadfec5508331619fc..4203dbf106624d95a8955f953e968822579af99b 100644 (file)
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .equ    dc21285_high, ARMCSR_BASE & 0xff000000
                .equ    dc21285_low, ARMCSR_BASE & 0x00ffffff
 
index 84140a28dfcf8bec343ef7a3341ac1671b9a8341..241ec221a0471e4bef8f71a253e5db061ce394d1 100644 (file)
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
                ldr     \base, =(EP93XX_AHB_VIRT_BASE)
                orr     \base, \base, #0x000b0000
index 8f165648e2af0718a5d21e9fbc40ceea6987be00..38dd63ae104ea4c3c78f3f60fb645b477fb38cda 100644 (file)
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
 #if defined (CONFIG_CPU_H7201) || defined (CONFIG_CPU_H7202)
                @ we could use the id register on H7202, but this is not
index 61bb0bdc1b1651744c0b888a5ffd73a8461dd50c..0b84e81031c34f75a5d9223001e46626a3c20c31 100644 (file)
 
                .macro  disable_fiq
                .endm
+
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
 #define AITC_NIVECSR   0x40
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
                ldr     \base, =IO_ADDRESS(IMX_AITC_BASE)
index 69838d04f90bc9882c36c06ffa65a3b513737021..491af1a23de55ca28cf35703009ce72e30142d68 100644 (file)
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
 /* FIXME: should not be using soo many LDRs here */
                ldr     \base, =IO_ADDRESS(INTEGRATOR_IC_BASE)
index 94c50283dc56388f5cce96ba78ea0536d71f03f3..a624a7870c64b36deb67a91598af6e765fbbeba6 100644 (file)
        .macro  disable_fiq
        .endm
 
+       .macro get_irqnr_preamble, base, tmp
+       mrc     p15, 0, \tmp, c15, c1, 0
+       orr     \tmp, \tmp, #(1 << 6)
+       mcr     p15, 0, \tmp, c15, c1, 0        @ Enable cp6 access
+       .endm
+
        /*
         * Note: a 1-cycle window exists where iintvec will return the value
         * of iintbase, so we explicitly check for "bad zeros"
         */
        .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-       mrc     p15, 0, \tmp, c15, c1, 0
-       orr     \tmp, \tmp, #(1 << 6)
-       mcr     p15, 0, \tmp, c15, c1, 0        @ Enable cp6 access
-
        mrc     p6, 0, \irqnr, c3, c2, 0        @ Read IINTVEC
        cmp     \irqnr, #0
        mrceq   p6, 0, \irqnr, c3, c2, 0        @ Re-read on potentially bad zero
        adds    \irqstat, \irqnr, #1            @ Check for 0xffffffff
        movne   \irqnr, \irqnr, lsr #2          @ Convert to irqnr
+       .endm
 
-       biceq   \tmp, \tmp, #(1 << 6)
-       mcreq   p15, 0, \tmp, c15, c1, 0        @ Disable cp6 access if no more interrupts
+       .macro arch_ret_to_user, tmp1, tmp2
+       mrc     p15, 0, \tmp1, c15, c1, 0
+       ands    \tmp2, \tmp1, #(1 << 6)
+       bicne   \tmp1, \tmp1, #(1 << 6)
+       mcrne   p15, 0, \tmp1, c15, c1, 0       @ Disable cp6 access
        .endm
index a88522a0ff8ea8480993f877a4d62cbad46bd72c..d26b755a98795f57dadfad23e54fc97faa4ebf76 100644 (file)
@@ -9,34 +9,6 @@ void iop13xx_init_irq(void);
 void iop13xx_map_io(void);
 void iop13xx_platform_init(void);
 void iop13xx_init_irq(void);
-void iop13xx_init_time(unsigned long tickrate);
-unsigned long iop13xx_gettimeoffset(void);
-
-/* handle cp6 access
- * to do: handle access in entry-armv5.S and unify with
- * the iop3xx implementation
- * note: use iop13xx_cp6_enable_irq_save and iop13xx_cp6_irq_restore (irq.h)
- * when interrupts are enabled
- */
-static inline unsigned long iop13xx_cp6_save(void)
-{
-       u32 temp, cp_flags;
-
-       asm volatile (
-               "mrc    p15, 0, %1, c15, c1, 0\n\t"
-               "orr    %0, %1, #(1 << 6)\n\t"
-               "mcr    p15, 0, %0, c15, c1, 0\n\t"
-               : "=r" (temp), "=r"(cp_flags));
-
-       return cp_flags;
-}
-
-static inline void iop13xx_cp6_restore(unsigned long cp_flags)
-{
-       asm volatile (
-               "mcr    p15, 0, %0, c15, c1, 0\n\t"
-               : : "r" (cp_flags) );
-}
 
 /* CPUID CP6 R0 Page 0 */
 static inline int iop13xx_cpu_id(void)
@@ -479,14 +451,4 @@ static inline int iop13xx_cpu_id(void)
 #define IOP13XX_PBI_BAR1               IOP13XX_PBI_OFFSET(0x10)
 #define IOP13XX_PBI_LR1                IOP13XX_PBI_OFFSET(0x14)
 
-#define IOP13XX_TMR_TC                 0x01
-#define IOP13XX_TMR_EN                 0x02
-#define IOP13XX_TMR_RELOAD             0x04
-#define IOP13XX_TMR_PRIVILEGED         0x08
-
-#define IOP13XX_TMR_RATIO_1_1          0x00
-#define IOP13XX_TMR_RATIO_4_1          0x10
-#define IOP13XX_TMR_RATIO_8_1          0x20
-#define IOP13XX_TMR_RATIO_16_1         0x30
-
 #endif /* _IOP13XX_HW_H_ */
index 442e35a403596afdf42bf0bc3c9331394081c853..5c6fac2a400497118bc2209effb0698a4b5cea27 100644 (file)
@@ -3,8 +3,6 @@
 
 #ifndef __ASSEMBLER__
 #include <linux/types.h>
-#include <asm/system.h> /* local_irq_save */
-#include <asm/arch/iop13xx.h> /* iop13xx_cp6_* */
 
 /* INTPND0 CP6 R0 Page 3
  */
@@ -41,21 +39,6 @@ static inline u32 read_intpnd_3(void)
        asm volatile("mrc p6, 0, %0, c3, c3, 0":"=r" (val));
        return val;
 }
-
-static inline void
-iop13xx_cp6_enable_irq_save(unsigned long *cp_flags, unsigned long *irq_flags)
-{
-       local_irq_save(*irq_flags);
-       *cp_flags = iop13xx_cp6_save();
-}
-
-static inline void
-iop13xx_cp6_irq_restore(unsigned long *cp_flags,
-       unsigned long *irq_flags)
-{
-       iop13xx_cp6_restore(*cp_flags);
-       local_irq_restore(*irq_flags);
-}
 #endif
 
 #define INTBASE 0
index ee3a62530af26525f5b164c754f6a20b82afb709..127827058e1f4841e1eb00f248b544b94db6d23a 100644 (file)
@@ -48,12 +48,10 @@ static inline void arch_reset(char mode)
        /*
         * Reset the internal bus (warning both cores are reset)
         */
-       u32 cp_flags = iop13xx_cp6_save();
        write_wdtcr(IOP13XX_WDTCR_EN_ARM);
        write_wdtcr(IOP13XX_WDTCR_EN);
        write_wdtsr(IOP13XX_WDTSR_WRITE_EN | IOP13XX_WDTCR_IB_RESET);
        write_wdtcr(0x1000);
-       iop13xx_cp6_restore(cp_flags);
 
        for(;;);
 }
diff --git a/include/asm-arm/arch-iop13xx/time.h b/include/asm-arm/arch-iop13xx/time.h
new file mode 100644 (file)
index 0000000..77a837a
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef _IOP13XX_TIME_H_
+#define _IOP13XX_TIME_H_
+#define IRQ_IOP_TIMER0 IRQ_IOP13XX_TIMER0
+
+#define IOP_TMR_EN         0x02
+#define IOP_TMR_RELOAD     0x04
+#define IOP_TMR_PRIVILEGED 0x08
+#define IOP_TMR_RATIO_1_1  0x00
+
+void iop_init_time(unsigned long tickrate);
+unsigned long iop_gettimeoffset(void);
+
+static inline void write_tmr0(u32 val)
+{
+       asm volatile("mcr p6, 0, %0, c0, c9, 0" : : "r" (val));
+}
+
+static inline void write_tmr1(u32 val)
+{
+       asm volatile("mcr p6, 0, %0, c1, c9, 0" : : "r" (val));
+}
+
+static inline u32 read_tcr0(void)
+{
+       u32 val;
+       asm volatile("mrc p6, 0, %0, c2, c9, 0" : "=r" (val));
+       return val;
+}
+
+static inline u32 read_tcr1(void)
+{
+       u32 val;
+       asm volatile("mrc p6, 0, %0, c3, c9, 0" : "=r" (val));
+       return val;
+}
+
+static inline void write_trr0(u32 val)
+{
+       asm volatile("mcr p6, 0, %0, c4, c9, 0" : : "r" (val));
+}
+
+static inline void write_trr1(u32 val)
+{
+       asm volatile("mcr p6, 0, %0, c5, c9, 0" : : "r" (val));
+}
+
+static inline void write_tisr(u32 val)
+{
+       asm volatile("mcr p6, 0, %0, c6, c9, 0" : : "r" (val));
+}
+#endif
index 1500cbbd2295802644dbea87c3575e8477f5e98d..207db99dfbd2130f655235cc86d447817dd2216a 100644 (file)
@@ -9,13 +9,28 @@
  */
 #include <asm/arch/iop32x.h>
 
-               .macro  disable_fiq
-               .endm
+       .macro  disable_fiq
+       .endm
 
-               .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-               ldr     \base, =IOP3XX_REG_ADDR(0x07D8)
-               ldr     \irqstat, [\base]               @ Read IINTSRC
-               cmp     \irqstat, #0
-               clzne   \irqnr, \irqstat
-               rsbne   \irqnr, \irqnr, #31
-               .endm
+       .macro get_irqnr_preamble, base, tmp
+       mrc     p15, 0, \tmp, c15, c1, 0
+       orr     \tmp, \tmp, #(1 << 6)
+       mcr     p15, 0, \tmp, c15, c1, 0        @ Enable cp6 access
+       mrc     p15, 0, \tmp, c15, c1, 0
+       mov     \tmp, \tmp
+       sub     pc, pc, #4                      @ cp_wait
+       .endm
+
+       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+       mrc     p6, 0, \irqstat, c8, c0, 0      @ Read IINTSRC
+       cmp     \irqstat, #0
+       clzne   \irqnr, \irqstat
+       rsbne   \irqnr, \irqnr, #31
+       .endm
+
+       .macro arch_ret_to_user, tmp1, tmp2
+       mrc     p15, 0, \tmp1, c15, c1, 0
+       ands    \tmp2, \tmp1, #(1 << 6)
+       bicne   \tmp1, \tmp1, #(1 << 6)
+       mcrne   p15, 0, \tmp1, c15, c1, 0       @ Disable cp6 access
+       .endm
diff --git a/include/asm-arm/arch-iop32x/time.h b/include/asm-arm/arch-iop32x/time.h
new file mode 100644 (file)
index 0000000..0f28c99
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef _IOP32X_TIME_H_
+#define _IOP32X_TIME_H_
+#define IRQ_IOP_TIMER0 IRQ_IOP32X_TIMER0
+#endif
index 92b791702e3418fbf85fc80d52212f4d54b46457..b8e3d449e88276fb271430cd7315b8848417e2be 100644 (file)
@@ -9,14 +9,29 @@
  */
 #include <asm/arch/iop33x.h>
 
-               .macro  disable_fiq
-               .endm
+       .macro  disable_fiq
+       .endm
 
-               .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-               ldr     \base, =IOP3XX_REG_ADDR(0x07C8)
-               ldr     \irqstat, [\base]               @ Read IINTVEC
-               cmp     \irqstat, #0
-               ldreq   \irqstat, [\base]               @ erratum 63 workaround
-               adds    \irqnr, \irqstat, #1
-               movne   \irqnr, \irqstat, lsr #2
-               .endm
+       .macro get_irqnr_preamble, base, tmp
+       mrc     p15, 0, \tmp, c15, c1, 0
+       orr     \tmp, \tmp, #(1 << 6)
+       mcr     p15, 0, \tmp, c15, c1, 0        @ Enable cp6 access
+       mrc     p15, 0, \tmp, c15, c1, 0
+       mov     \tmp, \tmp
+       sub     pc, pc, #4                      @ cp_wait
+       .endm
+
+       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+       mrc     p6, 0, \irqstat, c14, c0, 0     @ Read IINTVEC
+       cmp     \irqstat, #0
+       mrceq   p6, 0, \irqstat, c14, c0, 0     @ erratum 63 workaround
+       adds    \irqnr, \irqstat, #1
+       movne   \irqnr, \irqstat, lsr #2
+       .endm
+
+       .macro arch_ret_to_user, tmp1, tmp2
+       mrc     p15, 0, \tmp1, c15, c1, 0
+       ands    \tmp2, \tmp1, #(1 << 6)
+       bicne   \tmp1, \tmp1, #(1 << 6)
+       mcrne   p15, 0, \tmp1, c15, c1, 0       @ Disable cp6 access
+       .endm
diff --git a/include/asm-arm/arch-iop33x/time.h b/include/asm-arm/arch-iop33x/time.h
new file mode 100644 (file)
index 0000000..4ac4d76
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef _IOP33X_TIME_H_
+#define _IOP33X_TIME_H_
+#define IRQ_IOP_TIMER0 IRQ_IOP33X_TIMER0
+#endif
index 16e1e6124b319bec4e7b043abb3e13c9d126229d..11d512ad594586274e147cf64d8402ed65336deb 100644 (file)
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
 
                mov     \irqnr, #0x0              @clear out irqnr as default
index 867761677b572d6c17816284a6d42bd88d2fcd14..ec9dd6fc2d0f6592d44dcd2f0d96023d2cb7ea2c 100644 (file)
@@ -5,6 +5,12 @@
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
                ldr     \irqnr, =(IXP23XX_INTC_VIRT + IXP23XX_INTR_IRQ_ENC_ST_OFFSET)
                ldr     \irqnr, [\irqnr]        @ get interrupt number
index 4a24f8f1565518d0d904a9cd7107370746e54563..d5e8a43d7bbdf4103f50f7e05608f550710212a5 100644 (file)
@@ -46,7 +46,7 @@
 #define IXDP2351_VIRT_NVRAM_BASE       IXDP2351_BB_AREA_BASE(0x0)
 #define IXDP2351_NVRAM_SIZE            (0x20000)
 
-#define IXDP2351_VIRT_MB_IXF1104_BASE  IXDP3251_BB_AREA_BASE(0x00020000)
+#define IXDP2351_VIRT_MB_IXF1104_BASE  IXDP2351_BB_AREA_BASE(0x00020000)
 #define IXDP2351_VIRT_ADD_UART_BASE    IXDP2351_BB_AREA_BASE(0x000240C0)
 #define IXDP2351_VIRT_FIC_BASE         IXDP2351_BB_AREA_BASE(0x00200000)
 #define IXDP2351_VIRT_DB0_BASE         IXDP2351_BB_AREA_BASE(0x00400000)
index 27e124132e4cde02926eae5b52aeb26cdefbd896..dadb568b7ef0f07a00c747e61b3f57836bbe7ead 100644 (file)
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
                ldr     \irqstat, =(IXP4XX_INTC_BASE_VIRT+IXP4XX_ICIP_OFFSET)
                ldr     \irqstat, [\irqstat]            @ get interrupts
index 8b6342dc4be2aaee619483e76e0bbcbfc62cd641..63411d3e9df49e87108215364d29a55bb8b4f53f 100644 (file)
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
                mov     \irqstat, #irq_base_addr                @ Virt addr IRQ regs
                add     \irqstat, \irqstat, #0x00001000         @ Status reg
index 9fc7f4988124af1b81247778df5890095e6acd6f..502700604e0000752716988e64f1a13bde66e56a 100644 (file)
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
 
 branch_irq_lh7a400: b 1000f
index 658df4d60ff36f13836a34b14fc0d4d39cbe5651..83ad188a08474c4239224526282ef6d6f22deb04 100644 (file)
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
                mov     \base, #io_p2v(0x00100000)
                add     \base, \base, #0x000ff000
index 467a1986d2594f66dad11a955eb6bd7f0a77d9b2..86aec87303e46c2d2b1be533348d6d745f050731 100644 (file)
 #include <asm/hardware.h>
 #include <asm/arch-ns9xxx/regs-sys.h>
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
                ldr     \base, =SYS_ISRADDR
                ldr     \irqstat, [\base, #(SYS_ISA - SYS_ISRADDR)]
index 0ffb1185f1ac90b930fd486e6fe57c85bf0a0bcd..f6967c8df32336c6d780005e6ff3251dcb6e79ea 100644 (file)
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
                ldr     \base, =IO_ADDRESS(OMAP_IH1_BASE)
                ldr     \irqnr, [\base, #IRQ_ITR_REG_OFFSET]
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
                ldr     \base, =VA_IC_BASE
                ldr     \irqnr, [\base, #0x98] /* IRQ pending reg 1 */
index df50dd53e1dde37f3733887e09e231173394eac0..48fabc493163fc44c004e8dcac03d86ff6c9ecae 100644 (file)
@@ -70,7 +70,7 @@
 
 #define virt_to_lbus(x)                ((x) - PAGE_OFFSET + OMAP1510_LB_OFFSET)
 #define lbus_to_virt(x)                ((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET)
-#define is_lbus_device(dev)    (cpu_is_omap1510() && dev && (strncmp(dev->bus_id, "ohci", 4) == 0))
+#define is_lbus_device(dev)    (cpu_is_omap15xx() && dev && (strncmp(dev->bus_id, "ohci", 4) == 0))
 
 #define __arch_page_to_dma(dev, page)  ({is_lbus_device(dev) ? \
                                        (dma_addr_t)virt_to_lbus(page_address(page)) : \
index df4695474e3d89606d0c0542d2c178466ea92bd8..fcaf44c14714c8f36f2c9d75eec216bb01027f41 100644 (file)
@@ -65,7 +65,7 @@ struct audio_stream {
        int period;             /* current transfer period */
        int periods;            /* current count of periods registerd in the DMA engine */
        spinlock_t dma_lock;    /* for locking in DMA operations */
-       snd_pcm_substream_t *stream;    /* the pcm stream */
+       struct snd_pcm_substream *stream;       /* the pcm stream */
        unsigned linked:1;      /* dma channels linked */
        int offset;             /* store start position of the last period in the alsa buffer */
        int (*hw_start)(void);  /* interface to start HW interface, e.g. McBSP */
@@ -76,8 +76,8 @@ struct audio_stream {
  * Alsa card structure for aic23
  */
 struct snd_card_omap_codec {
-       snd_card_t *card;
-       snd_pcm_t *pcm;
+       struct snd_card *card;
+       struct snd_pcm *pcm;
        long samplerate;
        struct audio_stream s[2];       /* playback & capture */
 };
@@ -89,9 +89,9 @@ struct snd_card_omap_codec {
 struct omap_alsa_codec_config {
        char    *name;
        struct  omap_mcbsp_reg_cfg *mcbsp_regs_alsa;
-       snd_pcm_hw_constraint_list_t *hw_constraints_rates;
-       snd_pcm_hardware_t *snd_omap_alsa_playback;
-       snd_pcm_hardware_t *snd_omap_alsa_capture;
+       struct  snd_pcm_hw_constraint_list *hw_constraints_rates;
+       struct  snd_pcm_hardware *snd_omap_alsa_playback;
+       struct  snd_pcm_hardware *snd_omap_alsa_capture;
        void    (*codec_configure_dev)(void);
        void    (*codec_set_samplerate)(long);
        void    (*codec_clock_setup)(void);
index c1c198e3680bde3bf442be47b3ab469bc2c573dc..f11731974e5d5a2b2b3123783b16cb8b7bc19375 100644 (file)
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
 /* decode the MIC interrupt numbers */
                ldr     \base, =IO_ADDRESS(PNX4008_INTCTRLMIC_BASE)
index 4985e33afc12de2cc389dad3e76dc60182345d57..1d5fbb9b379a03652b3c8347ef1adaed15bce146 100644 (file)
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
 #ifdef CONFIG_PXA27x
                mrc     p6, 0, \irqstat, c0, c0, 0              @ ICIP
index e67c238210173c1aed8974903794a0eefa128272..3d348a3511575fb4083359a944740fe12746098c 100644 (file)
 #define __ASM_ARCH_PXA_GPIO_H
 
 #include <asm/arch/pxa-regs.h>
-#include <asm/arch/irqs.h>
-#include <asm/arch/hardware.h>
-
-#include <asm/errno.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
 
 static inline int gpio_request(unsigned gpio, const char *label)
 {
@@ -42,26 +40,36 @@ static inline void gpio_free(unsigned gpio)
 
 static inline int gpio_direction_input(unsigned gpio)
 {
-       if (gpio > PXA_LAST_GPIO)
-               return -EINVAL;
-       pxa_gpio_mode(gpio | GPIO_IN);
+       return pxa_gpio_mode(gpio | GPIO_IN);
 }
 
 static inline int gpio_direction_output(unsigned gpio)
 {
-       if (gpio > PXA_LAST_GPIO)
-               return -EINVAL;
-       pxa_gpio_mode(gpio | GPIO_OUT);
+       return pxa_gpio_mode(gpio | GPIO_OUT);
 }
 
-/* REVISIT these macros are correct, but suffer code explosion
- * for non-constant parameters.  Provide out-line versions too.
- */
-#define gpio_get_value(gpio) \
-       (GPLR(gpio) & GPIO_bit(gpio))
+static inline int __gpio_get_value(unsigned gpio)
+{
+       return GPLR(gpio) & GPIO_bit(gpio);
+}
+
+#define gpio_get_value(gpio)                   \
+       (__builtin_constant_p(gpio) ?           \
+        __gpio_get_value(gpio) :               \
+        pxa_gpio_get_value(gpio))
+
+static inline void __gpio_set_value(unsigned gpio, int value)
+{
+       if (value)
+               GPSR(gpio) = GPIO_bit(gpio);
+       else
+               GPCR(gpio) = GPIO_bit(gpio);
+}
 
-#define gpio_set_value(gpio,value) \
-       ((value) ? (GPSR(gpio) = GPIO_bit(gpio)):(GPCR(gpio) = GPIO_bit(gpio)))
+#define gpio_set_value(gpio,value)             \
+       (__builtin_constant_p(gpio) ?           \
+        __gpio_set_value(gpio, value) :        \
+        pxa_gpio_set_value(gpio, value))
 
 #include <asm-generic/gpio.h>                  /* cansleep wrappers */
 
index 3e70bd95472ca8baa912995791b62c6e3bd8e545..e2bdc2fbede1efdd52e1a393601edb3c2f5f4e91 100644 (file)
 /*
  * Handy routine to set GPIO alternate functions
  */
-extern void pxa_gpio_mode( int gpio_mode );
+extern int pxa_gpio_mode( int gpio_mode );
+
+/*
+ * Return GPIO level, nonzero means high, zero is low
+ */
+extern int pxa_gpio_get_value(unsigned gpio);
+
+/*
+ * Set output GPIO level
+ */
+extern void pxa_gpio_set_value(unsigned gpio, int value);
 
 /*
  * Routine to enable or disable CKEN
index 1a6eec86bd476581b0e29f5ae566d9a49c61d27b..138838d4ad7575460b0995cb2b9cf3d90c0aa39a 100644 (file)
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                /*
                 * The interrupt numbering scheme is defined in the
                 * interrupt controller spec.  To wit:
index c9e5395e510614a50259c4cd5719d724f4320ad9..0cfb89b229d18da94b1595aa4d429b1d24a5f7ab 100644 (file)
@@ -1,3 +1,8 @@
 #include <asm/hardware.h>
 #include <asm/hardware/entry-macro-iomd.S>
+       .macro  get_irqnr_preamble, base, tmp
+       .endm
+
+       .macro  arch_ret_to_user, tmp1, tmp2
+       .endm
 
index 65e0acffa1aded6a29bc74bfa148cd20d5f1f838..0a6977fb57701a6f0667ad9a6a802678b6de5c0f 100644 (file)
@@ -31,9 +31,9 @@ struct s3c24xx_iis_ops {
        int     (*suspend)(struct s3c24xx_iis_ops *me);
        int     (*resume)(struct s3c24xx_iis_ops *me);
 
-       int     (*open)(struct s3c24xx_iis_ops *me, snd_pcm_substream_t *strm);
-       int     (*close)(struct s3c24xx_iis_ops *me, snd_pcm_substream_t *strm);
-       int     (*prepare)(struct s3c24xx_iis_ops *me, snd_pcm_substream_t *strm, snd_pcm_runtime_t *rt);
+       int     (*open)(struct s3c24xx_iis_ops *me, struct snd_pcm_substream *strm);
+       int     (*close)(struct s3c24xx_iis_ops *me, struct snd_pcm_substream *strm);
+       int     (*prepare)(struct s3c24xx_iis_ops *me, struct snd_pcm_substream *strm, struct snd_pcm_runtime *rt);
 };
 
 struct s3c24xx_platdata_iis {
index 1eb4e6b8d249c70ed2a53be4c7252aed5dbaf23c..bbec0a8ff158649b8d828f3aa97e44ee811bcb88 100644 (file)
 #include <asm/hardware.h>
 #include <asm/irq.h>
 
+       .macro  get_irqnr_preamble, base, tmp
+       .endm
+
+       .macro  arch_ret_to_user, tmp1, tmp2
+       .endm
+
        .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
 
                mov     \base, #S3C24XX_VA_IRQ
index 67b8b9ab22e966cae226512f3b47c76f0160cb91..d47ae453f8cae3eb4728964bc5c08d4546e0687e 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * linux/include/asm-arm/arch-pxa/gpio.h
+ * linux/include/asm-arm/arch-s3c2410/gpio.h
  *
- * S3C2400 GPIO wrappers for arch-neutral GPIO calls
+ * S3C2410 GPIO wrappers for arch-neutral GPIO calls
  *
  * Written by Philipp Zabel <philipp.zabel@gmail.com>
  *
  *
  */
 
-#ifndef __ASM_ARCH_PXA_GPIO_H
-#define __ASM_ARCH_PXA_GPIO_H
+#ifndef __ASM_ARCH_S3C2410_GPIO_H
+#define __ASM_ARCH_S3C2410_GPIO_H
 
-#include <asm/arch/pxa-regs.h>
-#include <asm/arch/irqs.h>
-#include <asm/arch/hardware.h>
-
-#include <asm/errno.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/arch/regs-gpio.h>
 
 static inline int gpio_request(unsigned gpio, const char *label)
 {
@@ -57,8 +55,11 @@ static inline int gpio_direction_output(unsigned gpio)
 
 #include <asm-generic/gpio.h>                  /* cansleep wrappers */
 
-/* FIXME or maybe s3c2400_gpio_getirq() ... */
+#ifdef CONFIG_CPU_S3C2400
+#define gpio_to_irq(gpio)              s3c2400_gpio_getirq(gpio)
+#else
 #define gpio_to_irq(gpio)              s3c2410_gpio_getirq(gpio)
+#endif
 
 /* FIXME implement irq_to_gpio() */
 
index 51fb50ce11690eb4dc48fad0108deb53e234af82..028967629340b60164cc98061b78443703a7e50c 100644 (file)
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
                mov     r4, #0xfa000000                 @ ICIP = 0xfa050000
                add     r4, r4, #0x00050000
index a331fe3f6e48b176e9edef9469b08d81a0414525..da7575b0e5d0f2f00ca58b09cc4aeaa22635f93a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/include/asm-arm/arch-pxa/gpio.h
+ * linux/include/asm-arm/arch-sa1100/gpio.h
  *
  * SA1100 GPIO wrappers for arch-neutral GPIO calls
  *
 #ifndef __ASM_ARCH_SA1100_GPIO_H
 #define __ASM_ARCH_SA1100_GPIO_H
 
-#include <asm/arch/SA-1100.h>
-#include <asm/arch/irqs.h>
-#include <asm/arch/hardware.h>
-
-#include <asm/errno.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
 
 static inline int gpio_request(unsigned gpio, const char *label)
 {
@@ -40,26 +37,23 @@ static inline void gpio_free(unsigned gpio)
        return;
 }
 
-static inline int gpio_direction_input(unsigned gpio)
+extern int gpio_direction_input(unsigned gpio);
+extern int gpio_direction_output(unsigned gpio);
+
+
+static inline int gpio_get_value(unsigned gpio)
 {
-       if (gpio > GPIO_MAX)
-               return -EINVAL;
-       GPDR = (GPDR_In << gpio) 0
+       return GPLR & GPIO_GPIO(gpio);
 }
 
-static inline int gpio_direction_output(unsigned gpio)
+static inline void gpio_set_value(unsigned gpio, int value)
 {
-       if (gpio > GPIO_MAX)
-               return -EINVAL;
-       GPDR = (GPDR_Out << gpio) 0
+       if (value)
+               GPSR = GPIO_GPIO(gpio);
+       else
+               GPCR = GPIO_GPIO(gpio);
 }
 
-#define gpio_get_value(gpio) \
-       (GPLR & GPIO_GPIO(gpio))
-
-#define gpio_set_value(gpio,value) \
-       ((value) ? (GPSR = GPIO_GPIO(gpio)) : (GPCR(gpio) = GPIO_GPIO(gpio)))
-
 #include <asm-generic/gpio.h>                  /* cansleep wrappers */
 
 static inline unsigned gpio_to_irq(unsigned gpio)
index a924f27fb8d98c7161a26f90aae9f4dc0808c4b2..82463f30f3dfc7e02dcbbafd270e352aa1c1a048 100644 (file)
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
                mov     r4, #0xe0000000
 
index feff771c0a0a950630cbef18d231da9c5d665d47..0fae002637a06c832db730c9796c229d4dfdee24 100644 (file)
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
                ldr     \base, =IO_ADDRESS(VERSATILE_VIC_BASE)
                ldr     \irqstat, [\base, #VIC_IRQ_STATUS]      @ get masked status
index c91b546e20ef8040419fbd86cb9170192581d915..15141a9caca8352a641117341caa042af3cedff2 100644 (file)
@@ -188,14 +188,10 @@ extern void gpio_line_set(int line, int value);
 #define IOP3XX_TU_TRR1         (volatile u32 *)IOP3XX_TIMER_REG(0x0014)
 #define IOP3XX_TU_TISR         (volatile u32 *)IOP3XX_TIMER_REG(0x0018)
 #define IOP3XX_TU_WDTCR                (volatile u32 *)IOP3XX_TIMER_REG(0x001c)
-#define IOP3XX_TMR_TC          0x01
-#define IOP3XX_TMR_EN          0x02
-#define IOP3XX_TMR_RELOAD      0x04
-#define IOP3XX_TMR_PRIVILEGED  0x09
-#define IOP3XX_TMR_RATIO_1_1   0x00
-#define IOP3XX_TMR_RATIO_4_1   0x10
-#define IOP3XX_TMR_RATIO_8_1   0x20
-#define IOP3XX_TMR_RATIO_16_1  0x30
+#define IOP_TMR_EN         0x02
+#define IOP_TMR_RELOAD     0x04
+#define IOP_TMR_PRIVILEGED 0x08
+#define IOP_TMR_RATIO_1_1  0x00
 
 /* Application accelerator unit  */
 #define IOP3XX_AAU_ACR         (volatile u32 *)IOP3XX_REG_ADDR(0x0800)
@@ -276,40 +272,52 @@ extern void gpio_line_set(int line, int value);
 
 #ifndef __ASSEMBLY__
 void iop3xx_map_io(void);
-void iop3xx_init_time(unsigned long);
-unsigned long iop3xx_gettimeoffset(void);
 void iop_init_cp6_handler(void);
+void iop_init_time(unsigned long tickrate);
+unsigned long iop_gettimeoffset(void);
 
-extern struct platform_device iop3xx_i2c0_device;
-extern struct platform_device iop3xx_i2c1_device;
+static inline void write_tmr0(u32 val)
+{
+       asm volatile("mcr p6, 0, %0, c0, c1, 0" : : "r" (val));
+}
+
+static inline void write_tmr1(u32 val)
+{
+       asm volatile("mcr p6, 0, %0, c1, c1, 0" : : "r" (val));
+}
+
+static inline u32 read_tcr0(void)
+{
+       u32 val;
+       asm volatile("mrc p6, 0, %0, c2, c1, 0" : "=r" (val));
+       return val;
+}
 
-extern inline void iop3xx_cp6_enable(void)
+static inline u32 read_tcr1(void)
 {
-       u32 temp;
+       u32 val;
+       asm volatile("mrc p6, 0, %0, c3, c1, 0" : "=r" (val));
+       return val;
+}
 
-       asm volatile (
-               "mrc    p15, 0, %0, c15, c1, 0\n\t"
-               "orr    %0, %0, #(1 << 6)\n\t"
-               "mcr    p15, 0, %0, c15, c1, 0\n\t"
-               "mrc    p15, 0, %0, c15, c1, 0\n\t"
-               "mov    %0, %0\n\t"
-               "sub    pc, pc, #4\n\t"
-               : "=r" (temp) );
+static inline void write_trr0(u32 val)
+{
+       asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (val));
 }
 
-extern inline void iop3xx_cp6_disable(void)
+static inline void write_trr1(u32 val)
 {
-       u32 temp;
+       asm volatile("mcr p6, 0, %0, c5, c1, 0" : : "r" (val));
+}
 
-       asm volatile (
-               "mrc    p15, 0, %0, c15, c1, 0\n\t"
-               "bic    %0, %0, #(1 << 6)\n\t"
-               "mcr    p15, 0, %0, c15, c1, 0\n\t"
-               "mrc    p15, 0, %0, c15, c1, 0\n\t"
-               "mov    %0, %0\n\t"
-               "sub    pc, pc, #4\n\t"
-               : "=r" (temp) );
+static inline void write_tisr(u32 val)
+{
+       asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (val));
 }
+
+extern struct platform_device iop3xx_i2c0_device;
+extern struct platform_device iop3xx_i2c1_device;
+
 #endif
 
 
index f4386906b200002d6d6a3612f4037382a9ba9cef..f06d8a43fdee9eed0553cbb910ef279ee2813a82 100644 (file)
@@ -167,11 +167,25 @@ extern unsigned int user_debug;
                                    : : "r" (0) : "memory")
 #define dmb() __asm__ __volatile__ ("" : : : "memory")
 #endif
-#define mb() dmb()
-#define rmb() mb()
-#define wmb() mb()
-#define read_barrier_depends() do { } while(0)
-#define set_mb(var, value)  do { var = value; mb(); } while (0)
+
+#define mb()                   barrier()
+#define rmb()                  barrier()
+#define wmb()                  barrier()
+#define read_barrier_depends() do { } while(0)
+
+#ifdef CONFIG_SMP
+#define smp_mb()               dmb()
+#define smp_rmb()              dmb()
+#define smp_wmb()              dmb()
+#define smp_read_barrier_depends()     read_barrier_depends()
+#else
+#define smp_mb()               barrier()
+#define smp_rmb()              barrier()
+#define smp_wmb()              barrier()
+#define smp_read_barrier_depends()     read_barrier_depends()
+#endif /* CONFIG_SMP */
+
+#define set_mb(var, value)     do { var = value; smp_mb(); } while (0)
 #define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
 
 extern unsigned long cr_no_alignment;  /* defined in entry-armv.S */
@@ -243,22 +257,6 @@ static inline void sched_cacheflush(void)
 {
 }
 
-#ifdef CONFIG_SMP
-
-#define smp_mb()               mb()
-#define smp_rmb()              rmb()
-#define smp_wmb()              wmb()
-#define smp_read_barrier_depends()             read_barrier_depends()
-
-#else
-
-#define smp_mb()               barrier()
-#define smp_rmb()              barrier()
-#define smp_wmb()              barrier()
-#define smp_read_barrier_depends()             do { } while(0)
-
-#endif /* CONFIG_SMP */
-
 #if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110)
 /*
  * On the StrongARM, "swp" is terminally broken since it bypasses the
index 8770e73ce93845dbfdb12457c599d2cafe8ff859..3136628ba8d20feba7de4ed07a51261a65c4a3b2 100644 (file)
@@ -1,3 +1,3 @@
 include include/asm-generic/Kbuild.asm
 
-headers-y      += cachectl.h
+header-y       += cachectl.h
index 115813e48fe0c11005181dee7bda548ebad73bb6..21bb60bbb9a1889e3eb058f5b4045238b45bf33a 100644 (file)
@@ -274,6 +274,24 @@ dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
        dma_cache_sync(dev, bus_to_virt(dma_handle), size, direction);
 }
 
+static inline void
+dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
+                             unsigned long offset, size_t size,
+                             enum dma_data_direction direction)
+{
+       /* just sync everything, that's all the pci API can do */
+       dma_sync_single_for_cpu(dev, dma_handle, offset+size, direction);
+}
+
+static inline void
+dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
+                                unsigned long offset, size_t size,
+                                enum dma_data_direction direction)
+{
+       /* just sync everything, that's all the pci API can do */
+       dma_sync_single_for_device(dev, dma_handle, offset+size, direction);
+}
+
 /**
  * dma_sync_sg_for_cpu
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
index ba1b37df69d50d6147a2150b052c5e8cc89dd9de..8a05aa168616f6d548bd78e03d7e474eee3cf1ad 100644 (file)
@@ -70,7 +70,11 @@ static inline int pte_file(pte_t pte) { return 0; }
 
 #define swapper_pg_dir         ((pgd_t *) NULL)
 
-#define pgtable_cache_init()   do {} while(0)
+#define pgtable_cache_init()           do {} while (0)
+#define arch_enter_lazy_mmu_mode()     do {} while (0)
+#define arch_leave_lazy_mmu_mode()     do {} while (0)
+#define arch_enter_lazy_cpu_mode()     do {} while (0)
+#define arch_leave_lazy_cpu_mode()     do {} while (0)
 
 #else /* !CONFIG_MMU */
 /*****************************************************************************/
index b55052ce233035ff31b8bbe5909870d3be862f00..a96b5d986b6e8b1f05fb896adacae85b4243149c 100644 (file)
@@ -4,51 +4,21 @@
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
-#include <linux/log2.h>
+#include <linux/compiler.h>
 
-/*
- * non-const pure 2^n version of get_order
- * - the arch may override these in asm/bitops.h if they can be implemented
- *   more efficiently than using the arch log2 routines
- * - we use the non-const log2() instead if the arch has defined one suitable
- */
-#ifndef ARCH_HAS_GET_ORDER
-static inline __attribute__((const))
-int __get_order(unsigned long size, int page_shift)
+/* Pure 2^n version of get_order */
+static __inline__ __attribute_const__ int get_order(unsigned long size)
 {
-#if BITS_PER_LONG == 32 && defined(ARCH_HAS_ILOG2_U32)
-       int order = __ilog2_u32(size) - page_shift;
-       return order >= 0 ? order : 0;
-#elif BITS_PER_LONG == 64 && defined(ARCH_HAS_ILOG2_U64)
-       int order = __ilog2_u64(size) - page_shift;
-       return order >= 0 ? order : 0;
-#else
        int order;
 
-       size = (size - 1) >> (page_shift - 1);
+       size = (size - 1) >> (PAGE_SHIFT - 1);
        order = -1;
        do {
                size >>= 1;
                order++;
        } while (size);
        return order;
-#endif
 }
-#endif
-
-/**
- * get_order - calculate log2(pages) to hold a block of the specified size
- * @n - size
- *
- * calculate allocation order based on the current page size
- * - this can be used to initialise global variables from constant data
- */
-#define get_order(n)                                                   \
-(                                                                      \
-       __builtin_constant_p(n) ?                                       \
-       ((n < (1UL << PAGE_SHIFT)) ? 0 : ilog2(n) - PAGE_SHIFT) :       \
-       __get_order(n, PAGE_SHIFT)                                      \
- )
 
 #endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
index 32d6678d0bbf2b1815019f1eaec21b60c2f17fee..9ae5e3782ed879dbd13b64df6aacdc186c998af9 100644 (file)
@@ -16,13 +16,6 @@ extern void __ndelay(unsigned long nsecs);
 extern void __const_udelay(unsigned long usecs);
 extern void __delay(unsigned long loops);
 
-#if defined(CONFIG_PARAVIRT) && !defined(USE_REAL_TIME_DELAY)
-#define udelay(n) paravirt_ops.const_udelay((n) * 0x10c7ul)
-
-#define ndelay(n) paravirt_ops.const_udelay((n) * 5ul)
-
-#else /* !PARAVIRT || USE_REAL_TIME_DELAY */
-
 /* 0x10c7 is 2**32 / 1000000 (rounded up) */
 #define udelay(n) (__builtin_constant_p(n) ? \
        ((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \
@@ -32,7 +25,6 @@ extern void __delay(unsigned long loops);
 #define ndelay(n) (__builtin_constant_p(n) ? \
        ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
        __ndelay(n))
-#endif
 
 void use_tsc_delay(void);
 
diff --git a/include/asm-i386/idle.h b/include/asm-i386/idle.h
deleted file mode 100644 (file)
index 87ab939..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef _ASM_I386_IDLE_H
-#define _ASM_I386_IDLE_H 1
-
-#define IDLE_START 1
-#define IDLE_END 2
-
-struct notifier_block;
-void idle_notifier_register(struct notifier_block *n);
-void idle_notifier_unregister(struct notifier_block *n);
-
-void exit_idle(void);
-void enter_idle(void);
-
-#endif
index 059a9ff28b4d03b66fff8a2aff97ba962d14ceb4..340764076d5f4e56585779eaafb4ba249269f0a4 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <asm/types.h>
 #include <asm/mpspec.h>
+#include <asm/apicdef.h>
 
 /*
  * Intel IO-APIC support for SMP and UP systems.
index 6db40d0583f1083e4b4c2c684e1637abdc9126a2..ec3b6803fd36dc33472c23e63d2b0ee487ecf087 100644 (file)
@@ -83,6 +83,20 @@ static inline void wrmsrl (unsigned long msr, unsigned long long val)
                          : "c" (counter))
 #endif /* !CONFIG_PARAVIRT */
 
+#ifdef CONFIG_SMP
+void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
+void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
+#else  /*  CONFIG_SMP  */
+static inline void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
+{
+       rdmsr(msr_no, *l, *h);
+}
+static inline void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
+{
+       wrmsr(msr_no, l, h);
+}
+#endif  /*  CONFIG_SMP  */
+
 /* symbolic names for some interesting MSRs */
 /* Intel defined MSRs. */
 #define MSR_IA32_P5_MC_ADDR            0
index b04333ea6f31e9bd338b9842d1afeec1ea9f7ba4..64544cb85d6a40b4d06928a33c15728a5d265378 100644 (file)
@@ -33,7 +33,7 @@ extern int nmi_watchdog_tick (struct pt_regs * regs, unsigned reason);
 
 extern atomic_t nmi_active;
 extern unsigned int nmi_watchdog;
-#define NMI_DEFAULT     -1
+#define NMI_DEFAULT     0
 #define NMI_NONE       0
 #define NMI_IO_APIC    1
 #define NMI_LOCAL_APIC 2
index 6317e0a4d73565f9a61dcf0cba131782cc8ce3ba..f8319cae2ac5c6b789ed974c0de59a044efd9877 100644 (file)
@@ -94,6 +94,8 @@ struct paravirt_ops
 
        u64 (*read_tsc)(void);
        u64 (*read_pmc)(void);
+       u64 (*get_scheduled_cycles)(void);
+       unsigned long (*get_cpu_khz)(void);
 
        void (*load_tr_desc)(void);
        void (*load_gdt)(const struct Xgt_desc_struct *);
@@ -115,7 +117,6 @@ struct paravirt_ops
        void (*set_iopl_mask)(unsigned mask);
 
        void (*io_delay)(void);
-       void (*const_udelay)(unsigned long loops);
 
 #ifdef CONFIG_X86_LOCAL_APIC
        void (*apic_write)(unsigned long reg, unsigned long v);
@@ -129,6 +130,8 @@ struct paravirt_ops
        void (*flush_tlb_kernel)(void);
        void (*flush_tlb_single)(u32 addr);
 
+       void (fastcall *map_pt_hook)(int type, pte_t *va, u32 pfn);
+
        void (*alloc_pt)(u32 pfn);
        void (*alloc_pd)(u32 pfn);
        void (*alloc_pd_clone)(u32 pfn, u32 clonepfn, u32 start, u32 count);
@@ -183,9 +186,9 @@ static inline int set_wallclock(unsigned long nowtime)
        return paravirt_ops.set_wallclock(nowtime);
 }
 
-static inline void do_time_init(void)
+static inline void (*choose_time_init(void))(void)
 {
-       return paravirt_ops.time_init();
+       return paravirt_ops.time_init;
 }
 
 /* The paravirtualized CPUID instruction. */
@@ -273,6 +276,9 @@ static inline void halt(void)
 
 #define rdtscll(val) (val = paravirt_ops.read_tsc())
 
+#define get_scheduled_cycles(val) (val = paravirt_ops.get_scheduled_cycles())
+#define calculate_cpu_khz() (paravirt_ops.get_cpu_khz())
+
 #define write_tsc(val1,val2) wrmsr(0x10, val1, val2)
 
 #define rdpmc(counter,low,high) do {                           \
@@ -349,6 +355,8 @@ static inline void startup_ipi_hook(int phys_apicid, unsigned long start_eip,
 #define __flush_tlb_global() paravirt_ops.flush_tlb_kernel()
 #define __flush_tlb_single(addr) paravirt_ops.flush_tlb_single(addr)
 
+#define paravirt_map_pt_hook(type, va, pfn) paravirt_ops.map_pt_hook(type, va, pfn)
+
 #define paravirt_alloc_pt(pfn) paravirt_ops.alloc_pt(pfn)
 #define paravirt_release_pt(pfn) paravirt_ops.release_pt(pfn)
 
index e6a4723f0eb1f088affdc67cd42a8f5d7c02ce21..c3b58d473a551b1e22413c610f8bd5e622ae487d 100644 (file)
@@ -263,6 +263,7 @@ static inline pte_t pte_mkhuge(pte_t pte)   { (pte).pte_low |= _PAGE_PSE; return p
  */
 #define pte_update(mm, addr, ptep)             do { } while (0)
 #define pte_update_defer(mm, addr, ptep)       do { } while (0)
+#define paravirt_map_pt_hook(slot, va, pfn)    do { } while (0)
 #endif
 
 /*
@@ -469,10 +470,24 @@ extern pte_t *lookup_address(unsigned long address);
 #endif
 
 #if defined(CONFIG_HIGHPTE)
-#define pte_offset_map(dir, address) \
-       ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + pte_index(address))
-#define pte_offset_map_nested(dir, address) \
-       ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + pte_index(address))
+#define pte_offset_map(dir, address)                           \
+({                                                             \
+       pte_t *__ptep;                                          \
+       unsigned pfn = pmd_val(*(dir)) >> PAGE_SHIFT;           \
+       __ptep = (pte_t *)kmap_atomic(pfn_to_page(pfn),KM_PTE0);\
+       paravirt_map_pt_hook(KM_PTE0,__ptep, pfn);              \
+       __ptep = __ptep + pte_index(address);                   \
+       __ptep;                                                 \
+})
+#define pte_offset_map_nested(dir, address)                    \
+({                                                             \
+       pte_t *__ptep;                                          \
+       unsigned pfn = pmd_val(*(dir)) >> PAGE_SHIFT;           \
+       __ptep = (pte_t *)kmap_atomic(pfn_to_page(pfn),KM_PTE1);\
+       paravirt_map_pt_hook(KM_PTE1,__ptep, pfn);              \
+       __ptep = __ptep + pte_index(address);                   \
+       __ptep;                                                 \
+})
 #define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0)
 #define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1)
 #else
index edfbe46a5e13c8042a1b589ee23f2f2c45918a73..11bf899de8aa157dbe30e5b442f911ece82a0c91 100644 (file)
@@ -257,14 +257,6 @@ static inline void __mwait(unsigned long eax, unsigned long ecx)
                : :"a" (eax), "c" (ecx));
 }
 
-static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
-{
-       /* "mwait %eax,%ecx;" */
-       asm volatile(
-               "sti; .byte 0x0f,0x01,0xc9;"
-               : :"a" (eax), "c" (ecx));
-}
-
 extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
 
 /* from system description table in BIOS.  Mostly for MCA use, but
index 571b4294dc2e84d4029120fd05853a5fa62153ac..eac011366dc2c09337abfe3d146bafcb01b1d686 100644 (file)
@@ -28,14 +28,16 @@ static inline int native_set_wallclock(unsigned long nowtime)
        return retval;
 }
 
+extern void (*late_time_init)(void);
+extern void hpet_time_init(void);
+
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt.h>
-extern unsigned long long native_sched_clock(void);
 #else /* !CONFIG_PARAVIRT */
 
 #define get_wallclock() native_get_wallclock()
 #define set_wallclock(x) native_set_wallclock(x)
-#define do_time_init() time_init_hook()
+#define choose_time_init() hpet_time_init
 
 #endif /* CONFIG_PARAVIRT */
 
index 4752c3a6a7089580eaf6b18333f26eadc94e18c8..12dd67bf760f8f270ef577b9675235aff5054283 100644 (file)
@@ -4,13 +4,21 @@
 #include <linux/pm.h>
 
 #define TICK_SIZE (tick_nsec / 1000)
+
 void setup_pit_timer(void);
+unsigned long long native_sched_clock(void);
+unsigned long native_calculate_cpu_khz(void);
+
 /* Modifiers for buggy PIT handling */
 extern int pit_latch_buggy;
 extern int timer_ack;
 extern int no_timer_check;
-extern unsigned long long (*custom_sched_clock)(void);
 extern int no_sync_cmos_clock;
 extern int recalibrate_cpu_khz(void);
 
+#ifndef CONFIG_PARAVIRT
+#define get_scheduled_cycles(val) rdtscll(val)
+#define calculate_cpu_khz() native_calculate_cpu_khz()
+#endif
+
 #endif
index ac58580ad6647a86d30dd4ae5928c4c1b87a26ca..7fc512d90ea85762884f419b3ae8285a34e2028f 100644 (file)
@@ -85,7 +85,6 @@ static inline int node_to_first_cpu(int node)
        .idle_idx               = 1,                    \
        .newidle_idx            = 2,                    \
        .wake_idx               = 1,                    \
-       .per_cpu_gain           = 100,                  \
        .flags                  = SD_LOAD_BALANCE       \
                                | SD_BALANCE_EXEC       \
                                | SD_BALANCE_FORK       \
index e997891cc7cc8bfdedf6b9447996e291e5b0a9b1..84016ff481b9d2e5df72a2e8bb7411088d971d53 100644 (file)
@@ -1 +1,67 @@
-#include <asm-x86_64/tsc.h>
+/*
+ * linux/include/asm-i386/tsc.h
+ *
+ * i386 TSC related functions
+ */
+#ifndef _ASM_i386_TSC_H
+#define _ASM_i386_TSC_H
+
+#include <asm/processor.h>
+
+/*
+ * Standard way to access the cycle counter.
+ */
+typedef unsigned long long cycles_t;
+
+extern unsigned int cpu_khz;
+extern unsigned int tsc_khz;
+
+static inline cycles_t get_cycles(void)
+{
+       unsigned long long ret = 0;
+
+#ifndef CONFIG_X86_TSC
+       if (!cpu_has_tsc)
+               return 0;
+#endif
+
+#if defined(CONFIG_X86_GENERIC) || defined(CONFIG_X86_TSC)
+       rdtscll(ret);
+#endif
+       return ret;
+}
+
+/* Like get_cycles, but make sure the CPU is synchronized. */
+static __always_inline cycles_t get_cycles_sync(void)
+{
+       unsigned long long ret;
+#ifdef X86_FEATURE_SYNC_RDTSC
+       unsigned eax;
+
+       /*
+        * Don't do an additional sync on CPUs where we know
+        * RDTSC is already synchronous:
+        */
+       alternative_io("cpuid", ASM_NOP2, X86_FEATURE_SYNC_RDTSC,
+                         "=a" (eax), "0" (1) : "ebx","ecx","edx","memory");
+#else
+       sync_core();
+#endif
+       rdtscll(ret);
+
+       return ret;
+}
+
+extern void tsc_init(void);
+extern void mark_tsc_unstable(void);
+extern int unsynchronized_tsc(void);
+extern void init_tsc_clocksource(void);
+
+/*
+ * Boot-time check whether the TSCs are synchronized across
+ * all CPUs/cores:
+ */
+extern void check_tsc_sync_source(int cpu);
+extern void check_tsc_sync_target(void);
+
+#endif
index 43c89333037e3661beb548dd8fc56e100d788760..eb8bd892c01e2f5a3edeb3bc129d86c3c557a01a 100644 (file)
@@ -97,6 +97,7 @@
 #define VMI_CALL_SetInitialAPState     62
 #define VMI_CALL_APICWrite             63
 #define VMI_CALL_APICRead              64
+#define VMI_CALL_IODelay               65
 #define VMI_CALL_SetLazyMode           73
 
 /*
index c12931211007c70eae07c7b6fa50ddd0bd6ea551..94d0a12a4114920c5613717439eec03bc125efcb 100644 (file)
@@ -49,7 +49,8 @@ extern struct vmi_timer_ops {
 extern void __init vmi_time_init(void);
 extern unsigned long vmi_get_wallclock(void);
 extern int vmi_set_wallclock(unsigned long now);
-extern unsigned long long vmi_sched_clock(void);
+extern unsigned long long vmi_get_sched_cycles(void);
+extern unsigned long vmi_cpu_khz(void);
 
 #ifdef CONFIG_X86_LOCAL_APIC
 extern void __init vmi_timer_setup_boot_alarm(void);
@@ -60,6 +61,14 @@ extern void apic_vmi_timer_interrupt(void);
 #ifdef CONFIG_NO_IDLE_HZ
 extern int vmi_stop_hz_timer(void);
 extern void vmi_account_time_restart_hz_timer(void);
+#else
+static inline int vmi_stop_hz_timer(void)
+{
+       return 0;
+}
+static inline void vmi_account_time_restart_hz_timer(void)
+{
+}
 #endif
 
 /*
index f2ad469a6ddfac76c6592b535a489eb2cb27e85f..41299ddfee30e0c742102420725e3645bd711999 100644 (file)
@@ -22,7 +22,6 @@
         } while(0)
 
 extern struct kimage *ia64_kimage;
-DECLARE_PER_CPU(u64, ia64_mca_pal_base);
 extern const unsigned int relocate_new_kernel_size;
 extern void relocate_new_kernel(unsigned long, unsigned long,
                struct ia64_boot_param *, unsigned long);
index ee97f7c2d462e350b7554454861ef35bd9d73e93..41098f459684c41f82cc26c6812f3b21deacb400 100644 (file)
@@ -156,6 +156,8 @@ struct ia64_mca_notify_die {
        int *monarch_cpu;
 };
 
+DECLARE_PER_CPU(u64, ia64_mca_pal_base);
+
 #else  /* __ASSEMBLY__ */
 
 #define IA64_MCA_CORRECTED     0x0     /* Error has been corrected by OS_MCA */
index 6dd476b652c6aba995e03d3208c50f21adcba594..21ec5f3d23deb4478cbb355f0b942e0cd2514e72 100644 (file)
  *     - kernel code & data
  *     - crash dumping code reserved region
  *     - Kernel memory map built from EFI memory map
+ *     - ELF core header
  *
  * More could be added if necessary
  */
-#define IA64_MAX_RSVD_REGIONS 7
+#define IA64_MAX_RSVD_REGIONS 8
 
 struct rsvd_region {
        unsigned long start;    /* virtual address of beginning of element */
@@ -36,6 +37,9 @@ extern void find_initrd (void);
 extern int filter_rsvd_memory (unsigned long start, unsigned long end, void *arg);
 extern void efi_memmap_init(unsigned long *, unsigned long *);
 
+extern unsigned long vmcore_find_descriptor_size(unsigned long address);
+extern int reserve_elfcorehdr(unsigned long *start, unsigned long *end);
+
 /*
  * For rounding an address to the next IA64_GRANULE_SIZE or order
  */
index e43021a99a20b0e523f9125fcb7b2cdc189b6392..67656ce767c22d1f06c78f6e06d0ac1528fd583d 100644 (file)
@@ -371,6 +371,7 @@ typedef u64                                 pal_mc_info_index_t;
                                                         * dependent
                                                         */
 
+#define PAL_TLB_CHECK_OP_PURGE                 8
 
 typedef struct pal_process_state_info_s {
        u64             reserved1       : 2,
index 5160233bbfac3a35f660174f01302f647e4cb55b..5a5d1c2ce39d1510e1d2a56dc1322929bab25029 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <asm/io.h>
 #include <asm/scatterlist.h>
+#include <asm/hw_irq.h>
 
 /*
  * Can be used to override the logic in pci_scan_bus for skipping already-configured bus
@@ -170,7 +171,7 @@ pcibios_select_root(struct pci_dev *pdev, struct resource *res)
 #define HAVE_ARCH_PCI_GET_LEGACY_IDE_IRQ
 static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 {
-       return channel ? 15 : 14;
+       return channel ? isa_irq_to_vector(15) : isa_irq_to_vector(14);
 }
 
 #endif /* _ASM_IA64_PCI_H */
index 77b1eee01f30e2285e8e6cb1084fce583294ae5c..ba2272a87fc7b4ce41c99f202c5598bc7055c65c 100644 (file)
@@ -2,7 +2,6 @@
 #define _ASM_IA64_RESOURCE_H
 
 #include <asm/ustack.h>
-#define _STK_LIM_MAX   DEFAULT_USER_STACK_SIZE
 #include <asm-generic/resource.h>
 
 #endif /* _ASM_IA64_RESOURCE_H */
index d000689d91421f6b0103660fe047146b166d50d0..46cadf5aaac57a3dd1136f2e140905103c4188e0 100644 (file)
@@ -847,12 +847,13 @@ extern int ia64_sal_oemcall_reentrant(struct ia64_sal_retval *, u64, u64, u64,
  */
 struct sal_to_os_boot {
        u64 rr[8];              /* Region Registers */
-       u64     br[6];          /* br0: return addr into SAL boot rendez routine */
+       u64 br[6];              /* br0:
+                                * return addr into SAL boot rendez routine */
        u64 gr1;                /* SAL:GP */
        u64 gr12;               /* SAL:SP */
        u64 gr13;               /* SAL: Task Pointer */
        u64 fpsr;
-       u64     pfs;
+       u64 pfs;
        u64 rnat;
        u64 unat;
        u64 bspstore;
diff --git a/include/asm-ia64/swiotlb.h b/include/asm-ia64/swiotlb.h
deleted file mode 100644 (file)
index 452c162..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _ASM_SWIOTLB_H
-#define _ASM_SWIOTLB_H 1
-
-#include <asm/machvec.h>
-
-#define SWIOTLB_ARCH_NEED_LATE_INIT
-#define SWIOTLB_ARCH_NEED_ALLOC
-
-#endif /* _ASM_SWIOTLB_H */
index 22ed6749557eaf0bc6d240da6bd8c96647b762e8..233f1caae048b2b5454c255248bd664d600eefc9 100644 (file)
@@ -65,7 +65,6 @@ void build_cpu_to_node_map(void);
        .max_interval           = 4,                    \
        .busy_factor            = 64,                   \
        .imbalance_pct          = 125,                  \
-       .per_cpu_gain           = 100,                  \
        .cache_nice_tries       = 2,                    \
        .busy_idx               = 2,                    \
        .idle_idx               = 1,                    \
@@ -97,7 +96,6 @@ void build_cpu_to_node_map(void);
        .newidle_idx            = 0, /* unused */       \
        .wake_idx               = 1,                    \
        .forkexec_idx           = 1,                    \
-       .per_cpu_gain           = 100,                  \
        .flags                  = SD_LOAD_BALANCE       \
                                | SD_BALANCE_EXEC       \
                                | SD_BALANCE_FORK       \
index 5df0276b0493eaa6354cbdd019b69d35b20440c5..1af3875f1a57b1be81467582f9951788ddcfc3a8 100644 (file)
@@ -81,7 +81,7 @@ struct unw_frame_info {
        struct unw_ireg {
                unsigned long *loc;
                struct unw_ireg_nat {
-                       long type : 3;                  /* enum unw_nat_type */
+                       unsigned long type : 3;         /* enum unw_nat_type */
                        signed long off : 61;           /* NaT word is at loc+nat.off */
                } nat;
        } r4, r5, r6, r7;
index 1a3b1ae06b1e788b828c2d489fab6ac039f80856..28bf783a5d6df7302d03371ae7ad6528750eb064 100644 (file)
@@ -47,6 +47,9 @@
 /* set Port AS pin for I2C or UART */
 #define MCF5282_GPIO_PASPAR     (volatile u16 *) (MCF_IPSBAR + 0x00100056)
 
+/* Port UA Pin Assignment Register (8 Bit) */
+#define MCF5282_GPIO_PUAPAR    0x10005C
+
 /* Interrupt Mask Register Register Low */ 
 #define MCF5282_INTC0_IMRL      (volatile u32 *) (MCF_IPSBAR + 0x0C0C)
 /* Interrupt Control Register 7 */
index 89436b96ad66ea9953309aa5ef8ba4560b03584b..8959da245cfbb751d77b2186870a98ca1816301a 100644 (file)
@@ -54,6 +54,7 @@
 static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 {
        unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
+       unsigned short bit = nr & SZLONG_MASK;
        unsigned long temp;
 
        if (cpu_has_llsc && R10000_LLSC_WAR) {
@@ -65,9 +66,9 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
                "       beqzl   %0, 1b                                  \n"
                "       .set    mips0                                   \n"
                : "=&r" (temp), "=m" (*m)
-               : "ir" (1UL << (nr & SZLONG_MASK)), "m" (*m));
+               : "ir" (1UL << bit), "m" (*m));
 #ifdef CONFIG_CPU_MIPSR2
-       } else if (__builtin_constant_p(nr)) {
+       } else if (__builtin_constant_p(bit)) {
                __asm__ __volatile__(
                "1:     " __LL "%0, %1                  # set_bit       \n"
                "       " __INS "%0, %4, %2, 1                          \n"
@@ -77,7 +78,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
                "2:     b       1b                                      \n"
                "       .previous                                       \n"
                : "=&r" (temp), "=m" (*m)
-               : "ir" (nr & SZLONG_MASK), "m" (*m), "r" (~0));
+               : "ir" (bit), "m" (*m), "r" (~0));
 #endif /* CONFIG_CPU_MIPSR2 */
        } else if (cpu_has_llsc) {
                __asm__ __volatile__(
@@ -91,14 +92,14 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
                "       .previous                                       \n"
                "       .set    mips0                                   \n"
                : "=&r" (temp), "=m" (*m)
-               : "ir" (1UL << (nr & SZLONG_MASK)), "m" (*m));
+               : "ir" (1UL << bit), "m" (*m));
        } else {
                volatile unsigned long *a = addr;
                unsigned long mask;
                unsigned long flags;
 
                a += nr >> SZLONG_LOG;
-               mask = 1UL << (nr & SZLONG_MASK);
+               mask = 1UL << bit;
                local_irq_save(flags);
                *a |= mask;
                local_irq_restore(flags);
@@ -118,6 +119,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
 {
        unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
+       unsigned short bit = nr & SZLONG_MASK;
        unsigned long temp;
 
        if (cpu_has_llsc && R10000_LLSC_WAR) {
@@ -129,9 +131,9 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
                "       beqzl   %0, 1b                                  \n"
                "       .set    mips0                                   \n"
                : "=&r" (temp), "=m" (*m)
-               : "ir" (~(1UL << (nr & SZLONG_MASK))), "m" (*m));
+               : "ir" (~(1UL << bit)), "m" (*m));
 #ifdef CONFIG_CPU_MIPSR2
-       } else if (__builtin_constant_p(nr)) {
+       } else if (__builtin_constant_p(bit)) {
                __asm__ __volatile__(
                "1:     " __LL "%0, %1                  # clear_bit     \n"
                "       " __INS "%0, $0, %2, 1                          \n"
@@ -141,7 +143,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
                "2:     b       1b                                      \n"
                "       .previous                                       \n"
                : "=&r" (temp), "=m" (*m)
-               : "ir" (nr & SZLONG_MASK), "m" (*m));
+               : "ir" (bit), "m" (*m));
 #endif /* CONFIG_CPU_MIPSR2 */
        } else if (cpu_has_llsc) {
                __asm__ __volatile__(
@@ -155,14 +157,14 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
                "       .previous                                       \n"
                "       .set    mips0                                   \n"
                : "=&r" (temp), "=m" (*m)
-               : "ir" (~(1UL << (nr & SZLONG_MASK))), "m" (*m));
+               : "ir" (~(1UL << bit)), "m" (*m));
        } else {
                volatile unsigned long *a = addr;
                unsigned long mask;
                unsigned long flags;
 
                a += nr >> SZLONG_LOG;
-               mask = 1UL << (nr & SZLONG_MASK);
+               mask = 1UL << bit;
                local_irq_save(flags);
                *a &= ~mask;
                local_irq_restore(flags);
@@ -180,6 +182,8 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
  */
 static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
 {
+       unsigned short bit = nr & SZLONG_MASK;
+
        if (cpu_has_llsc && R10000_LLSC_WAR) {
                unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
                unsigned long temp;
@@ -192,7 +196,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
                "       beqzl   %0, 1b                          \n"
                "       .set    mips0                           \n"
                : "=&r" (temp), "=m" (*m)
-               : "ir" (1UL << (nr & SZLONG_MASK)), "m" (*m));
+               : "ir" (1UL << bit), "m" (*m));
        } else if (cpu_has_llsc) {
                unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
                unsigned long temp;
@@ -208,14 +212,14 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
                "       .previous                               \n"
                "       .set    mips0                           \n"
                : "=&r" (temp), "=m" (*m)
-               : "ir" (1UL << (nr & SZLONG_MASK)), "m" (*m));
+               : "ir" (1UL << bit), "m" (*m));
        } else {
                volatile unsigned long *a = addr;
                unsigned long mask;
                unsigned long flags;
 
                a += nr >> SZLONG_LOG;
-               mask = 1UL << (nr & SZLONG_MASK);
+               mask = 1UL << bit;
                local_irq_save(flags);
                *a ^= mask;
                local_irq_restore(flags);
@@ -233,6 +237,8 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
 static inline int test_and_set_bit(unsigned long nr,
        volatile unsigned long *addr)
 {
+       unsigned short bit = nr & SZLONG_MASK;
+
        if (cpu_has_llsc && R10000_LLSC_WAR) {
                unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
                unsigned long temp, res;
@@ -246,7 +252,7 @@ static inline int test_and_set_bit(unsigned long nr,
                "       and     %2, %0, %3                              \n"
                "       .set    mips0                                   \n"
                : "=&r" (temp), "=m" (*m), "=&r" (res)
-               : "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
+               : "r" (1UL << bit), "m" (*m)
                : "memory");
 
                return res != 0;
@@ -269,7 +275,7 @@ static inline int test_and_set_bit(unsigned long nr,
                "       .previous                                       \n"
                "       .set    pop                                     \n"
                : "=&r" (temp), "=m" (*m), "=&r" (res)
-               : "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
+               : "r" (1UL << bit), "m" (*m)
                : "memory");
 
                return res != 0;
@@ -280,7 +286,7 @@ static inline int test_and_set_bit(unsigned long nr,
                unsigned long flags;
 
                a += nr >> SZLONG_LOG;
-               mask = 1UL << (nr & SZLONG_MASK);
+               mask = 1UL << bit;
                local_irq_save(flags);
                retval = (mask & *a) != 0;
                *a |= mask;
@@ -303,6 +309,8 @@ static inline int test_and_set_bit(unsigned long nr,
 static inline int test_and_clear_bit(unsigned long nr,
        volatile unsigned long *addr)
 {
+       unsigned short bit = nr & SZLONG_MASK;
+
        if (cpu_has_llsc && R10000_LLSC_WAR) {
                unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
                unsigned long temp, res;
@@ -317,7 +325,7 @@ static inline int test_and_clear_bit(unsigned long nr,
                "       and     %2, %0, %3                              \n"
                "       .set    mips0                                   \n"
                : "=&r" (temp), "=m" (*m), "=&r" (res)
-               : "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
+               : "r" (1UL << bit), "m" (*m)
                : "memory");
 
                return res != 0;
@@ -336,7 +344,7 @@ static inline int test_and_clear_bit(unsigned long nr,
                "2:     b       1b                                      \n"
                "       .previous                                       \n"
                : "=&r" (temp), "=m" (*m), "=&r" (res)
-               : "ri" (nr & SZLONG_MASK), "m" (*m)
+               : "ri" (bit), "m" (*m)
                : "memory");
 
                return res;
@@ -361,7 +369,7 @@ static inline int test_and_clear_bit(unsigned long nr,
                "       .previous                                       \n"
                "       .set    pop                                     \n"
                : "=&r" (temp), "=m" (*m), "=&r" (res)
-               : "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
+               : "r" (1UL << bit), "m" (*m)
                : "memory");
 
                return res != 0;
@@ -372,7 +380,7 @@ static inline int test_and_clear_bit(unsigned long nr,
                unsigned long flags;
 
                a += nr >> SZLONG_LOG;
-               mask = 1UL << (nr & SZLONG_MASK);
+               mask = 1UL << bit;
                local_irq_save(flags);
                retval = (mask & *a) != 0;
                *a &= ~mask;
@@ -395,6 +403,8 @@ static inline int test_and_clear_bit(unsigned long nr,
 static inline int test_and_change_bit(unsigned long nr,
        volatile unsigned long *addr)
 {
+       unsigned short bit = nr & SZLONG_MASK;
+
        if (cpu_has_llsc && R10000_LLSC_WAR) {
                unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
                unsigned long temp, res;
@@ -408,7 +418,7 @@ static inline int test_and_change_bit(unsigned long nr,
                "       and     %2, %0, %3                              \n"
                "       .set    mips0                                   \n"
                : "=&r" (temp), "=m" (*m), "=&r" (res)
-               : "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
+               : "r" (1UL << bit), "m" (*m)
                : "memory");
 
                return res != 0;
@@ -431,7 +441,7 @@ static inline int test_and_change_bit(unsigned long nr,
                "       .previous                                       \n"
                "       .set    pop                                     \n"
                : "=&r" (temp), "=m" (*m), "=&r" (res)
-               : "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
+               : "r" (1UL << bit), "m" (*m)
                : "memory");
 
                return res != 0;
@@ -441,7 +451,7 @@ static inline int test_and_change_bit(unsigned long nr,
                unsigned long flags;
 
                a += nr >> SZLONG_LOG;
-               mask = 1UL << (nr & SZLONG_MASK);
+               mask = 1UL << bit;
                local_irq_save(flags);
                retval = (mask & *a) != 0;
                *a ^= mask;
index e06ef0776d48950f3b0ea556219ea2c2c84a3fce..833437d31ef1634c1286d957b8cca8971bc158f2 100644 (file)
@@ -74,7 +74,7 @@
  *
  */
 
-#ifndef GENERIC_ISA_DMA_SUPPORT_BROKEN
+#ifndef CONFIG_GENERIC_ISA_DMA_SUPPORT_BROKEN
 #define MAX_DMA_CHANNELS       8
 #endif
 
diff --git a/include/asm-mips/ds1742.h b/include/asm-mips/ds1742.h
deleted file mode 100644 (file)
index c2f2c32..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * 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) 2006 by Ralf Baechle (ralf@linux-mips.org)
- */
-#ifndef _ASM_DS1742_H
-#define _ASM_DS1742_H
-
-#include <ds1742.h>
-
-#endif /* _ASM_DS1742_H */
index cba641a6ce09a5b674081820a14767c507ff1bd4..2036fcb9f117aa8d024724ca5829f542812a8b2b 100644 (file)
 #define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS)
 #define _IOC_DIRSHIFT  (_IOC_SIZESHIFT+_IOC_SIZEBITS)
 
-/*
- * We to additionally limit parameters to a maximum 255 bytes.
- */
-#define _IOC_SLMASK    0xff
-
 /*
  * Direction bits _IOC_NONE could be 0, but OSF/1 gives it a bit.
  * And this turns out useful to catch old ioctl numbers in header
index baf412967afa1920843730b05ca920c7d4565303..c50e68ffa3af85fe078c6a9e9094e80dff26789b 100644 (file)
@@ -179,12 +179,6 @@ static inline int jmr3927_have_isac(void)
 #define jmr3927_have_nvram() \
        ((jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR) & JMR3927_IDT_MASK) == JMR3927_IOC_IDT)
 
-/* NVRAM macro */
-#define jmr3927_nvram_in(ofs) \
-       jmr3927_ioc_reg_in(JMR3927_IOC_NVRAMB_ADDR + ((ofs) << 1))
-#define jmr3927_nvram_out(d, ofs) \
-       jmr3927_ioc_reg_out(d, JMR3927_IOC_NVRAMB_ADDR + ((ofs) << 1))
-
 /* LED macro */
 #define jmr3927_led_set(n/*0-16*/)     jmr3927_ioc_reg_out(~(n), JMR3927_IOC_LED_ADDR)
 #define jmr3927_io_led_set(n/*0-3*/)   jmr3927_isac_reg_out((n), JMR3927_ISAC_LED_ADDR)
index 181afc5c0f1d3e9b0b3119bc83fc13b2ade36f3b..42077e367a5bbe44dc38b63735aae3c4047812bd 100644 (file)
@@ -237,8 +237,6 @@ static inline void lasat_ndelay(unsigned int ns)
             __delay(ns / lasat_ndelay_divider);
 }
 
-extern void (* prom_printf)(const char *fmt, ...);
-
 #endif /* !defined (_LANGUAGE_ASSEMBLY) */
 
 #define LASAT_SERVICEMODE_MAGIC_1     0xdeadbeef
index a73a5698420c1cde3486c42adbd4f5db6d349988..51d337e1bbd12f0ec1dba6871c6d743230eef2e7 100644 (file)
@@ -55,6 +55,6 @@ static inline void CMOS_WRITE(unsigned char data, unsigned long addr)
 
 #define RTC_ALWAYS_BCD 0
 
-#define mc146818_decode_year(year) ((year) < 70 ? (year) + 2000 : (year) + 1970)
+#define mc146818_decode_year(year) ((year) < 70 ? (year) + 2000 : (year) + 1900)
 
 #endif /* __ASM_MACH_ATLAS_MC146818RTC_H */
index df71822fd27bd892739add507ef88f5fe695cbf8..76e04e7feb844988c634203cf933d7305e7637a5 100644 (file)
 
 struct device;
 
-static dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size)
+static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
+       size_t size)
 {
        return virt_to_phys(addr);
 }
 
-static dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page)
+static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
+       struct page *page)
 {
        return page_to_phys(page);
 }
 
-static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+static inline unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
 {
        return dma_addr;
 }
 
-static void plat_unmap_dma_mem(dma_addr_t dma_addr)
+static inline void plat_unmap_dma_mem(dma_addr_t dma_addr)
 {
 }
 
index 90c2e6f77faa7821b32546c4fdaeeb510281316c..0b9a942f079d0a8f1c325d7ab5b988145ce124fb 100644 (file)
@@ -30,7 +30,7 @@ static inline void CMOS_WRITE(unsigned char data, unsigned long addr)
 #define RTC_ALWAYS_BCD 1
 
 #ifndef mc146818_decode_year
-#define mc146818_decode_year(year) ((year) < 70 ? (year) + 2000 : (year) + 1970)
+#define mc146818_decode_year(year) ((year) < 70 ? (year) + 2000 : (year) + 1900)
 #endif
 
 #endif /* __ASM_MACH_GENERIC_MC146818RTC_H */
index 44790fdc5d00d989fbf7c5fbd81d007f3119876d..61d9be3f31759f7aea84bbfbef5852c2183d02bd 100644 (file)
@@ -28,7 +28,6 @@ extern unsigned char __node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES];
        .busy_factor            = 32,                   \
        .imbalance_pct          = 125,                  \
        .cache_nice_tries       = 1,                    \
-       .per_cpu_gain           = 100,                  \
        .flags                  = SD_LOAD_BALANCE       \
                                | SD_BALANCE_EXEC       \
                                | SD_WAKE_BALANCE,      \
diff --git a/include/asm-mips/mach-jmr3927/ds1742.h b/include/asm-mips/mach-jmr3927/ds1742.h
deleted file mode 100644 (file)
index 8a8fef6..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * 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) 2003, 06 by Ralf Baechle
- */
-#ifndef __ASM_MACH_JMR3927_DS1742_H
-#define __ASM_MACH_JMR3927_DS1742_H
-
-#include <asm/jmr3927/jmr3927.h>
-
-#define rtc_read(reg)          (jmr3927_nvram_in(reg))
-#define rtc_write(data, reg)   (jmr3927_nvram_out((data),(reg)))
-
-#endif /* __ASM_MACH_JMR3927_DS1742_H */
diff --git a/include/asm-mips/mach-jmr3927/mangle-port.h b/include/asm-mips/mach-jmr3927/mangle-port.h
new file mode 100644 (file)
index 0000000..501a202
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef __ASM_MACH_JMR3927_MANGLE_PORT_H
+#define __ASM_MACH_JMR3927_MANGLE_PORT_H
+
+extern unsigned long __swizzle_addr_b(unsigned long port);
+#define __swizzle_addr_w(port) (port)
+#define __swizzle_addr_l(port) (port)
+#define __swizzle_addr_q(port) (port)
+
+#define ioswabb(a,x)           (x)
+#define __mem_ioswabb(a,x)     (x)
+#define ioswabw(a,x)           le16_to_cpu(x)
+#define __mem_ioswabw(a,x)     (x)
+#define ioswabl(a,x)           le32_to_cpu(x)
+#define __mem_ioswabl(a,x)     (x)
+#define ioswabq(a,x)           le64_to_cpu(x)
+#define __mem_ioswabq(a,x)     (x)
+
+#endif /* __ASM_MACH_JMR3927_MANGLE_PORT_H */
index 6730ba0665766ff329705c6c59c5358f9900621b..ea612f37f61484c7b0c0f29371086027c7ffb24e 100644 (file)
@@ -43,6 +43,6 @@ static inline void CMOS_WRITE(unsigned char data, unsigned long addr)
 
 #define RTC_ALWAYS_BCD 0
 
-#define mc146818_decode_year(year) ((year) < 70 ? (year) + 2000 : (year) + 1970)
+#define mc146818_decode_year(year) ((year) < 70 ? (year) + 2000 : (year) + 1900)
 
 #endif /* __ASM_MACH_MALTA_MC146818RTC_H */
index d37ae68dc6a3d05cae4d5f3c9558b00a798da159..145bce096fe9b036573bc0d930c8b8323a697a03 100644 (file)
@@ -7,11 +7,15 @@
  *
  * RTC routines for PC style attached Dallas chip with ARC epoch.
  */
-#ifndef __ASM_MACH_RM200_MC146818RTC_H
-#define __ASM_MACH_RM200_MC146818RTC_H
+#ifndef __ASM_MACH_RM_MC146818RTC_H
+#define __ASM_MACH_RM_MC146818RTC_H
 
+#ifdef CONFIG_CPU_BIG_ENDIAN
+#define mc146818_decode_year(year) ((year) < 70 ? (year) + 2000 : (year) + 1900)
+#else
 #define mc146818_decode_year(year) ((year) + 1980)
+#endif
 
 #include_next <mc146818rtc.h>
 
-#endif /* __ASM_MACH_RM200_MC146818RTC_H */
+#endif /* __ASM_MACH_RM_MC146818RTC_H */
index 7bf6f5f6ab9c0845db161e521d21cef8d9ad642b..daaf9f98fc63ce7547a3660b915cb0ee2599e547 100644 (file)
@@ -28,8 +28,6 @@
 
 extern char *prom_getcmdline(void);
 extern char *prom_getenv(char *name);
-extern void setup_prom_printf(int tty_no);
-extern void prom_printf(char *fmt, ...);
 extern void prom_init_cmdline(void);
 extern void prom_meminit(void);
 extern void prom_fixup_mem_map(unsigned long start_mem, unsigned long end_mem);
index fdfff0b8ce42575af3f3f78a2842600a84d725e0..8045abc78d0fc2a6eca35ba721f1e4e923307d36 100644 (file)
@@ -6,6 +6,8 @@
 #ifndef __ASM_MIPS_MT_H
 #define __ASM_MIPS_MT_H
 
+#include <linux/cpumask.h>
+
 extern cpumask_t mt_fpu_cpumask;
 extern unsigned long mt_fpemul_threshold;
 
index 8a1f2b6f04aca4e4b68fd9b63a2f4a42f7021da0..1906938285c0fdf5d36de2e8e232bb777e32a635 100644 (file)
@@ -21,6 +21,7 @@
 #define FPC_EIR                70
 #define DSP_BASE       71              /* 3 more hi / lo register pairs */
 #define DSP_CONTROL    77
+#define ACX            78
 
 /*
  * This struct defines the way the registers are stored on the stack during a
@@ -39,6 +40,9 @@ struct pt_regs {
        unsigned long cp0_status;
        unsigned long hi;
        unsigned long lo;
+#ifdef CONFIG_CPU_HAS_SMARTMIPS
+       unsigned long acx;
+#endif
        unsigned long cp0_badvaddr;
        unsigned long cp0_cause;
        unsigned long cp0_epc;
index 73f09731550236874b41c13ffbd3c631370f96ea..bfce5c786f1c2772c0a5515c3e10b62b7e6d6185 100644 (file)
@@ -33,9 +33,6 @@ extern int prom_flags;
 extern void prom_putchar(char c);
 extern char prom_getchar(void);
 
-/* Generic printf() using ARCS console I/O. */
-extern void prom_printf(char *fmt, ...);
-
 /* Memory descriptor management. */
 #define PROM_MAX_PMEMBLOCKS    32
 struct prom_pmemblock {
index 2ba6988ddc8e897a3c43fdd2844d08a625a7d054..dfb29e13bce0c5d162a297c851538eaef2603049 100644 (file)
@@ -57,8 +57,6 @@ extern void bcm1480_mask_irq(int cpu, int irq);
 extern void bcm1480_unmask_irq(int cpu, int irq);
 extern void bcm1480_smp_finish(void);
 
-extern void prom_printf(char *fmt, ...);
-
 #define AT_spin \
        __asm__ __volatile__ (          \
                ".set noat\n"           \
diff --git a/include/asm-mips/sibyte/trace_prof.h b/include/asm-mips/sibyte/trace_prof.h
deleted file mode 100644 (file)
index 5577920..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2001 Broadcom Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#ifndef __ASM_SIBYTE_TRACE_PROF_H
-#define __ASM_SIBYTE_TRACE_PROF_H
-
-#undef DBG
-#if SBPROF_TB_DEBUG
-#define DBG(a) a
-#else
-#define DBG(a)
-#endif
-
-#define SBPROF_TB_MAJOR 240
-#define DEVNAME "bcm1250_tbprof"
-
-typedef u_int64_t tb_sample_t[6*256];
-
-struct sbprof_tb {
-       int          open;
-       tb_sample_t *sbprof_tbbuf;
-       int          next_tb_sample;
-
-       volatile int tb_enable;
-       volatile int tb_armed;
-
-       wait_queue_head_t tb_sync;
-       wait_queue_head_t tb_read;
-};
-
-#define MAX_SAMPLE_BYTES (24*1024*1024)
-#define MAX_TBSAMPLE_BYTES (12*1024*1024)
-
-#define MAX_SAMPLES (MAX_SAMPLE_BYTES/sizeof(u_int32_t))
-#define TB_SAMPLE_SIZE (sizeof(tb_sample_t))
-#define MAX_TB_SAMPLES (MAX_TBSAMPLE_BYTES/TB_SAMPLE_SIZE)
-
-/* IOCTLs */
-#define SBPROF_ZBSTART         _IOW('s', 0, int)
-#define SBPROF_ZBSTOP          _IOW('s', 1, int)
-#define SBPROF_ZBWAITFULL      _IOW('s', 2, int)
-
-/***************************************************************************
- * Routines for gathering ZBbus profiles using trace buffer
- ***************************************************************************/
-
-/* Requires: Already called zclk_timer_init with a value that won't
-            saturate 40 bits.  No subsequent use of SCD performance counters
-            or trace buffer.
-   Effect:   Starts gathering random ZBbus profiles using trace buffer. */
-extern int sbprof_zbprof_start(struct file *filp);
-
-/* Effect: Stops collection of ZBbus profiles */
-extern int sbprof_zbprof_stop(void);
-
-
-/***************************************************************************
- * Routines for using 40-bit SCD cycle counter
- *
- * Client responsible for either handling interrupts or making sure
- * the cycles counter never saturates, e.g., by doing
- * zclk_timer_init(0) at least every 2^40 - 1 ZCLKs.
- ***************************************************************************/
-
-/* Configures SCD counter 0 to count ZCLKs starting from val;
-   Configures SCD counters1,2,3 to count nothing.
-   Must not be called while gathering ZBbus profiles.
-
-unsigned long long val; */
-#define zclk_timer_init(val) \
-  __asm__ __volatile__ (".set push;" \
-                       ".set mips64;" \
-                       "la   $8, 0xb00204c0;" /* SCD perf_cnt_cfg */ \
-                       "sd   %0, 0x10($8);"   /* write val to counter0 */ \
-                       "sd   %1, 0($8);"      /* config counter0 for zclks*/ \
-                       ".set pop" \
-                       : /* no outputs */ \
-                                                    /* enable, counter0 */ \
-                       : /* inputs */ "r"(val), "r" ((1ULL << 33) | 1ULL) \
-                       : /* modifies */ "$8" )
-
-
-/* Reads SCD counter 0 and puts result in value
-   unsigned long long val; */
-#define zclk_get(val) \
-  __asm__ __volatile__ (".set push;" \
-                       ".set mips64;" \
-                       "la   $8, 0xb00204c0;" /* SCD perf_cnt_cfg */ \
-                       "ld   %0, 0x10($8);"   /* write val to counter0 */ \
-                       ".set pop" \
-                       : /* outputs */ "=r"(val) \
-                       : /* inputs */ \
-                       : /* modifies */ "$8" )
-
-#endif /* __ASM_SIBYTE_TRACE_PROF_H */
index 972947474eb7e48a733e92f8497d0d6a8213ac00..9ce0607d7a4e9391ba9d4c592f312b1e999f8b31 100644 (file)
@@ -23,7 +23,7 @@ struct sigcontext {
        unsigned long long      sc_pc;
        unsigned long long      sc_regs[32];
        unsigned long long      sc_fpregs[32];
-       unsigned int            sc_ownedfp;     /* Unused */
+       unsigned int            sc_acx;         /* Was sc_ownedfp */
        unsigned int            sc_fpc_csr;
        unsigned int            sc_fpc_eir;     /* Unused */
        unsigned int            sc_used_math;
@@ -79,7 +79,7 @@ struct sigcontext32 {
        __u64           sc_pc;
        __u64           sc_regs[32];
        __u64           sc_fpregs[32];
-       __u32           sc_ownedfp;     /* Unused */
+       __u32           sc_acx;         /* Only MIPS32; was sc_ownedfp */
        __u32           sc_fpc_csr;
        __u32           sc_fpc_eir;     /* Unused */
        __u32           sc_used_math;
index e1941d1b8726b389f652a910600e2083351af8cc..44dfa4adecf323e970fcdd17d6c1aed8e67ab32e 100644 (file)
@@ -34,6 +34,9 @@ typedef long asiduse;
 
 extern asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];
 
+struct mm_struct;
+struct task_struct;
+
 void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu);
 
 void smtc_flush_tlb_asid(unsigned long asid);
index 55f3419f65465892f35630c3a32b730866ed77e1..360ea6d250c7a7aab3ec8516cffb99413bfe0e66 100644 (file)
@@ -4,6 +4,8 @@
 #ifndef __ASM_SMTC_IPI_H
 #define __ASM_SMTC_IPI_H
 
+#include <linux/spinlock.h>
+
 //#define SMTC_IPI_DEBUG
 
 #ifdef SMTC_IPI_DEBUG
index 62f9be6f7320f2844ba4dc5a0bac904292233de2..f257509b914f11dfe30380e10a64f86f1372de72 100644 (file)
@@ -141,10 +141,9 @@ extern unsigned int sni_brd_type;
 #define A20R_PT_TIM0_ACK        0xbc050000
 #define A20R_PT_TIM1_ACK        0xbc060000
 
-#define SNI_MIPS_IRQ_CPU_BASE   16
-#define SNI_MIPS_IRQ_CPU_TIMER  (SNI_MIPS_IRQ_CPU_BASE+7)
+#define SNI_MIPS_IRQ_CPU_TIMER  (MIPS_CPU_IRQ_BASE+7)
 
-#define SNI_A20R_IRQ_BASE       SNI_MIPS_IRQ_CPU_BASE
+#define SNI_A20R_IRQ_BASE       MIPS_CPU_IRQ_BASE
 #define SNI_A20R_IRQ_TIMER      (SNI_A20R_IRQ_BASE+5)
 
 #define SNI_DS1216_A20R_BASE    0xbc081ffc
@@ -155,7 +154,7 @@ extern unsigned int sni_brd_type;
 #define SNI_PCIT_INT_START      24
 #define SNI_PCIT_INT_END        30
 
-#define PCIT_IRQ_ETHERNET       (SNI_MIPS_IRQ_CPU_BASE + 5)
+#define PCIT_IRQ_ETHERNET       (MIPS_CPU_IRQ_BASE + 5)
 #define PCIT_IRQ_INTA           (SNI_PCIT_INT_START + 0)
 #define PCIT_IRQ_INTB           (SNI_PCIT_INT_START + 1)
 #define PCIT_IRQ_INTC           (SNI_PCIT_INT_START + 2)
@@ -180,7 +179,7 @@ extern unsigned int sni_brd_type;
 #define PCIMT_IRQ_EISA         29
 #define PCIMT_IRQ_SCSI         30
 
-#define PCIMT_IRQ_ETHERNET     (SNI_MIPS_IRQ_CPU_BASE+6)
+#define PCIMT_IRQ_ETHERNET     (MIPS_CPU_IRQ_BASE+6)
 
 #if 0
 #define PCIMT_IRQ_TEMPERATURE  24
index f1755d28a36a6f3a44f44bebd3f2f061617e8695..35e431cd796bf499bccfc2d6ef4bd76ad578009e 100644 (file)
@@ -287,7 +287,7 @@ static inline int __raw_read_trylock(raw_rwlock_t *rw)
                "       .set    noreorder       # __raw_read_trylock    \n"
                "       li      %2, 0                                   \n"
                "1:     ll      %1, %3                                  \n"
-               "       bnez    %1, 2f                                  \n"
+               "       bltz    %1, 2f                                  \n"
                "        addu   %1, 1                                   \n"
                "       sc      %1, %0                                  \n"
                "       .set    reorder                                 \n"
@@ -304,7 +304,7 @@ static inline int __raw_read_trylock(raw_rwlock_t *rw)
                "       .set    noreorder       # __raw_read_trylock    \n"
                "       li      %2, 0                                   \n"
                "1:     ll      %1, %3                                  \n"
-               "       bnez    %1, 2f                                  \n"
+               "       bltz    %1, 2f                                  \n"
                "        addu   %1, 1                                   \n"
                "       sc      %1, %0                                  \n"
                "       beqz    %1, 1b                                  \n"
index 1fae5dc581381cd4de2b1022023a53c1acf6647a..7afa1fdf70ca6a5dcba909b985869f66c72aca76 100644 (file)
                .endm
 
                .macro  SAVE_TEMP
+#ifdef CONFIG_CPU_HAS_SMARTMIPS
+               mflhxu  v1
+               LONG_S  v1, PT_LO(sp)
+               mflhxu  v1
+               LONG_S  v1, PT_HI(sp)
+               mflhxu  v1
+               LONG_S  v1, PT_ACX(sp)
+#else
                mfhi    v1
+               LONG_S  v1, PT_HI(sp)
+               mflo    v1
+               LONG_S  v1, PT_LO(sp)
+#endif
 #ifdef CONFIG_32BIT
                LONG_S  $8, PT_R8(sp)
                LONG_S  $9, PT_R9(sp)
 #endif
-               LONG_S  v1, PT_HI(sp)
-               mflo    v1
                LONG_S  $10, PT_R10(sp)
                LONG_S  $11, PT_R11(sp)
-               LONG_S  v1,  PT_LO(sp)
                LONG_S  $12, PT_R12(sp)
                LONG_S  $13, PT_R13(sp)
                LONG_S  $14, PT_R14(sp)
                .endm
 
                .macro  RESTORE_TEMP
+#ifdef CONFIG_CPU_HAS_SMARTMIPS
+               LONG_L  $24, PT_ACX(sp)
+               mtlhx   $24
+               LONG_L  $24, PT_HI(sp)
+               mtlhx   $24
                LONG_L  $24, PT_LO(sp)
+               mtlhx   $24
+#else
+               LONG_L  $24, PT_LO(sp)
+               mtlo    $24
+               LONG_L  $24, PT_HI(sp)
+               mthi    $24
+#endif
 #ifdef CONFIG_32BIT
                LONG_L  $8, PT_R8(sp)
                LONG_L  $9, PT_R9(sp)
 #endif
-               mtlo    $24
-               LONG_L  $24, PT_HI(sp)
                LONG_L  $10, PT_R10(sp)
                LONG_L  $11, PT_R11(sp)
-               mthi    $24
                LONG_L  $12, PT_R12(sp)
                LONG_L  $13, PT_R13(sp)
                LONG_L  $14, PT_R14(sp)
index c62c20e7b5c669dc29dd7273c7bb771e7dc12f14..b25511787ee0277ba5830b4178435d282278c846 100644 (file)
@@ -435,6 +435,8 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
        __cu_len;                                                       \
 })
 
+extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n);
+
 #define __copy_to_user_inatomic(to,from,n)                             \
 ({                                                                     \
        void __user *__cu_to;                                           \
index 696cff39a1d3e38dc7de8e49e77f55ebc172281d..2f1087b3a20278241d719fa60d594f744780bebf 100644 (file)
 #define __NR_kexec_load                        (__NR_Linux + 311)
 #define __NR_getcpu                    (__NR_Linux + 312)
 #define __NR_epoll_pwait               (__NR_Linux + 313)
+#define __NR_ioprio_set                        (__NR_Linux + 314)
+#define __NR_ioprio_get                        (__NR_Linux + 315)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls            313
+#define __NR_Linux_syscalls            315
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux                 4000
-#define __NR_O32_Linux_syscalls                313
+#define __NR_O32_Linux_syscalls                315
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
 #define __NR_kexec_load                        (__NR_Linux + 270)
 #define __NR_getcpu                    (__NR_Linux + 271)
 #define __NR_epoll_pwait               (__NR_Linux + 272)
+#define __NR_ioprio_set                        (__NR_Linux + 273)
+#define __NR_ioprio_get                        (__NR_Linux + 274)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls            272
+#define __NR_Linux_syscalls            274
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux                  5000
-#define __NR_64_Linux_syscalls         272
+#define __NR_64_Linux_syscalls         274
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
 #define __NR_kexec_load                        (__NR_Linux + 274)
 #define __NR_getcpu                    (__NR_Linux + 275)
 #define __NR_epoll_pwait               (__NR_Linux + 276)
+#define __NR_ioprio_set                        (__NR_Linux + 277)
+#define __NR_ioprio_get                        (__NR_Linux + 278)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls            276
+#define __NR_Linux_syscalls            278
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux                 6000
-#define __NR_N32_Linux_syscalls                276
+#define __NR_N32_Linux_syscalls                278
 
 #ifdef __KERNEL__
 
index 5a1e0e8b1c32d7843b77eccddc4049a46b27777c..5587f00238815d876c427cbfbba4b0e246d3f275 100644 (file)
 #define STREGM std,ma
 #define SHRREG shrd
 #define SHLREG shld
+#define ADDIB   addib,*
+#define CMPB    cmpb,*
+#define ANDCM   andcm,*
 #define RP_OFFSET      16
 #define FRAME_SIZE     128
 #define CALLEE_REG_FRAME_SIZE  144
+#define ASM_ULONG_INSN .dword
 #else  /* CONFIG_64BIT */
 #define LDREG  ldw
 #define STREG  stw
 #define STREGM stwm
 #define SHRREG shr
 #define SHLREG shlw
+#define ADDIB   addib,
+#define CMPB    cmpb,
+#define ANDCM   andcm
 #define RP_OFFSET      20
 #define FRAME_SIZE     64
 #define CALLEE_REG_FRAME_SIZE  128
+#define ASM_ULONG_INSN .word
 #endif
 
 #define CALLEE_SAVE_FRAME_SIZE (CALLEE_REG_FRAME_SIZE + CALLEE_FLOAT_FRAME_SIZE)
@@ -65,7 +73,7 @@
 
 #ifdef __ASSEMBLY__
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 /* the 64-bit pa gnu assembler unfortunately defaults to .level 1.1 or 2.0 so
  * work around that for now... */
        .level 2.0w
        .endm
 
        .macro loadgp
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        ldil            L%__gp, %r27
        ldo             R%__gp(%r27), %r27
 #else
        fldd,mb -8(%r30),   %fr12
        .endm
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        .macro  callee_save
        std,ma    %r3,   CALLEE_REG_FRAME_SIZE(%r30)
        mfctl     %cr27, %r3
        ldd,mb  -CALLEE_REG_FRAME_SIZE(%r30),    %r3
        .endm
 
-#else /* ! __LP64__ */
+#else /* ! CONFIG_64BIT */
 
        .macro  callee_save
        stw,ma   %r3,   CALLEE_REG_FRAME_SIZE(%r30)
        mtctl   %r3, %cr27
        ldw,mb  -CALLEE_REG_FRAME_SIZE(%r30),   %r3
        .endm
-#endif /* ! __LP64__ */
+#endif /* ! CONFIG_64BIT */
 
        .macro  save_specials   regs
 
        mtctl    %r0,   %cr18
        SAVE_CR  (%cr18, PT_IAOQ1(\regs))
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        /* cr11 (sar) is a funny one.  5 bits on PA1.1 and 6 bit on PA2.0
         * For PA2.0 mtsar or mtctl always write 6 bits, but mfctl only
         * reads 5 bits.  Use mfctl,w to read all six bits.  Otherwise
index 48bf9b8ab8ff7fe0f22c049712993881d429c79f..7d57d34fcca8a969e520e4817b04cfe641506857 100644 (file)
@@ -58,7 +58,7 @@ extern void __xchg_called_with_bad_pointer(void);
 /* __xchg32/64 defined in arch/parisc/lib/bitops.c */
 extern unsigned long __xchg8(char, char *);
 extern unsigned long __xchg32(int, int *);
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 extern unsigned long __xchg64(unsigned long, unsigned long *);
 #endif
 
@@ -67,7 +67,7 @@ static __inline__ unsigned long
 __xchg(unsigned long x, __volatile__ void * ptr, int size)
 {
        switch(size) {
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        case 8: return __xchg64(x,(unsigned long *) ptr);
 #endif
        case 4: return __xchg32((int) x, (int *) ptr);
@@ -81,7 +81,7 @@ __xchg(unsigned long x, __volatile__ void * ptr, int size)
 /*
 ** REVISIT - Abandoned use of LDCW in xchg() for now:
 ** o need to test sizeof(*ptr) to avoid clearing adjacent bytes
-** o and while we are at it, could __LP64__ code use LDCD too?
+** o and while we are at it, could CONFIG_64BIT code use LDCD too?
 **
 **     if (__builtin_constant_p(x) && (x == NULL))
 **             if (((unsigned long)p & 0xf) == 0)
@@ -105,7 +105,7 @@ static __inline__ unsigned long
 __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size)
 {
        switch(size) {
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        case 8: return __cmpxchg_u64((unsigned long *)ptr, old, new_);
 #endif
        case 4: return __cmpxchg_u32((unsigned int *)ptr, (unsigned int) old, (unsigned int) new_);
@@ -218,7 +218,7 @@ static __inline__ int atomic_read(const atomic_t *v)
 #define smp_mb__before_atomic_inc()    smp_mb()
 #define smp_mb__after_atomic_inc()     smp_mb()
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 
 typedef struct { volatile s64 counter; } atomic64_t;
 
@@ -270,7 +270,7 @@ atomic64_read(const atomic64_t *v)
 #define atomic64_dec_and_test(v)       (atomic64_dec_return(v) == 0)
 #define atomic64_sub_and_test(i,v)     (atomic64_sub_return((i),(v)) == 0)
 
-#endif /* __LP64__ */
+#endif /* CONFIG_64BIT */
 
 #include <asm-generic/atomic.h>
 
index 900561922c4c26c5786e16625f510c5cfaf397f3..015cb0d379bd991d42c719d32bd2111f9573b63f 100644 (file)
@@ -60,31 +60,37 @@ static __inline__ void change_bit(int nr, volatile unsigned long * addr)
 static __inline__ int test_and_set_bit(int nr, volatile unsigned long * addr)
 {
        unsigned long mask = 1UL << CHOP_SHIFTCOUNT(nr);
-       unsigned long oldbit;
+       unsigned long old;
        unsigned long flags;
+       int set;
 
        addr += (nr >> SHIFT_PER_LONG);
        _atomic_spin_lock_irqsave(addr, flags);
-       oldbit = *addr;
-       *addr = oldbit | mask;
+       old = *addr;
+       set = (old & mask) ? 1 : 0;
+       if (!set)
+               *addr = old | mask;
        _atomic_spin_unlock_irqrestore(addr, flags);
 
-       return (oldbit & mask) ? 1 : 0;
+       return set;
 }
 
 static __inline__ int test_and_clear_bit(int nr, volatile unsigned long * addr)
 {
        unsigned long mask = 1UL << CHOP_SHIFTCOUNT(nr);
-       unsigned long oldbit;
+       unsigned long old;
        unsigned long flags;
+       int set;
 
        addr += (nr >> SHIFT_PER_LONG);
        _atomic_spin_lock_irqsave(addr, flags);
-       oldbit = *addr;
-       *addr = oldbit & ~mask;
+       old = *addr;
+       set = (old & mask) ? 1 : 0;
+       if (set)
+               *addr = old & ~mask;
        _atomic_spin_unlock_irqrestore(addr, flags);
 
-       return (oldbit & mask) ? 1 : 0;
+       return set;
 }
 
 static __inline__ int test_and_change_bit(int nr, volatile unsigned long * addr)
@@ -130,7 +136,7 @@ static __inline__ unsigned long __ffs(unsigned long x)
        unsigned long ret;
 
        __asm__(
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
                " ldi       63,%1\n"
                " extrd,u,*<>  %0,63,32,%%r0\n"
                " extrd,u,*TR  %0,31,32,%0\n"   /* move top 32-bits down */
index 695588da41f8a73bb31d3fbeb7c686bf0fdfa751..83ba510ed5d874ea77c70ec9d8ed7352fd31b6dc 100644 (file)
@@ -1,14 +1,92 @@
 #ifndef _PARISC_BUG_H
 #define _PARISC_BUG_H
 
+/*
+ * Tell the user there is some problem.
+ * The offending file and line are encoded in the __bug_table section.
+ */
+
 #ifdef CONFIG_BUG
 #define HAVE_ARCH_BUG
-#define BUG() do { \
-       printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
-       dump_stack(); \
-       panic("BUG!"); \
-} while (0)
+#define HAVE_ARCH_WARN_ON
+
+/* the break instruction is used as BUG() marker.  */
+#define        PARISC_BUG_BREAK_ASM    "break 0x1f, 0x1fff"
+#define        PARISC_BUG_BREAK_INSN   0x03ffe01f  /* PARISC_BUG_BREAK_ASM */
+
+#if defined(CONFIG_64BIT)
+#define ASM_WORD_INSN          ".dword\t"
+#else
+#define ASM_WORD_INSN          ".word\t"
+#endif
+
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+#define BUG()                                                          \
+       do {                                                            \
+               asm volatile("\n"                                       \
+                            "1:\t" PARISC_BUG_BREAK_ASM "\n"           \
+                            "\t.pushsection __bug_table,\"a\"\n"       \
+                            "2:\t" ASM_WORD_INSN "1b, %c0\n"           \
+                            "\t.short %c1, %c2\n"                      \
+                            "\t.org 2b+%c3\n"                          \
+                            "\t.popsection"                            \
+                            : : "i" (__FILE__), "i" (__LINE__),        \
+                            "i" (0), "i" (sizeof(struct bug_entry)) ); \
+               for(;;) ;                                               \
+       } while(0)
+
+#else
+#define BUG()                                                          \
+       do {                                                            \
+               asm volatile(PARISC_BUG_BREAK_ASM : : );                \
+               for(;;) ;                                               \
+       } while(0)
+#endif
+
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+#define __WARN()                                                       \
+       do {                                                            \
+               asm volatile("\n"                                       \
+                            "1:\t" PARISC_BUG_BREAK_ASM "\n"           \
+                            "\t.pushsection __bug_table,\"a\"\n"       \
+                            "2:\t" ASM_WORD_INSN "1b, %c0\n"           \
+                            "\t.short %c1, %c2\n"                      \
+                            "\t.org 2b+%c3\n"                          \
+                            "\t.popsection"                            \
+                            : : "i" (__FILE__), "i" (__LINE__),        \
+                            "i" (BUGFLAG_WARNING),                     \
+                            "i" (sizeof(struct bug_entry)) );          \
+       } while(0)
+#else
+#define __WARN()                                                       \
+       do {                                                            \
+               asm volatile("\n"                                       \
+                            "1:\t" PARISC_BUG_BREAK_ASM "\n"           \
+                            "\t.pushsection __bug_table,\"a\"\n"       \
+                            "2:\t" ASM_WORD_INSN "1b\n"                \
+                            "\t.short %c0\n"                           \
+                            "\t.org 2b+%c1\n"                          \
+                            "\t.popsection"                            \
+                            : : "i" (BUGFLAG_WARNING),                 \
+                            "i" (sizeof(struct bug_entry)) );          \
+       } while(0)
+#endif
+
+
+#define WARN_ON(x) ({                                          \
+       typeof(x) __ret_warn_on = (x);                          \
+       if (__builtin_constant_p(__ret_warn_on)) {              \
+               if (__ret_warn_on)                              \
+                       __WARN();                               \
+       } else {                                                \
+               if (unlikely(__ret_warn_on))                    \
+                       __WARN();                               \
+       }                                                       \
+       unlikely(__ret_warn_on);                                \
+})
+
 #endif
 
 #include <asm-generic/bug.h>
 #endif
+
index 7d22fa206fc407f04908372f52d6b3685b6c3f99..32c2cca74345995d9cdbc80fc46c59081f734871 100644 (file)
 
 #define __read_mostly __attribute__((__section__(".data.read_mostly")))
 
-extern void flush_data_cache_local(void *);  /* flushes local data-cache only */
-extern void flush_instruction_cache_local(void *); /* flushes local code-cache only */
-#ifdef CONFIG_SMP
-extern void flush_data_cache(void); /* flushes data-cache only (all processors) */
-extern void flush_instruction_cache(void); /* flushes i-cache only (all processors) */
-#else
-#define flush_data_cache() flush_data_cache_local(NULL)
-#define flush_instruction_cache() flush_instruction_cache_local(NULL)
-#endif
-
-extern void parisc_cache_init(void);   /* initializes cache-flushing */
-extern void flush_all_caches(void);     /* flush everything (tlb & cache) */
-extern int get_cache_info(char *);
-extern void flush_user_icache_range_asm(unsigned long, unsigned long);
-extern void flush_kernel_icache_range_asm(unsigned long, unsigned long);
-extern void flush_user_dcache_range_asm(unsigned long, unsigned long);
-extern void flush_kernel_dcache_range_asm(unsigned long, unsigned long);
-extern void flush_kernel_dcache_page_asm(void *);
-extern void flush_kernel_icache_page(void *);
-extern void disable_sr_hashing(void);   /* turns off space register hashing */
-extern void disable_sr_hashing_asm(int); /* low level support for above */
-extern void free_sid(unsigned long);
+void parisc_cache_init(void);  /* initializes cache-flushing */
+void disable_sr_hashing_asm(int); /* low level support for above */
+void disable_sr_hashing(void);   /* turns off space register hashing */
+void free_sid(unsigned long);
 unsigned long alloc_sid(void);
-extern void flush_user_dcache_page(unsigned long);
-extern void flush_user_icache_page(unsigned long);
 
 struct seq_file;
 extern void show_cache_info(struct seq_file *m);
@@ -63,6 +43,7 @@ extern int split_tlb;
 extern int dcache_stride;
 extern int icache_stride;
 extern struct pdc_cache_info cache_info;
+void parisc_setup_cache_timing(void);
 
 #define pdtlb(addr)         asm volatile("pdtlb 0(%%sr1,%0)" : : "r" (addr));
 #define pitlb(addr)         asm volatile("pitlb 0(%%sr1,%0)" : : "r" (addr));
index a799dd8ef395a94f9a923848ffa6384384eb1efc..2f1e1b05440a50cf1de278e03c7b698cf09851bb 100644 (file)
@@ -2,60 +2,46 @@
 #define _PARISC_CACHEFLUSH_H
 
 #include <linux/mm.h>
-#include <asm/cache.h> /* for flush_user_dcache_range_asm() proto */
 
 /* The usual comment is "Caches aren't brain-dead on the <architecture>".
  * Unfortunately, that doesn't apply to PA-RISC. */
 
-/* Cache flush operations */
-
+/* Internal implementation */
+void flush_data_cache_local(void *);  /* flushes local data-cache only */
+void flush_instruction_cache_local(void *); /* flushes local code-cache only */
 #ifdef CONFIG_SMP
-#define flush_cache_mm(mm) flush_cache_all()
+void flush_data_cache(void); /* flushes data-cache only (all processors) */
+void flush_instruction_cache(void); /* flushes i-cache only (all processors) */
 #else
-#define flush_cache_mm(mm) flush_cache_all_local()
+#define flush_data_cache() flush_data_cache_local(NULL)
+#define flush_instruction_cache() flush_instruction_cache_local(NULL)
 #endif
 
 #define flush_cache_dup_mm(mm) flush_cache_mm(mm)
 
-#define flush_kernel_dcache_range(start,size) \
-       flush_kernel_dcache_range_asm((start), (start)+(size));
+void flush_user_icache_range_asm(unsigned long, unsigned long);
+void flush_kernel_icache_range_asm(unsigned long, unsigned long);
+void flush_user_dcache_range_asm(unsigned long, unsigned long);
+void flush_kernel_dcache_range_asm(unsigned long, unsigned long);
+void flush_kernel_dcache_page_asm(void *);
+void flush_kernel_icache_page(void *);
+void flush_user_dcache_page(unsigned long);
+void flush_user_icache_page(unsigned long);
+void flush_user_dcache_range(unsigned long, unsigned long);
+void flush_user_icache_range(unsigned long, unsigned long);
 
-extern void flush_cache_all_local(void);
+/* Cache flush operations */
 
-static inline void cacheflush_h_tmp_function(void *dummy)
-{
-       flush_cache_all_local();
-}
+void flush_cache_all_local(void);
+void flush_cache_all(void);
+void flush_cache_mm(struct mm_struct *mm);
 
-static inline void flush_cache_all(void)
-{
-       on_each_cpu(cacheflush_h_tmp_function, NULL, 1, 1);
-}
+#define flush_kernel_dcache_range(start,size) \
+       flush_kernel_dcache_range_asm((start), (start)+(size));
 
 #define flush_cache_vmap(start, end)           flush_cache_all()
 #define flush_cache_vunmap(start, end)         flush_cache_all()
 
-extern int parisc_cache_flush_threshold;
-void parisc_setup_cache_timing(void);
-
-static inline void
-flush_user_dcache_range(unsigned long start, unsigned long end)
-{
-       if ((end - start) < parisc_cache_flush_threshold)
-               flush_user_dcache_range_asm(start,end);
-       else
-               flush_data_cache();
-}
-
-static inline void
-flush_user_icache_range(unsigned long start, unsigned long end)
-{
-       if ((end - start) < parisc_cache_flush_threshold)
-               flush_user_icache_range_asm(start,end);
-       else
-               flush_instruction_cache();
-}
-
 extern void flush_dcache_page(struct page *page);
 
 #define flush_dcache_mmap_lock(mapping) \
@@ -63,9 +49,15 @@ extern void flush_dcache_page(struct page *page);
 #define flush_dcache_mmap_unlock(mapping) \
        write_unlock_irq(&(mapping)->tree_lock)
 
-#define flush_icache_page(vma,page)    do { flush_kernel_dcache_page(page); flush_kernel_icache_page(page_address(page)); } while (0)
+#define flush_icache_page(vma,page)    do {            \
+       flush_kernel_dcache_page(page);                 \
+       flush_kernel_icache_page(page_address(page));   \
+} while (0)
 
-#define flush_icache_range(s,e)                do { flush_kernel_dcache_range_asm(s,e); flush_kernel_icache_range_asm(s,e); } while (0)
+#define flush_icache_range(s,e)                do {            \
+       flush_kernel_dcache_range_asm(s,e);             \
+       flush_kernel_icache_range_asm(s,e);             \
+} while (0)
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
 do { \
@@ -80,118 +72,17 @@ do { \
        memcpy(dst, src, len); \
 } while (0)
 
-static inline void flush_cache_range(struct vm_area_struct *vma,
-               unsigned long start, unsigned long end)
-{
-       int sr3;
-
-       if (!vma->vm_mm->context) {
-               BUG();
-               return;
-       }
-
-       sr3 = mfsp(3);
-       if (vma->vm_mm->context == sr3) {
-               flush_user_dcache_range(start,end);
-               flush_user_icache_range(start,end);
-       } else {
-               flush_cache_all();
-       }
-}
-
-/* Simple function to work out if we have an existing address translation
- * for a user space vma. */
-static inline int translation_exists(struct vm_area_struct *vma,
-                               unsigned long addr, unsigned long pfn)
-{
-       pgd_t *pgd = pgd_offset(vma->vm_mm, addr);
-       pmd_t *pmd;
-       pte_t pte;
-
-       if(pgd_none(*pgd))
-               return 0;
-
-       pmd = pmd_offset(pgd, addr);
-       if(pmd_none(*pmd) || pmd_bad(*pmd))
-               return 0;
-
-       /* We cannot take the pte lock here: flush_cache_page is usually
-        * called with pte lock already held.  Whereas flush_dcache_page
-        * takes flush_dcache_mmap_lock, which is lower in the hierarchy:
-        * the vma itself is secure, but the pte might come or go racily.
-        */
-       pte = *pte_offset_map(pmd, addr);
-       /* But pte_unmap() does nothing on this architecture */
-
-       /* Filter out coincidental file entries and swap entries */
-       if (!(pte_val(pte) & (_PAGE_FLUSH|_PAGE_PRESENT)))
-               return 0;
-
-       return pte_pfn(pte) == pfn;
-}
-
-/* Private function to flush a page from the cache of a non-current
- * process.  cr25 contains the Page Directory of the current user
- * process; we're going to hijack both it and the user space %sr3 to
- * temporarily make the non-current process current.  We have to do
- * this because cache flushing may cause a non-access tlb miss which
- * the handlers have to fill in from the pgd of the non-current
- * process. */
-static inline void
-flush_user_cache_page_non_current(struct vm_area_struct *vma,
-                                 unsigned long vmaddr)
-{
-       /* save the current process space and pgd */
-       unsigned long space = mfsp(3), pgd = mfctl(25);
-
-       /* we don't mind taking interrups since they may not
-        * do anything with user space, but we can't
-        * be preempted here */
-       preempt_disable();
-
-       /* make us current */
-       mtctl(__pa(vma->vm_mm->pgd), 25);
-       mtsp(vma->vm_mm->context, 3);
-
-       flush_user_dcache_page(vmaddr);
-       if(vma->vm_flags & VM_EXEC)
-               flush_user_icache_page(vmaddr);
-
-       /* put the old current process back */
-       mtsp(space, 3);
-       mtctl(pgd, 25);
-       preempt_enable();
-}
-
-static inline void
-__flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr)
-{
-       if (likely(vma->vm_mm->context == mfsp(3))) {
-               flush_user_dcache_page(vmaddr);
-               if (vma->vm_flags & VM_EXEC)
-                       flush_user_icache_page(vmaddr);
-       } else {
-               flush_user_cache_page_non_current(vma, vmaddr);
-       }
-}
-
-static inline void
-flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn)
-{
-       BUG_ON(!vma->vm_mm->context);
-
-       if (likely(translation_exists(vma, vmaddr, pfn)))
-               __flush_cache_page(vma, vmaddr);
-
-}
+void flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn);
+void flush_cache_range(struct vm_area_struct *vma,
+               unsigned long start, unsigned long end);
 
+#define ARCH_HAS_FLUSH_ANON_PAGE
 static inline void
 flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr)
 {
        if (PageAnon(page))
                flush_user_dcache_page(vmaddr);
 }
-#define ARCH_HAS_FLUSH_ANON_PAGE
 
 #define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
 void flush_kernel_dcache_page_addr(void *addr);
index 66f0b408c66907cd90b42ee8861507760ac5b67d..c6c0e9ff6bdea3eeb623893fb2d8d3a078d893f9 100644 (file)
@@ -236,7 +236,7 @@ int ccio_allocate_resource(const struct parisc_device *dev,
                unsigned long min, unsigned long max, unsigned long align);
 #else /* !CONFIG_IOMMU_CCIO */
 #define ccio_get_iommu(dev) NULL
-#define ccio_request_resource(dev, res) request_resource(&iomem_resource, res)
+#define ccio_request_resource(dev, res) insert_resource(&iomem_resource, res)
 #define ccio_allocate_resource(dev, res, size, min, max, align) \
                allocate_resource(&iomem_resource, res, size, min, max, \
                                align, NULL, NULL)
index adea65fc43c904e5da19bd29e88741b8f2b2368e..f628ac7de83dca17868b3737732b00c61354f62a 100644 (file)
@@ -220,7 +220,7 @@ typedef struct elf64_fdesc {
  * macros, and then it includes fs/binfmt_elf.c to provide an alternate
  * elf binary handler for 32 bit binaries (on the 64 bit kernel).
  */
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 #define ELF_CLASS       ELFCLASS64
 #else
 #define ELF_CLASS      ELFCLASS32
index 106d3f7cd882385a373417938ce74532804addd4..76d880dc4baebb4de2e62185cc78197c92be4768 100644 (file)
@@ -1,19 +1,13 @@
 #ifndef _PARISC_HARDWARE_H
 #define _PARISC_HARDWARE_H
 
+#include <linux/mod_devicetable.h>
 #include <asm/pdc.h>
 
-struct parisc_device_id {
-       unsigned char   hw_type;        /* 5 bits used */
-       unsigned char   hversion_rev;   /* 4 bits */
-       unsigned short  hversion;       /* 12 bits */
-       unsigned int    sversion;       /* 20 bits */
-};
-
-#define HWTYPE_ANY_ID  0xff
-#define HVERSION_REV_ANY_ID    0xff
-#define HVERSION_ANY_ID        0xffff
-#define SVERSION_ANY_ID        0xffffffffU
+#define HWTYPE_ANY_ID          PA_HWTYPE_ANY_ID
+#define HVERSION_ANY_ID                PA_HVERSION_ANY_ID
+#define HVERSION_REV_ANY_ID    PA_HVERSION_REV_ANY_ID
+#define SVERSION_ANY_ID                PA_SVERSION_ANY_ID
 
 struct hp_hardware {
        unsigned short  hw_type:5;      /* HPHW_xxx */
index ca46e7cc094044f2649a5274967e978d83ad72b0..c0fed91da3a22a86f987bfe134405c620a429b4b 100644 (file)
@@ -67,7 +67,7 @@ static inline unsigned long long gsc_readq(unsigned long addr)
 {
        unsigned long long ret;
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        __asm__ __volatile__(
        "       ldda    0(%1),%0\n"
        :  "=r" (ret) : "r" (addr) );
@@ -108,7 +108,7 @@ static inline void gsc_writel(unsigned int val, unsigned long addr)
 
 static inline void gsc_writeq(unsigned long long val, unsigned long addr)
 {
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        __asm__ __volatile__(
        "       stda    %0,0(%1)\n"
        : :  "r" (val), "r" (addr) );
index efadfd543ec64fea09a942c00adc268d1e880cd3..c3405ab9d60ad14d76d4b1cc86acd46ff9611d83 100644 (file)
@@ -31,7 +31,7 @@ void __init register_led_regions(void);
 
 #ifdef CONFIG_CHASSIS_LCD_LED
 /* writes a string to the LCD display (if possible on this h/w) */
-int lcd_print(char *str);
+int lcd_print(const char *str);
 #else
 #define lcd_print(str)
 #endif
index 291c2d01c44f29dad20f7623783b8bad362eaddf..7a09d911b53895eb5976ab96fd62d53989018d11 100644 (file)
@@ -1,6 +1,28 @@
-#ifndef __ASM_LINKAGE_H
-#define __ASM_LINKAGE_H
+#ifndef __ASM_PARISC_LINKAGE_H
+#define __ASM_PARISC_LINKAGE_H
 
-/* Nothing to see here... */
+#ifndef __ALIGN
+#define __ALIGN         .align 4
+#define __ALIGN_STR     ".align 4"
+#endif
+
+/*
+ * In parisc assembly a semicolon marks a comment while a
+ * exclamation mark is used to seperate independend lines.
+ */
+#define ENTRY(name) \
+       .export name !\
+       ALIGN !\
+name:
 
+#ifdef CONFIG_64BIT
+#define ENDPROC(name) \
+       END(name)
+#else
+#define ENDPROC(name) \
+       .type name, @function !\
+       END(name)
 #endif
+
+
+#endif  /* __ASM_PARISC_LINKAGE_H */
index c87813662d4da83d80d78dc8cb65a7fd43a64822..9608d2cf214ac7d33d76661b6bff10cc9dad00c1 100644 (file)
@@ -35,7 +35,7 @@ extern struct node_map_data node_data[];
 #define PFNNID_MAP_MAX  512     /* support 512GB */
 extern unsigned char pfnnid_map[PFNNID_MAP_MAX];
 
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
 #define pfn_is_io(pfn) ((pfn & (0xf0000000UL >> PAGE_SHIFT)) == (0xf0000000UL >> PAGE_SHIFT))
 #else
 /* io can be 0xf0f0f0f0f0xxxxxx or 0xfffffffff0000000 */
index 00f06885f843b1d1395ff097cbec7d8553e079f3..c2cb49e934c1d66110bb2618d14efe6ae0811228 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file contains the parisc architecture specific module code.
  */
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 #define Elf_Shdr Elf64_Shdr
 #define Elf_Sym Elf64_Sym
 #define Elf_Ehdr Elf64_Ehdr
index 14ffc2782f1e31dad3fde5befd2f59d34c7160ca..fe88f2649418e63c77022ed74ff43b12c1bccda2 100644 (file)
 
 struct msqid64_ds {
        struct ipc64_perm msg_perm;
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
        unsigned int   __pad1;
 #endif
        __kernel_time_t msg_stime;      /* last msgsnd time */
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
        unsigned int   __pad2;
 #endif
        __kernel_time_t msg_rtime;      /* last msgrcv time */
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
        unsigned int   __pad3;
 #endif
        __kernel_time_t msg_ctime;      /* last change time */
index 3567208191e37d09f47199a26a0a223dce1b6c28..f6bba4c136649e8bfb9a363388cc6d6b0d23fdc4 100644 (file)
@@ -105,7 +105,7 @@ extern int npmem_ranges;
 /* WARNING: The definitions below must match exactly to sizeof(pte_t)
  * etc
  */
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 #define BITS_PER_PTE_ENTRY     3
 #define BITS_PER_PMD_ENTRY     2
 #define BITS_PER_PGD_ENTRY     2
@@ -127,7 +127,11 @@ extern int npmem_ranges;
 /* This governs the relationship between virtual and physical addresses.
  * If you alter it, make sure to take care of our various fixed mapping
  * segments in fixmap.h */
-#define __PAGE_OFFSET           (0x10000000)
+#ifdef CONFIG_64BIT
+#define __PAGE_OFFSET  (0x40000000)    /* 1GB */
+#else
+#define __PAGE_OFFSET  (0x10000000)    /* 256MB */
+#endif
 
 #define PAGE_OFFSET            ((unsigned long)__PAGE_OFFSET)
 
index e12624d8941d69cbc6bb35bb70d452d70642b428..7aa13f2add7a837d36653a7f4f63a0bcc521fbb0 100644 (file)
@@ -15,7 +15,7 @@ struct parisc_device {
        unsigned int    num_addrs;      /* some devices have additional address ranges. */
        unsigned long   *addr;          /* which will be stored here */
  
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        /* parms for pdc_pat_cell_module() call */
        unsigned long   pcell_loc;      /* Physical Cell location */
        unsigned long   mod_index;      /* PAT specific - Misc Module info */
index 423c2b84b4a02360fa49d43b5c5376fcfb46d9bd..876fd8116d4ae5c9a4c0313d383c5ee47c2cce62 100644 (file)
@@ -341,7 +341,7 @@ struct pdc_model {          /* for PDC_MODEL */
 
 struct pdc_cache_cf {          /* for PDC_CACHE  (I/D-caches) */
     unsigned long
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
                cc_padW:32,
 #endif
                cc_alias: 4,    /* alias boundaries for virtual addresses   */
@@ -357,7 +357,7 @@ struct pdc_cache_cf {               /* for PDC_CACHE  (I/D-caches) */
 
 struct pdc_tlb_cf {            /* for PDC_CACHE (I/D-TLB's) */
     unsigned long tc_pad0:12,  /* reserved */
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
                tc_padW:32,
 #endif
                tc_sh   : 2,    /* 0 = separate I/D-TLB, else shared I/D-TLB */
@@ -445,7 +445,7 @@ struct pdc_btlb_info {      /* PDC_BLOCK_TLB, return of PDC_BTLB_INFO */
 
 #endif /* !CONFIG_PA20 */
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 struct pdc_memory_table_raddr { /* PDC_MEM/PDC_MEM_TABLE (return info) */
        unsigned long entries_returned;
        unsigned long entries_total;
@@ -456,7 +456,7 @@ struct pdc_memory_table {       /* PDC_MEM/PDC_MEM_TABLE (arguments) */
        unsigned int  pages;
        unsigned int  reserved;
 };
-#endif /* __LP64__ */
+#endif /* CONFIG_64BIT */
 
 struct pdc_system_map_mod_info { /* PDC_SYSTEM_MAP/FIND_MODULE */
        unsigned long mod_addr;
@@ -752,7 +752,7 @@ int pdc_get_initiator(struct hardware_path *, struct pdc_initiator *);
 int pdc_tod_read(struct pdc_tod *tod);
 int pdc_tod_set(unsigned long sec, unsigned long usec);
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 int pdc_mem_mem_table(struct pdc_memory_table_raddr *r_addr,
                struct pdc_memory_table *tbl, unsigned long entries);
 #endif
index b4b34c0e8c1a81140fef4f6422b77b95c7295fd7..47539f11795835e8397bb77602d8e82d99e14a3f 100644 (file)
@@ -250,7 +250,7 @@ struct pdc_pat_pd_addr_map_entry {
 #define PAT_GET_ENTITY(value)  (((value) >> 56) & 0xffUL)
 #define PAT_GET_DVI(value)     (((value) >> 48) & 0xffUL)
 #define PAT_GET_IOC(value)     (((value) >> 40) & 0xffUL)
-#define PAT_GET_MOD_PAGES(value)(((value) & 0xffffffUL)
+#define PAT_GET_MOD_PAGES(value) ((value) & 0xffffffUL)
 
 
 /*
@@ -303,35 +303,6 @@ extern int pdc_pat_io_pci_cfg_write(unsigned long pci_addr, int pci_size, u32 va
 */
 extern int pdc_pat;     /* arch/parisc/kernel/inventory.c */
 
-/********************************************************************
-* PDC_PAT_CELL[Return Cell Module] memaddr[0] conf_base_addr
-* ----------------------------------------------------------
-* Bit  0 to 51 - conf_base_addr
-* Bit 52 to 62 - reserved
-* Bit       63 - endianess bit
-********************************************************************/
-#define PAT_GET_CBA(value) ((value) & 0xfffffffffffff000UL)
-
-/********************************************************************
-* PDC_PAT_CELL[Return Cell Module] memaddr[1] mod_info
-* ----------------------------------------------------
-* Bit  0 to  7 - entity type
-*    0 = central agent,            1 = processor,
-*    2 = memory controller,        3 = system bus adapter,
-*    4 = local bus adapter,        5 = processor bus converter,
-*    6 = crossbar fabric connect,  7 = fabric interconnect,
-*    8 to 254 reserved,            255 = unknown.
-* Bit  8 to 15 - DVI
-* Bit 16 to 23 - IOC functions
-* Bit 24 to 39 - reserved
-* Bit 40 to 63 - mod_pages
-*    number of 4K pages a module occupies starting at conf_base_addr
-********************************************************************/
-#define PAT_GET_ENTITY(value)  (((value) >> 56) & 0xffUL)
-#define PAT_GET_DVI(value)     (((value) >> 48) & 0xffUL)
-#define PAT_GET_IOC(value)     (((value) >> 40) & 0xffUL)
-#define PAT_GET_MOD_PAGES(value)(((value) & 0xffffffUL)
-
 #endif /* __ASSEMBLY__ */
 
 #endif /* ! __PARISC_PATPDC_H */
index 3122fad38a1b766417ac8dd38f510ff181424f71..1af1a41e07233fa52e6d5da67afceecaf1d69301 100644 (file)
@@ -14,7 +14,7 @@
  * Here (for 64 bit kernels) we implement a Hybrid L2/L3 scheme: we
  * allocate the first pmd adjacent to the pgd.  This means that we can
  * subtract a constant offset to get to it.  The pmd and pgd sizes are
- * arranged so that a single pmd covers 4GB (giving a full LP64
+ * arranged so that a single pmd covers 4GB (giving a full 64-bit
  * process access to 8TB) so our lookups are effectively L2 for the
  * first 4GB of the kernel (i.e. for all ILP32 processes and all the
  * kernel for machines with under 4GB of memory) */
@@ -26,7 +26,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 
        if (likely(pgd != NULL)) {
                memset(pgd, 0, PAGE_SIZE<<PGD_ALLOC_ORDER);
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
                actual_pgd += PTRS_PER_PGD;
                /* Populate first pmd with allocated memory.  We mark it
                 * with PxD_FLAG_ATTACHED as a signal to the system that this
@@ -45,7 +45,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 
 static inline void pgd_free(pgd_t *pgd)
 {
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        pgd -= PTRS_PER_PGD;
 #endif
        free_pages((unsigned long)pgd, PGD_ALLOC_ORDER);
@@ -72,7 +72,7 @@ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
 
 static inline void pmd_free(pmd_t *pmd)
 {
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        if(pmd_flag(*pmd) & PxD_FLAG_ATTACHED)
                /* This is the permanent pmd attached to the pgd;
                 * cannot free it */
@@ -99,7 +99,7 @@ static inline void pmd_free(pmd_t *pmd)
 static inline void
 pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte)
 {
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
        /* preserve the gateway marker if this is the beginning of
         * the permanent pmd */
        if(pmd_flag(*pmd) & PxD_FLAG_ATTACHED)
index c0b61e0d14973d9e4765f4f8528c103a850138b0..d7e1b10da5c62bdebc0124380ff74965305ab054 100644 (file)
@@ -10,7 +10,6 @@
  * we simulate an x86-style page table for the linux mm code
  */
 
-#include <linux/spinlock.h>
 #include <linux/mm.h>          /* for vm_area_struct */
 #include <asm/processor.h>
 #include <asm/cache.h>
index 9b19970de619ed6871c07142f5bc0b62763004d9..b634e3c47fdce61d08f2fdaef2abf5f2c3f464c1 100644 (file)
@@ -20,7 +20,7 @@ typedef int                   __kernel_timer_t;
 typedef int                    __kernel_clockid_t;
 typedef int                    __kernel_daddr_t;
 /* Note these change from narrow to wide kernels */
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 typedef unsigned long          __kernel_size_t;
 typedef long                   __kernel_ssize_t;
 typedef long                   __kernel_ptrdiff_t;
index fd7866dc8c83462b2d8a3274ac4118b5315de8d2..d2f396721d3eb9461c41c307dc6d6da7c93d7f63 100644 (file)
@@ -9,13 +9,10 @@
 #define __ASM_PARISC_PROCESSOR_H
 
 #ifndef __ASSEMBLY__
-#include <asm/prefetch.h>      /* lockdep.h needs <linux/prefetch.h> */
-
 #include <linux/threads.h>
-#include <linux/spinlock_types.h>
 
+#include <asm/prefetch.h>
 #include <asm/hardware.h>
-#include <asm/page.h>
 #include <asm/pdc.h>
 #include <asm/ptrace.h>
 #include <asm/types.h>
@@ -41,7 +38,7 @@
 #define DEFAULT_TASK_SIZE32    (0xFFF00000UL)
 #define DEFAULT_MAP_BASE32     (0x40000000UL)
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 #define DEFAULT_TASK_SIZE       (MAX_ADDRESS-0xf000000)
 #define DEFAULT_MAP_BASE        (0x200000000UL)
 #else
@@ -87,7 +84,6 @@ struct cpuinfo_parisc {
        unsigned long hpa;          /* Host Physical address */
        unsigned long txn_addr;     /* MMIO addr of EIR or id_eid */
 #ifdef CONFIG_SMP
-       spinlock_t lock;            /* synchronization for ipi's */
        unsigned long pending_ipi;  /* bitmap of type ipi_message_type */
        unsigned long ipi_count;    /* number ipi Interrupts */
 #endif
@@ -277,7 +273,7 @@ on downward growing arches, it looks like this:
  * it in here from the current->personality
  */
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 #define USER_WIDE_MODE (!test_thread_flag(TIF_32BIT))
 #else
 #define USER_WIDE_MODE 0
index 1083368ef8dbc5426607c9f3785b877952ce5bcd..1e59ffd3bd1ee6663acc20e663e4dafe282f4b2b 100644 (file)
 
 struct semid64_ds {
        struct ipc64_perm sem_perm;             /* permissions .. see ipc.h */
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
        unsigned int    __pad1;
 #endif
        __kernel_time_t sem_otime;              /* last semop time */
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
        unsigned int    __pad2;
 #endif
        __kernel_time_t sem_ctime;              /* last change time */
index 623b6c0c49e6b315c0934736a646d358b146fcf0..0a3eada1863b71e1e859e5bf1536da089a65ffd1 100644 (file)
 
 struct shmid64_ds {
        struct ipc64_perm       shm_perm;       /* operation perms */
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
        unsigned int            __pad1;
 #endif
        __kernel_time_t         shm_atime;      /* last attach time */
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
        unsigned int            __pad2;
 #endif
        __kernel_time_t         shm_dtime;      /* last detach time */
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
        unsigned int            __pad3;
 #endif
        __kernel_time_t         shm_ctime;      /* last change time */
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
        unsigned int            __pad4;
 #endif
        size_t                  shm_segsz;      /* size of segment (bytes) */
@@ -36,7 +36,7 @@ struct shmid64_ds {
        unsigned int            __unused2;
 };
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 /* The 'unsigned int' (formerly 'unsigned long') data types below will
  * ensure that a 32-bit app calling shmctl(*,IPC_INFO,*) will work on
  * a wide kernel, but if some of these values are meant to contain pointers
index 98a82fa0cfdbffeb53bee0ba8d2f61cfeccb0185..c20356375d1d5630f07d98ed27212b6e5d08a257 100644 (file)
 struct siginfo;
 
 /* Type of a signal handler.  */
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 /* function pointers on 64-bit parisc are pointers to little structs and the
  * compiler doesn't support code which changes or tests the address of
  * the function in the little struct.  This is really ugly -PB
index d4c0e26afcd1a88fa9bfdaa2fccefe227c92f5ff..306f4950e32ebe49428931c0447121b1e5d7dc3d 100644 (file)
@@ -41,14 +41,6 @@ extern void smp_send_all_nop(void);
  
 #define PROC_CHANGE_PENALTY    15              /* Schedule penalty */
 
-#undef ENTRY_SYS_CPUS
-#ifdef ENTRY_SYS_CPUS
-#define STATE_RENDEZVOUS                       0
-#define STATE_STOPPED                          1 
-#define STATE_RUNNING                          2
-#define STATE_HALTED                           3
-#endif
-
 extern unsigned long cpu_present_mask;
 
 #define raw_smp_processor_id() (current_thread_info()->cpu)
index d6b479bdb8865b565071779747dfd526f1447a1b..3f72f47cf4b20c798ac09a0b3ac520a069062046 100644 (file)
@@ -1,10 +1,6 @@
 #ifndef __ASM_SPINLOCK_TYPES_H
 #define __ASM_SPINLOCK_TYPES_H
 
-#ifndef __LINUX_SPINLOCK_TYPES_H
-# error "please don't include this file directly"
-#endif
-
 typedef struct {
 #ifdef CONFIG_PA20
        volatile unsigned int slock;
index a52d8f93f05cef647096cc445940a3b5b356f73b..1d2b8130b23d61ee1f1be7c9430e58f682a847ef 100644 (file)
@@ -30,11 +30,11 @@ struct statfs {
 struct statfs64 {
        long f_type;
        long f_bsize;
-       u64 f_blocks;
-       u64 f_bfree;
-       u64 f_bavail;
-       u64 f_files;
-       u64 f_ffree;
+       __u64 f_blocks;
+       __u64 f_bfree;
+       __u64 f_bavail;
+       __u64 f_files;
+       __u64 f_ffree;
        __kernel_fsid_t f_fsid;
        long f_namelen;
        long f_frsize;
index 74f037a39e6f032ce6a76ae974d521f6357d1f6e..7e9afa720d4389b31e5a4fc1e1164ec23df5def0 100644 (file)
@@ -34,7 +34,7 @@ struct pa_psw {
        unsigned int i:1;
 };
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 #define pa_psw(task) ((struct pa_psw *) ((char *) (task) + TASK_PT_PSW + 4))
 #else
 #define pa_psw(task) ((struct pa_psw *) ((char *) (task) + TASK_PT_PSW))
index f2f83b04cd8b8fad0c1bc5c19fa3b839d5cc1704..949314cf6188998dae95213b930e79a7edbb4c7b 100644 (file)
@@ -62,6 +62,7 @@ struct thread_info {
 #define TIF_POLLING_NRFLAG     4       /* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_32BIT               5       /* 32 bit binary */
 #define TIF_MEMDIE             6
+#define TIF_RESTORE_SIGMASK    7       /* restore saved signal mask */
 
 #define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME     (1 << TIF_NOTIFY_RESUME)
@@ -69,9 +70,10 @@ struct thread_info {
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG    (1 << TIF_POLLING_NRFLAG)
 #define _TIF_32BIT             (1 << TIF_32BIT)
+#define _TIF_RESTORE_SIGMASK   (1 << TIF_RESTORE_SIGMASK)
 
 #define _TIF_USER_WORK_MASK     (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
-                                 _TIF_NEED_RESCHED)
+                                 _TIF_NEED_RESCHED | _TIF_RESTORE_SIGMASK)
 
 #endif /* __KERNEL__ */
 
index f662e837dea14a1a0533e59b368daa5ef5406032..3313da9ea00f317b95efcc0cee36784f68f5d3be 100644 (file)
@@ -73,33 +73,11 @@ static inline void flush_tlb_page(struct vm_area_struct *vma,
        purge_tlb_end();
 }
 
-static inline void flush_tlb_range(struct vm_area_struct *vma,
-       unsigned long start, unsigned long end)
-{
-       unsigned long npages;
+void __flush_tlb_range(unsigned long sid,
+       unsigned long start, unsigned long end);
 
-       npages = ((end - (start & PAGE_MASK)) + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
-       if (npages >= 512)  /* 2MB of space: arbitrary, should be tuned */
-               flush_tlb_all();
-       else {
-               mtsp(vma->vm_mm->context,1);
-               purge_tlb_start();
-               if (split_tlb) {
-                       while (npages--) {
-                               pdtlb(start);
-                               pitlb(start);
-                               start += PAGE_SIZE;
-                       }
-               } else {
-                       while (npages--) {
-                               pdtlb(start);
-                               start += PAGE_SIZE;
-                       }
-               }
-               purge_tlb_end();
-       }
-}
+#define flush_tlb_range(vma,start,end) __flush_tlb_range((vma)->vm_mm->context,start,end)
 
-#define flush_tlb_kernel_range(start, end) flush_tlb_all()
+#define flush_tlb_kernel_range(start, end) __flush_tlb_range(0,start,end)
 
 #endif
index 34fdce361a5abbebfef5645a3399a20e0515f226..d4aa33033d98d334d2b28d977e3f17355eccb3d1 100644 (file)
@@ -31,7 +31,7 @@ typedef unsigned long long __u64;
  */
 #ifdef __KERNEL__
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 #define BITS_PER_LONG 64
 #define SHIFT_PER_LONG 6
 #else
index d973e8b3466ca805afbdf52a846211434f2e8269..4878b9501f245ec77bb826a800d2878e34c7cc0e 100644 (file)
@@ -4,7 +4,6 @@
 /*
  * User space memory access functions
  */
-#include <linux/sched.h>
 #include <asm/page.h>
 #include <asm/system.h>
 #include <asm/cache.h>
@@ -43,16 +42,18 @@ static inline long access_ok(int type, const void __user * addr,
 #define put_user __put_user
 #define get_user __get_user
 
-#if BITS_PER_LONG == 32
+#if !defined(CONFIG_64BIT)
 #define LDD_KERNEL(ptr)                __get_kernel_bad();
 #define LDD_USER(ptr)          __get_user_bad();
 #define STD_KERNEL(x, ptr)     __put_kernel_asm64(x,ptr)
 #define STD_USER(x, ptr)       __put_user_asm64(x,ptr)
+#define ASM_WORD_INSN          ".word\t"
 #else
-#define LDD_KERNEL(ptr) __get_kernel_asm("ldd",ptr)
-#define LDD_USER(ptr) __get_user_asm("ldd",ptr)
-#define STD_KERNEL(x, ptr) __put_kernel_asm("std",x,ptr)
-#define STD_USER(x, ptr) __put_user_asm("std",x,ptr)
+#define LDD_KERNEL(ptr)                __get_kernel_asm("ldd",ptr)
+#define LDD_USER(ptr)          __get_user_asm("ldd",ptr)
+#define STD_KERNEL(x, ptr)     __put_kernel_asm("std",x,ptr)
+#define STD_USER(x, ptr)       __put_user_asm("std",x,ptr)
+#define ASM_WORD_INSN          ".dword\t"
 #endif
 
 /*
@@ -66,6 +67,11 @@ struct exception_table_entry {
        long fixup;          /* fixup routine */
 };
 
+#define ASM_EXCEPTIONTABLE_ENTRY( fault_addr, except_addr )\
+       ".section __ex_table,\"aw\"\n"                     \
+       ASM_WORD_INSN #fault_addr ", " #except_addr "\n\t" \
+       ".previous\n"
+
 /*
  * The page fault handler stores, in a per-cpu area, the following information
  * if a fixup routine is available.
@@ -104,43 +110,19 @@ struct exception_data {
        __gu_err;                                       \
 })
 
-#ifdef __LP64__
-#define __get_kernel_asm(ldx,ptr)                       \
-       __asm__("\n1:\t" ldx "\t0(%2),%0\n"             \
-               "\t.section __ex_table,\"aw\"\n"        \
-               "\t.dword\t1b,fixup_get_user_skip_1\n"  \
-               "\t.previous"                           \
-               : "=r"(__gu_val), "=r"(__gu_err)        \
-               : "r"(ptr), "1"(__gu_err)               \
-               : "r1");
-
-#define __get_user_asm(ldx,ptr)                         \
-       __asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n"       \
-               "\t.section __ex_table,\"aw\"\n"        \
-               "\t.dword\t1b,fixup_get_user_skip_1\n"  \
-               "\t.previous"                           \
-               : "=r"(__gu_val), "=r"(__gu_err)        \
-               : "r"(ptr), "1"(__gu_err)               \
-               : "r1");
-#else
 #define __get_kernel_asm(ldx,ptr)                       \
-       __asm__("\n1:\t" ldx "\t0(%2),%0\n"             \
-               "\t.section __ex_table,\"aw\"\n"        \
-               "\t.word\t1b,fixup_get_user_skip_1\n"   \
-               "\t.previous"                           \
+       __asm__("\n1:\t" ldx "\t0(%2),%0\n\t"           \
+               ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_get_user_skip_1)\
                : "=r"(__gu_val), "=r"(__gu_err)        \
                : "r"(ptr), "1"(__gu_err)               \
                : "r1");
 
 #define __get_user_asm(ldx,ptr)                         \
-       __asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n"       \
-               "\t.section __ex_table,\"aw\"\n"        \
-                "\t.word\t1b,fixup_get_user_skip_1\n"  \
-                "\t.previous"                          \
+       __asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n\t"     \
+               ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_get_user_skip_1)\
                : "=r"(__gu_val), "=r"(__gu_err)        \
                : "r"(ptr), "1"(__gu_err)               \
                : "r1");
-#endif /* !__LP64__ */
 
 #define __put_user(x,ptr)                                       \
 ({                                                             \
@@ -179,80 +161,54 @@ struct exception_data {
  * r8/r9 are already listed as err/val.
  */
 
-#ifdef __LP64__
 #define __put_kernel_asm(stx,x,ptr)                         \
        __asm__ __volatile__ (                              \
-               "\n1:\t" stx "\t%2,0(%1)\n"                 \
-               "\t.section __ex_table,\"aw\"\n"            \
-               "\t.dword\t1b,fixup_put_user_skip_1\n"      \
-               "\t.previous"                               \
+               "\n1:\t" stx "\t%2,0(%1)\n\t"               \
+               ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_put_user_skip_1)\
                : "=r"(__pu_err)                            \
                : "r"(ptr), "r"(x), "0"(__pu_err)           \
                : "r1")
 
 #define __put_user_asm(stx,x,ptr)                           \
        __asm__ __volatile__ (                              \
-               "\n1:\t" stx "\t%2,0(%%sr3,%1)\n"           \
-               "\t.section __ex_table,\"aw\"\n"            \
-                "\t.dword\t1b,fixup_put_user_skip_1\n"     \
-                "\t.previous"                              \
-               : "=r"(__pu_err)                            \
-               : "r"(ptr), "r"(x), "0"(__pu_err)           \
-               : "r1")
-#else
-#define __put_kernel_asm(stx,x,ptr)                         \
-       __asm__ __volatile__ (                              \
-               "\n1:\t" stx "\t%2,0(%1)\n"                 \
-               "\t.section __ex_table,\"aw\"\n"            \
-                "\t.word\t1b,fixup_put_user_skip_1\n"      \
-                "\t.previous"                              \
+               "\n1:\t" stx "\t%2,0(%%sr3,%1)\n\t"         \
+               ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_put_user_skip_1)\
                : "=r"(__pu_err)                            \
                : "r"(ptr), "r"(x), "0"(__pu_err)           \
                : "r1")
 
-#define __put_user_asm(stx,x,ptr)                           \
-       __asm__ __volatile__ (                              \
-               "\n1:\t" stx "\t%2,0(%%sr3,%1)\n"           \
-               "\t.section __ex_table,\"aw\"\n"            \
-                "\t.word\t1b,fixup_put_user_skip_1\n"      \
-                "\t.previous"                              \
-               : "=r"(__pu_err)                            \
-               : "r"(ptr), "r"(x), "0"(__pu_err)           \
-               : "r1")
 
-#define __put_kernel_asm64(__val,ptr) do {                         \
-       u64 __val64 = (u64)(__val);                                 \
-       u32 hi = (__val64) >> 32;                                           \
-       u32 lo = (__val64) & 0xffffffff;                                    \
+#if !defined(CONFIG_64BIT)
+
+#define __put_kernel_asm64(__val,ptr) do {                 \
+       u64 __val64 = (u64)(__val);                         \
+       u32 hi = (__val64) >> 32;                           \
+       u32 lo = (__val64) & 0xffffffff;                    \
        __asm__ __volatile__ (                              \
-               "\n1:\tstw %2,0(%1)\n"                      \
-               "\n2:\tstw %3,4(%1)\n"                      \
-               "\t.section __ex_table,\"aw\"\n"            \
-                "\t.word\t1b,fixup_put_user_skip_2\n"      \
-                "\t.word\t2b,fixup_put_user_skip_1\n"      \
-                "\t.previous"                              \
+               "\n1:\tstw %2,0(%1)"                        \
+               "\n2:\tstw %3,4(%1)\n\t"                    \
+               ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_put_user_skip_2)\
+               ASM_EXCEPTIONTABLE_ENTRY(2b,fixup_put_user_skip_1)\
                : "=r"(__pu_err)                            \
                : "r"(ptr), "r"(hi), "r"(lo), "0"(__pu_err) \
                : "r1");                                    \
 } while (0)
 
-#define __put_user_asm64(__val,ptr) do {                           \
-       u64 __val64 = (u64)__val;                                   \
-       u32 hi = (__val64) >> 32;                                           \
-       u32 lo = (__val64) & 0xffffffff;                                    \
+#define __put_user_asm64(__val,ptr) do {                   \
+       u64 __val64 = (u64)(__val);                         \
+       u32 hi = (__val64) >> 32;                           \
+       u32 lo = (__val64) & 0xffffffff;                    \
        __asm__ __volatile__ (                              \
-               "\n1:\tstw %2,0(%%sr3,%1)\n"                \
-               "\n2:\tstw %3,4(%%sr3,%1)\n"                \
-               "\t.section __ex_table,\"aw\"\n"            \
-                "\t.word\t1b,fixup_get_user_skip_2\n"      \
-                "\t.word\t2b,fixup_get_user_skip_1\n"      \
-                "\t.previous"                              \
+               "\n1:\tstw %2,0(%%sr3,%1)"                  \
+               "\n2:\tstw %3,4(%%sr3,%1)\n\t"              \
+               ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_put_user_skip_2)\
+               ASM_EXCEPTIONTABLE_ENTRY(2b,fixup_put_user_skip_1)\
                : "=r"(__pu_err)                            \
                : "r"(ptr), "r"(hi), "r"(lo), "0"(__pu_err) \
                : "r1");                                    \
 } while (0)
 
-#endif /* !__LP64__ */
+#endif /* !defined(CONFIG_64BIT) */
 
 
 /*
index 53b0f5d290e457d405d2950cb8982693658514df..2f7c40861c91dbb2cae7ca888271140820b6ba12 100644 (file)
 #define __NR_mknodat           (__NR_Linux + 277)
 #define __NR_fchownat          (__NR_Linux + 278)
 #define __NR_futimesat         (__NR_Linux + 279)
-#define __NR_newfstatat                (__NR_Linux + 280)
+#define __NR_fstatat64         (__NR_Linux + 280)
 #define __NR_unlinkat          (__NR_Linux + 281)
 #define __NR_renameat          (__NR_Linux + 282)
 #define __NR_linkat            (__NR_Linux + 283)
 #define __NR_splice            (__NR_Linux + 291)
 #define __NR_sync_file_range   (__NR_Linux + 292)
 #define __NR_tee               (__NR_Linux + 293)
+#define __NR_vmsplice          (__NR_Linux + 294)
+#define __NR_move_pages                (__NR_Linux + 295)
+#define __NR_getcpu            (__NR_Linux + 296)
+#define __NR_epoll_pwait       (__NR_Linux + 297)
+#define __NR_statfs64          (__NR_Linux + 298)
+#define __NR_fstatfs64         (__NR_Linux + 299)
 
-#define __NR_Linux_syscalls     294
+#define __NR_Linux_syscalls     (__NR_fstatfs64 + 1)
 
 #define HPUX_GATEWAY_ADDR       0xC0000004
 #define LINUX_GATEWAY_ADDR      0x100
@@ -951,6 +957,8 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)       \
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 
 #endif /* __ASSEMBLY__ */
 
index 6610495f5f166201f5d0e6f3f4ed1b2b665f933c..0ad21a849b5fb5dad0b4e50a88df61b8a4bf1a13 100644 (file)
@@ -57,7 +57,6 @@ static inline int pcibus_to_node(struct pci_bus *bus)
        .busy_factor            = 32,                   \
        .imbalance_pct          = 125,                  \
        .cache_nice_tries       = 1,                    \
-       .per_cpu_gain           = 100,                  \
        .busy_idx               = 3,                    \
        .idle_idx               = 1,                    \
        .newidle_idx            = 2,                    \
index af20c7462485f06de1dfb888e6f48769f0e64e9e..c17bdbf220672bb522b0a81d241c703d157b0427 100644 (file)
@@ -215,6 +215,8 @@ static __inline__ void atomic64_set_mask(unsigned long mask, atomic64_t * v)
               __CSG_LOOP(v, mask, "ogr");
 }
 
+#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
+
 static __inline__ long long atomic64_cmpxchg(atomic64_t *v,
                                             long long old, long long new)
 {
index 2c365962131470b035e3c89db537c5f87ae474fe..011f1e6a2a6cd8af7078fbc39eed791368dd3056 100644 (file)
@@ -16,7 +16,7 @@
  *      void check_bugs(void);
  */
 
-static void __init check_bugs(void)
+static inline void check_bugs(void)
 {
   /* s390 has no bugs ... */
 }
diff --git a/include/asm-s390/ipl.h b/include/asm-s390/ipl.h
new file mode 100644 (file)
index 0000000..660f782
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * s390 (re)ipl support
+ *
+ * Copyright IBM Corp. 2007
+ */
+
+#ifndef _ASM_S390_IPL_H
+#define _ASM_S390_IPL_H
+
+#include <asm/types.h>
+
+#define IPL_PARMBLOCK_ORIGIN   0x2000
+
+#define IPL_PARM_BLK_FCP_LEN (sizeof(struct ipl_list_hdr) + \
+                             sizeof(struct ipl_block_fcp))
+
+#define IPL_PARM_BLK_CCW_LEN (sizeof(struct ipl_list_hdr) + \
+                             sizeof(struct ipl_block_ccw))
+
+#define IPL_MAX_SUPPORTED_VERSION (0)
+
+#define IPL_PARMBLOCK_START    ((struct ipl_parameter_block *) \
+                                IPL_PARMBLOCK_ORIGIN)
+#define IPL_PARMBLOCK_SIZE     (IPL_PARMBLOCK_START->hdr.len)
+
+struct ipl_list_hdr {
+       u32 len;
+       u8  reserved1[3];
+       u8  version;
+       u32 blk0_len;
+       u8  pbt;
+       u8  flags;
+       u16 reserved2;
+} __attribute__((packed));
+
+struct ipl_block_fcp {
+       u8  reserved1[313-1];
+       u8  opt;
+       u8  reserved2[3];
+       u16 reserved3;
+       u16 devno;
+       u8  reserved4[4];
+       u64 wwpn;
+       u64 lun;
+       u32 bootprog;
+       u8  reserved5[12];
+       u64 br_lba;
+       u32 scp_data_len;
+       u8  reserved6[260];
+       u8  scp_data[];
+} __attribute__((packed));
+
+struct ipl_block_ccw {
+       u8  load_param[8];
+       u8  reserved1[84];
+       u8  reserved2[2];
+       u16 devno;
+       u8  vm_flags;
+       u8  reserved3[3];
+       u32 vm_parm_len;
+} __attribute__((packed));
+
+struct ipl_parameter_block {
+       struct ipl_list_hdr hdr;
+       union {
+               struct ipl_block_fcp fcp;
+               struct ipl_block_ccw ccw;
+       } ipl_info;
+} __attribute__((packed));
+
+/*
+ * IPL validity flags and parameters as detected in head.S
+ */
+extern u32 ipl_flags;
+extern u16 ipl_devno;
+
+extern u32 dump_prefix_page;
+extern void do_reipl(void);
+extern void ipl_save_parameters(void);
+
+enum {
+       IPL_DEVNO_VALID         = 1,
+       IPL_PARMBLOCK_VALID     = 2,
+       IPL_NSS_VALID           = 4,
+};
+
+/*
+ * DIAG 308 support
+ */
+enum diag308_subcode  {
+       DIAG308_REL_HSA = 2,
+       DIAG308_IPL     = 3,
+       DIAG308_DUMP    = 4,
+       DIAG308_SET     = 5,
+       DIAG308_STORE   = 6,
+};
+
+enum diag308_ipl_type {
+       DIAG308_IPL_TYPE_FCP    = 0,
+       DIAG308_IPL_TYPE_CCW    = 2,
+};
+
+enum diag308_opt {
+       DIAG308_IPL_OPT_IPL     = 0x10,
+       DIAG308_IPL_OPT_DUMP    = 0x20,
+};
+
+enum diag308_rc {
+       DIAG308_RC_OK   = 1,
+};
+
+extern int diag308(unsigned long subcode, void *addr);
+
+#endif /* _ASM_S390_IPL_H */
index 86745a1b29bb614fcef946aea28b7d938c8db38b..c11c530f74d02877738b3b6edb5d59102a9bf01c 100644 (file)
@@ -1,58 +1 @@
-#ifndef _ASM_LOCAL_H
-#define _ASM_LOCAL_H
-
-#include <linux/percpu.h>
-#include <asm/atomic.h>
-
-#ifndef __s390x__
-
-typedef atomic_t local_t;
-
-#define LOCAL_INIT(i)  ATOMIC_INIT(i)
-#define local_read(v)  atomic_read(v)
-#define local_set(v,i) atomic_set(v,i)
-
-#define local_inc(v)   atomic_inc(v)
-#define local_dec(v)   atomic_dec(v)
-#define local_add(i, v)        atomic_add(i, v)
-#define local_sub(i, v)        atomic_sub(i, v)
-
-#else
-
-typedef atomic64_t local_t;
-
-#define LOCAL_INIT(i)  ATOMIC64_INIT(i)
-#define local_read(v)  atomic64_read(v)
-#define local_set(v,i) atomic64_set(v,i)
-
-#define local_inc(v)   atomic64_inc(v)
-#define local_dec(v)   atomic64_dec(v)
-#define local_add(i, v)        atomic64_add(i, v)
-#define local_sub(i, v)        atomic64_sub(i, v)
-
-#endif
-
-#define __local_inc(v)         ((v)->counter++)
-#define __local_dec(v)         ((v)->counter--)
-#define __local_add(i,v)       ((v)->counter+=(i))
-#define __local_sub(i,v)       ((v)->counter-=(i))
-
-/*
- * Use these for per-cpu local_t variables: on some archs they are
- * much more efficient than these naive implementations.  Note they take
- * a variable, not an address.
- */
-#define cpu_local_read(v)      local_read(&__get_cpu_var(v))
-#define cpu_local_set(v, i)    local_set(&__get_cpu_var(v), (i))
-
-#define cpu_local_inc(v)       local_inc(&__get_cpu_var(v))
-#define cpu_local_dec(v)       local_dec(&__get_cpu_var(v))
-#define cpu_local_add(i, v)    local_add((i), &__get_cpu_var(v))
-#define cpu_local_sub(i, v)    local_sub((i), &__get_cpu_var(v))
-
-#define __cpu_local_inc(v)     __local_inc(&__get_cpu_var(v))
-#define __cpu_local_dec(v)     __local_dec(&__get_cpu_var(v))
-#define __cpu_local_add(i, v)  __local_add((i), &__get_cpu_var(v))
-#define __cpu_local_sub(i, v)  __local_sub((i), &__get_cpu_var(v))
-
-#endif /* _ASM_LOCAL_H */
+#include <asm-generic/local.h>
index 4c1b739403519839aa8a0b50d37191e66e07816f..33b80ced4bc1767546af9afe44f75abfe2d61dec 100644 (file)
@@ -36,6 +36,11 @@ typedef struct
         unsigned int unused  : 16;
 } __attribute__ ((packed)) cpuid_t;
 
+static inline void get_cpu_id(cpuid_t *ptr)
+{
+       asm volatile("stidp 0(%1)" : "=m" (*ptr) : "a" (ptr));
+}
+
 struct cpuinfo_S390
 {
         cpuid_t  cpu_id;
index 1c5a2c4ccdad29af3ccb5c0ed4436b79522cf128..fbd9116eb17bf2c73d80952af2108eecdf4db1ed 100644 (file)
@@ -3,6 +3,6 @@
 
 #include <asm-generic/sections.h>
 
-extern char _eshared[];
+extern char _eshared[], _ehead[];
 
 #endif
index 3388bb52597cb79593efa30053c882cf66be9bee..44c7aee2bd340151824a13281f0da91129847b8a 100644 (file)
@@ -16,7 +16,6 @@
 
 #define PARMAREA               0x10400
 #define MEMORY_CHUNKS          16      /* max 0x7fff */
-#define IPL_PARMBLOCK_ORIGIN   0x2000
 
 #ifndef __ASSEMBLY__
 
@@ -97,82 +96,9 @@ extern char vmpoff_cmd[];
 #define SET_CONSOLE_3215       do { console_mode = 2; } while (0)
 #define SET_CONSOLE_3270       do { console_mode = 3; } while (0)
 
-struct ipl_list_hdr {
-       u32 len;
-       u8  reserved1[3];
-       u8  version;
-       u32 blk0_len;
-       u8  pbt;
-       u8  flags;
-       u16 reserved2;
-} __attribute__((packed));
-
-struct ipl_block_fcp {
-       u8  reserved1[313-1];
-       u8  opt;
-       u8  reserved2[3];
-       u16 reserved3;
-       u16 devno;
-       u8  reserved4[4];
-       u64 wwpn;
-       u64 lun;
-       u32 bootprog;
-       u8  reserved5[12];
-       u64 br_lba;
-       u32 scp_data_len;
-       u8  reserved6[260];
-       u8  scp_data[];
-} __attribute__((packed));
-
-struct ipl_block_ccw {
-       u8  load_param[8];
-       u8  reserved1[84];
-       u8  reserved2[2];
-       u16 devno;
-       u8  vm_flags;
-       u8  reserved3[3];
-       u32 vm_parm_len;
-} __attribute__((packed));
-
-struct ipl_parameter_block {
-       struct ipl_list_hdr hdr;
-       union {
-               struct ipl_block_fcp fcp;
-               struct ipl_block_ccw ccw;
-       } ipl_info;
-} __attribute__((packed));
-
-#define IPL_PARM_BLK_FCP_LEN (sizeof(struct ipl_list_hdr) + \
-                             sizeof(struct ipl_block_fcp))
-
-#define IPL_PARM_BLK_CCW_LEN (sizeof(struct ipl_list_hdr) + \
-                             sizeof(struct ipl_block_ccw))
-
-#define IPL_MAX_SUPPORTED_VERSION (0)
-
-/*
- * IPL validity flags and parameters as detected in head.S
- */
-extern u32 ipl_flags;
-extern u16 ipl_devno;
-
-extern void do_reipl(void);
-extern void ipl_save_parameters(void);
-
-enum {
-       IPL_DEVNO_VALID = 1,
-       IPL_PARMBLOCK_VALID = 2,
-       IPL_NSS_VALID = 4,
-};
-
 #define NSS_NAME_SIZE  8
-
 extern char kernel_nss_name[];
 
-#define IPL_PARMBLOCK_START    ((struct ipl_parameter_block *) \
-                                IPL_PARMBLOCK_ORIGIN)
-#define IPL_PARMBLOCK_SIZE     (IPL_PARMBLOCK_START->hdr.len)
-
 #else /* __ASSEMBLY__ */
 
 #ifndef __s390x__
index e3a180cf506285dbffe07273c60bc35837f54ce9..9a3cb6ba9d156622d0738be6fd18ba224de9cf4c 100644 (file)
@@ -21,6 +21,7 @@
 
 #define L1_CACHE_ALIGN(x)      (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
 
+#ifndef __ASSEMBLY__
 struct cache_info {
        unsigned int ways;              /* Number of cache ways */
        unsigned int sets;              /* Number of cache sets */
@@ -47,6 +48,6 @@ struct cache_info {
 
        unsigned long flags;
 };
-
+#endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_CACHE_H */
index 22f12634975b7b350cca273601227cf38a6d0fc1..07f62ec9ff0c8b9309d223f0424b0926afb86f4b 100644 (file)
@@ -30,8 +30,5 @@ extern void __flush_invalidate_region(void *start, int size);
 
 #define HAVE_ARCH_UNMAPPED_AREA
 
-/* Page flag for lazy dcache write-back for the aliasing UP caches */
-#define PG_dcache_dirty        PG_arch_1
-
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_CACHEFLUSH_H */
index 6fabbba228de88ed9a64c7c279d955aa282a53bc..f70d8ef76a15f6b3d980bb4e01eb36516b2bae86 100644 (file)
@@ -36,6 +36,8 @@
  /* 32KB cache, 4kb PAGE sizes need to check bit 12 */
 #define CACHE_ALIAS 0x00001000
 
+#define PG_mapped      PG_arch_1
+
 void flush_cache_all(void);
 void flush_cache_mm(struct mm_struct *mm);
 #define flush_cache_dup_mm(mm) flush_cache_mm(mm)
index b3746a936a0966a868bd0a55a6be50e5ab7e3dac..5fd5c89ef86a8c859429d257f31bc488dfdc47cf 100644 (file)
@@ -39,4 +39,6 @@ void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
 /* Initialization of P3 area for copy_user_page */
 void p3_cache_init(void);
 
+#define PG_mapped      PG_arch_1
+
 #endif /* __ASM_CPU_SH4_CACHEFLUSH_H */
index 9214c015fe14a52e7c318f8ac79c78fcdd659286..184d7fcaaf107a068f3c5e8967f60a1fd5aaa934 100644 (file)
@@ -583,6 +583,11 @@ struct mm_struct;
 extern unsigned int kobjsize(const void *objp);
 #endif /* !CONFIG_MMU */
 
+#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+extern pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
+#endif
+
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 extern void paging_init(void);
 
index 279e70a77c75350a8ce7fc24e5fe707e766d69d6..31d55e3782d519571cfa62343d21e67ac13353ac 100644 (file)
@@ -111,6 +111,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SIGPENDING         2       /* signal pending */
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
 #define TIF_RESTORE_SIGMASK    4       /* restore signal mask in do_signal() */
+#define TIF_SINGLESTEP         5       /* singlestepping active */
 #define TIF_USEDFPU            16      /* FPU was used by this task this quantum (SMP) */
 #define TIF_POLLING_NRFLAG     17      /* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE             18
@@ -121,6 +122,7 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
 #define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
+#define _TIF_SINGLESTEP                (1<<TIF_SINGLESTEP)
 #define _TIF_USEDFPU           (1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 #define _TIF_FREEZE            (1<<TIF_FREEZE)
index 38644742f01192012d565fb9f78fba88539db479..a750c688408bb418d702153619380a9d5100d8d6 100644 (file)
@@ -165,6 +165,9 @@ static inline int pci_dma_mapping_error(dma_addr_t dma_addr)
         return (dma_addr == PCI_DMA_ERROR_CODE);
 }
 
+struct device_node;
+extern struct device_node *pci_device_to_OF_node(struct pci_dev *pdev);
+
 #endif /* __KERNEL__ */
 
 /* generic pci stuff */
index 86c13dccea3d37f36cc9416d19e7e6c60fc83b8e..274868d8598db47bce0284afecb0a1dcc4d1e763 100644 (file)
@@ -91,6 +91,7 @@ extern struct property *of_find_property(struct device_node *np,
 extern int of_device_is_compatible(struct device_node *device, const char *);
 extern void *of_get_property(struct device_node *node, const char *name,
                             int *lenp);
+#define get_property(node,name,lenp) of_get_property(node,name,lenp)
 extern int of_set_property(struct device_node *node, const char *name, void *val, int len);
 extern int of_getintprop_default(struct device_node *np,
                                 const char *name,
index 93e5a062df880ee991c332edca71a532eb2341cb..a9fd0618397231e917bd32c8665af80d1495c849 100644 (file)
 #include <asm/delay.h>
 #include <asm/oplib.h>
 
-extern spinlock_t  dma_spin_lock;
-
-#define claim_dma_lock() \
-({     unsigned long flags; \
-       spin_lock_irqsave(&dma_spin_lock, flags); \
-       flags; \
-})
-
-#define release_dma_lock(__flags) \
-       spin_unlock_irqrestore(&dma_spin_lock, __flags);
-
 /* These are irrelevant for Sparc DMA, but we leave it in so that
  * things can compile.
  */
@@ -205,10 +194,6 @@ do {       u32 tmp = sbus_readl((__regs) + DMA_CSR); \
 #define for_each_dvma(dma) \
         for((dma) = dma_chain; (dma); (dma) = (dma)->next)
 
-extern int get_dma_list(char *);
-extern int request_dma(unsigned int, __const__ char *);
-extern void free_dma(unsigned int);
-
 /* From PCI */
 
 #ifdef CONFIG_PCI
index dbe033e494dbeabf14524c1b78b71e6659d26cd7..331013a0053e667d55dddaef3870e7f6714421ab 100644 (file)
@@ -854,4 +854,15 @@ static unsigned long __init sun_floppy_init(void)
 
 #define EXTRA_FLOPPY_PARAMS
 
+static DEFINE_SPINLOCK(dma_spin_lock);
+
+#define claim_dma_lock() \
+({     unsigned long flags; \
+       spin_lock_irqsave(&dma_spin_lock, flags); \
+       flags; \
+})
+
+#define release_dma_lock(__flags) \
+       spin_unlock_irqrestore(&dma_spin_lock, __flags);
+
 #endif /* !(__ASM_SPARC64_FLOPPY_H) */
index d3895873e4c715775c90346e06935c4384c0694d..284dfd01a33d5421cc7c96a4035e3aae0b375e9a 100644 (file)
  */
 #define HAS_DMA
 
+static DEFINE_SPINLOCK(dma_spin_lock);
+
+#define claim_dma_lock() \
+({     unsigned long flags; \
+       spin_lock_irqsave(&dma_spin_lock, flags); \
+       flags; \
+})
+
+#define release_dma_lock(__flags) \
+       spin_unlock_irqrestore(&dma_spin_lock, __flags);
+
 static struct sparc_ebus_info {
        struct ebus_dma_info info;
        unsigned int addr;
        unsigned int count;
+       int lock;
 } sparc_ebus_dmas[PARPORT_PC_MAX_PORTS];
 
+static __inline__ int request_dma(unsigned int dmanr, const char *device_id)
+{
+       if (dmanr >= PARPORT_PC_MAX_PORTS)
+               return -EINVAL;
+       if (xchg(&sparc_ebus_dmas[dmanr].lock, 1) != 0)
+               return -EBUSY;
+       return 0;
+}
+
+static __inline__ void free_dma(unsigned int dmanr)
+{
+       if (dmanr >= PARPORT_PC_MAX_PORTS) {
+               printk(KERN_WARNING "Trying to free DMA%d\n", dmanr);
+               return;
+       }
+       if (xchg(&sparc_ebus_dmas[dmanr].lock, 0) == 0) {
+               printk(KERN_WARNING "Trying to free free DMA%d\n", dmanr);
+               return;
+       }       
+}
+
 static __inline__ void enable_dma(unsigned int dmanr)
 {
        ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 1);
index ca6560288ae826f9181f15fd5d4a6532dcc754e7..b14a725b430dc4d0e536d4652d5f66efd79ca668 100644 (file)
@@ -312,6 +312,9 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
        return PCI_IRQ_NONE;
 }
 
+struct device_node;
+extern struct device_node *pci_device_to_OF_node(struct pci_dev *pdev);
+
 #endif /* __KERNEL__ */
 
 #endif /* __SPARC64_PCI_H */
index 99671ed6625d15a8fa19f2a721ed9eb28f5255ef..0eca2d98627f15eba7e9f9e98ed55884be3ff97e 100644 (file)
@@ -99,6 +99,7 @@ extern struct property *of_find_property(struct device_node *np,
 extern int of_device_is_compatible(struct device_node *device, const char *);
 extern void *of_get_property(struct device_node *node, const char *name,
                             int *lenp);
+#define get_property(node,name,lenp) of_get_property(node,name,lenp)
 extern int of_set_property(struct device_node *node, const char *name, void *val, int len);
 extern int of_getintprop_default(struct device_node *np,
                                 const char *name,
index e57ff136ee510e884ea4474a7e2f21bde36b2390..1b1090a91a58f2954bfe5455edcc561e253cc83f 100644 (file)
@@ -270,7 +270,7 @@ static inline pte_t pte_wrprotect(pte_t pte)
 
 static inline pte_t pte_mkread(pte_t pte)
 { 
-       pte_set_bits(pte, _PAGE_RW);
+       pte_set_bits(pte, _PAGE_USER);
        return(pte_mknewprot(pte)); 
 }
 
index 552df5f10a6d462026eb10414766efd42a76a347..2e4b7a5ed1c401e522a48164c7e9dd410b1608af 100644 (file)
 #define IA32_SYSCALL_VECTOR    0x80
 
 
+/* Reserve the lowest usable priority level 0x20 - 0x2f for triggering
+ * cleanup after irq migration.
+ */
+#define IRQ_MOVE_CLEANUP_VECTOR        FIRST_EXTERNAL_VECTOR
 /*
  * Vectors 0x20-0x2f are used for ISA interrupts.
  */
+#define IRQ0_VECTOR            FIRST_EXTERNAL_VECTOR + 0x10
+#define IRQ1_VECTOR            IRQ0_VECTOR + 1
+#define IRQ2_VECTOR            IRQ0_VECTOR + 2
+#define IRQ3_VECTOR            IRQ0_VECTOR + 3
+#define IRQ4_VECTOR            IRQ0_VECTOR + 4
+#define IRQ5_VECTOR            IRQ0_VECTOR + 5 
+#define IRQ6_VECTOR            IRQ0_VECTOR + 6
+#define IRQ7_VECTOR            IRQ0_VECTOR + 7
+#define IRQ8_VECTOR            IRQ0_VECTOR + 8
+#define IRQ9_VECTOR            IRQ0_VECTOR + 9
+#define IRQ10_VECTOR           IRQ0_VECTOR + 10
+#define IRQ11_VECTOR           IRQ0_VECTOR + 11
+#define IRQ12_VECTOR           IRQ0_VECTOR + 12
+#define IRQ13_VECTOR           IRQ0_VECTOR + 13
+#define IRQ14_VECTOR           IRQ0_VECTOR + 14
+#define IRQ15_VECTOR           IRQ0_VECTOR + 15
 
 /*
  * Special IRQ vectors used by the SMP architecture, 0xf0-0xff
 
 /*
  * First APIC vector available to drivers: (vectors 0x30-0xee)
- * we start at 0x31 to spread out vectors evenly between priority
+ * we start at 0x41 to spread out vectors evenly between priority
  * levels. (0x80 is the syscall vector)
  */
-#define FIRST_DEVICE_VECTOR    0x31
+#define FIRST_DEVICE_VECTOR    (IRQ15_VECTOR + 2)
 #define FIRST_SYSTEM_VECTOR    0xef   /* duplicated in irq.h */
 
 
index f4fb238c89f14212f84b51a9258fc5960a69a46d..969d225a93502bff46ec0ad92f9ce64143f1ebf1 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <asm/types.h>
 #include <asm/mpspec.h>
+#include <asm/apicdef.h>
 
 /*
  * Intel IO-APIC support for SMP and UP systems.
index 3227bc93d69b86a826cdca9b669d12c329444b53..902f9a58617e66ddd912ecac3555a526eb9123b4 100644 (file)
@@ -160,6 +160,19 @@ static inline unsigned int cpuid_edx(unsigned int op)
 #define MSR_IA32_UCODE_WRITE           0x79
 #define MSR_IA32_UCODE_REV             0x8b
 
+#ifdef CONFIG_SMP
+void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
+void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
+#else  /*  CONFIG_SMP  */
+static inline void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
+{
+       rdmsr(msr_no, *l, *h);
+}
+static inline void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
+{
+       wrmsr(msr_no, l, h);
+}
+#endif  /*  CONFIG_SMP  */
 
 #endif
 
index 72375e7d32a895846200ff921ebfd5e8776296bf..ceb3d8dac33d43e03d9d6f489b1592754edc8616 100644 (file)
@@ -64,7 +64,7 @@ extern int setup_nmi_watchdog(char *);
 
 extern atomic_t nmi_active;
 extern unsigned int nmi_watchdog;
-#define NMI_DEFAULT    -1
+#define NMI_DEFAULT    0
 #define NMI_NONE       0
 #define NMI_IO_APIC    1
 #define NMI_LOCAL_APIC 2
index ab913ffcad569201bb921bc6e7c4bfc1db5f450b..f9c589539a82b7c11fae1425c5782b5189db9cc1 100644 (file)
@@ -44,7 +44,6 @@ extern void swiotlb_init(void);
 extern int swiotlb_force;
 
 #ifdef CONFIG_SWIOTLB
-#define SWIOTLB_ARCH_NEED_ALLOC
 extern int swiotlb;
 #else
 #define swiotlb 0
index 2facec5914d2cb4793b96bc4cdfdbc908341b861..4fd6fb23953e997134c701252cbe4af8bf19c3e9 100644 (file)
@@ -43,7 +43,6 @@ extern int __node_distance(int, int);
        .newidle_idx            = 0,                    \
        .wake_idx               = 1,                    \
        .forkexec_idx           = 1,                    \
-       .per_cpu_gain           = 100,                  \
        .flags                  = SD_LOAD_BALANCE       \
                                | SD_BALANCE_FORK       \
                                | SD_BALANCE_EXEC       \
index 9a0a368852c72955826ffe3772917b10a2c3baf3..d66ba6ef25f68cde13fe89194a0e9c3c5cfb5196 100644 (file)
@@ -1,66 +1 @@
-/*
- * linux/include/asm-x86_64/tsc.h
- *
- * x86_64 TSC related functions
- */
-#ifndef _ASM_x86_64_TSC_H
-#define _ASM_x86_64_TSC_H
-
-#include <asm/processor.h>
-
-/*
- * Standard way to access the cycle counter.
- */
-typedef unsigned long long cycles_t;
-
-extern unsigned int cpu_khz;
-extern unsigned int tsc_khz;
-
-static inline cycles_t get_cycles(void)
-{
-       unsigned long long ret = 0;
-
-#ifndef CONFIG_X86_TSC
-       if (!cpu_has_tsc)
-               return 0;
-#endif
-
-#if defined(CONFIG_X86_GENERIC) || defined(CONFIG_X86_TSC)
-       rdtscll(ret);
-#endif
-       return ret;
-}
-
-/* Like get_cycles, but make sure the CPU is synchronized. */
-static __always_inline cycles_t get_cycles_sync(void)
-{
-       unsigned long long ret;
-#ifdef X86_FEATURE_SYNC_RDTSC
-       unsigned eax;
-
-       /*
-        * Don't do an additional sync on CPUs where we know
-        * RDTSC is already synchronous:
-        */
-       alternative_io("cpuid", ASM_NOP2, X86_FEATURE_SYNC_RDTSC,
-                         "=a" (eax), "0" (1) : "ebx","ecx","edx","memory");
-#else
-       sync_core();
-#endif
-       rdtscll(ret);
-
-       return ret;
-}
-
-extern void tsc_init(void);
-extern void mark_tsc_unstable(void);
-extern int unsynchronized_tsc(void);
-
-/*
- * Boot-time check whether the TSCs are synchronized across
- * all CPUs/cores:
- */
-extern void check_tsc_sync_source(int cpu);
-extern void check_tsc_sync_target(void);
-
-#endif
+#include <asm-i386/tsc.h>
index 272736e37990b7d96b71d7f4b0972ee2d7033d77..c331da2da5f7af3c90b783efac81e2184a27b7c7 100644 (file)
@@ -282,7 +282,6 @@ struct ata_taskfile {
 };
 
 #define ata_id_is_ata(id)      (((id)[0] & (1 << 15)) == 0)
-#define ata_id_is_sata(id)     ((id)[93] == 0)
 #define ata_id_rahead_enabled(id) ((id)[85] & (1 << 6))
 #define ata_id_wcache_enabled(id) ((id)[85] & (1 << 5))
 #define ata_id_hpa_enabled(id) ((id)[85] & (1 << 10))
@@ -324,6 +323,11 @@ static inline unsigned int ata_id_major_version(const u16 *id)
        return mver;
 }
 
+static inline int ata_id_is_sata(const u16 *id)
+{
+       return ata_id_major_version(id) >= 5 && id[93] == 0;
+}
+
 static inline int ata_id_current_chs_valid(const u16 *id)
 {
        /* For ATA-1 devices, if the INITIALIZE DEVICE PARAMETERS command
@@ -350,7 +354,7 @@ static inline int ata_id_is_cfa(const u16 *id)
 
 static inline int ata_drive_40wire(const u16 *dev_id)
 {
-       if (ata_id_major_version(dev_id) >= 5 && ata_id_is_sata(dev_id))
+       if (ata_id_is_sata(dev_id))
                return 0;       /* SATA */
        if ((dev_id[93] & 0xE000) == 0x6000)
                return 0;       /* 80 wire */
index 229fa012c893472f16a312afd5f008e075e4cf8d..773e30df11ee74eba717cd671fad6028d2dc3cbf 100644 (file)
@@ -24,6 +24,7 @@
 #ifndef _LINUX_AUDIT_H_
 #define _LINUX_AUDIT_H_
 
+#include <linux/types.h>
 #include <linux/elf-em.h>
 
 /* The netlink messages for the audit system is divided into blocks:
index 0a6bc52ffe881948cbaab4f2a25a0a7c2d86a82c..31a29541b504234174c0a9678bba9b60bc60e7ac 100644 (file)
@@ -59,6 +59,13 @@ struct autofs_packet_expire_multi {
        char name[NAME_MAX+1];
 };
 
+union autofs_packet_union {
+       struct autofs_packet_hdr hdr;
+       struct autofs_packet_missing missing;
+       struct autofs_packet_expire expire;
+       struct autofs_packet_expire_multi expire_multi;
+};
+
 /* autofs v5 common packet struct */
 struct autofs_v5_packet {
        struct autofs_packet_hdr hdr;
@@ -78,12 +85,13 @@ typedef struct autofs_v5_packet autofs_packet_expire_indirect_t;
 typedef struct autofs_v5_packet autofs_packet_missing_direct_t;
 typedef struct autofs_v5_packet autofs_packet_expire_direct_t;
 
-union autofs_packet_union {
+union autofs_v5_packet_union {
        struct autofs_packet_hdr hdr;
-       struct autofs_packet_missing missing;
-       struct autofs_packet_expire expire;
-       struct autofs_packet_expire_multi expire_multi;
        struct autofs_v5_packet v5_packet;
+       autofs_packet_missing_indirect_t missing_indirect;
+       autofs_packet_expire_indirect_t expire_indirect;
+       autofs_packet_missing_direct_t missing_direct;
+       autofs_packet_expire_direct_t expire_direct;
 };
 
 #define AUTOFS_IOC_EXPIRE_MULTI                _IOW(0x93,0x66,int)
index a5cf1beacb443a18edbfcd1767e2866a24dc6299..1023ba0d6e5541aadfbca392ef42cc68a94a9acd 100644 (file)
@@ -9,17 +9,28 @@
 #define _LINUX_BACKLIGHT_H
 
 #include <linux/device.h>
+#include <linux/mutex.h>
 #include <linux/notifier.h>
 
+/* Notes on locking:
+ *
+ * backlight_device->ops_lock is an internal backlight lock protecting the
+ * ops pointer and no code outside the core should need to touch it.
+ *
+ * Access to update_status() is serialised by the update_lock mutex since
+ * most drivers seem to need this and historically get it wrong.
+ *
+ * Most drivers don't need locking on their get_brightness() method.
+ * If yours does, you need to implement it in the driver. You can use the
+ * update_lock mutex if appropriate.
+ *
+ * Any other use of the locks below is probably wrong.
+ */
+
 struct backlight_device;
 struct fb_info;
 
-/* This structure defines all the properties of a backlight
-   (usually attached to a LCD). */
-struct backlight_properties {
-       /* Owner module */
-       struct module *owner;
-
+struct backlight_ops {
        /* Notify the backlight driver some property has changed */
        int (*update_status)(struct backlight_device *);
        /* Return the current backlight brightness (accounting for power,
@@ -28,7 +39,10 @@ struct backlight_properties {
        /* Check if given framebuffer device is the one bound to this backlight;
           return 0 if not, !=0 if it is. If NULL, backlight always matches the fb. */
        int (*check_fb)(struct fb_info *);
+};
 
+/* This structure defines all the properties of a backlight */
+struct backlight_properties {
        /* Current User requested brightness (0 - max_brightness) */
        int brightness;
        /* Maximal value for brightness (read-only) */
@@ -41,20 +55,34 @@ struct backlight_properties {
 };
 
 struct backlight_device {
-       /* This protects the 'props' field. If 'props' is NULL, the driver that
+       /* Backlight properties */
+       struct backlight_properties props;
+
+       /* Serialise access to update_status method */
+       struct mutex update_lock;
+
+       /* This protects the 'ops' field. If 'ops' is NULL, the driver that
           registered this device has been unloaded, and if class_get_devdata()
           points to something in the body of that driver, it is also invalid. */
-       struct semaphore sem;
-       /* If this is NULL, the backing module is unloaded */
-       struct backlight_properties *props;
+       struct mutex ops_lock;
+       struct backlight_ops *ops;
+
        /* The framebuffer notifier block */
        struct notifier_block fb_notif;
        /* The class device structure */
        struct class_device class_dev;
 };
 
+static inline void backlight_update_status(struct backlight_device *bd)
+{
+       mutex_lock(&bd->update_lock);
+       if (bd->ops && bd->ops->update_status)
+               bd->ops->update_status(bd);
+       mutex_unlock(&bd->update_lock);
+}
+
 extern struct backlight_device *backlight_device_register(const char *name,
-       struct device *dev,void *devdata,struct backlight_properties *bp);
+       struct device *dev, void *devdata, struct backlight_ops *ops);
 extern void backlight_device_unregister(struct backlight_device *bd);
 
 #define to_backlight_device(obj) container_of(obj, struct backlight_device, class_dev)
index bbbe7b4da0bbc65c9a12f0043f280a2e6c5e1a65..f50f04bdbc166ab1df21c60ef67760aaae942236 100644 (file)
@@ -939,7 +939,7 @@ struct cdrom_device_info {
        int speed;                      /* maximum speed for reading data */
        int capacity;                   /* number of discs in jukebox */
 /* device-related storage */
-       int options             : 30;   /* options flags */
+       unsigned int options    : 30;   /* options flags */
        unsigned mc_flags       : 2;    /* media change buffer flags */
        int use_count;                  /* number of times device opened */
        char name[20];                  /* name of the device type */
index 0bc45e69da5a9f9508ce2bd0ab25a05cb9f7ef82..1605dd8aa6463a3edef46cc6bb1ff7216bdb825c 100644 (file)
@@ -73,5 +73,10 @@ extern void cfag12864b_disable(void);
  */
 extern unsigned char cfag12864b_isenabled(void);
 
+/*
+ * Is the module inited?
+ */
+extern unsigned char cfag12864b_isinited(void);
+
 #endif /* _CFAG12864B_H_ */
 
index 80b17f440ec191ce352ad7bdb108e8a2fb806bd8..ccd863dd77fae4a654981181ba189f5c4604c155 100644 (file)
@@ -234,5 +234,24 @@ asmlinkage long compat_sys_migrate_pages(compat_pid_t pid,
                compat_ulong_t maxnode, const compat_ulong_t __user *old_nodes,
                const compat_ulong_t __user *new_nodes);
 
+/*
+ * epoll (fs/eventpoll.c) compat bits follow ...
+ */
+#ifndef CONFIG_HAS_COMPAT_EPOLL_EVENT
+struct epoll_event;
+#define compat_epoll_event     epoll_event
+#else
+asmlinkage long compat_sys_epoll_ctl(int epfd, int op, int fd,
+                       struct compat_epoll_event __user *event);
+asmlinkage long compat_sys_epoll_wait(int epfd,
+                       struct compat_epoll_event __user *events,
+                       int maxevents, int timeout);
+#endif
+asmlinkage long compat_sys_epoll_pwait(int epfd,
+                       struct compat_epoll_event __user *events,
+                       int maxevents, int timeout,
+                       const compat_sigset_t __user *sigmask,
+                       compat_size_t sigsetsize);
+
 #endif /* CONFIG_COMPAT */
 #endif /* _LINUX_COMPAT_H */
index d0e8c8b0e34dee03a78823c81d2c7536ce88e2cc..23f55140ccd570fd45c321b8275ce04edc451288 100644 (file)
@@ -398,11 +398,11 @@ extern cpumask_t cpu_present_map;
 #endif
 
 #ifdef CONFIG_SMP
-int highest_possible_processor_id(void);
+extern int nr_cpu_ids;
 #define any_online_cpu(mask) __any_online_cpu(&(mask))
 int __any_online_cpu(const cpumask_t *mask);
 #else
-#define highest_possible_processor_id()        0
+#define nr_cpu_ids                     1
 #define any_online_cpu(mask)           0
 #endif
 
index d1a3a27c3988fea20a71e0bcd2a8c02283ea009b..39a3199a826db2726e60475195f64f03465c5acb 100644 (file)
@@ -294,8 +294,6 @@ extern void class_device_initialize(struct class_device *);
 extern int __must_check class_device_add(struct class_device *);
 extern void class_device_del(struct class_device *);
 
-extern int class_device_rename(struct class_device *, char *);
-
 extern struct class_device * class_device_get(struct class_device *);
 extern void class_device_put(struct class_device *);
 
diff --git a/include/linux/ds1742rtc.h b/include/linux/ds1742rtc.h
deleted file mode 100644 (file)
index a83cdd1..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * ds1742rtc.h - register definitions for the Real-Time-Clock / CMOS RAM
- *
- * Copyright (C) 1999-2001 Toshiba Corporation
- * Copyright (C) 2003 Ralf Baechle (ralf@linux-mips.org)
- *
- * Permission is hereby granted to copy, modify and redistribute this code
- * in terms of the GNU Library General Public License, Version 2 or later,
- * at your option.
- */
-#ifndef __LINUX_DS1742RTC_H
-#define __LINUX_DS1742RTC_H
-
-#include <asm/ds1742.h>
-
-#define RTC_BRAM_SIZE          0x800
-#define RTC_OFFSET             0x7f8
-
-/*
- * Register summary
- */
-#define RTC_CONTROL            (RTC_OFFSET + 0)
-#define RTC_CENTURY            (RTC_OFFSET + 0)
-#define RTC_SECONDS            (RTC_OFFSET + 1)
-#define RTC_MINUTES            (RTC_OFFSET + 2)
-#define RTC_HOURS              (RTC_OFFSET + 3)
-#define RTC_DAY                        (RTC_OFFSET + 4)
-#define RTC_DATE               (RTC_OFFSET + 5)
-#define RTC_MONTH              (RTC_OFFSET + 6)
-#define RTC_YEAR               (RTC_OFFSET + 7)
-
-#define RTC_CENTURY_MASK       0x3f
-#define RTC_SECONDS_MASK       0x7f
-#define RTC_DAY_MASK           0x07
-
-/*
- * Bits in the Control/Century register
- */
-#define RTC_WRITE              0x80
-#define RTC_READ               0x40
-
-/*
- * Bits in the Seconds register
- */
-#define RTC_STOP               0x80
-
-/*
- * Bits in the Day register
- */
-#define RTC_BATT_FLAG          0x80
-#define RTC_FREQ_TEST          0x40
-
-#endif /* __LINUX_DS1742RTC_H */
index a78e25683f820bc056e80db62814180ee063e413..be913ec871692e58fc9dfe798aa4ad0154629bd5 100644 (file)
@@ -516,13 +516,15 @@ struct fb_cursor_user {
 #define FB_EVENT_GET_CONSOLE_MAP        0x07
 /*      CONSOLE-SPECIFIC: set console to framebuffer mapping */
 #define FB_EVENT_SET_CONSOLE_MAP        0x08
-/*      A display blank is requested       */
+/*      A hardware display blank change occured */
 #define FB_EVENT_BLANK                  0x09
 /*      Private modelist is to be replaced */
 #define FB_EVENT_NEW_MODELIST           0x0A
 /*     The resolution of the passed in fb_info about to change and
         all vc's should be changed         */
 #define FB_EVENT_MODE_CHANGE_ALL       0x0B
+/*     A software display blank change occured */
+#define FB_EVENT_CONBLANK               0x0C
 
 struct fb_event {
        struct fb_info *info;
@@ -767,16 +769,13 @@ struct fb_info {
        struct fb_videomode *mode;      /* current mode */
 
 #ifdef CONFIG_FB_BACKLIGHT
-       /* Lock ordering:
-        * bl_mutex (protects bl_dev and bl_curve)
-        *   bl_dev->sem (backlight class)
-        */
-       struct mutex bl_mutex;
-
        /* assigned backlight device */
+       /* set before framebuffer registration, 
+          remove after unregister */
        struct backlight_device *bl_dev;
 
        /* Backlight level curve */
+       struct mutex bl_curve_mutex;    
        u8 bl_curve[FB_BACKLIGHT_LEVELS];
 #endif
 
index d26b08f461f2eeb2986f0ad1a7c30f62c61fdb5e..8c97d4d3fdb05cdaf66c2b43c9a46e38b342f1e2 100644 (file)
@@ -6,7 +6,7 @@
  *
  *  Copyright (c) 1999 Andreas Gal
  *  Copyright (c) 2000-2001 Vojtech Pavlik
- *  Copyright (c) 2006 Jiri Kosina
+ *  Copyright (c) 2006-2007 Jiri Kosina
  */
 
 /*
@@ -267,6 +267,8 @@ struct hid_item {
 #define HID_QUIRK_SKIP_OUTPUT_REPORTS          0x00020000
 #define HID_QUIRK_IGNORE_MOUSE                 0x00040000
 #define HID_QUIRK_SONY_PS3_CONTROLLER          0x00080000
+#define HID_QUIRK_LOGITECH_S510_DESCRIPTOR     0x00100000
+#define HID_QUIRK_DUPLICATE_USAGES             0x00200000
 
 /*
  * This is the global environment of the parser. This information is
@@ -292,7 +294,7 @@ struct hid_global {
  */
 
 #define HID_MAX_DESCRIPTOR_SIZE                4096
-#define HID_MAX_USAGES                 1024
+#define HID_MAX_USAGES                 8192
 #define HID_DEFAULT_NUM_COLLECTIONS    16
 
 struct hid_local {
index 37f9279192a998f50641d81056a57692a8eaf538..5bdbc744e773096dbcbdd49d12a81afe90beaa90 100644 (file)
@@ -47,7 +47,7 @@ enum hrtimer_restart {
  *     HRTIMER_CB_IRQSAFE:             Callback may run in hardirq context
  *     HRTIMER_CB_IRQSAFE_NO_RESTART:  Callback may run in hardirq context and
  *                                     does not restart the timer
- *     HRTIMER_CB_IRQSAFE_NO_SOFTIRQ:  Callback must run in softirq context
+ *     HRTIMER_CB_IRQSAFE_NO_SOFTIRQ:  Callback must run in hardirq context
  *                                     Special mode for tick emultation
  */
 enum hrtimer_cb_mode {
@@ -139,7 +139,8 @@ struct hrtimer_sleeper {
 };
 
 /**
- * struct hrtimer_base - the timer base for a specific clock
+ * struct hrtimer_clock_base - the timer base for a specific clock
+ * @cpu_base:          per cpu clock base
  * @index:             clock type index for per_cpu support when moving a
  *                     timer to a base on another cpu.
  * @active:            red black tree root node for the active timers
index a60995afe3348a7ce3ebd0808252679a17164c98..3f3e7a648da3947c76839e02670c75c2cfd27710 100644 (file)
@@ -4,6 +4,7 @@
 #ifdef CONFIG_HUGETLB_PAGE
 
 #include <linux/mempolicy.h>
+#include <linux/shm.h>
 #include <asm/tlbflush.h>
 
 struct ctl_table;
@@ -168,7 +169,12 @@ void hugetlb_put_quota(struct address_space *mapping);
 
 static inline int is_file_hugepages(struct file *file)
 {
-       return file->f_op == &hugetlbfs_file_operations;
+       if (file->f_op == &hugetlbfs_file_operations)
+               return 1;
+       if (is_file_shm_hugepages(file))
+               return 1;
+
+       return 0;
 }
 
 static inline void set_file_hugepages(struct file *file)
index 79c028251c70c29458110f9b4319164d505b7670..34f2676b3c625a20ac5a93e6251e5be006b39dbf 100644 (file)
@@ -1359,7 +1359,8 @@ u8 ide_dump_status(ide_drive_t *, const char *, u8);
 typedef struct ide_pio_timings_s {
        int     setup_time;     /* Address setup (ns) minimum */
        int     active_time;    /* Active pulse (ns) minimum */
-       int     cycle_time;     /* Cycle time (ns) minimum = (setup + active + recovery) */
+       int     cycle_time;     /* Cycle time (ns) minimum = */
+                               /* active + recovery (+ setup for some chips) */
 } ide_pio_timings_t;
 
 typedef struct ide_pio_data_s {
index 4fab3d0a4bcef5e7d6e0c9047b30b09afdead916..e33ee763c052ebfeeaf24d9d1cd2876ff0228008 100644 (file)
@@ -114,6 +114,7 @@ struct pppoe_hdr {
 #ifdef __KERNEL__
 struct pppoe_opt {
        struct net_device      *dev;      /* device associated with socket*/
+       int                     ifindex;  /* ifindex of device associated with socket */
        struct pppoe_addr       pa;       /* what this socket is bound to*/
        struct sockaddr_pppox   relay;    /* what socket data will be
                                             relayed to (PPPoE relaying) */
@@ -132,6 +133,7 @@ struct pppox_sock {
        unsigned short          num;
 };
 #define pppoe_dev      proto.pppoe.dev
+#define pppoe_ifindex  proto.pppoe.ifindex
 #define pppoe_pa       proto.pppoe.pa
 #define pppoe_relay    proto.pppoe.relay
 
index 35cb385735837a2e5b0eca166770bcc647c41fd9..d103580c72d26f769e6e9e9af6a7e9e2c1eeb0dd 100644 (file)
@@ -70,15 +70,34 @@ extern void vlan_ioctl_set(int (*hook)(void __user *));
  * depends on completely exhausting the VLAN identifier space.  Thus
  * it gives constant time look-up, but in many cases it wastes memory.
  */
-#define VLAN_GROUP_ARRAY_LEN 4096
+#define VLAN_GROUP_ARRAY_LEN          4096
+#define VLAN_GROUP_ARRAY_SPLIT_PARTS  8
+#define VLAN_GROUP_ARRAY_PART_LEN     (VLAN_GROUP_ARRAY_LEN/VLAN_GROUP_ARRAY_SPLIT_PARTS)
 
 struct vlan_group {
        int real_dev_ifindex; /* The ifindex of the ethernet(like) device the vlan is attached to. */
        struct hlist_node       hlist;  /* linked list */
-       struct net_device *vlan_devices[VLAN_GROUP_ARRAY_LEN];
+       struct net_device **vlan_devices_arrays[VLAN_GROUP_ARRAY_SPLIT_PARTS];
        struct rcu_head         rcu;
 };
 
+static inline struct net_device *vlan_group_get_device(struct vlan_group *vg, int vlan_id)
+{
+       struct net_device **array;
+       array = vg->vlan_devices_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN];
+       return array[vlan_id % VLAN_GROUP_ARRAY_PART_LEN];
+}
+
+static inline void vlan_group_set_device(struct vlan_group *vg, int vlan_id,
+                                        struct net_device *dev)
+{
+       struct net_device **array;
+       if (!vg)
+               return;
+       array = vg->vlan_devices_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN];
+       array[vlan_id % VLAN_GROUP_ARRAY_PART_LEN] = dev;
+}
+
 struct vlan_priority_tci_mapping {
        unsigned long priority;
        unsigned short vlan_qos; /* This should be shifted when first set, so we only do it
@@ -160,7 +179,7 @@ static inline int __vlan_hwaccel_rx(struct sk_buff *skb,
                return NET_RX_DROP;
        }
 
-       skb->dev = grp->vlan_devices[vlan_tag & VLAN_VID_MASK];
+       skb->dev = vlan_group_get_device(grp, vlan_tag & VLAN_VID_MASK);
        if (skb->dev == NULL) {
                dev_kfree_skb_any(skb);
 
index 9dbb525c5178d59bef3725ddba461b77342a2c9e..a113fe68d8a1c24c9dfb680e1a1ad0b9fc477ba1 100644 (file)
@@ -218,5 +218,7 @@ extern void ip_mc_up(struct in_device *);
 extern void ip_mc_down(struct in_device *);
 extern void ip_mc_dec_group(struct in_device *in_dev, __be32 addr);
 extern void ip_mc_inc_group(struct in_device *in_dev, __be32 addr);
+extern void ip_mc_rejoin_group(struct ip_mc_list *im);
+
 #endif
 #endif
index aa5b3e6178a03657681915bfad659fec34111c40..a6899402b5220233c53fe926655d788b2dce7f1c 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/spinlock.h>
 #include <linux/cpumask.h>
 #include <linux/irqreturn.h>
+#include <linux/errno.h>
 
 #include <asm/irq.h>
 #include <asm/ptrace.h>
@@ -199,17 +200,6 @@ extern int setup_irq(unsigned int irq, struct irqaction *new);
 # define handle_dynamic_tick(a)                do { } while (0)
 #endif
 
-#ifdef CONFIG_SMP
-static inline void set_native_irq_info(int irq, cpumask_t mask)
-{
-       irq_desc[irq].affinity = mask;
-}
-#else
-static inline void set_native_irq_info(int irq, cpumask_t mask)
-{
-}
-#endif
-
 #ifdef CONFIG_SMP
 
 #if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE)
index 2e79f816703be86b918b4797e74bde58ea9da63b..63bd9cf821a763953cd94243d385a74e8672ee5c 100644 (file)
@@ -174,9 +174,26 @@ char *capi_info2str(__u16 reason);
 /*
  * Debugging / Tracing functions
  */
+
 char *capi_cmd2str(__u8 cmd, __u8 subcmd);
-char *capi_cmsg2str(_cmsg * cmsg);
-char *capi_message2str(__u8 * msg);
+
+typedef struct {
+       u_char  *buf;
+       u_char  *p;
+       size_t  size;
+       size_t  pos;
+} _cdebbuf;
+
+#define        CDEBUG_SIZE     1024
+#define        CDEBUG_GSIZE    4096
+
+_cdebbuf *cdebbuf_alloc(void);
+void cdebbuf_free(_cdebbuf *cdb);
+int cdebug_init(void);
+void cdebug_exit(void);
+
+_cdebbuf *capi_cmsg2str(_cmsg *cmsg);
+_cdebbuf *capi_message2str(__u8 *msg);
 
 /*-----------------------------------------------------------------------*/
 
index bceea527dd37ffe02af7821d4cec50653dc7eac5..4c2c3737e415e26115ea02658fd87bb9cfed2e08 100644 (file)
@@ -87,6 +87,7 @@ static inline unsigned sysv_minor(u32 dev)
        return dev & 0x3ffff;
 }
 
+bool is_lanana_major(unsigned int major);
 
 #else /* __KERNEL__ */
 
index cc8e674ae27ad3b7a4414773d9bf010e7c91cde8..10f505c8431dc320f46d77a88095df20cb475cb8 100644 (file)
 #ifdef CONFIG_KMOD
 /* modprobe exit status on success, -ve on error.  Return value
  * usually useless though. */
-extern void kmod_sysfs_init(void);
 extern int request_module(const char * name, ...) __attribute__ ((format (printf, 1, 2)));
 #else
-static inline void kmod_sysfs_init(void) {};
 static inline int request_module(const char * name, ...) { return -ENOSYS; }
 #endif
 
index 8047d4b17bf1416a3d0e8765795c1c89bb525678..a2c54acceb4e9da1b21ab6e5dea9dc8c7e5fd362 100644 (file)
@@ -43,4 +43,7 @@ extern void ks0108_address(unsigned char address);
 /* Set the controller's current page (0..7) */
 extern void ks0108_page(unsigned char page);
 
+/* Is the module inited? */
+extern unsigned char ks0108_isinited(void);
+
 #endif /* _KS0108_H_ */
index f3604593fb76ded7fe359da2eea2e2ee640bd5b5..275354ffa1cbf6604bbcf0ce924660195764a090 100644 (file)
@@ -11,7 +11,7 @@
 #include <asm/types.h>
 #include <linux/ioctl.h>
 
-#define KVM_API_VERSION 3
+#define KVM_API_VERSION 4
 
 /*
  * Architectural interrupt line count, and the size of the bitmap needed
@@ -52,11 +52,10 @@ enum kvm_exit_reason {
 /* for KVM_RUN */
 struct kvm_run {
        /* in */
-       __u32 vcpu;
        __u32 emulated;  /* skip current instruction */
        __u32 mmio_completed; /* mmio request completed */
        __u8 request_interrupt_window;
-       __u8 padding1[3];
+       __u8 padding1[7];
 
        /* out */
        __u32 exit_type;
@@ -111,10 +110,6 @@ struct kvm_run {
 
 /* for KVM_GET_REGS and KVM_SET_REGS */
 struct kvm_regs {
-       /* in */
-       __u32 vcpu;
-       __u32 padding;
-
        /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
        __u64 rax, rbx, rcx, rdx;
        __u64 rsi, rdi, rsp, rbp;
@@ -141,10 +136,6 @@ struct kvm_dtable {
 
 /* for KVM_GET_SREGS and KVM_SET_SREGS */
 struct kvm_sregs {
-       /* in */
-       __u32 vcpu;
-       __u32 padding;
-
        /* out (KVM_GET_SREGS) / in (KVM_SET_SREGS) */
        struct kvm_segment cs, ds, es, fs, gs, ss;
        struct kvm_segment tr, ldt;
@@ -163,8 +154,8 @@ struct kvm_msr_entry {
 
 /* for KVM_GET_MSRS and KVM_SET_MSRS */
 struct kvm_msrs {
-       __u32 vcpu;
        __u32 nmsrs; /* number of msrs in entries */
+       __u32 pad;
 
        struct kvm_msr_entry entries[0];
 };
@@ -179,8 +170,6 @@ struct kvm_msr_list {
 struct kvm_translation {
        /* in */
        __u64 linear_address;
-       __u32 vcpu;
-       __u32 padding;
 
        /* out */
        __u64 physical_address;
@@ -193,7 +182,6 @@ struct kvm_translation {
 /* for KVM_INTERRUPT */
 struct kvm_interrupt {
        /* in */
-       __u32 vcpu;
        __u32 irq;
 };
 
@@ -206,8 +194,8 @@ struct kvm_breakpoint {
 /* for KVM_DEBUG_GUEST */
 struct kvm_debug_guest {
        /* int */
-       __u32 vcpu;
        __u32 enabled;
+       __u32 pad;
        struct kvm_breakpoint breakpoints[4];
        __u32 singlestep;
 };
@@ -224,20 +212,36 @@ struct kvm_dirty_log {
 
 #define KVMIO 0xAE
 
+/*
+ * ioctls for /dev/kvm fds:
+ */
 #define KVM_GET_API_VERSION       _IO(KVMIO, 1)
+#define KVM_CREATE_VM             _IO(KVMIO, 2) /* returns a VM fd */
+#define KVM_GET_MSR_INDEX_LIST    _IOWR(KVMIO, 15, struct kvm_msr_list)
+
+/*
+ * ioctls for VM fds
+ */
+#define KVM_SET_MEMORY_REGION     _IOW(KVMIO, 10, struct kvm_memory_region)
+/*
+ * KVM_CREATE_VCPU receives as a parameter the vcpu slot, and returns
+ * a vcpu fd.
+ */
+#define KVM_CREATE_VCPU           _IOW(KVMIO, 11, int)
+#define KVM_GET_DIRTY_LOG         _IOW(KVMIO, 12, struct kvm_dirty_log)
+
+/*
+ * ioctls for vcpu fds
+ */
 #define KVM_RUN                   _IOWR(KVMIO, 2, struct kvm_run)
-#define KVM_GET_REGS              _IOWR(KVMIO, 3, struct kvm_regs)
+#define KVM_GET_REGS              _IOR(KVMIO, 3, struct kvm_regs)
 #define KVM_SET_REGS              _IOW(KVMIO, 4, struct kvm_regs)
-#define KVM_GET_SREGS             _IOWR(KVMIO, 5, struct kvm_sregs)
+#define KVM_GET_SREGS             _IOR(KVMIO, 5, struct kvm_sregs)
 #define KVM_SET_SREGS             _IOW(KVMIO, 6, struct kvm_sregs)
 #define KVM_TRANSLATE             _IOWR(KVMIO, 7, struct kvm_translation)
 #define KVM_INTERRUPT             _IOW(KVMIO, 8, struct kvm_interrupt)
 #define KVM_DEBUG_GUEST           _IOW(KVMIO, 9, struct kvm_debug_guest)
-#define KVM_SET_MEMORY_REGION     _IOW(KVMIO, 10, struct kvm_memory_region)
-#define KVM_CREATE_VCPU           _IOW(KVMIO, 11, int /* vcpu_slot */)
-#define KVM_GET_DIRTY_LOG         _IOW(KVMIO, 12, struct kvm_dirty_log)
 #define KVM_GET_MSRS              _IOWR(KVMIO, 13, struct kvm_msrs)
-#define KVM_SET_MSRS              _IOWR(KVMIO, 14, struct kvm_msrs)
-#define KVM_GET_MSR_INDEX_LIST    _IOWR(KVMIO, 15, struct kvm_msr_list)
+#define KVM_SET_MSRS              _IOW(KVMIO, 14, struct kvm_msrs)
 
 #endif
diff --git a/include/linux/kvm_para.h b/include/linux/kvm_para.h
new file mode 100644 (file)
index 0000000..3b29256
--- /dev/null
@@ -0,0 +1,73 @@
+#ifndef __LINUX_KVM_PARA_H
+#define __LINUX_KVM_PARA_H
+
+/*
+ * Guest OS interface for KVM paravirtualization
+ *
+ * Note: this interface is totally experimental, and is certain to change
+ *       as we make progress.
+ */
+
+/*
+ * Per-VCPU descriptor area shared between guest and host. Writable to
+ * both guest and host. Registered with the host by the guest when
+ * a guest acknowledges paravirtual mode.
+ *
+ * NOTE: all addresses are guest-physical addresses (gpa), to make it
+ * easier for the hypervisor to map between the various addresses.
+ */
+struct kvm_vcpu_para_state {
+       /*
+        * API version information for compatibility. If there's any support
+        * mismatch (too old host trying to execute too new guest) then
+        * the host will deny entry into paravirtual mode. Any other
+        * combination (new host + old guest and new host + new guest)
+        * is supposed to work - new host versions will support all old
+        * guest API versions.
+        */
+       u32 guest_version;
+       u32 host_version;
+       u32 size;
+       u32 ret;
+
+       /*
+        * The address of the vm exit instruction (VMCALL or VMMCALL),
+        * which the host will patch according to the CPU model the
+        * VM runs on:
+        */
+       u64 hypercall_gpa;
+
+} __attribute__ ((aligned(PAGE_SIZE)));
+
+#define KVM_PARA_API_VERSION 1
+
+/*
+ * This is used for an RDMSR's ECX parameter to probe for a KVM host.
+ * Hopefully no CPU vendor will use up this number. This is placed well
+ * out of way of the typical space occupied by CPU vendors' MSR indices,
+ * and we think (or at least hope) it wont be occupied in the future
+ * either.
+ */
+#define MSR_KVM_API_MAGIC 0x87655678
+
+#define KVM_EINVAL 1
+
+/*
+ * Hypercall calling convention:
+ *
+ * Each hypercall may have 0-6 parameters.
+ *
+ * 64-bit hypercall index is in RAX, goes from 0 to __NR_hypercalls-1
+ *
+ * 64-bit parameters 1-6 are in the standard gcc x86_64 calling convention
+ * order: RDI, RSI, RDX, RCX, R8, R9.
+ *
+ * 32-bit index is EBX, parameters are: EAX, ECX, EDX, ESI, EDI, EBP.
+ * (the first 3 are according to the gcc regparm calling convention)
+ *
+ * No registers are clobbered by the hypercall, except that the
+ * return value is in RAX.
+ */
+#define __NR_hypercalls                        0
+
+#endif
index d739b2e7eac26a64fa215909cd552345463493e2..598793c0745b3c97ec593f1329b351b5743c3b1d 100644 (file)
@@ -9,22 +9,38 @@
 #define _LINUX_LCD_H
 
 #include <linux/device.h>
+#include <linux/mutex.h>
 #include <linux/notifier.h>
 
+/* Notes on locking:
+ *
+ * lcd_device->ops_lock is an internal backlight lock protecting the ops
+ * field and no code outside the core should need to touch it.
+ *
+ * Access to set_power() is serialised by the update_lock mutex since
+ * most drivers seem to need this and historically get it wrong.
+ *
+ * Most drivers don't need locking on their get_power() method.
+ * If yours does, you need to implement it in the driver. You can use the
+ * update_lock mutex if appropriate.
+ *
+ * Any other use of the locks below is probably wrong.
+ */
+
 struct lcd_device;
 struct fb_info;
 
-/* This structure defines all the properties of a LCD flat panel. */
 struct lcd_properties {
-       /* Owner module */
-       struct module *owner;
+       /* The maximum value for contrast (read-only) */
+       int max_contrast;
+};
+
+struct lcd_ops {
        /* Get the LCD panel power status (0: full on, 1..3: controller
           power on, flat panel power off, 4: full off), see FB_BLANK_XXX */
        int (*get_power)(struct lcd_device *);
        /* Enable or disable power to the LCD (0: on; 4: off, see FB_BLANK_XXX) */
        int (*set_power)(struct lcd_device *, int power);
-       /* The maximum value for contrast (read-only) */
-       int max_contrast;
        /* Get the current contrast setting (0-max_contrast) */
        int (*get_contrast)(struct lcd_device *);
        /* Set LCD panel contrast */
@@ -35,20 +51,31 @@ struct lcd_properties {
 };
 
 struct lcd_device {
-       /* This protects the 'props' field. If 'props' is NULL, the driver that
+       struct lcd_properties props;
+       /* This protects the 'ops' field. If 'ops' is NULL, the driver that
           registered this device has been unloaded, and if class_get_devdata()
           points to something in the body of that driver, it is also invalid. */
-       struct semaphore sem;
+       struct mutex ops_lock;
        /* If this is NULL, the backing module is unloaded */
-       struct lcd_properties *props;
+       struct lcd_ops *ops;
+       /* Serialise access to set_power method */
+       struct mutex update_lock;
        /* The framebuffer notifier block */
        struct notifier_block fb_notif;
        /* The class device structure */
        struct class_device class_dev;
 };
 
+static inline void lcd_set_power(struct lcd_device *ld, int power)
+{
+       mutex_lock(&ld->update_lock);
+       if (ld->ops && ld->ops->set_power)
+               ld->ops->set_power(ld, power);
+       mutex_unlock(&ld->update_lock);
+}
+
 extern struct lcd_device *lcd_device_register(const char *name,
-       void *devdata, struct lcd_properties *lp);
+       void *devdata, struct lcd_ops *ops);
 extern void lcd_device_unregister(struct lcd_device *ld);
 
 #define to_lcd_device(obj) container_of(obj, struct lcd_device, class_dev)
index 86762a9f52ba19bb4622662264750d8c6b943646..e3f32f3189b26431461f8f10c177d30accd8c1b7 100644 (file)
@@ -403,8 +403,7 @@ struct ata_host {
        void                    *private_data;
        const struct ata_port_operations *ops;
        unsigned long           flags;
-       int                     simplex_claimed;        /* Keep seperate in case we
-                                                          ever need to do this locked */
+       struct ata_port         *simplex_claimed;       /* channel owning the DMA */
        struct ata_port         *ports[0];
 };
 
@@ -495,6 +494,7 @@ struct ata_device {
 
        /* error history */
        struct ata_ering        ering;
+       int                     spdn_cnt;
        unsigned int            horkage;        /* List of broken features */
 #ifdef CONFIG_SATA_ACPI
        /* ACPI objects info */
@@ -535,8 +535,8 @@ struct ata_port {
        spinlock_t              *lock;
        unsigned long           flags;  /* ATA_FLAG_xxx */
        unsigned int            pflags; /* ATA_PFLAG_xxx */
-       unsigned int            id;     /* unique id req'd by scsi midlyr */
-       unsigned int            port_no; /* unique port #; from zero */
+       unsigned int            print_id; /* user visible unique port ID */
+       unsigned int            port_no; /* 0 based port no. inside the host */
 
        struct ata_prd          *prd;    /* our SG list */
        dma_addr_t              prd_dma; /* and its DMA mapping */
@@ -718,10 +718,12 @@ extern void ata_std_ports(struct ata_ioports *ioaddr);
 extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
                             unsigned int n_ports);
 extern void ata_pci_remove_one (struct pci_dev *pdev);
+#ifdef CONFIG_PM
 extern void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t mesg);
 extern int __must_check ata_pci_device_do_resume(struct pci_dev *pdev);
 extern int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
 extern int ata_pci_device_resume(struct pci_dev *pdev);
+#endif
 extern int ata_pci_clear_simplex(struct pci_dev *pdev);
 #endif /* CONFIG_PCI */
 extern int ata_device_add(const struct ata_probe_ent *ent);
@@ -747,10 +749,12 @@ extern int sata_scr_write(struct ata_port *ap, int reg, u32 val);
 extern int sata_scr_write_flush(struct ata_port *ap, int reg, u32 val);
 extern int ata_port_online(struct ata_port *ap);
 extern int ata_port_offline(struct ata_port *ap);
+#ifdef CONFIG_PM
 extern int ata_scsi_device_resume(struct scsi_device *);
 extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t mesg);
 extern int ata_host_suspend(struct ata_host *host, pm_message_t mesg);
 extern void ata_host_resume(struct ata_host *host);
+#endif
 extern int ata_ratelimit(void);
 extern int ata_busy_sleep(struct ata_port *ap,
                          unsigned long timeout_pat, unsigned long timeout);
@@ -759,6 +763,7 @@ extern void ata_port_queue_task(struct ata_port *ap, work_func_t fn,
 extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
                             unsigned long interval_msec,
                             unsigned long timeout_msec);
+extern unsigned int ata_dev_try_classify(struct ata_port *, unsigned int, u8 *);
 
 /*
  * Default driver ops implementations
@@ -786,10 +791,12 @@ extern void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf,
 extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
                 unsigned int n_elem);
 extern unsigned int ata_dev_classify(const struct ata_taskfile *tf);
+extern void ata_dev_disable(struct ata_device *adev);
 extern void ata_id_string(const u16 *id, unsigned char *s,
                          unsigned int ofs, unsigned int len);
 extern void ata_id_c_string(const u16 *id, unsigned char *s,
                            unsigned int ofs, unsigned int len);
+extern void ata_id_to_dma_mode(struct ata_device *dev, u8 unknown);
 extern unsigned long ata_device_blacklisted(const struct ata_device *dev);
 extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
 extern void ata_bmdma_start (struct ata_queued_cmd *qc);
@@ -890,10 +897,10 @@ extern void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
  * printk helpers
  */
 #define ata_port_printk(ap, lv, fmt, args...) \
-       printk(lv"ata%u: "fmt, (ap)->id , ##args)
+       printk(lv"ata%u: "fmt, (ap)->print_id , ##args)
 
 #define ata_dev_printk(dev, lv, fmt, args...) \
-       printk(lv"ata%u.%02u: "fmt, (dev)->ap->id, (dev)->devno , ##args)
+       printk(lv"ata%u.%02u: "fmt, (dev)->ap->print_id, (dev)->devno , ##args)
 
 /*
  * ata_eh_info helpers
@@ -1031,6 +1038,21 @@ static inline u8 ata_chk_status(struct ata_port *ap)
        return ap->ops->check_status(ap);
 }
 
+/**
+ *     ata_ncq_enabled - Test whether NCQ is enabled
+ *     @dev: ATA device to test for
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host lock)
+ *
+ *     RETURNS:
+ *     1 if NCQ is enabled for @dev, 0 otherwise.
+ */
+static inline int ata_ncq_enabled(struct ata_device *dev)
+{
+       return (dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ_OFF |
+                             ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ;
+}
 
 /**
  *     ata_pause - Flush writes and pause 400 nanoseconds.
index b32c8a97fcec51b3ea266b75a964df505d36f542..a9c6567fe70c02fa3493915c01da90738bbb3abb 100644 (file)
@@ -13,6 +13,7 @@
 #define HPFS_SUPER_MAGIC       0xf995e849
 #define ISOFS_SUPER_MAGIC      0x9660
 #define JFFS2_SUPER_MAGIC      0x72b6
+#define KVMFS_SUPER_MAGIC      0x19700426
 
 #define MINIX_SUPER_MAGIC      0x137F          /* original minix fs */
 #define MINIX_SUPER_MAGIC2     0x138F          /* minix fs, 30 char names */
index 48148e0cdbd179725de653eff14a229c26ad6153..75e55dcdeb183bfc76c55fa8ffc05c930bbd49d1 100644 (file)
@@ -5,6 +5,14 @@
 
 typedef struct page *new_page_t(struct page *, unsigned long private, int **);
 
+/* Check if a vma is migratable */
+static inline int vma_migratable(struct vm_area_struct *vma)
+{
+       if (vma->vm_flags & (VM_IO|VM_HUGETLB|VM_PFNMAP|VM_RESERVED))
+               return 0;
+       return 1;
+}
+
 #ifdef CONFIG_MIGRATION
 extern int isolate_lru_page(struct page *p, struct list_head *pagelist);
 extern int putback_lru_pages(struct list_head *l);
index 9850d513ff60e9b023273a9aa6a29f3b0baf2ed0..0e39745f5111b90d930998aae2caadade96c99e8 100644 (file)
@@ -78,8 +78,7 @@ struct minix_super_block {
  * V3 minix super-block data on disk
  */
 struct minix3_super_block {
-       __u16 s_ninodes;
-       __u16 s_nzones;
+       __u32 s_ninodes;
        __u16 s_pad0;
        __u16 s_imap_blocks;
        __u16 s_zmap_blocks;
index a0eec16eb0bdbb6a2092b443f299f28c5c11cc25..60e0e4a592d29fd28a62053b5cabde4c1f285673 100644 (file)
@@ -660,15 +660,11 @@ static inline int page_mapped(struct page *page)
 extern void show_free_areas(void);
 
 #ifdef CONFIG_SHMEM
-struct page *shmem_nopage(struct vm_area_struct *vma,
-                       unsigned long address, int *type);
 int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *new);
 struct mempolicy *shmem_get_policy(struct vm_area_struct *vma,
                                        unsigned long addr);
 int shmem_lock(struct file *file, int lock, struct user_struct *user);
 #else
-#define shmem_nopage filemap_nopage
-
 static inline int shmem_lock(struct file *file, int lock,
                             struct user_struct *user)
 {
@@ -688,7 +684,6 @@ static inline struct mempolicy *shmem_get_policy(struct vm_area_struct *vma,
 }
 #endif
 struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags);
-extern int shmem_mmap(struct file *file, struct vm_area_struct *vma);
 
 int shmem_zero_setup(struct vm_area_struct *);
 
index 913e5752569f1c70f7c3cb6315af0d3514a22c92..bfcef8a1ad8b69e971baeff4b0341d0e53706b9b 100644 (file)
@@ -62,6 +62,12 @@ struct mmc_ios {
 
 #define MMC_BUS_WIDTH_1                0
 #define MMC_BUS_WIDTH_4                2
+
+       unsigned char   timing;                 /* timing specification used */
+
+#define MMC_TIMING_LEGACY      0
+#define MMC_TIMING_MMC_HS      1
+#define MMC_TIMING_SD_HS       2
 };
 
 struct mmc_host_ops {
@@ -87,6 +93,8 @@ struct mmc_host {
 #define MMC_CAP_4_BIT_DATA     (1 << 0)        /* Can the host do 4 bit transfers */
 #define MMC_CAP_MULTIWRITE     (1 << 1)        /* Can accurately report bytes sent to card on error */
 #define MMC_CAP_BYTEBLOCK      (1 << 2)        /* Can do non-log2 block sizes */
+#define MMC_CAP_MMC_HIGHSPEED  (1 << 3)        /* Can do MMC high-speed timing */
+#define MMC_CAP_SD_HIGHSPEED   (1 << 4)        /* Can do SD high-speed timing */
 
        /* host specific block data */
        unsigned int            max_seg_size;   /* see blk_queue_max_segment_size */
index e0c393cc724048696b43e0ac4b2af04c3053cca3..e96b2dee10bb8544d18e9804adb155a8d27bdd03 100644 (file)
@@ -320,4 +320,16 @@ struct eisa_device_id {
 
 #define EISA_DEVICE_MODALIAS_FMT "eisa:s%s"
 
+struct parisc_device_id {
+       __u8    hw_type;        /* 5 bits used */
+       __u8    hversion_rev;   /* 4 bits */
+       __u16   hversion;       /* 12 bits */
+       __u32   sversion;       /* 20 bits */
+};
+
+#define PA_HWTYPE_ANY_ID       0xff
+#define PA_HVERSION_REV_ANY_ID 0xff
+#define PA_HVERSION_ANY_ID     0xffff
+#define PA_SVERSION_ANY_ID     0xffffffff
+
 #endif /* LINUX_MOD_DEVICETABLE_H */
diff --git a/include/linux/mtd/iflash.h b/include/linux/mtd/iflash.h
deleted file mode 100644 (file)
index 9aa5b4f..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/* $Id: iflash.h,v 1.2 2000/11/13 18:01:54 dwmw2 Exp $ */
-
-#ifndef __MTD_IFLASH_H__
-#define __MTD_IFLASH_H__
-
-/* Extended CIS registers for Series 2 and 2+ cards */
-/* The registers are all offsets from 0x4000 */
-#define CISREG_CSR             0x0100
-#define CISREG_WP              0x0104
-#define CISREG_RDYBSY          0x0140
-
-/* Extended CIS registers for Series 2 cards */
-#define CISREG_SLEEP           0x0118
-#define CISREG_RDY_MASK                0x0120
-#define CISREG_RDY_STATUS      0x0130
-
-/* Extended CIS registers for Series 2+ cards */
-#define CISREG_VCR             0x010c
-
-/* Card Status Register */
-#define CSR_SRESET             0x20    /* Soft reset */
-#define CSR_CMWP               0x10    /* Common memory write protect */
-#define CSR_PWRDOWN            0x08    /* Power down status */
-#define CSR_CISWP              0x04    /* Common memory CIS WP */
-#define CSR_WP                 0x02    /* Mechanical write protect */
-#define CSR_READY              0x01    /* Ready/busy status */
-
-/* Write Protection Register */
-#define WP_BLKEN               0x04    /* Enable block locking */
-#define WP_CMWP                        0x02    /* Common memory write protect */
-#define WP_CISWP               0x01    /* Common memory CIS WP */
-
-/* Voltage Control Register */
-#define VCR_VCC_LEVEL          0x80    /* 0 = 5V, 1 = 3.3V */
-#define VCR_VPP_VALID          0x02    /* Vpp Valid */
-#define VCR_VPP_GEN            0x01    /* Integrated Vpp generator */
-
-/* Ready/Busy Mode Register */
-#define RDYBSY_RACK            0x02    /* Ready acknowledge */
-#define RDYBSY_MODE            0x01    /* 1 = high performance */
-
-#define LOW(x) ((x) & 0xff)
-
-/* 28F008SA-Compatible Command Set */
-#define IF_READ_ARRAY          0xffff
-#define IF_INTEL_ID            0x9090
-#define IF_READ_CSR            0x7070
-#define IF_CLEAR_CSR           0x5050
-#define IF_WRITE               0x4040
-#define IF_BLOCK_ERASE         0x2020
-#define IF_ERASE_SUSPEND       0xb0b0
-#define IF_CONFIRM             0xd0d0
-
-/* 28F016SA Performance Enhancement Commands */
-#define IF_READ_PAGE           0x7575
-#define IF_PAGE_SWAP           0x7272
-#define IF_SINGLE_LOAD         0x7474
-#define IF_SEQ_LOAD            0xe0e0
-#define IF_PAGE_WRITE          0x0c0c
-#define IF_RDY_MODE            0x9696
-#define IF_RDY_LEVEL           0x0101
-#define IF_RDY_PULSE_WRITE     0x0202
-#define IF_RDY_PULSE_ERASE     0x0303
-#define IF_RDY_DISABLE         0x0404
-#define IF_LOCK_BLOCK          0x7777
-#define IF_UPLOAD_STATUS       0x9797
-#define IF_READ_ESR            0x7171
-#define IF_ERASE_UNLOCKED      0xa7a7
-#define IF_SLEEP               0xf0f0
-#define IF_ABORT               0x8080
-#define IF_UPLOAD_DEVINFO      0x9999
-
-/* Definitions for Compatible Status Register */
-#define CSR_WR_READY           0x8080  /* Write state machine status */
-#define CSR_ERA_SUSPEND                0x4040  /* Erase suspend status */
-#define CSR_ERA_ERR            0x2020  /* Erase status */
-#define CSR_WR_ERR             0x1010  /* Data write status */
-#define CSR_VPP_LOW            0x0808  /* Vpp status */
-
-/* Definitions for Global Status Register */
-#define GSR_WR_READY           0x8080  /* Write state machine status */
-#define GSR_OP_SUSPEND         0x4040  /* Operation suspend status */
-#define GSR_OP_ERR             0x2020  /* Device operation status */
-#define GSR_SLEEP              0x1010  /* Device sleep status */
-#define GSR_QUEUE_FULL         0x0808  /* Queue status */
-#define GSR_PAGE_AVAIL         0x0404  /* Page buffer available status */
-#define GSR_PAGE_READY         0x0202  /* Page buffer status */
-#define GSR_PAGE_SELECT                0x0101  /* Page buffer select status */
-
-/* Definitions for Block Status Register */
-#define BSR_READY              0x8080  /* Block status */
-#define BSR_UNLOCK             0x4040  /* Block lock status */
-#define BSR_FAILED             0x2020  /* Block operation status */
-#define BSR_ABORTED            0x1010  /* Operation abort status */
-#define BSR_QUEUE_FULL         0x0808  /* Queue status */
-#define BSR_VPP_LOW            0x0404  /* Vpp status */
-
-#endif /* __MTD_IFLASH_H__ */
index 6a8570be331bbdb3deb587983953485427901ef5..3d956c3abb310d06867abd729f8aacd0433be00b 100644 (file)
@@ -121,6 +121,7 @@ struct mtd_info {
        u_int32_t writesize;
 
        u_int32_t oobsize;   // Amount of OOB data per block (e.g. 16)
+       u_int32_t oobavail;  // Available OOB bytes per block
 
        // Kernel-only stuff starts here.
        char *name;
index d8af8a95e58d86305227afb9a8385911b4b67b18..a56d24ada5057eacddc91cb51ee4254cfdcfed13 100644 (file)
@@ -82,7 +82,8 @@ struct onenand_bufferram {
  * @wq:                        [INTERN] wait queue to sleep on if a OneNAND
  *                     operation is in progress
  * @state:             [INTERN] the current state of the OneNAND device
- * @page_buf:          data buffer
+ * @page_buf:          [INTERN] page main data buffer
+ * @oob_buf:           [INTERN] page oob data buffer
  * @subpagesize:       [INTERN] holds the subpagesize
  * @ecclayout:         [REPLACEABLE] the default ecc placement scheme
  * @bbm:               [REPLACEABLE] pointer to Bad Block Management
@@ -122,6 +123,7 @@ struct onenand_chip {
        wait_queue_head_t       wq;
        onenand_state_t         state;
        unsigned char           *page_buf;
+       unsigned char           *oob_buf;
 
        int                     subpagesize;
        struct nand_ecclayout   *ecclayout;
@@ -156,6 +158,7 @@ struct onenand_chip {
 #define ONENAND_HAS_CONT_LOCK          (0x0001)
 #define ONENAND_HAS_UNLOCK_ALL         (0x0002)
 #define ONENAND_PAGEBUF_ALLOC          (0x1000)
+#define ONENAND_OOBBUF_ALLOC           (0x2000)
 
 /*
  * OneNAND Flash Manufacturer ID Codes
index aff25c000abfba988e6a3922192a97b15ea2adf0..c6d4ab86b83c45b6cb29c24fbffa5e1a7f74a1c4 100644 (file)
@@ -1288,7 +1288,7 @@ struct mv64xxx_i2c_pdata {
 #define MV643XX_ETH_NAME       "mv643xx_eth"
 
 struct mv643xx_eth_platform_data {
-       char            *mac_addr;      /* pointer to mac address */
+       int             port_number;
        u16             force_phy_addr; /* force override if phy_addr == 0 */
        u16             phy_addr;
 
@@ -1303,6 +1303,7 @@ struct mv643xx_eth_platform_data {
        u32             tx_sram_size;
        u32             rx_sram_addr;
        u32             rx_sram_size;
+       u8              mac_addr[6];    /* mac address if non-zero*/
 };
 
 #endif /* __ASM_MV643XX_H */
index a503052138bdd0fa7600cfb1742f003154bf81f6..6330fc76b00fb481d8580a392425b45a5556d93c 100644 (file)
@@ -50,6 +50,8 @@ struct ncp_server {
        int packet_size;
        unsigned char *packet;  /* Here we prepare requests and
                                   receive replies */
+       unsigned char *txbuf;   /* Storage for current request */
+       unsigned char *rxbuf;   /* Storage for reply to current request */
 
        int lock;               /* To prevent mismatch in protocols. */
        struct mutex mutex;
index 907d4f5ca5dc50f2384ad69730f8c5686e085cf1..e3a6df07aa4bf111aee987c63530a05b88380ef0 100644 (file)
@@ -45,7 +45,7 @@ static inline int ip_conntrack_confirm(struct sk_buff **pskb)
        int ret = NF_ACCEPT;
 
        if (ct) {
-               if (!is_confirmed(ct))
+               if (!is_confirmed(ct) && !is_dying(ct))
                        ret = __ip_conntrack_confirm(pskb);
                ip_ct_deliver_cached_events(ct);
        }
index b1063e9cdb1b77c35f3b8d2ec72656138ff93b5a..52c54a5720f3f308ff162039211c95cd3e6b403e 100644 (file)
@@ -352,7 +352,7 @@ extern nodemask_t node_possible_map;
 #define node_possible(node)    node_isset((node), node_possible_map)
 #define first_online_node      first_node(node_online_map)
 #define next_online_node(nid)  next_node((nid), node_online_map)
-int highest_possible_node_id(void);
+extern int nr_node_ids;
 #else
 #define num_online_nodes()     1
 #define num_possible_nodes()   1
@@ -360,7 +360,7 @@ int highest_possible_node_id(void);
 #define node_possible(node)    ((node) == 0)
 #define first_online_node      0
 #define next_online_node(nid)  (MAX_NUMNODES)
-#define highest_possible_node_id()     0
+#define nr_node_ids            1
 #endif
 
 #define any_online_node(mask)                  \
index 350878a2d848cf2efe561449ac7d9ccece15630b..9cd0d0eaf5239a3276aecb6b2a83e7f399acda27 100644 (file)
@@ -76,7 +76,7 @@
 #define PG_active               6
 #define PG_slab                         7      /* slab debug (Suparna wants this) */
 
-#define PG_checked              8      /* kill me in 2.5.<early>. */
+#define PG_owner_priv_1                 8      /* Owner use. If pagecache, fs may use*/
 #define PG_arch_1               9
 #define PG_reserved            10
 #define PG_private             11      /* If pagecache, has fs-private data */
@@ -91,6 +91,8 @@
 #define PG_nosave_free         18      /* Used for system suspend/resume */
 #define PG_buddy               19      /* Page is free, on buddy lists */
 
+/* PG_owner_priv_1 users should have descriptive aliases */
+#define PG_checked             PG_owner_priv_1 /* Used by some filesystems */
 
 #if (BITS_PER_LONG > 32)
 /*
index 2c4b6842dfb91950d5007a3947aa4a0306a8940d..78417e421b4c2d942c0ce7038e22a677bf220742 100644 (file)
@@ -543,6 +543,7 @@ void pci_set_master(struct pci_dev *dev);
 int __must_check pci_set_mwi(struct pci_dev *dev);
 void pci_clear_mwi(struct pci_dev *dev);
 void pci_intx(struct pci_dev *dev, int enable);
+void pci_msi_off(struct pci_dev *dev);
 int pci_set_dma_mask(struct pci_dev *dev, u64 mask);
 int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask);
 void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno);
index 7a6d34ee5ab132593c2efce4000edd3bb3af3408..f09cce2357ff47e53183cdd3f09a39f1a51a05f5 100644 (file)
 #define PCI_MSI_DATA_64                12      /* 16 bits of data for 64-bit devices */
 #define PCI_MSI_MASK_BIT       16      /* Mask bits register */
 
-/* MSI-X registers (these are at offset PCI_MSI_FLAGS) */
-#define PCI_MSIX_FLAGS_QSIZE   0x7FF
-#define PCI_MSIX_FLAGS_ENABLE  (1 << 15)
+/* MSI-X registers (these are at offset PCI_MSIX_FLAGS) */
+#define PCI_MSIX_FLAGS         2
+#define  PCI_MSIX_FLAGS_QSIZE  0x7FF
+#define  PCI_MSIX_FLAGS_ENABLE (1 << 15)
 #define PCI_MSIX_FLAGS_BIRMASK (7 << 0)
 #define PCI_MSIX_FLAGS_BITMASK (1 << 0)
 
index 070394e846d008f2be06da51263677a63dc7e220..21db05ac7c0b3753bc8f0eafd4381cb30c84712c 100644 (file)
@@ -120,15 +120,48 @@ typedef int __bitwise suspend_disk_method_t;
 #define        PM_DISK_TESTPROC        ((__force suspend_disk_method_t) 6)
 #define        PM_DISK_MAX             ((__force suspend_disk_method_t) 7)
 
+/**
+ * struct pm_ops - Callbacks for managing platform dependent suspend states.
+ * @valid: Callback to determine whether the given state can be entered.
+ *     If %CONFIG_SOFTWARE_SUSPEND is set then %PM_SUSPEND_DISK is
+ *     always valid and never passed to this call.
+ *     If not assigned, all suspend states are advertised as valid
+ *     in /sys/power/state (but can still be rejected by prepare or enter.)
+ *
+ * @prepare: Prepare the platform for the given suspend state. Can return a
+ *     negative error code if necessary.
+ *
+ * @enter: Enter the given suspend state, must be assigned. Can return a
+ *     negative error code if necessary.
+ *
+ * @finish: Called when the system has left the given state and all devices
+ *     are resumed. The return value is ignored.
+ *
+ * @pm_disk_mode: Set to the disk method that the user should be able to
+ *     configure for suspend-to-disk. Since %PM_DISK_SHUTDOWN,
+ *     %PM_DISK_REBOOT, %PM_DISK_TEST and %PM_DISK_TESTPROC
+ *     are always allowed, currently only %PM_DISK_PLATFORM
+ *     makes sense. If the user then choses %PM_DISK_PLATFORM,
+ *     the @prepare call will be called before suspending to disk
+ *     (if present), the @enter call should be present and will
+ *     be called after all state has been saved and the machine
+ *     is ready to be shut down/suspended/..., and the @finish
+ *     callback is called after state has been restored. All
+ *     these calls are called with %PM_SUSPEND_DISK as the state.
+ */
 struct pm_ops {
-       suspend_disk_method_t pm_disk_mode;
        int (*valid)(suspend_state_t state);
        int (*prepare)(suspend_state_t state);
        int (*enter)(suspend_state_t state);
        int (*finish)(suspend_state_t state);
+       suspend_disk_method_t pm_disk_mode;
 };
 
-extern void pm_set_ops(struct pm_ops *);
+/**
+ * pm_set_ops - set platform dependent power management ops
+ * @pm_ops: The new power management operations to set.
+ */
+extern void pm_set_ops(struct pm_ops *pm_ops);
 extern struct pm_ops *pm_ops;
 extern int pm_suspend(suspend_state_t state);
 
index 5053dc01fad4148c89eff49723056ed0be7f9190..49fe2997a0168631731f7dbefcbd9e5ee7547161 100644 (file)
@@ -684,7 +684,6 @@ struct sched_domain {
        unsigned int imbalance_pct;     /* No balance until over watermark */
        unsigned long long cache_hot_time; /* Task considered cache hot (ns) */
        unsigned int cache_nice_tries;  /* Leave cache hot tasks for # tries */
-       unsigned int per_cpu_gain;      /* CPU % gained by adding domain cpus */
        unsigned int busy_idx;
        unsigned int idle_idx;
        unsigned int newidle_idx;
@@ -1329,6 +1328,7 @@ extern int kill_pid_info(int sig, struct siginfo *info, struct pid *pid);
 extern int kill_pid_info_as_uid(int, struct siginfo *, struct pid *, uid_t, uid_t, u32);
 extern int kill_pgrp(struct pid *pid, int sig, int priv);
 extern int kill_pid(struct pid *pid, int sig, int priv);
+extern int kill_proc_info(int, struct siginfo *, pid_t);
 extern void do_notify_parent(struct task_struct *, int);
 extern void force_sig(int, struct task_struct *);
 extern void force_sig_specific(int, struct task_struct *);
index a2c896ad0befa6819dbae3e1ffd47b1679597346..ad2e3af6599710d43269a7f4c243ebd90171925d 100644 (file)
@@ -96,12 +96,17 @@ struct shmid_kernel /* private to the kernel */
 
 #ifdef CONFIG_SYSVIPC
 long do_shmat(int shmid, char __user *shmaddr, int shmflg, unsigned long *addr);
+extern int is_file_shm_hugepages(struct file *file);
 #else
 static inline long do_shmat(int shmid, char __user *shmaddr,
                                int shmflg, unsigned long *addr)
 {
        return -ENOSYS;
 }
+static inline int is_file_shm_hugepages(struct file *file)
+{
+       return 0;
+}
 #endif
 
 #endif /* __KERNEL__ */
diff --git a/include/linux/sm501-regs.h b/include/linux/sm501-regs.h
new file mode 100644 (file)
index 0000000..cc9be4a
--- /dev/null
@@ -0,0 +1,357 @@
+/* sm501-regs.h
+ *
+ * Copyright 2006 Simtec Electronics
+ *
+ * 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.
+ *
+ * Silicon Motion SM501 register definitions
+*/
+
+/* System Configuration area */
+/* System config base */
+#define SM501_SYS_CONFIG               (0x000000)
+
+/* config 1 */
+#define SM501_SYSTEM_CONTROL           (0x000000)
+#define SM501_MISC_CONTROL             (0x000004)
+
+#define SM501_MISC_BUS_SH              (0x0)
+#define SM501_MISC_BUS_PCI             (0x1)
+#define SM501_MISC_BUS_XSCALE          (0x2)
+#define SM501_MISC_BUS_NEC             (0x6)
+#define SM501_MISC_BUS_MASK            (0x7)
+
+#define SM501_MISC_VR_62MB             (1<<3)
+#define SM501_MISC_CDR_RESET           (1<<7)
+#define SM501_MISC_USB_LB              (1<<8)
+#define SM501_MISC_USB_SLAVE           (1<<9)
+#define SM501_MISC_BL_1                        (1<<10)
+#define SM501_MISC_MC                  (1<<11)
+#define SM501_MISC_DAC_POWER           (1<<12)
+#define SM501_MISC_IRQ_INVERT          (1<<16)
+#define SM501_MISC_SH                  (1<<17)
+
+#define SM501_MISC_HOLD_EMPTY          (0<<18)
+#define SM501_MISC_HOLD_8              (1<<18)
+#define SM501_MISC_HOLD_16             (2<<18)
+#define SM501_MISC_HOLD_24             (3<<18)
+#define SM501_MISC_HOLD_32             (4<<18)
+#define SM501_MISC_HOLD_MASK           (7<<18)
+
+#define SM501_MISC_FREQ_12             (1<<24)
+#define SM501_MISC_PNL_24BIT           (1<<25)
+#define SM501_MISC_8051_LE             (1<<26)
+
+
+
+#define SM501_GPIO31_0_CONTROL         (0x000008)
+#define SM501_GPIO63_32_CONTROL                (0x00000C)
+#define SM501_DRAM_CONTROL             (0x000010)
+
+/* command list */
+#define SM501_ARBTRTN_CONTROL          (0x000014)
+
+/* command list */
+#define SM501_COMMAND_LIST_STATUS      (0x000024)
+
+/* interrupt debug */
+#define SM501_RAW_IRQ_STATUS           (0x000028)
+#define SM501_RAW_IRQ_CLEAR            (0x000028)
+#define SM501_IRQ_STATUS               (0x00002C)
+#define SM501_IRQ_MASK                 (0x000030)
+#define SM501_DEBUG_CONTROL            (0x000034)
+
+/* power management */
+#define SM501_CURRENT_GATE             (0x000038)
+#define SM501_CURRENT_CLOCK            (0x00003C)
+#define SM501_POWER_MODE_0_GATE                (0x000040)
+#define SM501_POWER_MODE_0_CLOCK       (0x000044)
+#define SM501_POWER_MODE_1_GATE                (0x000048)
+#define SM501_POWER_MODE_1_CLOCK       (0x00004C)
+#define SM501_SLEEP_MODE_GATE          (0x000050)
+#define SM501_POWER_MODE_CONTROL       (0x000054)
+
+/* power gates for units within the 501 */
+#define SM501_GATE_HOST                        (0)
+#define SM501_GATE_MEMORY              (1)
+#define SM501_GATE_DISPLAY             (2)
+#define SM501_GATE_2D_ENGINE           (3)
+#define SM501_GATE_CSC                 (4)
+#define SM501_GATE_ZVPORT              (5)
+#define SM501_GATE_GPIO                        (6)
+#define SM501_GATE_UART0               (7)
+#define SM501_GATE_UART1               (8)
+#define SM501_GATE_SSP                 (10)
+#define SM501_GATE_USB_HOST            (11)
+#define SM501_GATE_USB_GADGET          (12)
+#define SM501_GATE_UCONTROLLER         (17)
+#define SM501_GATE_AC97                        (18)
+
+/* panel clock */
+#define SM501_CLOCK_P2XCLK             (24)
+/* crt clock */
+#define SM501_CLOCK_V2XCLK             (16)
+/* main clock */
+#define SM501_CLOCK_MCLK               (8)
+/* SDRAM controller clock */
+#define SM501_CLOCK_M1XCLK             (0)
+
+/* config 2 */
+#define SM501_PCI_MASTER_BASE          (0x000058)
+#define SM501_ENDIAN_CONTROL           (0x00005C)
+#define SM501_DEVICEID                 (0x000060)
+/* 0x050100A0 */
+
+#define SM501_PLLCLOCK_COUNT           (0x000064)
+#define SM501_MISC_TIMING              (0x000068)
+#define SM501_CURRENT_SDRAM_CLOCK      (0x00006C)
+
+/* GPIO base */
+#define SM501_GPIO                     (0x010000)
+#define SM501_GPIO_DATA_LOW            (0x00)
+#define SM501_GPIO_DATA_HIGH           (0x04)
+#define SM501_GPIO_DDR_LOW             (0x08)
+#define SM501_GPIO_DDR_HIGH            (0x0C)
+#define SM501_GPIO_IRQ_SETUP           (0x10)
+#define SM501_GPIO_IRQ_STATUS          (0x14)
+#define SM501_GPIO_IRQ_RESET           (0x14)
+
+/* I2C controller base */
+#define SM501_I2C                      (0x010040)
+#define SM501_I2C_BYTE_COUNT           (0x00)
+#define SM501_I2C_CONTROL              (0x01)
+#define SM501_I2C_STATUS               (0x02)
+#define SM501_I2C_RESET                        (0x02)
+#define SM501_I2C_SLAVE_ADDRESS                (0x03)
+#define SM501_I2C_DATA                 (0x04)
+
+/* SSP base */
+#define SM501_SSP                      (0x020000)
+
+/* Uart 0 base */
+#define SM501_UART0                    (0x030000)
+
+/* Uart 1 base */
+#define SM501_UART1                    (0x030020)
+
+/* USB host port base */
+#define SM501_USB_HOST                 (0x040000)
+
+/* USB slave/gadget base */
+#define SM501_USB_GADGET               (0x060000)
+
+/* USB slave/gadget data port base */
+#define SM501_USB_GADGET_DATA          (0x070000)
+
+/* Display contoller/video engine base */
+#define SM501_DC                       (0x080000)
+
+/* common defines for the SM501 address registers */
+#define SM501_ADDR_FLIP                        (1<<31)
+#define SM501_ADDR_EXT                 (1<<27)
+#define SM501_ADDR_CS1                 (1<<26)
+#define SM501_ADDR_MASK                        (0x3f << 26)
+
+#define SM501_FIFO_MASK                        (0x3 << 16)
+#define SM501_FIFO_1                   (0x0 << 16)
+#define SM501_FIFO_3                   (0x1 << 16)
+#define SM501_FIFO_7                   (0x2 << 16)
+#define SM501_FIFO_11                  (0x3 << 16)
+
+/* common registers for panel and the crt */
+#define SM501_OFF_DC_H_TOT             (0x000)
+#define SM501_OFF_DC_V_TOT             (0x008)
+#define SM501_OFF_DC_H_SYNC            (0x004)
+#define SM501_OFF_DC_V_SYNC            (0x00C)
+
+#define SM501_DC_PANEL_CONTROL         (0x000)
+
+#define SM501_DC_PANEL_CONTROL_FPEN    (1<<27)
+#define SM501_DC_PANEL_CONTROL_BIAS    (1<<26)
+#define SM501_DC_PANEL_CONTROL_DATA    (1<<25)
+#define SM501_DC_PANEL_CONTROL_VDD     (1<<24)
+#define SM501_DC_PANEL_CONTROL_DP      (1<<23)
+
+#define SM501_DC_PANEL_CONTROL_TFT_888 (0<<21)
+#define SM501_DC_PANEL_CONTROL_TFT_333 (1<<21)
+#define SM501_DC_PANEL_CONTROL_TFT_444 (2<<21)
+
+#define SM501_DC_PANEL_CONTROL_DE      (1<<20)
+
+#define SM501_DC_PANEL_CONTROL_LCD_TFT (0<<18)
+#define SM501_DC_PANEL_CONTROL_LCD_STN8        (1<<18)
+#define SM501_DC_PANEL_CONTROL_LCD_STN12 (2<<18)
+
+#define SM501_DC_PANEL_CONTROL_CP      (1<<14)
+#define SM501_DC_PANEL_CONTROL_VSP     (1<<13)
+#define SM501_DC_PANEL_CONTROL_HSP     (1<<12)
+#define SM501_DC_PANEL_CONTROL_CK      (1<<9)
+#define SM501_DC_PANEL_CONTROL_TE      (1<<8)
+#define SM501_DC_PANEL_CONTROL_VPD     (1<<7)
+#define SM501_DC_PANEL_CONTROL_VP      (1<<6)
+#define SM501_DC_PANEL_CONTROL_HPD     (1<<5)
+#define SM501_DC_PANEL_CONTROL_HP      (1<<4)
+#define SM501_DC_PANEL_CONTROL_GAMMA   (1<<3)
+#define SM501_DC_PANEL_CONTROL_EN      (1<<2)
+
+#define SM501_DC_PANEL_CONTROL_8BPP    (0<<0)
+#define SM501_DC_PANEL_CONTROL_16BPP   (1<<0)
+#define SM501_DC_PANEL_CONTROL_32BPP   (2<<0)
+
+
+#define SM501_DC_PANEL_PANNING_CONTROL (0x004)
+#define SM501_DC_PANEL_COLOR_KEY       (0x008)
+#define SM501_DC_PANEL_FB_ADDR         (0x00C)
+#define SM501_DC_PANEL_FB_OFFSET       (0x010)
+#define SM501_DC_PANEL_FB_WIDTH                (0x014)
+#define SM501_DC_PANEL_FB_HEIGHT       (0x018)
+#define SM501_DC_PANEL_TL_LOC          (0x01C)
+#define SM501_DC_PANEL_BR_LOC          (0x020)
+#define SM501_DC_PANEL_H_TOT           (0x024)
+#define SM501_DC_PANEL_H_SYNC          (0x028)
+#define SM501_DC_PANEL_V_TOT           (0x02C)
+#define SM501_DC_PANEL_V_SYNC          (0x030)
+#define SM501_DC_PANEL_CUR_LINE                (0x034)
+
+#define SM501_DC_VIDEO_CONTROL         (0x040)
+#define SM501_DC_VIDEO_FB0_ADDR                (0x044)
+#define SM501_DC_VIDEO_FB_WIDTH                (0x048)
+#define SM501_DC_VIDEO_FB0_LAST_ADDR   (0x04C)
+#define SM501_DC_VIDEO_TL_LOC          (0x050)
+#define SM501_DC_VIDEO_BR_LOC          (0x054)
+#define SM501_DC_VIDEO_SCALE           (0x058)
+#define SM501_DC_VIDEO_INIT_SCALE      (0x05C)
+#define SM501_DC_VIDEO_YUV_CONSTANTS   (0x060)
+#define SM501_DC_VIDEO_FB1_ADDR                (0x064)
+#define SM501_DC_VIDEO_FB1_LAST_ADDR   (0x068)
+
+#define SM501_DC_VIDEO_ALPHA_CONTROL   (0x080)
+#define SM501_DC_VIDEO_ALPHA_FB_ADDR   (0x084)
+#define SM501_DC_VIDEO_ALPHA_FB_OFFSET (0x088)
+#define SM501_DC_VIDEO_ALPHA_FB_LAST_ADDR      (0x08C)
+#define SM501_DC_VIDEO_ALPHA_TL_LOC    (0x090)
+#define SM501_DC_VIDEO_ALPHA_BR_LOC    (0x094)
+#define SM501_DC_VIDEO_ALPHA_SCALE     (0x098)
+#define SM501_DC_VIDEO_ALPHA_INIT_SCALE        (0x09C)
+#define SM501_DC_VIDEO_ALPHA_CHROMA_KEY        (0x0A0)
+#define SM501_DC_VIDEO_ALPHA_COLOR_LOOKUP      (0x0A4)
+
+#define SM501_DC_PANEL_HWC_BASE                (0x0F0)
+#define SM501_DC_PANEL_HWC_ADDR                (0x0F0)
+#define SM501_DC_PANEL_HWC_LOC         (0x0F4)
+#define SM501_DC_PANEL_HWC_COLOR_1_2   (0x0F8)
+#define SM501_DC_PANEL_HWC_COLOR_3     (0x0FC)
+
+#define SM501_HWC_EN                   (1<<31)
+
+#define SM501_OFF_HWC_ADDR             (0x00)
+#define SM501_OFF_HWC_LOC              (0x04)
+#define SM501_OFF_HWC_COLOR_1_2                (0x08)
+#define SM501_OFF_HWC_COLOR_3          (0x0C)
+
+#define SM501_DC_ALPHA_CONTROL         (0x100)
+#define SM501_DC_ALPHA_FB_ADDR         (0x104)
+#define SM501_DC_ALPHA_FB_OFFSET       (0x108)
+#define SM501_DC_ALPHA_TL_LOC          (0x10C)
+#define SM501_DC_ALPHA_BR_LOC          (0x110)
+#define SM501_DC_ALPHA_CHROMA_KEY      (0x114)
+#define SM501_DC_ALPHA_COLOR_LOOKUP    (0x118)
+
+#define SM501_DC_CRT_CONTROL           (0x200)
+
+#define SM501_DC_CRT_CONTROL_TVP       (1<<15)
+#define SM501_DC_CRT_CONTROL_CP                (1<<14)
+#define SM501_DC_CRT_CONTROL_VSP       (1<<13)
+#define SM501_DC_CRT_CONTROL_HSP       (1<<12)
+#define SM501_DC_CRT_CONTROL_VS                (1<<11)
+#define SM501_DC_CRT_CONTROL_BLANK     (1<<10)
+#define SM501_DC_CRT_CONTROL_SEL       (1<<9)
+#define SM501_DC_CRT_CONTROL_TE                (1<<8)
+#define SM501_DC_CRT_CONTROL_PIXEL_MASK (0xF << 4)
+#define SM501_DC_CRT_CONTROL_GAMMA     (1<<3)
+#define SM501_DC_CRT_CONTROL_ENABLE    (1<<2)
+
+#define SM501_DC_CRT_CONTROL_8BPP      (0<<0)
+#define SM501_DC_CRT_CONTROL_16BPP     (1<<0)
+#define SM501_DC_CRT_CONTROL_32BPP     (2<<0)
+
+#define SM501_DC_CRT_FB_ADDR           (0x204)
+#define SM501_DC_CRT_FB_OFFSET         (0x208)
+#define SM501_DC_CRT_H_TOT             (0x20C)
+#define SM501_DC_CRT_H_SYNC            (0x210)
+#define SM501_DC_CRT_V_TOT             (0x214)
+#define SM501_DC_CRT_V_SYNC            (0x218)
+#define SM501_DC_CRT_SIGNATURE_ANALYZER        (0x21C)
+#define SM501_DC_CRT_CUR_LINE          (0x220)
+#define SM501_DC_CRT_MONITOR_DETECT    (0x224)
+
+#define SM501_DC_CRT_HWC_BASE          (0x230)
+#define SM501_DC_CRT_HWC_ADDR          (0x230)
+#define SM501_DC_CRT_HWC_LOC           (0x234)
+#define SM501_DC_CRT_HWC_COLOR_1_2     (0x238)
+#define SM501_DC_CRT_HWC_COLOR_3       (0x23C)
+
+#define SM501_DC_PANEL_PALETTE         (0x400)
+
+#define SM501_DC_VIDEO_PALETTE         (0x800)
+
+#define SM501_DC_CRT_PALETTE           (0xC00)
+
+/* Zoom Video port base */
+#define SM501_ZVPORT                   (0x090000)
+
+/* AC97/I2S base */
+#define SM501_AC97                     (0x0A0000)
+
+/* 8051 micro controller base */
+#define SM501_UCONTROLLER              (0x0B0000)
+
+/* 8051 micro controller SRAM base */
+#define SM501_UCONTROLLER_SRAM         (0x0C0000)
+
+/* DMA base */
+#define SM501_DMA                      (0x0D0000)
+
+/* 2d engine base */
+#define SM501_2D_ENGINE                        (0x100000)
+#define SM501_2D_SOURCE                        (0x00)
+#define SM501_2D_DESTINATION           (0x04)
+#define SM501_2D_DIMENSION             (0x08)
+#define SM501_2D_CONTROL               (0x0C)
+#define SM501_2D_PITCH                 (0x10)
+#define SM501_2D_FOREGROUND            (0x14)
+#define SM501_2D_BACKGROUND            (0x18)
+#define SM501_2D_STRETCH               (0x1C)
+#define SM501_2D_COLOR_COMPARE         (0x20)
+#define SM501_2D_COLOR_COMPARE_MASK    (0x24)
+#define SM501_2D_MASK                  (0x28)
+#define SM501_2D_CLIP_TL               (0x2C)
+#define SM501_2D_CLIP_BR               (0x30)
+#define SM501_2D_MONO_PATTERN_LOW      (0x34)
+#define SM501_2D_MONO_PATTERN_HIGH     (0x38)
+#define SM501_2D_WINDOW_WIDTH          (0x3C)
+#define SM501_2D_SOURCE_BASE           (0x40)
+#define SM501_2D_DESTINATION_BASE      (0x44)
+#define SM501_2D_ALPHA                 (0x48)
+#define SM501_2D_WRAP                  (0x4C)
+#define SM501_2D_STATUS                        (0x50)
+
+#define SM501_CSC_Y_SOURCE_BASE                (0xC8)
+#define SM501_CSC_CONSTANTS            (0xCC)
+#define SM501_CSC_Y_SOURCE_X           (0xD0)
+#define SM501_CSC_Y_SOURCE_Y           (0xD4)
+#define SM501_CSC_U_SOURCE_BASE                (0xD8)
+#define SM501_CSC_V_SOURCE_BASE                (0xDC)
+#define SM501_CSC_SOURCE_DIMENSION     (0xE0)
+#define SM501_CSC_SOURCE_PITCH         (0xE4)
+#define SM501_CSC_DESTINATION          (0xE8)
+#define SM501_CSC_DESTINATION_DIMENSION        (0xEC)
+#define SM501_CSC_DESTINATION_PITCH    (0xF0)
+#define SM501_CSC_SCALE_FACTOR         (0xF4)
+#define SM501_CSC_DESTINATION_BASE     (0xF8)
+#define SM501_CSC_CONTROL              (0xFC)
+
+/* 2d engine data port base */
+#define SM501_2D_ENGINE_DATA           (0x110000)
diff --git a/include/linux/sm501.h b/include/linux/sm501.h
new file mode 100644 (file)
index 0000000..9e3aaad
--- /dev/null
@@ -0,0 +1,170 @@
+/* include/linux/sm501.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *     Vincent Sanders <vince@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License
+ *
+ * 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
+*/
+
+extern int sm501_unit_power(struct device *dev,
+                           unsigned int unit, unsigned int to);
+
+extern unsigned long sm501_set_clock(struct device *dev,
+                                    int clksrc, unsigned long freq);
+
+extern unsigned long sm501_find_clock(int clksrc, unsigned long req_freq);
+
+/* sm501_misc_control
+ *
+ * Modify the SM501's MISC_CONTROL register
+*/
+
+extern int sm501_misc_control(struct device *dev,
+                             unsigned long set, unsigned long clear);
+
+/* sm501_modify_reg
+ *
+ * Modify a register in the SM501 which may be shared with other
+ * drivers.
+*/
+
+extern unsigned long sm501_modify_reg(struct device *dev,
+                                     unsigned long reg,
+                                     unsigned long set,
+                                     unsigned long clear);
+
+/* sm501_gpio_set
+ *
+ * set the state of the given GPIO line
+*/
+
+extern void sm501_gpio_set(struct device *dev,
+                          unsigned long gpio,
+                          unsigned int to,
+                          unsigned int dir);
+
+/* sm501_gpio_get
+ *
+ * get the state of the given GPIO line
+*/
+
+extern unsigned long sm501_gpio_get(struct device *dev,
+                                   unsigned long gpio);
+
+
+/* Platform data definitions */
+
+#define SM501FB_FLAG_USE_INIT_MODE     (1<<0)
+#define SM501FB_FLAG_DISABLE_AT_EXIT   (1<<1)
+#define SM501FB_FLAG_USE_HWCURSOR      (1<<2)
+#define SM501FB_FLAG_USE_HWACCEL       (1<<3)
+
+struct sm501_platdata_fbsub {
+       struct fb_videomode     *def_mode;
+       unsigned int             def_bpp;
+       unsigned long            max_mem;
+       unsigned int             flags;
+};
+
+enum sm501_fb_routing {
+       SM501_FB_OWN            = 0,    /* CRT=>CRT, Panel=>Panel */
+       SM501_FB_CRT_PANEL      = 1,    /* Panel=>CRT, Panel=>Panel */
+};
+
+/* sm501_platdata_fb flag field bit definitions */
+
+#define SM501_FBPD_SWAP_FB_ENDIAN      (1<<0)  /* need to endian swap */
+
+/* sm501_platdata_fb
+ *
+ * configuration data for the framebuffer driver
+*/
+
+struct sm501_platdata_fb {
+       enum sm501_fb_routing            fb_route;
+       unsigned int                     flags;
+       struct sm501_platdata_fbsub     *fb_crt;
+       struct sm501_platdata_fbsub     *fb_pnl;
+};
+
+/* gpio i2c */
+
+struct sm501_platdata_gpio_i2c {
+       unsigned int            pin_sda;
+       unsigned int            pin_scl;
+};
+
+/* sm501_initdata
+ *
+ * use for initialising values that may not have been setup
+ * before the driver is loaded.
+*/
+
+struct sm501_reg_init {
+       unsigned long           set;
+       unsigned long           mask;
+};
+
+#define SM501_USE_USB_HOST     (1<<0)
+#define SM501_USE_USB_SLAVE    (1<<1)
+#define SM501_USE_SSP0         (1<<2)
+#define SM501_USE_SSP1         (1<<3)
+#define SM501_USE_UART0                (1<<4)
+#define SM501_USE_UART1                (1<<5)
+#define SM501_USE_FBACCEL      (1<<6)
+#define SM501_USE_AC97         (1<<7)
+#define SM501_USE_I2S          (1<<8)
+
+#define SM501_USE_ALL          (0xffffffff)
+
+struct sm501_initdata {
+       struct sm501_reg_init   gpio_low;
+       struct sm501_reg_init   gpio_high;
+       struct sm501_reg_init   misc_timing;
+       struct sm501_reg_init   misc_control;
+
+       unsigned long           devices;
+       unsigned long           mclk;           /* non-zero to modify */
+       unsigned long           m1xclk;         /* non-zero to modify */
+};
+
+/* sm501_init_gpio
+ *
+ * default gpio settings
+*/
+
+struct sm501_init_gpio {
+       struct sm501_reg_init   gpio_data_low;
+       struct sm501_reg_init   gpio_data_high;
+       struct sm501_reg_init   gpio_ddr_low;
+       struct sm501_reg_init   gpio_ddr_high;
+};
+
+/* sm501_platdata
+ *
+ * This is passed with the platform device to allow the board
+ * to control the behaviour of the SM501 driver(s) which attach
+ * to the device.
+ *
+*/
+
+struct sm501_platdata {
+       struct sm501_initdata           *init;
+       struct sm501_init_gpio          *init_gpiop;
+       struct sm501_platdata_fb        *fb;
+
+       struct sm501_platdata_gpio_i2c  *gpio_i2c;
+       unsigned int                     gpio_i2c_nr;
+};
index 28157a36e6ccd69ce4ae091fe835162364813e7c..fcd35a210e7f7d5eed13b7c4e243b4ee3a9c7a50 100644 (file)
@@ -16,7 +16,7 @@ struct __kernel_sockaddr_storage {
                                /* _SS_MAXSIZE value minus size of ss_family */
 } __attribute__ ((aligned(_K_SS_ALIGNSIZE)));  /* force desired alignment */
 
-#ifdef __KERNEL__
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
 
 #include <asm/socket.h>                        /* arch-dependent defines       */
 #include <linux/sockios.h>             /* the SIOCxxx I/O controls     */
index 61fef376ed2e6161299719f8b3a7cfaf4f246b33..a946176db638c7198705a20a7d2fd715279dfc2d 100644 (file)
@@ -282,6 +282,43 @@ do {                                               \
        1 : ({ local_irq_restore(flags); 0; }); \
 })
 
+/*
+ * Locks two spinlocks l1 and l2.
+ * l1_first indicates if spinlock l1 should be taken first.
+ */
+static inline void double_spin_lock(spinlock_t *l1, spinlock_t *l2,
+                                   bool l1_first)
+       __acquires(l1)
+       __acquires(l2)
+{
+       if (l1_first) {
+               spin_lock(l1);
+               spin_lock(l2);
+       } else {
+               spin_lock(l2);
+               spin_lock(l1);
+       }
+}
+
+/*
+ * Unlocks two spinlocks l1 and l2.
+ * l1_taken_first indicates if spinlock l1 was taken first and therefore
+ * should be released after spinlock l2.
+ */
+static inline void double_spin_unlock(spinlock_t *l1, spinlock_t *l2,
+                                     bool l1_taken_first)
+       __releases(l1)
+       __releases(l2)
+{
+       if (l1_taken_first) {
+               spin_unlock(l2);
+               spin_unlock(l1);
+       } else {
+               spin_unlock(l1);
+               spin_unlock(l2);
+       }
+}
+
 /*
  * Pull the atomic_t declaration:
  * (asm-mips/atomic.h needs above definitions)
index 4f8539ccff6cf8addcf9d3561d58d5ba8b518c26..679ef0d70b6b1bae44fb4d9a60af100b1ec2d8fb 100644 (file)
@@ -7,7 +7,7 @@
 
 #endif
 
-#ifdef __KERNEL__
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
 
 #define S_IFMT  00170000
 #define S_IFSOCK 0140000
index de9fc576fa1c8000b56683650a6b250b15a7e5b6..3069ecca0129e9c46bf69223870c0788183ea3b3 100644 (file)
@@ -150,10 +150,10 @@ struct rpc_call_ops {
 #define RPC_TASK_HAS_TIMER     3
 #define RPC_TASK_ACTIVE                4
 
-#define RPC_IS_RUNNING(t)      (test_bit(RPC_TASK_RUNNING, &(t)->tk_runstate))
-#define rpc_set_running(t)     (set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate))
+#define RPC_IS_RUNNING(t)      test_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)
+#define rpc_set_running(t)     set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)
 #define rpc_test_and_set_running(t) \
-                               (test_and_set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate))
+                               test_and_set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)
 #define rpc_clear_running(t)   \
        do { \
                smp_mb__before_clear_bit(); \
@@ -161,8 +161,8 @@ struct rpc_call_ops {
                smp_mb__after_clear_bit(); \
        } while (0)
 
-#define RPC_IS_QUEUED(t)       (test_bit(RPC_TASK_QUEUED, &(t)->tk_runstate))
-#define rpc_set_queued(t)      (set_bit(RPC_TASK_QUEUED, &(t)->tk_runstate))
+#define RPC_IS_QUEUED(t)       test_bit(RPC_TASK_QUEUED, &(t)->tk_runstate)
+#define rpc_set_queued(t)      set_bit(RPC_TASK_QUEUED, &(t)->tk_runstate)
 #define rpc_clear_queued(t)    \
        do { \
                smp_mb__before_clear_bit(); \
@@ -179,7 +179,7 @@ struct rpc_call_ops {
                smp_mb__after_clear_bit(); \
        } while (0)
 
-#define RPC_IS_ACTIVATED(t)    (test_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate))
+#define RPC_IS_ACTIVATED(t)    test_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate)
 
 /*
  * Task priorities.
index 83b3c7b433aa452dae0e1e79028ba29171c1b9c3..35fa4d5aadd06e4685339abe13ff9986535645cf 100644 (file)
@@ -194,9 +194,7 @@ static inline void svc_putu32(struct kvec *iov, __be32 val)
 
 union svc_addr_u {
     struct in_addr     addr;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
     struct in6_addr    addr6;
-#endif
 };
 
 /*
index cccea0a0feb48e83923cc10df72cd1b26133f244..7909687557bf70f29b4bf18f9021061933d72cad 100644 (file)
@@ -66,7 +66,7 @@ struct svc_sock {
  * Function prototypes.
  */
 int            svc_makesock(struct svc_serv *, int, unsigned short, int flags);
-void           svc_close_socket(struct svc_sock *);
+void           svc_force_close_socket(struct svc_sock *);
 int            svc_recv(struct svc_rqst *, long);
 int            svc_send(struct svc_rqst *);
 void           svc_drop(struct svc_rqst *);
index ec639aa3a1d379aa724938933195afd213a7789c..ceb6cc5ceebbee56b69107daad587c512987794f 100644 (file)
@@ -108,7 +108,10 @@ extern void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd,
 #else
 
 #define make_migration_entry(page, write) swp_entry(0, 0)
-#define is_migration_entry(swp) 0
+static inline int is_migration_entry(swp_entry_t swp)
+{
+       return 0;
+}
 #define migration_entry_to_page(swp) NULL
 static inline void make_migration_entry_read(swp_entry_t *entryp) { }
 static inline void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd,
index 192de3afa96ba9244a5e69e98f0e66b17fc6df66..523405e1e1f6463a5f8aa925655d97234adaefae 100644 (file)
@@ -17,6 +17,7 @@
 struct kobject;
 struct module;
 struct nameidata;
+struct dentry;
 
 struct attribute {
        const char              * name;
@@ -68,18 +69,6 @@ struct sysfs_ops {
        ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);
 };
 
-struct sysfs_dirent {
-       atomic_t                s_count;
-       struct list_head        s_sibling;
-       struct list_head        s_children;
-       void                    * s_element;
-       int                     s_type;
-       umode_t                 s_mode;
-       struct dentry           * s_dentry;
-       struct iattr            * s_iattr;
-       atomic_t                s_event;
-};
-
 #define SYSFS_ROOT             0x0001
 #define SYSFS_DIR              0x0002
 #define SYSFS_KOBJ_ATTR        0x0004
@@ -126,6 +115,11 @@ void sysfs_remove_bin_file(struct kobject *kobj, struct bin_attribute *attr);
 int __must_check sysfs_create_group(struct kobject *,
                                        const struct attribute_group *);
 void sysfs_remove_group(struct kobject *, const struct attribute_group *);
+int sysfs_add_file_to_group(struct kobject *kobj,
+               const struct attribute *attr, const char *group);
+void sysfs_remove_file_from_group(struct kobject *kobj,
+               const struct attribute *attr, const char *group);
+
 void sysfs_notify(struct kobject * k, char *dir, char *attr);
 
 
@@ -210,6 +204,17 @@ static inline void sysfs_remove_group(struct kobject * k, const struct attribute
        ;
 }
 
+static inline int sysfs_add_file_to_group(struct kobject *kobj,
+               const struct attribute *attr, const char *group)
+{
+       return 0;
+}
+
+static inline void sysfs_remove_file_from_group(struct kobject *kobj,
+               const struct attribute *attr, const char *group)
+{
+}
+
 static inline void sysfs_notify(struct kobject * k, char *dir, char *attr)
 {
 }
index 6c5a6e6e813bcb4529a5ef84e23dc5c5370c2950..a9d1f049cc151aa07202ffbc41346dc78a95d4b3 100644 (file)
@@ -96,7 +96,6 @@
        .busy_factor            = 64,                   \
        .imbalance_pct          = 110,                  \
        .cache_nice_tries       = 0,                    \
-       .per_cpu_gain           = 25,                   \
        .busy_idx               = 0,                    \
        .idle_idx               = 0,                    \
        .newidle_idx            = 1,                    \
        .busy_factor            = 64,                   \
        .imbalance_pct          = 125,                  \
        .cache_nice_tries       = 1,                    \
-       .per_cpu_gain           = 100,                  \
        .busy_idx               = 2,                    \
        .idle_idx               = 1,                    \
        .newidle_idx            = 2,                    \
        .busy_factor            = 64,                   \
        .imbalance_pct          = 125,                  \
        .cache_nice_tries       = 1,                    \
-       .per_cpu_gain           = 100,                  \
        .busy_idx               = 2,                    \
        .idle_idx               = 1,                    \
        .newidle_idx            = 2,                    \
        .newidle_idx            = 0, /* unused */       \
        .wake_idx               = 0, /* unused */       \
        .forkexec_idx           = 0, /* unused */       \
-       .per_cpu_gain           = 100,                  \
        .flags                  = SD_LOAD_BALANCE       \
                                | SD_SERIALIZE, \
        .last_balance           = jiffies,              \
index a8e8d1ecebb17b4bbcd6e36c93d18947e78624b1..87dc75a6cee14e00a755cc49f9dd50e567373e19 100644 (file)
@@ -388,10 +388,14 @@ struct usb_device {
        struct usb_device *children[USB_MAXCHILDREN];
 
        int pm_usage_cnt;               /* usage counter for autosuspend */
+       u32 quirks;                     /* quirks of the whole device */
+
 #ifdef CONFIG_PM
        struct delayed_work autosuspend; /* for delayed autosuspends */
        struct mutex pm_mutex;          /* protects PM operations */
 
+       unsigned autosuspend_delay;     /* in jiffies */
+
        unsigned auto_pm:1;             /* autosuspend/resume in progress */
        unsigned do_remote_wakeup:1;    /* remote wakeup should be enabled */
 #endif
index 245c72531228346982598506248d68fa03d16461..1122a6c2c1a3dc3759c1dee7ef6988f24240dee3 100644 (file)
@@ -1,8 +1,9 @@
 /*
- * This file holds USB constants and structures that are needed for USB
- * device APIs.  These are used by the USB device model, which is defined
- * in chapter 9 of the USB 2.0 specification.  Linux has several APIs in C
- * that need these:
+ * This file holds USB constants and structures that are needed for
+ * USB device APIs.  These are used by the USB device model, which is
+ * defined in chapter 9 of the USB 2.0 specification and in the
+ * Wireless USB 1.0 (spread around).  Linux has several APIs in C that
+ * need these:
  *
  * - the master/host side Linux-USB kernel driver API;
  * - the "usbfs" user space API; and
  *
  * There's also "Wireless USB", using low power short range radios for
  * peripheral interconnection but otherwise building on the USB framework.
+ *
+ * Note all descriptors are declared '__attribute__((packed))' so that:
+ *
+ * [a] they never get padded, either internally (USB spec writers
+ *     probably handled that) or externally;
+ *
+ * [b] so that accessing bigger-than-a-bytes fields will never
+ *     generate bus errors on any platform, even when the location of
+ *     its descriptor inside a bundle isn't "naturally aligned", and
+ *
+ * [c] for consistency, removing all doubt even when it appears to
+ *     someone that the two other points are non-issues for that
+ *     particular descriptor type.
  */
 
 #ifndef __LINUX_USB_CH9_H
diff --git a/include/linux/usb/iowarrior.h b/include/linux/usb/iowarrior.h
new file mode 100644 (file)
index 0000000..cbbe020
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef _IOWARRIOR_H_
+#define _IOWARRIOR_H_
+
+#define CODEMERCS_MAGIC_NUMBER 0xC0    /* like COde Mercenaries */
+
+/* Define the ioctl commands for reading and writing data */
+#define IOW_WRITE      _IOW(CODEMERCS_MAGIC_NUMBER, 1, __u8 *)
+#define IOW_READ       _IOW(CODEMERCS_MAGIC_NUMBER, 2, __u8 *)
+
+/*
+   A struct for available device info which is read
+   with the ioctl IOW_GETINFO.
+   To be compatible with 2.4 userspace which didn't have an easy way to get
+   this information.
+*/
+struct iowarrior_info {
+       __u32 vendor;           /* vendor id : supposed to be USB_VENDOR_ID_CODEMERCS in all cases */
+       __u32 product;          /* product id : depends on type of chip (USB_DEVICE_ID_CODEMERCS_XXXXX) */
+       __u8 serial[9];         /* the serial number of our chip (if a serial-number is not available this is empty string) */
+       __u32 revision;         /* revision number of the chip */
+       __u32 speed;            /* USB-speed of the device (0=UNKNOWN, 1=LOW, 2=FULL 3=HIGH) */
+       __u32 power;            /* power consumption of the device in mA */
+       __u32 if_num;           /* the number of the endpoint */
+       __u32 report_size;      /* size of the data-packets on this interface */
+};
+
+/*
+  Get some device-information (product-id , serial-number etc.)
+  in order to identify a chip.
+*/
+#define IOW_GETINFO _IOR(CODEMERCS_MAGIC_NUMBER, 3, struct iowarrior_info)
+
+#endif  /* _IOWARRIOR_H_ */
diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h
new file mode 100644 (file)
index 0000000..6bac8fa
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * This file holds the definitions of quirks found in USB devices.
+ * Only quirks that affect the whole device, not an interface,
+ * belong here.
+ */
+
+/* device must not be autosuspended */
+#define USB_QUIRK_NO_AUTOSUSPEND       0x00000001
+
+/* string descriptors must not be fetched using a 255-byte read */
+#define USB_QUIRK_STRING_FETCH_255     0x00000002
index d94e2683be52a623d9947e8aed54e570cff47c44..441b877bf150ef84d467f89b318945dd0c622f88 100644 (file)
@@ -1,5 +1,45 @@
 /*
- *     Video for Linux Two
+ *  Video for Linux Two header file
+ *
+ *  Copyright (C) 1999-2007 the contributors
+ *
+ *  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.
+ *
+ *  Alternatively you can redistribute this file under the terms of the
+ *  BSD license as stated below:
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. 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.
+ *  3. The names of its contributors may not be used to endorse or promote
+ *     products derived from this software without specific prior written
+ *     permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS 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.
  *
  *     Header file for v4l or V4L2 drivers and applications
  * with public API.
@@ -8,8 +48,9 @@
  *
  *     See http://linuxtv.org for more info
  *
- *     Author: Bill Dirks <bdirks@pacbell.net>
+ *     Author: Bill Dirks <bill@thedirks.org>
  *             Justin Schoeman
+ *              Hans Verkuil <hverkuil@xs4all.nl>
  *             et al.
  */
 #ifndef __LINUX_VIDEODEV2_H
@@ -90,11 +131,8 @@ enum v4l2_buf_type {
        V4L2_BUF_TYPE_VIDEO_OVERLAY      = 3,
        V4L2_BUF_TYPE_VBI_CAPTURE        = 4,
        V4L2_BUF_TYPE_VBI_OUTPUT         = 5,
-#if 1
-       /* Experimental Sliced VBI */
        V4L2_BUF_TYPE_SLICED_VBI_CAPTURE = 6,
        V4L2_BUF_TYPE_SLICED_VBI_OUTPUT  = 7,
-#endif
        V4L2_BUF_TYPE_PRIVATE            = 0x80,
 };
 
@@ -186,10 +224,8 @@ struct v4l2_capability
 #define V4L2_CAP_VIDEO_OVERLAY         0x00000004  /* Can do video overlay */
 #define V4L2_CAP_VBI_CAPTURE           0x00000010  /* Is a raw VBI capture device */
 #define V4L2_CAP_VBI_OUTPUT            0x00000020  /* Is a raw VBI output device */
-#if 1
 #define V4L2_CAP_SLICED_VBI_CAPTURE    0x00000040  /* Is a sliced VBI capture device */
 #define V4L2_CAP_SLICED_VBI_OUTPUT     0x00000080  /* Is a sliced VBI output device */
-#endif
 #define V4L2_CAP_RDS_CAPTURE           0x00000100  /* RDS data capture */
 
 #define V4L2_CAP_TUNER                 0x00010000  /* has a tuner */
@@ -1156,6 +1192,55 @@ struct v4l2_audioout
        __u32   reserved[2];
 };
 
+/*
+ *     M P E G   S E R V I C E S
+ *
+ *     NOTE: EXPERIMENTAL API
+ */
+#if 1
+#define V4L2_ENC_IDX_FRAME_I    (0)
+#define V4L2_ENC_IDX_FRAME_P    (1)
+#define V4L2_ENC_IDX_FRAME_B    (2)
+#define V4L2_ENC_IDX_FRAME_MASK (0xf)
+
+struct v4l2_enc_idx_entry {
+       __u64 offset;
+       __u64 pts;
+       __u32 length;
+       __u32 flags;
+       __u32 reserved[2];
+};
+
+#define V4L2_ENC_IDX_ENTRIES (64)
+struct v4l2_enc_idx {
+       __u32 entries;
+       __u32 entries_cap;
+       __u32 reserved[4];
+       struct v4l2_enc_idx_entry entry[V4L2_ENC_IDX_ENTRIES];
+};
+
+
+#define V4L2_ENC_CMD_START      (0)
+#define V4L2_ENC_CMD_STOP       (1)
+#define V4L2_ENC_CMD_PAUSE      (2)
+#define V4L2_ENC_CMD_RESUME     (3)
+
+/* Flags for V4L2_ENC_CMD_STOP */
+#define V4L2_ENC_CMD_STOP_AT_GOP_END    (1 << 0)
+
+struct v4l2_encoder_cmd {
+       __u32 cmd;
+       __u32 flags;
+       union {
+               struct {
+                       __u32 data[8];
+               } raw;
+       };
+};
+
+#endif
+
+
 /*
  *     D A T A   S E R V I C E S   ( V B I )
  *
@@ -1179,7 +1264,6 @@ struct v4l2_vbi_format
 #define V4L2_VBI_UNSYNC                (1<< 0)
 #define V4L2_VBI_INTERLACED    (1<< 1)
 
-#if 1
 /* Sliced VBI
  *
  *    This implements is a proposal V4L2 API to allow SLICED VBI
@@ -1212,7 +1296,6 @@ struct v4l2_sliced_vbi_format
 #define V4L2_SLICED_VBI_525             (V4L2_SLICED_CAPTION_525)
 #define V4L2_SLICED_VBI_625             (V4L2_SLICED_TELETEXT_B | V4L2_SLICED_VPS | V4L2_SLICED_WSS_625)
 
-
 struct v4l2_sliced_vbi_cap
 {
        __u16   service_set;
@@ -1233,7 +1316,6 @@ struct v4l2_sliced_vbi_data
        __u32   reserved;       /* must be 0 */
        __u8    data[48];
 };
-#endif
 
 /*
  *     A G G R E G A T E   S T R U C T U R E S
@@ -1249,9 +1331,7 @@ struct v4l2_format
                struct v4l2_pix_format          pix;     // V4L2_BUF_TYPE_VIDEO_CAPTURE
                struct v4l2_window              win;     // V4L2_BUF_TYPE_VIDEO_OVERLAY
                struct v4l2_vbi_format          vbi;     // V4L2_BUF_TYPE_VBI_CAPTURE
-#if 1
                struct v4l2_sliced_vbi_format   sliced;  // V4L2_BUF_TYPE_SLICED_VBI_CAPTURE
-#endif
                __u8    raw_data[200];                   // user-defined
        } fmt;
 };
@@ -1270,6 +1350,25 @@ struct v4l2_streamparm
        } parm;
 };
 
+/*
+ *     A D V A N C E D   D E B U G G I N G
+ *
+ *     NOTE: EXPERIMENTAL API
+ */
+
+/* VIDIOC_DBG_G_REGISTER and VIDIOC_DBG_S_REGISTER */
+
+#define V4L2_CHIP_MATCH_HOST       0  /* Match against chip ID on host (0 for the host) */
+#define V4L2_CHIP_MATCH_I2C_DRIVER 1  /* Match against I2C driver ID */
+#define V4L2_CHIP_MATCH_I2C_ADDR   2  /* Match against I2C 7-bit address */
+
+struct v4l2_register {
+       __u32 match_type; /* Match type */
+       __u32 match_chip; /* Match this chip, meaning determined by match_type */
+       __u64 reg;
+       __u64 val;
+};
+
 /*
  *     I O C T L   C O D E S   F O R   V I D E O   D E V I C E S
  *
@@ -1328,9 +1427,7 @@ struct v4l2_streamparm
 #define VIDIOC_ENUMAUDOUT      _IOWR ('V', 66, struct v4l2_audioout)
 #define VIDIOC_G_PRIORITY       _IOR  ('V', 67, enum v4l2_priority)
 #define VIDIOC_S_PRIORITY       _IOW  ('V', 68, enum v4l2_priority)
-#if 1
 #define VIDIOC_G_SLICED_VBI_CAP _IOWR ('V', 69, struct v4l2_sliced_vbi_cap)
-#endif
 #define VIDIOC_LOG_STATUS       _IO   ('V', 70)
 #define VIDIOC_G_EXT_CTRLS     _IOWR ('V', 71, struct v4l2_ext_controls)
 #define VIDIOC_S_EXT_CTRLS     _IOWR ('V', 72, struct v4l2_ext_controls)
@@ -1338,6 +1435,13 @@ struct v4l2_streamparm
 #if 1
 #define VIDIOC_ENUM_FRAMESIZES _IOWR ('V', 74, struct v4l2_frmsizeenum)
 #define VIDIOC_ENUM_FRAMEINTERVALS     _IOWR ('V', 75, struct v4l2_frmivalenum)
+#define VIDIOC_G_ENC_INDEX      _IOR  ('V', 76, struct v4l2_enc_idx)
+#define VIDIOC_ENCODER_CMD      _IOWR ('V', 77, struct v4l2_encoder_cmd)
+#define VIDIOC_TRY_ENCODER_CMD  _IOWR ('V', 78, struct v4l2_encoder_cmd)
+
+/* Experimental, only implemented if CONFIG_VIDEO_ADV_DEBUG is defined */
+#define        VIDIOC_DBG_S_REGISTER   _IOW  ('V', 79, struct v4l2_register)
+#define        VIDIOC_DBG_G_REGISTER   _IOWR ('V', 80, struct v4l2_register)
 #endif
 
 #ifdef __OLD_VIDIOC_
index 7c269f4992eb1e599637b2df95d35ac252c71a26..447c52beb69127c36df67e0a3b4027f8074d32f0 100644 (file)
  * separate range because of collisions with other tools such as
  * 'mii-tool'.
  * We now have 32 commands, so a bit more space ;-).
- * Also, all 'odd' commands are only usable by root and don't return the
+ * Also, all 'even' commands are only usable by root and don't return the
  * content of ifr/iwr to user (but you are not obliged to use the set/get
  * convention, just use every other two command). More details in iwpriv.c.
  * And I repeat : you are not forced to use them with iwpriv, but you
 #define SIOCIWLAST     SIOCIWLASTPRIV          /* 0x8BFF */
 #define IW_IOCTL_IDX(cmd)      ((cmd) - SIOCIWFIRST)
 
-/* Even : get (world access), odd : set (root access) */
+/* Odd : get (world access), even : set (root access) */
 #define IW_IS_SET(cmd) (!((cmd) & 0x1))
 #define IW_IS_GET(cmd) ((cmd) & 0x1)
 
index fc35e6bdfb93e4bf4d5cac5b50c983e97e846c5a..0c78f7f4a976489064d2508d6e56ae610bf84311 100644 (file)
@@ -84,7 +84,7 @@ static inline void wait_on_inode(struct inode *inode)
 int wakeup_pdflush(long nr_pages);
 void laptop_io_completion(void);
 void laptop_sync_completion(void);
-void throttle_vm_writeout(void);
+void throttle_vm_writeout(gfp_t gfp_mask);
 
 /* These are exported to sysctl. */
 extern int dirty_background_ratio;
index ecad55bf0162ca408fa51d169a3c2e4ad829c31a..d758a52cf55659b8b4fdb072f126622d52bd6435 100644 (file)
@@ -57,7 +57,6 @@ struct cx2341x_mpeg_params {
        u16 video_b_frames;
        u16 video_gop_size;
        u16 video_gop_closure;
-       u16 video_pulldown;
        enum v4l2_mpeg_video_bitrate_mode video_bitrate_mode;
        u32 video_bitrate;
        u32 video_bitrate_peak;
@@ -121,8 +120,6 @@ void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix);
 #define CX2341X_DEC_SET_DISPLAY_BUFFERS                0x18
 #define CX2341X_DEC_EXTRACT_VBI                0x19
 #define CX2341X_DEC_SET_DECODER_SOURCE                 0x1a
-#define CX2341X_DEC_SET_AUDIO_OUTPUT           0x1b
-#define CX2341X_DEC_SET_AV_DELAY               0x1c
 #define CX2341X_DEC_SET_PREBUFFERING           0x1e
 
 /* MPEG encoder API */
@@ -141,7 +138,6 @@ void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix);
 #define CX2341X_ENC_SET_DNR_FILTER_PROPS       0x9d
 #define CX2341X_ENC_SET_CORING_LEVELS          0x9f
 #define CX2341X_ENC_SET_SPATIAL_FILTER_TYPE    0xa1
-#define CX2341X_ENC_SET_3_2_PULLDOWN           0xb1
 #define CX2341X_ENC_SET_VBI_LINE               0xb7
 #define CX2341X_ENC_SET_STREAM_TYPE            0xb9
 #define CX2341X_ENC_SET_OUTPUT_PORT            0xbb
index 4bb0ad81017903dc9e01f76d9ab49de6625317ee..9807a7c158300253df641b92af06afc7680fe551 100644 (file)
 #define IR_KEYCODE(tab,code)   (((unsigned)code < IR_KEYTAB_SIZE) \
                                 ? tab[code] : KEY_RESERVED)
 
+#define RC5_START(x)   (((x)>>12)&3)
+#define RC5_TOGGLE(x)  (((x)>>11)&1)
+#define RC5_ADDR(x)    (((x)>>6)&31)
+#define RC5_INSTR(x)   ((x)&63)
+
 struct ir_input_state {
        /* configuration */
        int                ir_type;
@@ -48,6 +53,40 @@ struct ir_input_state {
        int                keypressed;  /* current state */
 };
 
+/* this was saa7134_ir and bttv_ir, moved here for
+ * rc5 decoding. */
+struct card_ir {
+       struct input_dev        *dev;
+       struct ir_input_state   ir;
+       char                    name[32];
+       char                    phys[32];
+
+       /* Usual gpio signalling */
+
+       u32                     mask_keycode;
+       u32                     mask_keydown;
+       u32                     mask_keyup;
+       u32                     polling;
+       u32                     last_gpio;
+       int                     shift_by;
+       int                     start; // What should RC5_START() be
+       int                     addr; // What RC5_ADDR() should be.
+       int                     rc5_key_timeout;
+       int                     rc5_remote_gap;
+       struct work_struct      work;
+       struct timer_list       timer;
+
+       /* RC5 gpio */
+       u32 rc5_gpio;
+       struct timer_list timer_end;    /* timer_end for code completion */
+       struct timer_list timer_keyup;  /* timer_end for key release */
+       u32 last_rc5;                   /* last good rc5 code */
+       u32 last_bit;                   /* last raw bit seen */
+       u32 code;                       /* raw code under construction */
+       struct timeval base_time;       /* time of last seen code */
+       int active;                     /* building raw code */
+};
+
 void ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
                   int ir_type, IR_KEYTAB_TYPE *ir_codes);
 void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir);
@@ -58,6 +97,10 @@ int  ir_dump_samples(u32 *samples, int count);
 int  ir_decode_biphase(u32 *samples, int count, int low, int high);
 int  ir_decode_pulsedistance(u32 *samples, int count, int low, int high);
 
+u32 ir_rc5_decode(unsigned int code);
+void ir_rc5_timer_end(unsigned long data);
+void ir_rc5_timer_keyup(unsigned long data);
+
 /* Keymaps to be used by other modules */
 
 extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE];
@@ -94,6 +137,9 @@ extern IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_asus_pc39[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE];
 
 #endif
 
index 9f0e2285a099f0c63765477ea417670ac827abad..f677dfb9d373d7f87364ae8fd0b6d881c78bc8d3 100644 (file)
@@ -42,5 +42,8 @@
 #define SAA7115_FREQ_FL_CGCDIV (1 << 1)           /* SA 3A[6], CGCDIV, SAA7115 only */
 #define SAA7115_FREQ_FL_APLL   (1 << 2)           /* SA 3A[3], APLL, SAA7114/5 only */
 
+#define SAA7115_IPORT_ON    1
+#define SAA7115_IPORT_OFF   0
+
 #endif
 
index 91b19921f958af283e5fc78521847c5b7785ca3c..6eaeec98ed8908fc819193a7226002a4218e5ac4 100644 (file)
@@ -64,9 +64,6 @@
 /* Prints the ioctl in a human-readable format */
 extern void v4l_printk_ioctl(unsigned int cmd);
 
-/* Prints the ioctl and arg in a human-readable format */
-extern void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg);
-
 /* Use this macro for non-I2C drivers. Pass the driver name as the first arg. */
 #define v4l_print_ioctl(name, cmd)              \
        do {                                     \
@@ -97,14 +94,15 @@ u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id);
 
 /* ------------------------------------------------------------------------- */
 
-/* Internal ioctls */
+/* Register/chip ident helper function */
 
-/* VIDIOC_INT_G_REGISTER and VIDIOC_INT_S_REGISTER */
-struct v4l2_register {
-       u32 i2c_id;             /* I2C driver ID of the I2C chip. 0 for the I2C adapter. */
-       unsigned long reg;
-       u32 val;
-};
+struct i2c_client; /* forward reference */
+int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 id_type, u32 chip_id);
+int v4l2_chip_match_host(u32 id_type, u32 chip_id);
+
+/* ------------------------------------------------------------------------- */
+
+/* Internal ioctls */
 
 /* VIDIOC_INT_DECODE_VBI_LINE */
 struct v4l2_decode_vbi_line {
@@ -175,9 +173,7 @@ enum v4l2_chip_ident {
    Replacement of TUNER_SET_STANDBY. */
 #define VIDIOC_INT_S_STANDBY        _IOW('d', 94, u32)
 
-/* only implemented if CONFIG_VIDEO_ADV_DEBUG is defined */
-#define        VIDIOC_INT_S_REGISTER           _IOW ('d', 100, struct v4l2_register)
-#define        VIDIOC_INT_G_REGISTER           _IOWR('d', 101, struct v4l2_register)
+/* 100, 101 used by  VIDIOC_DBG_[SG]_REGISTER */
 
 /* Generic reset command. The argument selects which subsystems to reset.
    Passing 0 will always reset the whole chip. */
index fb96472a1bd38423c4a3ac0790fb14b78064a28e..1dd3d3239ecf56869e60fe6bf0fa414b8b0efecc 100644 (file)
@@ -271,6 +271,12 @@ struct video_device
                                        struct v4l2_jpegcompression *a);
        int (*vidioc_s_jpegcomp)       (struct file *file, void *fh,
                                        struct v4l2_jpegcompression *a);
+       int (*vidioc_g_enc_index)      (struct file *file, void *fh,
+                                       struct v4l2_enc_idx *a);
+       int (*vidioc_encoder_cmd)      (struct file *file, void *fh,
+                                       struct v4l2_encoder_cmd *a);
+       int (*vidioc_try_encoder_cmd)  (struct file *file, void *fh,
+                                       struct v4l2_encoder_cmd *a);
 
        /* Stream type-dependent parameter ioctls */
        int (*vidioc_g_parm)           (struct file *file, void *fh,
@@ -296,6 +302,15 @@ struct video_device
        int (*vidioc_log_status)       (struct file *file, void *fh);
 
 
+       /* Debugging ioctls */
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       int (*vidioc_g_register)       (struct file *file, void *fh,
+                                       struct v4l2_register *reg);
+       int (*vidioc_s_register)       (struct file *file, void *fh,
+                                       struct v4l2_register *reg);
+#endif
+
+
 #ifdef OBSOLETE_OWNER /* to be removed soon */
 /* obsolete -- fops->owner is used instead */
 struct module *owner;
index 1115a256969f0468e6ec079567aa6d32e6c338d5..d6f079476db34dc7b020177205b04a53a483deb1 100644 (file)
@@ -78,6 +78,9 @@ struct videobuf_dmabuf {
        /* for kernel buffers */
        void                *vmalloc;
 
+       /* Stores the userspace pointer to vmalloc area */
+       void                *varea;
+
        /* for overlay buffers (pci-pci dma) */
        dma_addr_t          bus_addr;
 
index f7be1ac736016e404f30e462b80aa6f42c35e922..09a2532699b236c0eb7f2af11ba5da7b6c93a709 100644 (file)
@@ -66,7 +66,7 @@ struct inet_hashinfo;
 struct inet_timewait_death_row {
        /* Short-time timewait calendar */
        int                     twcal_hand;
-       int                     twcal_jiffie;
+       unsigned long           twcal_jiffie;
        struct timer_list       twcal_timer;
        struct hlist_head       twcal_row[INET_TWDR_RECYCLE_SLOTS];
 
index 1cb0607fcbb948930d0d395c13d86a0aa2b8db2a..89fe534045f1c61f8cd6c3bad1e7905911f57d7e 100644 (file)
@@ -113,4 +113,20 @@ do { if(!(expr)) { \
 #define IAS_IRCOMM_ID 0x2343
 #define IAS_IRLPT_ID  0x9876
 
+struct net_device;
+struct packet_type;
+
+extern void irda_proc_register(void);
+extern void irda_proc_unregister(void);
+
+extern int irda_sysctl_register(void);
+extern void irda_sysctl_unregister(void);
+
+extern int irsock_init(void);
+extern void irsock_cleanup(void);
+
+extern int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
+                           struct packet_type *ptype,
+                           struct net_device *orig_dev);
+
 #endif /* NET_IRDA_H */
index 7fdc72c01356cf69a6d6b3a907838c47ccc2bb4e..85634e1865c31dca6356397e093698f18a9fd7fd 100644 (file)
@@ -64,7 +64,7 @@ static inline int nf_conntrack_confirm(struct sk_buff **pskb)
        int ret = NF_ACCEPT;
 
        if (ct) {
-               if (!nf_ct_is_confirmed(ct))
+               if (!nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct))
                        ret = __nf_conntrack_confirm(pskb);
                nf_ct_deliver_cached_events(ct);
        }
index 03684e702d13464cbc0a48b95354dc540341f504..2c7d60ca354858ac75ead88773d0886aedcc185c 100644 (file)
@@ -1278,7 +1278,7 @@ static inline int sock_writeable(const struct sock *sk)
 
 static inline gfp_t gfp_any(void)
 {
-       return in_softirq() ? GFP_ATOMIC : GFP_KERNEL;
+       return in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
 }
 
 static inline long sock_rcvtimeo(const struct sock *sk, int noblock)
index 92a1fc46ea593c6cfb2f0529568c4aa2e83a7c48..5a00aa85b756fe46a3297ace099e8520012f1d7a 100644 (file)
@@ -988,8 +988,9 @@ extern int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int,
 int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
 struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
                                          struct xfrm_selector *sel,
-                                         struct xfrm_sec_ctx *ctx, int delete);
-struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete);
+                                         struct xfrm_sec_ctx *ctx, int delete,
+                                         int *err);
+struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete, int *err);
 void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
 u32 xfrm_get_acqseq(void);
 void xfrm_alloc_spi(struct xfrm_state *x, __be32 minspi, __be32 maxspi);
index a9ba7ee699394aff8e3363d1bff2b10acf0d7bf7..5f7275000102f47ede042bc0b2a0c660ef4ddaf8 100644 (file)
@@ -1,3 +1,3 @@
 /* include/version.h.  Generated by alsa/ksync script.  */
-#define CONFIG_SND_VERSION "1.0.14rc2"
-#define CONFIG_SND_DATE " (Wed Feb 14 07:42:13 2007 UTC)"
+#define CONFIG_SND_VERSION "1.0.14rc3"
+#define CONFIG_SND_DATE " (Tue Mar 06 13:10:00 2007 UTC)"
index f977086e118a9ee936a4fd77e3cb5490857b7624..b170aa1d43bd127c75b7380237e18bbb2f1c3f2e 100644 (file)
@@ -304,6 +304,22 @@ config RELAY
 
          If unsure, say N.
 
+config BLK_DEV_INITRD
+       bool "Initial RAM filesystem and RAM disk (initramfs/initrd) support"
+       depends on BROKEN || !FRV
+       help
+         The initial RAM filesystem is a ramfs which is loaded by the
+         boot loader (loadlin or lilo) and that is mounted as root
+         before the normal boot procedure. It is typically used to
+         load modules needed to mount the "real" root file system,
+         etc. See <file:Documentation/initrd.txt> for details.
+
+         If RAM disk support (BLK_DEV_RAM) is also included, this
+         also enables initial RAM disk (initrd) support and adds
+         15 Kbytes (more on some other architectures) to the kernel size.
+
+         If unsure say Y.
+
 if BLK_DEV_INITRD
 
 source "usr/Kconfig"
index 1c5f6dce1bd2d062ab780a99b8417d9ceb7813b0..a92989e7836af6acb73bb6ce8b95ad76ee727f53 100644 (file)
@@ -387,14 +387,19 @@ static void __init setup_per_cpu_areas(void)
 /* Called by boot processor to activate the rest. */
 static void __init smp_init(void)
 {
-       unsigned int i;
+       unsigned int cpu;
+       unsigned highest = 0;
+
+       for_each_cpu_mask(cpu, cpu_possible_map)
+               highest = cpu;
+       nr_cpu_ids = highest + 1;
 
        /* FIXME: This should be done in userspace --RR */
-       for_each_present_cpu(i) {
+       for_each_present_cpu(cpu) {
                if (num_online_cpus() >= max_cpus)
                        break;
-               if (!cpu_online(i))
-                       cpu_up(i);
+               if (!cpu_online(cpu))
+                       cpu_up(cpu);
        }
 
        /* Any cleanup work */
index 0b5ecbe5f0456c121f2af016292fb0123f4bf4cd..554ac368be7945de13149bef0abdd0c1bb2cf7c9 100644 (file)
@@ -731,7 +731,8 @@ asmlinkage long sys_mq_unlink(const char __user *u_name)
        if (IS_ERR(name))
                return PTR_ERR(name);
 
-       mutex_lock(&mqueue_mnt->mnt_root->d_inode->i_mutex);
+       mutex_lock_nested(&mqueue_mnt->mnt_root->d_inode->i_mutex,
+                       I_MUTEX_PARENT);
        dentry = lookup_one_len(name, mqueue_mnt->mnt_root, strlen(name));
        if (IS_ERR(dentry)) {
                err = PTR_ERR(dentry);
index 5bb617f6306e8df814398505393b15e2b0c3c0ee..4fefbad7096d539d90345621ac6419d2ab904b85 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
 #include <linux/seq_file.h>
 #include <linux/mutex.h>
 #include <linux/nsproxy.h>
+#include <linux/mount.h>
 
 #include <asm/uaccess.h>
 
 #include "util.h"
 
+struct shm_file_data {
+       int id;
+       struct ipc_namespace *ns;
+       struct file *file;
+       const struct vm_operations_struct *vm_ops;
+};
+
+#define shm_file_data(file) (*((struct shm_file_data **)&(file)->private_data))
+
 static const struct file_operations shm_file_operations;
 static struct vm_operations_struct shm_vm_ops;
 
@@ -60,8 +70,8 @@ static struct ipc_ids init_shm_ids;
 
 static int newseg (struct ipc_namespace *ns, key_t key,
                int shmflg, size_t size);
-static void shm_open (struct vm_area_struct *shmd);
-static void shm_close (struct vm_area_struct *shmd);
+static void shm_open(struct vm_area_struct *vma);
+static void shm_close(struct vm_area_struct *vma);
 static void shm_destroy (struct ipc_namespace *ns, struct shmid_kernel *shp);
 #ifdef CONFIG_PROC_FS
 static int sysvipc_shm_proc_show(struct seq_file *s, void *it);
@@ -150,11 +160,14 @@ static inline int shm_addid(struct ipc_namespace *ns, struct shmid_kernel *shp)
 
 
 
-static inline void shm_inc(struct ipc_namespace *ns, int id)
+/* This is called by fork, once for every shm attach. */
+static void shm_open(struct vm_area_struct *vma)
 {
+       struct file *file = vma->vm_file;
+       struct shm_file_data *sfd = shm_file_data(file);
        struct shmid_kernel *shp;
 
-       shp = shm_lock(ns, id);
+       shp = shm_lock(sfd->ns, sfd->id);
        BUG_ON(!shp);
        shp->shm_atim = get_seconds();
        shp->shm_lprid = current->tgid;
@@ -162,15 +175,6 @@ static inline void shm_inc(struct ipc_namespace *ns, int id)
        shm_unlock(shp);
 }
 
-#define shm_file_ns(file) (*((struct ipc_namespace **)&(file)->private_data))
-
-/* This is called by fork, once for every shm attach. */
-static void shm_open(struct vm_area_struct *shmd)
-{
-       shm_inc(shm_file_ns(shmd->vm_file),
-                       shmd->vm_file->f_path.dentry->d_inode->i_ino);
-}
-
 /*
  * shm_destroy - free the struct shmid_kernel
  *
@@ -195,23 +199,21 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
 }
 
 /*
- * remove the attach descriptor shmd.
+ * remove the attach descriptor vma.
  * free memory for segment if it is marked destroyed.
  * The descriptor has already been removed from the current->mm->mmap list
  * and will later be kfree()d.
  */
-static void shm_close (struct vm_area_struct *shmd)
+static void shm_close(struct vm_area_struct *vma)
 {
-       struct file * file = shmd->vm_file;
-       int id = file->f_path.dentry->d_inode->i_ino;
+       struct file * file = vma->vm_file;
+       struct shm_file_data *sfd = shm_file_data(file);
        struct shmid_kernel *shp;
-       struct ipc_namespace *ns;
-
-       ns = shm_file_ns(file);
+       struct ipc_namespace *ns = sfd->ns;
 
        mutex_lock(&shm_ids(ns).mutex);
        /* remove from the list of attaches of the shm segment */
-       shp = shm_lock(ns, id);
+       shp = shm_lock(ns, sfd->id);
        BUG_ON(!shp);
        shp->shm_lprid = current->tgid;
        shp->shm_dtim = get_seconds();
@@ -224,46 +226,111 @@ static void shm_close (struct vm_area_struct *shmd)
        mutex_unlock(&shm_ids(ns).mutex);
 }
 
+static struct page *shm_nopage(struct vm_area_struct *vma,
+                              unsigned long address, int *type)
+{
+       struct file *file = vma->vm_file;
+       struct shm_file_data *sfd = shm_file_data(file);
+
+       return sfd->vm_ops->nopage(vma, address, type);
+}
+
+#ifdef CONFIG_NUMA
+int shm_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
+{
+       struct file *file = vma->vm_file;
+       struct shm_file_data *sfd = shm_file_data(file);
+       int err = 0;
+       if (sfd->vm_ops->set_policy)
+               err = sfd->vm_ops->set_policy(vma, new);
+       return err;
+}
+
+struct mempolicy *shm_get_policy(struct vm_area_struct *vma, unsigned long addr)
+{
+       struct file *file = vma->vm_file;
+       struct shm_file_data *sfd = shm_file_data(file);
+       struct mempolicy *pol = NULL;
+
+       if (sfd->vm_ops->get_policy)
+               pol = sfd->vm_ops->get_policy(vma, addr);
+       else
+               pol = vma->vm_policy;
+       return pol;
+}
+#endif
+
 static int shm_mmap(struct file * file, struct vm_area_struct * vma)
 {
+       struct shm_file_data *sfd = shm_file_data(file);
        int ret;
 
-       ret = shmem_mmap(file, vma);
-       if (ret == 0) {
-               vma->vm_ops = &shm_vm_ops;
-               if (!(vma->vm_flags & VM_WRITE))
-                       vma->vm_flags &= ~VM_MAYWRITE;
-               shm_inc(shm_file_ns(file), file->f_path.dentry->d_inode->i_ino);
-       }
+       ret = sfd->file->f_op->mmap(sfd->file, vma);
+       if (ret != 0)
+               return ret;
+       sfd->vm_ops = vma->vm_ops;
+       vma->vm_ops = &shm_vm_ops;
+       shm_open(vma);
 
        return ret;
 }
 
 static int shm_release(struct inode *ino, struct file *file)
 {
-       struct ipc_namespace *ns;
+       struct shm_file_data *sfd = shm_file_data(file);
 
-       ns = shm_file_ns(file);
-       put_ipc_ns(ns);
-       shm_file_ns(file) = NULL;
+       put_ipc_ns(sfd->ns);
+       shm_file_data(file) = NULL;
+       kfree(sfd);
        return 0;
 }
 
+static int shm_fsync(struct file *file, struct dentry *dentry, int datasync)
+{
+       int (*fsync) (struct file *, struct dentry *, int datasync);
+       struct shm_file_data *sfd = shm_file_data(file);
+       int ret = -EINVAL;
+
+       fsync = sfd->file->f_op->fsync;
+       if (fsync)
+               ret = fsync(sfd->file, sfd->file->f_path.dentry, datasync);
+       return ret;
+}
+
+static unsigned long shm_get_unmapped_area(struct file *file,
+       unsigned long addr, unsigned long len, unsigned long pgoff,
+       unsigned long flags)
+{
+       struct shm_file_data *sfd = shm_file_data(file);
+       return get_unmapped_area(sfd->file, addr, len, pgoff, flags);
+}
+
+int is_file_shm_hugepages(struct file *file)
+{
+       int ret = 0;
+
+       if (file->f_op == &shm_file_operations) {
+               struct shm_file_data *sfd;
+               sfd = shm_file_data(file);
+               ret = is_file_hugepages(sfd->file);
+       }
+       return ret;
+}
+
 static const struct file_operations shm_file_operations = {
        .mmap           = shm_mmap,
+       .fsync          = shm_fsync,
        .release        = shm_release,
-#ifndef CONFIG_MMU
-       .get_unmapped_area = shmem_get_unmapped_area,
-#endif
+       .get_unmapped_area      = shm_get_unmapped_area,
 };
 
 static struct vm_operations_struct shm_vm_ops = {
        .open   = shm_open,     /* callback for a new vm-area open */
        .close  = shm_close,    /* callback for when the vm-area is released */
-       .nopage = shmem_nopage,
-#if defined(CONFIG_NUMA) && defined(CONFIG_SHMEM)
-       .set_policy = shmem_set_policy,
-       .get_policy = shmem_get_policy,
+       .nopage = shm_nopage,
+#if defined(CONFIG_NUMA)
+       .set_policy = shm_set_policy,
+       .get_policy = shm_get_policy,
 #endif
 };
 
@@ -330,13 +397,6 @@ static int newseg (struct ipc_namespace *ns, key_t key, int shmflg, size_t size)
        shp->shm_nattch = 0;
        shp->id = shm_buildid(ns, id, shp->shm_perm.seq);
        shp->shm_file = file;
-       file->f_path.dentry->d_inode->i_ino = shp->id;
-
-       shm_file_ns(file) = get_ipc_ns(ns);
-
-       /* Hugetlb ops would have already been assigned. */
-       if (!(shmflg & SHM_HUGETLB))
-               file->f_op = &shm_file_operations;
 
        ns->shm_tot += numpages;
        shm_unlock(shp);
@@ -607,10 +667,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
                tbuf.shm_ctime  = shp->shm_ctim;
                tbuf.shm_cpid   = shp->shm_cprid;
                tbuf.shm_lpid   = shp->shm_lprid;
-               if (!is_file_hugepages(shp->shm_file))
-                       tbuf.shm_nattch = shp->shm_nattch;
-               else
-                       tbuf.shm_nattch = file_count(shp->shm_file) - 1;
+               tbuf.shm_nattch = shp->shm_nattch;
                shm_unlock(shp);
                if(copy_shmid_to_user (buf, &tbuf, version))
                        err = -EFAULT;
@@ -779,13 +836,16 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
        unsigned long flags;
        unsigned long prot;
        int acc_mode;
-       void *user_addr;
+       unsigned long user_addr;
        struct ipc_namespace *ns;
+       struct shm_file_data *sfd;
+       struct path path;
+       mode_t f_mode;
 
-       if (shmid < 0) {
-               err = -EINVAL;
+       err = -EINVAL;
+       if (shmid < 0)
                goto out;
-       else if ((addr = (ulong)shmaddr)) {
+       else if ((addr = (ulong)shmaddr)) {
                if (addr & (SHMLBA-1)) {
                        if (shmflg & SHM_RND)
                                addr &= ~(SHMLBA-1);       /* round down */
@@ -793,12 +853,12 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
 #ifndef __ARCH_FORCE_SHMLBA
                                if (addr & ~PAGE_MASK)
 #endif
-                                       return -EINVAL;
+                                       goto out;
                }
                flags = MAP_SHARED | MAP_FIXED;
        } else {
                if ((shmflg & SHM_REMAP))
-                       return -EINVAL;
+                       goto out;
 
                flags = MAP_SHARED;
        }
@@ -806,9 +866,11 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
        if (shmflg & SHM_RDONLY) {
                prot = PROT_READ;
                acc_mode = S_IRUGO;
+               f_mode = FMODE_READ;
        } else {
                prot = PROT_READ | PROT_WRITE;
                acc_mode = S_IRUGO | S_IWUGO;
+               f_mode = FMODE_READ | FMODE_WRITE;
        }
        if (shmflg & SHM_EXEC) {
                prot |= PROT_EXEC;
@@ -821,35 +883,50 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
         */
        ns = current->nsproxy->ipc_ns;
        shp = shm_lock(ns, shmid);
-       if(shp == NULL) {
-               err = -EINVAL;
+       if(shp == NULL)
                goto out;
-       }
+
        err = shm_checkid(ns, shp,shmid);
-       if (err) {
-               shm_unlock(shp);
-               goto out;
-       }
-       if (ipcperms(&shp->shm_perm, acc_mode)) {
-               shm_unlock(shp);
-               err = -EACCES;
-               goto out;
-       }
+       if (err)
+               goto out_unlock;
+
+       err = -EACCES;
+       if (ipcperms(&shp->shm_perm, acc_mode))
+               goto out_unlock;
 
        err = security_shm_shmat(shp, shmaddr, shmflg);
-       if (err) {
-               shm_unlock(shp);
-               return err;
-       }
-               
-       file = shp->shm_file;
-       size = i_size_read(file->f_path.dentry->d_inode);
+       if (err)
+               goto out_unlock;
+
+       path.dentry = dget(shp->shm_file->f_path.dentry);
+       path.mnt    = mntget(shp->shm_file->f_path.mnt);
        shp->shm_nattch++;
+       size = i_size_read(path.dentry->d_inode);
        shm_unlock(shp);
 
+       err = -ENOMEM;
+       sfd = kzalloc(sizeof(*sfd), GFP_KERNEL);
+       if (!sfd)
+               goto out_put_path;
+
+       err = -ENOMEM;
+       file = get_empty_filp();
+       if (!file)
+               goto out_free;
+
+       file->f_op = &shm_file_operations;
+       file->private_data = sfd;
+       file->f_path = path;
+       file->f_mapping = shp->shm_file->f_mapping;
+       file->f_mode = f_mode;
+       sfd->id = shp->id;
+       sfd->ns = get_ipc_ns(ns);
+       sfd->file = shp->shm_file;
+       sfd->vm_ops = NULL;
+
        down_write(&current->mm->mmap_sem);
        if (addr && !(shmflg & SHM_REMAP)) {
-               user_addr = ERR_PTR(-EINVAL);
+               err = -EINVAL;
                if (find_vma_intersection(current->mm, addr, addr + size))
                        goto invalid;
                /*
@@ -861,11 +938,17 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
                        goto invalid;
        }
                
-       user_addr = (void*) do_mmap (file, addr, size, prot, flags, 0);
-
+       user_addr = do_mmap (file, addr, size, prot, flags, 0);
+       *raddr = user_addr;
+       err = 0;
+       if (IS_ERR_VALUE(user_addr))
+               err = (long)user_addr;
 invalid:
        up_write(&current->mm->mmap_sem);
 
+       fput(file);
+
+out_nattch:
        mutex_lock(&shm_ids(ns).mutex);
        shp = shm_lock(ns, shmid);
        BUG_ON(!shp);
@@ -877,12 +960,19 @@ invalid:
                shm_unlock(shp);
        mutex_unlock(&shm_ids(ns).mutex);
 
-       *raddr = (unsigned long) user_addr;
-       err = 0;
-       if (IS_ERR(user_addr))
-               err = PTR_ERR(user_addr);
 out:
        return err;
+
+out_unlock:
+       shm_unlock(shp);
+       goto out;
+
+out_free:
+       kfree(sfd);
+out_put_path:
+       dput(path.dentry);
+       mntput(path.mnt);
+       goto out_nattch;
 }
 
 asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg)
@@ -944,7 +1034,7 @@ asmlinkage long sys_shmdt(char __user *shmaddr)
                 * a fragment created by mprotect() and/or munmap(), or it
                 * otherwise it starts at this address with no hassles.
                 */
-               if ((vma->vm_ops == &shm_vm_ops || is_vm_hugetlb_page(vma)) &&
+               if ((vma->vm_ops == &shm_vm_ops) &&
                        (vma->vm_start - addr)/PAGE_SIZE == vma->vm_pgoff) {
 
 
@@ -973,7 +1063,7 @@ asmlinkage long sys_shmdt(char __user *shmaddr)
                next = vma->vm_next;
 
                /* finding a matching vma now does not alter retval */
-               if ((vma->vm_ops == &shm_vm_ops || is_vm_hugetlb_page(vma)) &&
+               if ((vma->vm_ops == &shm_vm_ops) &&
                        (vma->vm_start - addr)/PAGE_SIZE == vma->vm_pgoff)
 
                        do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start);
@@ -1004,7 +1094,7 @@ static int sysvipc_shm_proc_show(struct seq_file *s, void *it)
                          shp->shm_segsz,
                          shp->shm_cprid,
                          shp->shm_lprid,
-                         is_file_hugepages(shp->shm_file) ? (file_count(shp->shm_file) - 1) : shp->shm_nattch,
+                         shp->shm_nattch,
                          shp->shm_perm.uid,
                          shp->shm_perm.gid,
                          shp->shm_perm.cuid,
index 476cb0c0b4a432bce65c1f113011aa60cd3060b0..ec4cb9f3e3b70c39044cf2ed41b6d7d3785f8d37 100644 (file)
@@ -540,19 +540,19 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
 /*
  * Switch to high resolution mode
  */
-static void hrtimer_switch_to_hres(void)
+static int hrtimer_switch_to_hres(void)
 {
        struct hrtimer_cpu_base *base = &__get_cpu_var(hrtimer_bases);
        unsigned long flags;
 
        if (base->hres_active)
-               return;
+               return 1;
 
        local_irq_save(flags);
 
        if (tick_init_highres()) {
                local_irq_restore(flags);
-               return;
+               return 0;
        }
        base->hres_active = 1;
        base->clock_base[CLOCK_REALTIME].resolution = KTIME_HIGH_RES;
@@ -565,13 +565,14 @@ static void hrtimer_switch_to_hres(void)
        local_irq_restore(flags);
        printk(KERN_INFO "Switched to high resolution mode on CPU %d\n",
               smp_processor_id());
+       return 1;
 }
 
 #else
 
 static inline int hrtimer_hres_active(void) { return 0; }
 static inline int hrtimer_is_hres_enabled(void) { return 0; }
-static inline void hrtimer_switch_to_hres(void) { }
+static inline int hrtimer_switch_to_hres(void) { return 0; }
 static inline void hrtimer_force_reprogram(struct hrtimer_cpu_base *base) { }
 static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
                                            struct hrtimer_clock_base *base)
@@ -1130,6 +1131,9 @@ static inline void run_hrtimer_queue(struct hrtimer_cpu_base *cpu_base,
                if (base->softirq_time.tv64 <= timer->expires.tv64)
                        break;
 
+#ifdef CONFIG_HIGH_RES_TIMERS
+               WARN_ON_ONCE(timer->cb_mode == HRTIMER_CB_IRQSAFE_NO_SOFTIRQ);
+#endif
                timer_stats_account_hrtimer(timer);
 
                fn = timer->function;
@@ -1173,7 +1177,8 @@ void hrtimer_run_queues(void)
         * deadlock vs. xtime_lock.
         */
        if (tick_check_oneshot_change(!hrtimer_is_hres_enabled()))
-               hrtimer_switch_to_hres();
+               if (hrtimer_switch_to_hres())
+                       return;
 
        hrtimer_get_softirq_time(cpu_base);
 
@@ -1355,17 +1360,16 @@ static void migrate_hrtimers(int cpu)
        tick_cancel_sched_timer(cpu);
 
        local_irq_disable();
-
-       spin_lock(&new_base->lock);
-       spin_lock(&old_base->lock);
+       double_spin_lock(&new_base->lock, &old_base->lock,
+                        smp_processor_id() < cpu);
 
        for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
                migrate_hrtimer_list(&old_base->clock_base[i],
                                     &new_base->clock_base[i]);
        }
-       spin_unlock(&old_base->lock);
-       spin_unlock(&new_base->lock);
 
+       double_spin_unlock(&new_base->lock, &old_base->lock,
+                          smp_processor_id() < cpu);
        local_irq_enable();
        put_cpu_var(hrtimer_bases);
 }
index 4baa3bbcd25a0c516e7ae05de2eeed2dbd523814..77b7acc875c5df6755954161736b72918fff49ad 100644 (file)
@@ -65,12 +65,11 @@ void move_native_irq(int irq)
        if (likely(!(desc->status & IRQ_MOVE_PENDING)))
                return;
 
-       if (likely(!(desc->status & IRQ_DISABLED)))
-               desc->chip->disable(irq);
+       if (unlikely(desc->status & IRQ_DISABLED))
+               return;
 
+       desc->chip->mask(irq);
        move_masked_irq(irq);
-
-       if (likely(!(desc->status & IRQ_DISABLED)))
-               desc->chip->enable(irq);
+       desc->chip->unmask(irq);
 }
 
index 9f923f8ce6a0cd3c225f73eb79c865777ac60967..796276141e51902bd466b1f5b81b5220c109ca4a 100644 (file)
@@ -36,8 +36,6 @@
 #include <linux/resource.h>
 #include <asm/uaccess.h>
 
-extern int delete_module(const char *name, unsigned int flags);
-
 extern int max_threads;
 
 static struct workqueue_struct *khelper_wq;
@@ -48,7 +46,6 @@ static struct workqueue_struct *khelper_wq;
        modprobe_path is set via /proc/sys.
 */
 char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe";
-struct module_kobject kmod_mk;
 
 /**
  * request_module - try to load a kernel module
@@ -78,11 +75,6 @@ int request_module(const char *fmt, ...)
        static atomic_t kmod_concurrent = ATOMIC_INIT(0);
 #define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */
        static int kmod_loop_msg;
-       char modalias[16 + MODULE_NAME_LEN] = "MODALIAS=";
-       char *uevent_envp[2] = {
-               modalias,
-               NULL
-       };
 
        va_start(args, fmt);
        ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args);
@@ -90,12 +82,6 @@ int request_module(const char *fmt, ...)
        if (ret >= MODULE_NAME_LEN)
                return -ENAMETOOLONG;
 
-       strcpy(&modalias[strlen("MODALIAS=")], module_name);
-       kobject_uevent_env(&kmod_mk.kobj, KOBJ_CHANGE, uevent_envp);
-
-       if (modprobe_path[0] == '\0')
-               goto out;
-
        /* If modprobe needs a service that is in a module, we get a recursive
         * loop.  Limit the number of running kmod threads to max_threads/2 or
         * MAX_KMOD_CONCURRENT, whichever is the smaller.  A cleaner method
@@ -122,115 +108,9 @@ int request_module(const char *fmt, ...)
 
        ret = call_usermodehelper(modprobe_path, argv, envp, 1);
        atomic_dec(&kmod_concurrent);
-out:
        return ret;
 }
 EXPORT_SYMBOL(request_module);
-
-static ssize_t store_mod_request(struct module_attribute *mattr,
-                                struct module *mod,
-                             const char *buffer, size_t count)
-{
-       char name[MODULE_NAME_LEN];
-       int ret;
-
-       if (count < 1 || count+1 > MODULE_NAME_LEN)
-               return -EINVAL;
-       memcpy(name, buffer, count);
-       name[count] = '\0';
-       if (name[count-1] == '\n')
-               name[count-1] = '\0';
-
-       ret = request_module(name);
-       if (ret < 0)
-               return ret;
-       return count;
-}
-
-static struct module_attribute mod_request = {
-       .attr = { .name = "mod_request", .mode = S_IWUSR, .owner = THIS_MODULE },
-       .store = store_mod_request,
-};
-
-#ifdef CONFIG_MODULE_UNLOAD
-static ssize_t store_mod_unload(struct module_attribute *mattr,
-                           struct module *mod,
-                           const char *buffer, size_t count)
-{
-       char name[MODULE_NAME_LEN];
-       int ret;
-
-       if (count < 1 || count+1 > MODULE_NAME_LEN)
-               return -EINVAL;
-       memcpy(name, buffer, count);
-       name[count] = '\0';
-       if (name[count-1] == '\n')
-               name[count-1] = '\0';
-
-       ret = delete_module(name, O_NONBLOCK);
-       if (ret < 0)
-               return ret;
-       return count;
-}
-
-static struct module_attribute mod_unload = {
-       .attr = { .name = "mod_unload", .mode = S_IWUSR, .owner = THIS_MODULE },
-       .store = store_mod_unload,
-};
-#endif
-
-static ssize_t show_mod_request_helper(struct module_attribute *mattr,
-                                      struct module *mod,
-                                      char *buffer)
-{
-       return sprintf(buffer, "%s\n", modprobe_path);
-}
-
-static ssize_t store_mod_request_helper(struct module_attribute *mattr,
-                                       struct module *mod,
-                                       const char *buffer, size_t count)
-{
-       if (count < 1 || count+1 > KMOD_PATH_LEN)
-               return -EINVAL;
-       memcpy(modprobe_path, buffer, count);
-       modprobe_path[count] = '\0';
-       if (modprobe_path[count-1] == '\n')
-               modprobe_path[count-1] = '\0';
-       return count;
-}
-
-static struct module_attribute mod_request_helper = {
-       .attr = {
-               .name = "mod_request_helper",
-               .mode = S_IWUSR | S_IRUGO,
-               .owner = THIS_MODULE
-       },
-       .show = show_mod_request_helper,
-       .store = store_mod_request_helper,
-};
-
-void __init kmod_sysfs_init(void)
-{
-       int ret;
-
-       kmod_mk.mod = THIS_MODULE;
-       kobj_set_kset_s(&kmod_mk, module_subsys);
-       kobject_set_name(&kmod_mk.kobj, "kmod");
-       kobject_init(&kmod_mk.kobj);
-       ret = kobject_add(&kmod_mk.kobj);
-       if (ret < 0)
-               goto out;
-
-       ret = sysfs_create_file(&kmod_mk.kobj, &mod_request_helper.attr);
-       ret = sysfs_create_file(&kmod_mk.kobj, &mod_request.attr);
-#ifdef CONFIG_MODULE_UNLOAD
-       ret = sysfs_create_file(&kmod_mk.kobj, &mod_unload.attr);
-#endif
-
-       kobject_uevent(&kmod_mk.kobj, KOBJ_ADD);
-out:
-       return;
-}
 #endif /* CONFIG_KMOD */
 
 struct subprocess_info {
index 6fcf8dd148d06b868d1ab1212b420f2e73833848..d25a9ada3f8eb57c8b6ab2ac43e7123fb49ffa9f 100644 (file)
@@ -39,6 +39,8 @@
 #include <linux/moduleloader.h>
 #include <linux/kallsyms.h>
 #include <linux/freezer.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
 #include <asm-generic/sections.h>
 #include <asm/cacheflush.h>
 #include <asm/errno.h>
@@ -778,6 +780,12 @@ int __kprobes register_kretprobe(struct kretprobe *rp)
        return -ENOSYS;
 }
 
+static int __kprobes pre_handler_kretprobe(struct kprobe *p,
+                                          struct pt_regs *regs)
+{
+       return 0;
+}
+
 #endif /* ARCH_SUPPORTS_KRETPROBES */
 
 void __kprobes unregister_kretprobe(struct kretprobe *rp)
@@ -815,7 +823,109 @@ static int __init init_kprobes(void)
        return err;
 }
 
-__initcall(init_kprobes);
+#ifdef CONFIG_DEBUG_FS
+static void __kprobes report_probe(struct seq_file *pi, struct kprobe *p,
+               const char *sym, int offset,char *modname)
+{
+       char *kprobe_type;
+
+       if (p->pre_handler == pre_handler_kretprobe)
+               kprobe_type = "r";
+       else if (p->pre_handler == setjmp_pre_handler)
+               kprobe_type = "j";
+       else
+               kprobe_type = "k";
+       if (sym)
+               seq_printf(pi, "%p  %s  %s+0x%x  %s\n", p->addr, kprobe_type,
+                       sym, offset, (modname ? modname : " "));
+       else
+               seq_printf(pi, "%p  %s  %p\n", p->addr, kprobe_type, p->addr);
+}
+
+static void __kprobes *kprobe_seq_start(struct seq_file *f, loff_t *pos)
+{
+       return (*pos < KPROBE_TABLE_SIZE) ? pos : NULL;
+}
+
+static void __kprobes *kprobe_seq_next(struct seq_file *f, void *v, loff_t *pos)
+{
+       (*pos)++;
+       if (*pos >= KPROBE_TABLE_SIZE)
+               return NULL;
+       return pos;
+}
+
+static void __kprobes kprobe_seq_stop(struct seq_file *f, void *v)
+{
+       /* Nothing to do */
+}
+
+static int __kprobes show_kprobe_addr(struct seq_file *pi, void *v)
+{
+       struct hlist_head *head;
+       struct hlist_node *node;
+       struct kprobe *p, *kp;
+       const char *sym = NULL;
+       unsigned int i = *(loff_t *) v;
+       unsigned long size, offset = 0;
+       char *modname, namebuf[128];
+
+       head = &kprobe_table[i];
+       preempt_disable();
+       hlist_for_each_entry_rcu(p, node, head, hlist) {
+               sym = kallsyms_lookup((unsigned long)p->addr, &size,
+                                       &offset, &modname, namebuf);
+               if (p->pre_handler == aggr_pre_handler) {
+                       list_for_each_entry_rcu(kp, &p->list, list)
+                               report_probe(pi, kp, sym, offset, modname);
+               } else
+                       report_probe(pi, p, sym, offset, modname);
+       }
+       preempt_enable();
+       return 0;
+}
+
+static struct seq_operations kprobes_seq_ops = {
+       .start = kprobe_seq_start,
+       .next  = kprobe_seq_next,
+       .stop  = kprobe_seq_stop,
+       .show  = show_kprobe_addr
+};
+
+static int __kprobes kprobes_open(struct inode *inode, struct file *filp)
+{
+       return seq_open(filp, &kprobes_seq_ops);
+}
+
+static struct file_operations debugfs_kprobes_operations = {
+       .open           = kprobes_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+static int __kprobes debugfs_kprobe_init(void)
+{
+       struct dentry *dir, *file;
+
+       dir = debugfs_create_dir("kprobes", NULL);
+       if (!dir)
+               return -ENOMEM;
+
+       file = debugfs_create_file("list", 0444, dir , 0 ,
+                               &debugfs_kprobes_operations);
+       if (!file) {
+               debugfs_remove(dir);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+late_initcall(debugfs_kprobe_init);
+#endif /* CONFIG_DEBUG_FS */
+
+module_init(init_kprobes);
 
 EXPORT_SYMBOL_GPL(register_kprobe);
 EXPORT_SYMBOL_GPL(unregister_kprobe);
@@ -824,4 +934,3 @@ EXPORT_SYMBOL_GPL(unregister_jprobe);
 EXPORT_SYMBOL_GPL(jprobe_return);
 EXPORT_SYMBOL_GPL(register_kretprobe);
 EXPORT_SYMBOL_GPL(unregister_kretprobe);
-
index 592c576d77a7c325cb4edfa4d496f244764b5ae5..8dc24c92dc6d2c1e867c8ce381caec43c9408583 100644 (file)
@@ -2228,6 +2228,10 @@ out_calc_hash:
 
        curr->lockdep_depth++;
        check_chain_key(curr);
+#ifdef CONFIG_DEBUG_LOCKDEP
+       if (unlikely(!debug_locks))
+               return 0;
+#endif
        if (unlikely(curr->lockdep_depth >= MAX_LOCK_DEPTH)) {
                debug_locks_off();
                printk("BUG: MAX_LOCK_DEPTH too low!\n");
@@ -2598,7 +2602,7 @@ out_restore:
        raw_local_irq_restore(flags);
 }
 
-void __init lockdep_init(void)
+void lockdep_init(void)
 {
        int i;
 
index 8c25b1a04fa6d8f3dbbda8f57a045cc2d32714bd..fbc51de6444e4bbb9973a12a90698adf1db700b2 100644 (file)
@@ -653,11 +653,20 @@ static void wait_for_zero_refcount(struct module *mod)
        mutex_lock(&module_mutex);
 }
 
-int delete_module(const char *name, unsigned int flags)
+asmlinkage long
+sys_delete_module(const char __user *name_user, unsigned int flags)
 {
        struct module *mod;
+       char name[MODULE_NAME_LEN];
        int ret, forced = 0;
 
+       if (!capable(CAP_SYS_MODULE))
+               return -EPERM;
+
+       if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
+               return -EFAULT;
+       name[MODULE_NAME_LEN-1] = '\0';
+
        if (mutex_lock_interruptible(&module_mutex) != 0)
                return -EINTR;
 
@@ -718,21 +727,6 @@ int delete_module(const char *name, unsigned int flags)
        return ret;
 }
 
-asmlinkage long
-sys_delete_module(const char __user *name_user, unsigned int flags)
-{
-       char name[MODULE_NAME_LEN];
-
-       if (!capable(CAP_SYS_MODULE))
-               return -EPERM;
-
-       if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
-               return -EFAULT;
-       name[MODULE_NAME_LEN-1] = '\0';
-
-       return delete_module(name, flags);
-}
-
 static void print_unload_info(struct seq_file *m, struct module *mod)
 {
        struct module_use *use;
index 7a751570b56d78222d9f2510938834f3391bfc45..e265b13195b165164f3f9f59d6880b560502c89e 100644 (file)
@@ -707,7 +707,6 @@ static int __init param_sysfs_init(void)
        }
 
        param_sysfs_builtin();
-       kmod_sysfs_init();
 
        return 0;
 }
index 95f6657fff73432880d14bd96e6304eea4aacff6..51a4dd0f1b74b2ae0dc700a524de8801e7c66e2b 100644 (file)
@@ -81,29 +81,34 @@ config SOFTWARE_SUSPEND
        bool "Software Suspend"
        depends on PM && SWAP && ((X86 && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP))
        ---help---
-         Enable the possibility of suspending the machine.
-         It doesn't need ACPI or APM.
-         You may suspend your machine by 'swsusp' or 'shutdown -z <time>' 
-         (patch for sysvinit needed). 
+         Enable the suspend to disk (STD) functionality.
 
-         It creates an image which is saved in your active swap. Upon next
+         You can suspend your machine with 'echo disk > /sys/power/state'.
+         Alternatively, you can use the additional userland tools available
+         from <http://suspend.sf.net>.
+
+         In principle it does not require ACPI or APM, although for example
+         ACPI will be used if available.
+
+         It creates an image which is saved in your active swap. Upon the next
          boot, pass the 'resume=/dev/swappartition' argument to the kernel to
          have it detect the saved image, restore memory state from it, and
          continue to run as before. If you do not want the previous state to
-         be reloaded, then use the 'noresume' kernel argument. However, note
-         that your partitions will be fsck'd and you must re-mkswap your swap
-         partitions. It does not work with swap files.
+         be reloaded, then use the 'noresume' kernel command line argument.
+         Note, however, that fsck will be run on your filesystems and you will
+         need to run mkswap against the swap partition used for the suspend.
 
-         Right now you may boot without resuming and then later resume but
-         in meantime you cannot use those swap partitions/files which were
-         involved in suspending. Also in this case there is a risk that buffers
-         on disk won't match with saved ones.
+         It also works with swap files to a limited extent (for details see
+         <file:Documentation/power/swsusp-and-swap-files.txt>).
 
-         For more information take a look at <file:Documentation/power/swsusp.txt>.
+         Right now you may boot without resuming and resume later but in the
+         meantime you cannot use the swap partition(s)/file(s) involved in
+         suspending.  Also in this case you must not use the filesystems
+         that were mounted before the suspend.  In particular, you MUST NOT
+         MOUNT any journaled filesystems mounted before the suspend or they
+         will get corrupted in a nasty way.
 
-         (For now, swsusp is incompatible with PAE aka HIGHMEM_64G on i386.
-         we need identity mapping for resume to work, and that is trivial
-         to get with 4MB pages, but less than trivial on PAE).
+         For more information take a look at <file:Documentation/power/swsusp.txt>.
 
 config PM_STD_PARTITION
        string "Default resume partition"
index e1c4131204698fd891af0b8046406ae4fd0ff76a..a064dfd8877a471db0abbe13fc2017c7f6d39dd7 100644 (file)
@@ -167,7 +167,10 @@ static inline int valid_state(suspend_state_t state)
        if (state == PM_SUSPEND_DISK)
                return 1;
 
-       if (pm_ops && pm_ops->valid && !pm_ops->valid(state))
+       /* all other states need lowlevel support and need to be
+        * valid to the lowlevel implementation, no valid callback
+        * implies that all are valid. */
+       if (!pm_ops || (pm_ops->valid && !pm_ops->valid(state)))
                return 0;
        return 1;
 }
index 482b11ff65cb9916df94fb5399bd00d908ea5428..bcd14e83ef39c44dbf77eb1d6cc89a2a34b3e55b 100644 (file)
@@ -60,19 +60,19 @@ static int test_no_idle_hz; /* Test RCU's support for tickless idle CPUs. */
 static int shuffle_interval = 5; /* Interval between shuffles (in sec)*/
 static char *torture_type = "rcu"; /* What RCU implementation to torture. */
 
-module_param(nreaders, int, 0);
+module_param(nreaders, int, 0444);
 MODULE_PARM_DESC(nreaders, "Number of RCU reader threads");
-module_param(nfakewriters, int, 0);
+module_param(nfakewriters, int, 0444);
 MODULE_PARM_DESC(nfakewriters, "Number of RCU fake writer threads");
-module_param(stat_interval, int, 0);
+module_param(stat_interval, int, 0444);
 MODULE_PARM_DESC(stat_interval, "Number of seconds between stats printk()s");
-module_param(verbose, bool, 0);
+module_param(verbose, bool, 0444);
 MODULE_PARM_DESC(verbose, "Enable verbose debugging printk()s");
-module_param(test_no_idle_hz, bool, 0);
+module_param(test_no_idle_hz, bool, 0444);
 MODULE_PARM_DESC(test_no_idle_hz, "Test support for tickless idle CPUs");
-module_param(shuffle_interval, int, 0);
+module_param(shuffle_interval, int, 0444);
 MODULE_PARM_DESC(shuffle_interval, "Number of seconds between shuffles");
-module_param(torture_type, charp, 0);
+module_param(torture_type, charp, 0444);
 MODULE_PARM_DESC(torture_type, "Type of RCU to torture (rcu, rcu_bh, srcu)");
 
 #define TORTURE_FLAG "-torture:"
index ef8a935710a27be3edc6c940f77878d2895d6434..577f251c7e28104f621d542a199169053a589c8b 100644 (file)
@@ -474,13 +474,12 @@ static void setup_callbacks(struct rchan *chan,
 }
 
 /**
- *
  *     relay_hotcpu_callback - CPU hotplug callback
  *     @nb: notifier block
  *     @action: hotplug action to take
  *     @hcpu: CPU number
  *
- *     Returns the success/failure of the operation. (NOTIFY_OK, NOTIFY_BAD)
+ *     Returns the success/failure of the operation. (%NOTIFY_OK, %NOTIFY_BAD)
  */
 static int __cpuinit relay_hotcpu_callback(struct notifier_block *nb,
                                unsigned long action,
index 0dc757246d89b02c96593df44ff8d75acb93e711..a4ca632c477cefcab0a1115d0bda5fe3724d0000 100644 (file)
@@ -3006,23 +3006,6 @@ static inline void idle_balance(int cpu, struct rq *rq)
 }
 #endif
 
-static inline void wake_priority_sleeper(struct rq *rq)
-{
-#ifdef CONFIG_SCHED_SMT
-       if (!rq->nr_running)
-               return;
-
-       spin_lock(&rq->lock);
-       /*
-        * If an SMT sibling task has been put to sleep for priority
-        * reasons reschedule the idle task to see if it can now run.
-        */
-       if (rq->nr_running)
-               resched_task(rq->idle);
-       spin_unlock(&rq->lock);
-#endif
-}
-
 DEFINE_PER_CPU(struct kernel_stat, kstat);
 
 EXPORT_PER_CPU_SYMBOL(kstat);
@@ -3239,10 +3222,7 @@ void scheduler_tick(void)
 
        update_cpu_clock(p, rq, now);
 
-       if (p == rq->idle)
-               /* Task on the idle queue */
-               wake_priority_sleeper(rq);
-       else
+       if (p != rq->idle)
                task_running_tick(rq, p);
 #ifdef CONFIG_SMP
        update_load(rq);
@@ -3251,136 +3231,6 @@ void scheduler_tick(void)
 #endif
 }
 
-#ifdef CONFIG_SCHED_SMT
-static inline void wakeup_busy_runqueue(struct rq *rq)
-{
-       /* If an SMT runqueue is sleeping due to priority reasons wake it up */
-       if (rq->curr == rq->idle && rq->nr_running)
-               resched_task(rq->idle);
-}
-
-/*
- * Called with interrupt disabled and this_rq's runqueue locked.
- */
-static void wake_sleeping_dependent(int this_cpu)
-{
-       struct sched_domain *tmp, *sd = NULL;
-       int i;
-
-       for_each_domain(this_cpu, tmp) {
-               if (tmp->flags & SD_SHARE_CPUPOWER) {
-                       sd = tmp;
-                       break;
-               }
-       }
-
-       if (!sd)
-               return;
-
-       for_each_cpu_mask(i, sd->span) {
-               struct rq *smt_rq = cpu_rq(i);
-
-               if (i == this_cpu)
-                       continue;
-               if (unlikely(!spin_trylock(&smt_rq->lock)))
-                       continue;
-
-               wakeup_busy_runqueue(smt_rq);
-               spin_unlock(&smt_rq->lock);
-       }
-}
-
-/*
- * number of 'lost' timeslices this task wont be able to fully
- * utilize, if another task runs on a sibling. This models the
- * slowdown effect of other tasks running on siblings:
- */
-static inline unsigned long
-smt_slice(struct task_struct *p, struct sched_domain *sd)
-{
-       return p->time_slice * (100 - sd->per_cpu_gain) / 100;
-}
-
-/*
- * To minimise lock contention and not have to drop this_rq's runlock we only
- * trylock the sibling runqueues and bypass those runqueues if we fail to
- * acquire their lock. As we only trylock the normal locking order does not
- * need to be obeyed.
- */
-static int
-dependent_sleeper(int this_cpu, struct rq *this_rq, struct task_struct *p)
-{
-       struct sched_domain *tmp, *sd = NULL;
-       int ret = 0, i;
-
-       /* kernel/rt threads do not participate in dependent sleeping */
-       if (!p->mm || rt_task(p))
-               return 0;
-
-       for_each_domain(this_cpu, tmp) {
-               if (tmp->flags & SD_SHARE_CPUPOWER) {
-                       sd = tmp;
-                       break;
-               }
-       }
-
-       if (!sd)
-               return 0;
-
-       for_each_cpu_mask(i, sd->span) {
-               struct task_struct *smt_curr;
-               struct rq *smt_rq;
-
-               if (i == this_cpu)
-                       continue;
-
-               smt_rq = cpu_rq(i);
-               if (unlikely(!spin_trylock(&smt_rq->lock)))
-                       continue;
-
-               smt_curr = smt_rq->curr;
-
-               if (!smt_curr->mm)
-                       goto unlock;
-
-               /*
-                * If a user task with lower static priority than the
-                * running task on the SMT sibling is trying to schedule,
-                * delay it till there is proportionately less timeslice
-                * left of the sibling task to prevent a lower priority
-                * task from using an unfair proportion of the
-                * physical cpu's resources. -ck
-                */
-               if (rt_task(smt_curr)) {
-                       /*
-                        * With real time tasks we run non-rt tasks only
-                        * per_cpu_gain% of the time.
-                        */
-                       if ((jiffies % DEF_TIMESLICE) >
-                               (sd->per_cpu_gain * DEF_TIMESLICE / 100))
-                                       ret = 1;
-               } else {
-                       if (smt_curr->static_prio < p->static_prio &&
-                               !TASK_PREEMPTS_CURR(p, smt_rq) &&
-                               smt_slice(smt_curr, sd) > task_timeslice(p))
-                                       ret = 1;
-               }
-unlock:
-               spin_unlock(&smt_rq->lock);
-       }
-       return ret;
-}
-#else
-static inline void wake_sleeping_dependent(int this_cpu)
-{
-}
-static inline int
-dependent_sleeper(int this_cpu, struct rq *this_rq, struct task_struct *p)
-{
-       return 0;
-}
-#endif
-
 #if defined(CONFIG_PREEMPT) && defined(CONFIG_DEBUG_PREEMPT)
 
 void fastcall add_preempt_count(int val)
@@ -3507,7 +3357,6 @@ need_resched_nonpreemptible:
                if (!rq->nr_running) {
                        next = rq->idle;
                        rq->expired_timestamp = 0;
-                       wake_sleeping_dependent(cpu);
                        goto switch_tasks;
                }
        }
@@ -3547,8 +3396,6 @@ need_resched_nonpreemptible:
                }
        }
        next->sleep_type = SLEEP_NORMAL;
-       if (dependent_sleeper(cpu, rq, next))
-               next = rq->idle;
 switch_tasks:
        if (next == rq->idle)
                schedstat_inc(rq, sched_goidle);
@@ -3566,7 +3413,7 @@ switch_tasks:
 
        sched_info_switch(prev, next);
        if (likely(prev != next)) {
-               next->timestamp = now;
+               next->timestamp = next->last_ran = now;
                rq->nr_switches++;
                rq->curr = next;
                ++*switch_count;
index e2a7d4bf7d57aac779c29384da8c06ed034fad1f..3670225ecbc01eb5cd6898677ef34f17b4962990 100644 (file)
@@ -1140,7 +1140,8 @@ int kill_pid_info(int sig, struct siginfo *info, struct pid *pid)
        return error;
 }
 
-static int kill_proc_info(int sig, struct siginfo *info, pid_t pid)
+int
+kill_proc_info(int sig, struct siginfo *info, pid_t pid)
 {
        int error;
        rcu_read_lock();
index 3ca1d5ff0319ea70321f196ab28b7b368179f271..1b255df4fcd0a4036c1c34fb6da31a0470742f59 100644 (file)
@@ -846,7 +846,8 @@ static ctl_table vm_table[] = {
                .extra2         = &one_hundred,
        },
 #endif
-#ifdef CONFIG_X86_32
+#if defined(CONFIG_X86_32) || \
+   (defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL))
        {
                .ctl_name       = VM_VDSO_ENABLED,
                .procname       = "vdso_enabled",
@@ -1359,8 +1360,7 @@ void unregister_sysctl_table(struct ctl_table_header * header)
 }
 
 #else /* !CONFIG_SYSCTL */
-struct ctl_table_header * register_sysctl_table(ctl_table * table,
-                                               int insert_at_head)
+struct ctl_table_header *register_sysctl_table(ctl_table * table)
 {
        return NULL;
 }
index 193a0793af95440dfbf712fab6432e5e9553d275..5b0e46b56fd0aeb08b16bafe437f0f0a1ce37796 100644 (file)
@@ -55,16 +55,18 @@ static DEFINE_SPINLOCK(clocksource_lock);
 static char override_name[32];
 static int finished_booting;
 
-/* clocksource_done_booting - Called near the end of bootup
+/* clocksource_done_booting - Called near the end of core bootup
  *
- * Hack to avoid lots of clocksource churn at boot time
+ * Hack to avoid lots of clocksource churn at boot time.
+ * We use fs_initcall because we want this to start before
+ * device_initcall but after subsys_initcall.
  */
 static int __init clocksource_done_booting(void)
 {
        finished_booting = 1;
        return 0;
 }
-late_initcall(clocksource_done_booting);
+fs_initcall(clocksource_done_booting);
 
 #ifdef CONFIG_CLOCKSOURCE_WATCHDOG
 static LIST_HEAD(watchdog_list);
index 12b3efeb9f6f0e5d8f416db1a224b0b112b0a206..5567745470f7121a284401beec86c1868ed026ae 100644 (file)
@@ -284,6 +284,42 @@ void tick_shutdown_broadcast(unsigned int *cpup)
        spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
 
+void tick_suspend_broadcast(void)
+{
+       struct clock_event_device *bc;
+       unsigned long flags;
+
+       spin_lock_irqsave(&tick_broadcast_lock, flags);
+
+       bc = tick_broadcast_device.evtdev;
+       if (bc && tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC)
+               clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN);
+
+       spin_unlock_irqrestore(&tick_broadcast_lock, flags);
+}
+
+int tick_resume_broadcast(void)
+{
+       struct clock_event_device *bc;
+       unsigned long flags;
+       int broadcast = 0;
+
+       spin_lock_irqsave(&tick_broadcast_lock, flags);
+
+       bc = tick_broadcast_device.evtdev;
+       if (bc) {
+               if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC &&
+                   !cpus_empty(tick_broadcast_mask))
+                       tick_broadcast_start_periodic(bc);
+
+               broadcast = cpu_isset(smp_processor_id(), tick_broadcast_mask);
+       }
+       spin_unlock_irqrestore(&tick_broadcast_lock, flags);
+
+       return broadcast;
+}
+
+
 #ifdef CONFIG_TICK_ONESHOT
 
 static cpumask_t tick_broadcast_oneshot_mask;
index 4500e347f1bb81e7bf9cbbce87713f6c2ff67592..43ba1bdec14cac3f6b4aa2aff26f4b268572915a 100644 (file)
@@ -77,6 +77,7 @@ static void tick_periodic(int cpu)
 void tick_handle_periodic(struct clock_event_device *dev)
 {
        int cpu = smp_processor_id();
+       ktime_t next;
 
        tick_periodic(cpu);
 
@@ -86,12 +87,12 @@ void tick_handle_periodic(struct clock_event_device *dev)
         * Setup the next period for devices, which do not have
         * periodic mode:
         */
+       next = ktime_add(dev->next_event, tick_period);
        for (;;) {
-               ktime_t next = ktime_add(dev->next_event, tick_period);
-
                if (!clockevents_program_event(dev, next, ktime_get()))
                        return;
                tick_periodic(cpu);
+               next = ktime_add(next, tick_period);
        }
 }
 
@@ -297,6 +298,28 @@ static void tick_shutdown(unsigned int *cpup)
        spin_unlock_irqrestore(&tick_device_lock, flags);
 }
 
+static void tick_suspend_periodic(void)
+{
+       struct tick_device *td = &__get_cpu_var(tick_cpu_device);
+       unsigned long flags;
+
+       spin_lock_irqsave(&tick_device_lock, flags);
+       if (td->mode == TICKDEV_MODE_PERIODIC)
+               clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_SHUTDOWN);
+       spin_unlock_irqrestore(&tick_device_lock, flags);
+}
+
+static void tick_resume_periodic(void)
+{
+       struct tick_device *td = &__get_cpu_var(tick_cpu_device);
+       unsigned long flags;
+
+       spin_lock_irqsave(&tick_device_lock, flags);
+       if (td->mode == TICKDEV_MODE_PERIODIC)
+               tick_setup_periodic(td->evtdev, 0);
+       spin_unlock_irqrestore(&tick_device_lock, flags);
+}
+
 /*
  * Notification about clock event devices
  */
@@ -324,6 +347,16 @@ static int tick_notify(struct notifier_block *nb, unsigned long reason,
                tick_shutdown(dev);
                break;
 
+       case CLOCK_EVT_NOTIFY_SUSPEND:
+               tick_suspend_periodic();
+               tick_suspend_broadcast();
+               break;
+
+       case CLOCK_EVT_NOTIFY_RESUME:
+               if (!tick_resume_broadcast())
+                       tick_resume_periodic();
+               break;
+
        default:
                break;
        }
index 54861a0f29ffd7bbc42f449bb8853c4b8191e46c..75890efd24ff315245562b8ca0c9aef796bc6628 100644 (file)
@@ -67,6 +67,8 @@ extern int tick_check_broadcast_device(struct clock_event_device *dev);
 extern int tick_is_broadcast_device(struct clock_event_device *dev);
 extern void tick_broadcast_on_off(unsigned long reason, int *oncpu);
 extern void tick_shutdown_broadcast(unsigned int *cpup);
+extern void tick_suspend_broadcast(void);
+extern int tick_resume_broadcast(void);
 
 extern void
 tick_set_periodic_handler(struct clock_event_device *dev, int broadcast);
@@ -90,6 +92,8 @@ static inline int tick_device_uses_broadcast(struct clock_event_device *dev,
 static inline void tick_do_periodic_broadcast(struct clock_event_device *d) { }
 static inline void tick_broadcast_on_off(unsigned long reason, int *oncpu) { }
 static inline void tick_shutdown_broadcast(unsigned int *cpup) { }
+static inline void tick_suspend_broadcast(void) { }
+static inline int tick_resume_broadcast(void) { return 0; }
 
 /*
  * Set the periodic handler in non broadcast mode
index 512a4a906467e1d0e5a08c00d7d3a83cbc8b69f0..51556b95f60f0db395cd7cdaf6a840479625fe1c 100644 (file)
@@ -21,6 +21,8 @@
 #include <linux/sched.h>
 #include <linux/tick.h>
 
+#include <asm/irq_regs.h>
+
 #include "tick-internal.h"
 
 /*
index cb1b86a9c52f5749f767625ffe6f6895f4b476aa..797cccb86431c1a423647141b62270f124c341dc 100644 (file)
@@ -711,6 +711,7 @@ static unsigned long cmp_next_hrtimer_event(unsigned long now,
 
 /**
  * next_timer_interrupt - return the jiffy of the next pending timer
+ * @now: current time (in jiffies)
  */
 unsigned long get_next_timer_interrupt(unsigned long now)
 {
@@ -861,6 +862,8 @@ int do_settimeofday(struct timespec *tv)
        clock->error = 0;
        ntp_clear();
 
+       update_vsyscall(&xtime, clock);
+
        write_sequnlock_irqrestore(&xtime_lock, flags);
 
        /* signal hrtimers about time change */
@@ -908,7 +911,7 @@ static inline void change_clocksource(void) { }
 #endif
 
 /**
- * timeofday_is_continuous - check to see if timekeeping is free running
+ * timekeeping_is_continuous - check to see if timekeeping is free running
  */
 int timekeeping_is_continuous(void)
 {
@@ -996,6 +999,9 @@ static int timekeeping_resume(struct sys_device *dev)
        write_sequnlock_irqrestore(&xtime_lock, flags);
 
        touch_softlockup_watchdog();
+
+       clockevents_notify(CLOCK_EVT_NOTIFY_RESUME, NULL);
+
        /* Resume hrtimers */
        clock_was_set();
 
@@ -1010,6 +1016,9 @@ static int timekeeping_suspend(struct sys_device *dev, pm_message_t state)
        timekeeping_suspended = 1;
        timekeeping_suspend_time = read_persistent_clock();
        write_sequnlock_irqrestore(&xtime_lock, flags);
+
+       clockevents_notify(CLOCK_EVT_NOTIFY_SUSPEND, NULL);
+
        return 0;
 }
 
@@ -1650,8 +1659,8 @@ static void __devinit migrate_timers(int cpu)
        new_base = get_cpu_var(tvec_bases);
 
        local_irq_disable();
-       spin_lock(&new_base->lock);
-       spin_lock(&old_base->lock);
+       double_spin_lock(&new_base->lock, &old_base->lock,
+                        smp_processor_id() < cpu);
 
        BUG_ON(old_base->running_timer);
 
@@ -1664,8 +1673,8 @@ static void __devinit migrate_timers(int cpu)
                migrate_timer_list(new_base, old_base->tv5.vec + i);
        }
 
-       spin_unlock(&old_base->lock);
-       spin_unlock(&new_base->lock);
+       double_spin_unlock(&new_base->lock, &old_base->lock,
+                          smp_processor_id() < cpu);
        local_irq_enable();
        put_cpu_var(tvec_bases);
 }
index 4448f91b865c10a48933a6a8d1c4ea645266b90c..3f3e7403dcac7b917f1079a5b0bdcec9296f52bd 100644 (file)
@@ -411,8 +411,6 @@ config LKDTM
 config FAULT_INJECTION
        bool "Fault-injection framework"
        depends on DEBUG_KERNEL
-       depends on STACKTRACE
-       select FRAME_POINTER
        help
          Provide fault-injection framework.
          For more details, see Documentation/fault-injection/.
@@ -440,3 +438,11 @@ config FAULT_INJECTION_DEBUG_FS
        depends on FAULT_INJECTION && SYSFS && DEBUG_FS
        help
          Enable configuration of fault-injection capabilities via debugfs.
+
+config FAULT_INJECTION_STACKTRACE_FILTER
+       bool "stacktrace filter for fault-injection capabilities"
+       depends on FAULT_INJECTION_DEBUG_FS && STACKTRACE_SUPPORT
+       select STACKTRACE
+       select FRAME_POINTER
+       help
+         Provide stacktrace filter for fault-injection capabilities
index ee6e58fce8f75f675c2688294b07e01655a4396e..26ebafa8c41d7e0ff602c0d2137a8ea284bb1ae5 100644 (file)
@@ -97,10 +97,10 @@ EXPORT_SYMBOL(__bitmap_complement);
 
 /**
  * __bitmap_shift_right - logical right shift of the bits in a bitmap
- *   @dst - destination bitmap
- *   @src - source bitmap
- *   @nbits - shift by this many bits
- *   @bits - bitmap size, in bits
+ *   @dst : destination bitmap
+ *   @src : source bitmap
+ *   @shift : shift by this many bits
+ *   @bits : bitmap size, in bits
  *
  * Shifting right (dividing) means moving bits in the MS -> LS bit
  * direction.  Zeros are fed into the vacated MS positions and the
@@ -141,10 +141,10 @@ EXPORT_SYMBOL(__bitmap_shift_right);
 
 /**
  * __bitmap_shift_left - logical left shift of the bits in a bitmap
- *   @dst - destination bitmap
- *   @src - source bitmap
- *   @nbits - shift by this many bits
- *   @bits - bitmap size, in bits
+ *   @dst : destination bitmap
+ *   @src : source bitmap
+ *   @shift : shift by this many bits
+ *   @bits : bitmap size, in bits
  *
  * Shifting left (multiplying) means moving bits in the LS -> MS
  * direction.  Zeros are fed into the vacated LS bit positions
index 3a67dc5ada7d5b2655ae461890519e995d50d7c9..1ea2c184315d12bb8c5c46674c28a53ab16815a1 100644 (file)
@@ -15,22 +15,8 @@ int __next_cpu(int n, const cpumask_t *srcp)
 }
 EXPORT_SYMBOL(__next_cpu);
 
-/*
- * Find the highest possible smp_processor_id()
- *
- * Note: if we're prepared to assume that cpu_possible_map never changes
- * (reasonable) then this function should cache its return value.
- */
-int highest_possible_processor_id(void)
-{
-       unsigned int cpu;
-       unsigned highest = 0;
-
-       for_each_cpu_mask(cpu, cpu_possible_map)
-               highest = cpu;
-       return highest;
-}
-EXPORT_SYMBOL(highest_possible_processor_id);
+int nr_cpu_ids;
+EXPORT_SYMBOL(nr_cpu_ids);
 
 int __any_online_cpu(const cpumask_t *mask)
 {
index b5a90fc056d3406b838cd71632b91985ce62b09e..0fabd12c39d79786e3bcf0ce1fa3bb68c48d01d9 100644 (file)
@@ -55,7 +55,7 @@ static bool fail_task(struct fault_attr *attr, struct task_struct *task)
 
 #define MAX_STACK_TRACE_DEPTH 32
 
-#if defined(CONFIG_STACKTRACE)
+#ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
 
 static bool fail_stacktrace(struct fault_attr *attr)
 {
@@ -90,17 +90,10 @@ static bool fail_stacktrace(struct fault_attr *attr)
 
 static inline bool fail_stacktrace(struct fault_attr *attr)
 {
-       static bool firsttime = true;
-
-       if (firsttime) {
-               printk(KERN_WARNING
-               "This architecture does not implement save_stack_trace()\n");
-               firsttime = false;
-       }
-       return false;
+       return true;
 }
 
-#endif
+#endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
 
 /*
  * This code is stolen from failmalloc-1.0
@@ -217,6 +210,8 @@ void cleanup_fault_attr_dentries(struct fault_attr *attr)
        debugfs_remove(attr->dentries.task_filter_file);
        attr->dentries.task_filter_file = NULL;
 
+#ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
+
        debugfs_remove(attr->dentries.stacktrace_depth_file);
        attr->dentries.stacktrace_depth_file = NULL;
 
@@ -232,6 +227,8 @@ void cleanup_fault_attr_dentries(struct fault_attr *attr)
        debugfs_remove(attr->dentries.reject_end_file);
        attr->dentries.reject_end_file = NULL;
 
+#endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
+
        if (attr->dentries.dir)
                WARN_ON(!simple_empty(attr->dentries.dir));
 
@@ -269,6 +266,13 @@ int init_fault_attr_dentries(struct fault_attr *attr, const char *name)
        attr->dentries.task_filter_file = debugfs_create_bool("task-filter",
                                                mode, dir, &attr->task_filter);
 
+       if (!attr->dentries.probability_file || !attr->dentries.interval_file ||
+           !attr->dentries.times_file || !attr->dentries.space_file ||
+           !attr->dentries.verbose_file || !attr->dentries.task_filter_file)
+               goto fail;
+
+#ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
+
        attr->dentries.stacktrace_depth_file =
                debugfs_create_ul_MAX_STACK_TRACE_DEPTH(
                        "stacktrace-depth", mode, dir, &attr->stacktrace_depth);
@@ -285,18 +289,15 @@ int init_fault_attr_dentries(struct fault_attr *attr, const char *name)
        attr->dentries.reject_end_file =
                debugfs_create_ul("reject-end", mode, dir, &attr->reject_end);
 
-
-       if (!attr->dentries.probability_file || !attr->dentries.interval_file
-           || !attr->dentries.times_file || !attr->dentries.space_file
-           || !attr->dentries.verbose_file || !attr->dentries.task_filter_file
-           || !attr->dentries.stacktrace_depth_file
-           || !attr->dentries.require_start_file
-           || !attr->dentries.require_end_file
-           || !attr->dentries.reject_start_file
-           || !attr->dentries.reject_end_file
-           )
+       if (!attr->dentries.stacktrace_depth_file ||
+           !attr->dentries.require_start_file ||
+           !attr->dentries.require_end_file ||
+           !attr->dentries.reject_start_file ||
+           !attr->dentries.reject_end_file)
                goto fail;
 
+#endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
+
        return 0;
 fail:
        cleanup_fault_attr_dentries(attr);
index 75ae68ce03e10be0596a1a86956360bf9fc012bb..eb7c2bab9ebf93f6ec8986f4ee8bacd7fe897075 100644 (file)
@@ -148,7 +148,7 @@ unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)
                        addr = chunk->start_addr +
                                            ((unsigned long)start_bit << order);
                        while (nbits--)
-                               __set_bit(start_bit++, &chunk->bits);
+                               __set_bit(start_bit++, chunk->bits);
                        spin_unlock_irqrestore(&chunk->lock, flags);
                        read_unlock(&pool->lock);
                        return addr;
@@ -187,7 +187,7 @@ void gen_pool_free(struct gen_pool *pool, unsigned long addr, size_t size)
                        spin_lock_irqsave(&chunk->lock, flags);
                        bit = (addr - chunk->start_addr) >> order;
                        while (nbits--)
-                               __clear_bit(bit++, &chunk->bits);
+                               __clear_bit(bit++, chunk->bits);
                        spin_unlock_irqrestore(&chunk->lock, flags);
                        break;
                }
index f4f6176dcd1286313c57ae80239ec1f0f7bbf65e..057921c5945a551777f56706b397c5e4f737aaf3 100644 (file)
@@ -385,9 +385,11 @@ int kobject_move(struct kobject *kobj, struct kobject *new_parent)
                goto out;
        old_parent = kobj->parent;
        kobj->parent = new_parent;
+       new_parent = NULL;
        kobject_put(old_parent);
        kobject_uevent_env(kobj, KOBJ_MOVE, envp);
 out:
+       kobject_put(new_parent);
        kobject_put(kobj);
        kfree(devpath_string);
        kfree(devpath);
index 623a68af8b18dec5a6346046503ac7dbd05c4096..9970e55c90bd7b28d90c5912bf3f63da3a4c7dc2 100644 (file)
@@ -28,7 +28,6 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/scatterlist.h>
-#include <asm/swiotlb.h>
 
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #define OFFSET(val,align) ((unsigned long)     \
                           ( (val) & ( (align) - 1)))
 
-#ifndef SG_ENT_VIRT_ADDRESS
 #define SG_ENT_VIRT_ADDRESS(sg)        (page_address((sg)->page) + (sg)->offset)
 #define SG_ENT_PHYS_ADDRESS(sg)        virt_to_bus(SG_ENT_VIRT_ADDRESS(sg))
-#endif
 
 /*
  * Maximum allowable number of contiguous slabs to map,
@@ -104,25 +101,13 @@ static unsigned int io_tlb_index;
  * We need to save away the original address corresponding to a mapped entry
  * for the sync operations.
  */
-#ifndef SWIOTLB_ARCH_HAS_IO_TLB_ADDR_T
-typedef char *io_tlb_addr_t;
-#define swiotlb_orig_addr_null(buffer) (!(buffer))
-#define ptr_to_io_tlb_addr(ptr) (ptr)
-#define page_to_io_tlb_addr(pg, off) (page_address(pg) + (off))
-#define sg_to_io_tlb_addr(sg) SG_ENT_VIRT_ADDRESS(sg)
-#endif
-static io_tlb_addr_t *io_tlb_orig_addr;
+static unsigned char **io_tlb_orig_addr;
 
 /*
  * Protect the above data structures in the map and unmap calls
  */
 static DEFINE_SPINLOCK(io_tlb_lock);
 
-#ifdef SWIOTLB_EXTRA_VARIABLES
-SWIOTLB_EXTRA_VARIABLES;
-#endif
-
-#ifndef SWIOTLB_ARCH_HAS_SETUP_IO_TLB_NPAGES
 static int __init
 setup_io_tlb_npages(char *str)
 {
@@ -137,25 +122,9 @@ setup_io_tlb_npages(char *str)
                swiotlb_force = 1;
        return 1;
 }
-#endif
 __setup("swiotlb=", setup_io_tlb_npages);
 /* make io_tlb_overflow tunable too? */
 
-#ifndef swiotlb_adjust_size
-#define swiotlb_adjust_size(size) ((void)0)
-#endif
-
-#ifndef swiotlb_adjust_seg
-#define swiotlb_adjust_seg(start, size) ((void)0)
-#endif
-
-#ifndef swiotlb_print_info
-#define swiotlb_print_info(bytes) \
-       printk(KERN_INFO "Placing %luMB software IO TLB between 0x%lx - " \
-              "0x%lx\n", bytes >> 20, \
-              virt_to_bus(io_tlb_start), virt_to_bus(io_tlb_end))
-#endif
-
 /*
  * Statically reserve bounce buffer space and initialize bounce buffer data
  * structures for the software IO TLB used to implement the DMA API.
@@ -169,8 +138,6 @@ swiotlb_init_with_default_size(size_t default_size)
                io_tlb_nslabs = (default_size >> IO_TLB_SHIFT);
                io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
        }
-       swiotlb_adjust_size(io_tlb_nslabs);
-       swiotlb_adjust_size(io_tlb_overflow);
 
        bytes = io_tlb_nslabs << IO_TLB_SHIFT;
 
@@ -188,14 +155,10 @@ swiotlb_init_with_default_size(size_t default_size)
         * between io_tlb_start and io_tlb_end.
         */
        io_tlb_list = alloc_bootmem(io_tlb_nslabs * sizeof(int));
-       for (i = 0; i < io_tlb_nslabs; i++) {
-               if ( !(i % IO_TLB_SEGSIZE) )
-                       swiotlb_adjust_seg(io_tlb_start + (i << IO_TLB_SHIFT),
-                               IO_TLB_SEGSIZE << IO_TLB_SHIFT);
+       for (i = 0; i < io_tlb_nslabs; i++)
                io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
-       }
        io_tlb_index = 0;
-       io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(io_tlb_addr_t));
+       io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(char *));
 
        /*
         * Get the overflow emergency buffer
@@ -203,21 +166,17 @@ swiotlb_init_with_default_size(size_t default_size)
        io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow);
        if (!io_tlb_overflow_buffer)
                panic("Cannot allocate SWIOTLB overflow buffer!\n");
-       swiotlb_adjust_seg(io_tlb_overflow_buffer, io_tlb_overflow);
 
-       swiotlb_print_info(bytes);
+       printk(KERN_INFO "Placing software IO TLB between 0x%lx - 0x%lx\n",
+              virt_to_bus(io_tlb_start), virt_to_bus(io_tlb_end));
 }
-#ifndef __swiotlb_init_with_default_size
-#define __swiotlb_init_with_default_size swiotlb_init_with_default_size
-#endif
 
 void __init
 swiotlb_init(void)
 {
-       __swiotlb_init_with_default_size(64 * (1<<20)); /* default to 64MB */
+       swiotlb_init_with_default_size(64 * (1<<20));   /* default to 64MB */
 }
 
-#ifdef SWIOTLB_ARCH_NEED_LATE_INIT
 /*
  * Systems with larger DMA zones (those that don't support ISA) can
  * initialize the swiotlb later using the slab allocator if needed.
@@ -275,12 +234,12 @@ swiotlb_late_init_with_default_size(size_t default_size)
                io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
        io_tlb_index = 0;
 
-       io_tlb_orig_addr = (io_tlb_addr_t *)__get_free_pages(GFP_KERNEL,
-                                  get_order(io_tlb_nslabs * sizeof(io_tlb_addr_t)));
+       io_tlb_orig_addr = (unsigned char **)__get_free_pages(GFP_KERNEL,
+                                  get_order(io_tlb_nslabs * sizeof(char *)));
        if (!io_tlb_orig_addr)
                goto cleanup3;
 
-       memset(io_tlb_orig_addr, 0, io_tlb_nslabs * sizeof(io_tlb_addr_t));
+       memset(io_tlb_orig_addr, 0, io_tlb_nslabs * sizeof(char *));
 
        /*
         * Get the overflow emergency buffer
@@ -290,17 +249,19 @@ swiotlb_late_init_with_default_size(size_t default_size)
        if (!io_tlb_overflow_buffer)
                goto cleanup4;
 
-       swiotlb_print_info(bytes);
+       printk(KERN_INFO "Placing %luMB software IO TLB between 0x%lx - "
+              "0x%lx\n", bytes >> 20,
+              virt_to_bus(io_tlb_start), virt_to_bus(io_tlb_end));
 
        return 0;
 
 cleanup4:
-       free_pages((unsigned long)io_tlb_orig_addr,
-                  get_order(io_tlb_nslabs * sizeof(io_tlb_addr_t)));
+       free_pages((unsigned long)io_tlb_orig_addr, get_order(io_tlb_nslabs *
+                                                             sizeof(char *)));
        io_tlb_orig_addr = NULL;
 cleanup3:
-       free_pages((unsigned long)io_tlb_list,
-                  get_order(io_tlb_nslabs * sizeof(int)));
+       free_pages((unsigned long)io_tlb_list, get_order(io_tlb_nslabs *
+                                                        sizeof(int)));
        io_tlb_list = NULL;
 cleanup2:
        io_tlb_end = NULL;
@@ -310,9 +271,7 @@ cleanup1:
        io_tlb_nslabs = req_nslabs;
        return -ENOMEM;
 }
-#endif
 
-#ifndef SWIOTLB_ARCH_HAS_NEEDS_MAPPING
 static int
 address_needs_mapping(struct device *hwdev, dma_addr_t addr)
 {
@@ -323,35 +282,11 @@ address_needs_mapping(struct device *hwdev, dma_addr_t addr)
        return (addr & ~mask) != 0;
 }
 
-static inline int range_needs_mapping(const void *ptr, size_t size)
-{
-       return swiotlb_force;
-}
-
-static inline int order_needs_mapping(unsigned int order)
-{
-       return 0;
-}
-#endif
-
-static void
-__sync_single(io_tlb_addr_t buffer, char *dma_addr, size_t size, int dir)
-{
-#ifndef SWIOTLB_ARCH_HAS_SYNC_SINGLE
-       if (dir == DMA_TO_DEVICE)
-               memcpy(dma_addr, buffer, size);
-       else
-               memcpy(buffer, dma_addr, size);
-#else
-       __swiotlb_arch_sync_single(buffer, dma_addr, size, dir);
-#endif
-}
-
 /*
  * Allocates bounce buffer and returns its kernel virtual address.
  */
 static void *
-map_single(struct device *hwdev, io_tlb_addr_t buffer, size_t size, int dir)
+map_single(struct device *hwdev, char *buffer, size_t size, int dir)
 {
        unsigned long flags;
        char *dma_addr;
@@ -424,7 +359,7 @@ map_single(struct device *hwdev, io_tlb_addr_t buffer, size_t size, int dir)
         */
        io_tlb_orig_addr[index] = buffer;
        if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)
-               __sync_single(buffer, dma_addr, size, DMA_TO_DEVICE);
+               memcpy(dma_addr, buffer, size);
 
        return dma_addr;
 }
@@ -438,18 +373,17 @@ unmap_single(struct device *hwdev, char *dma_addr, size_t size, int dir)
        unsigned long flags;
        int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
        int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
-       io_tlb_addr_t buffer = io_tlb_orig_addr[index];
+       char *buffer = io_tlb_orig_addr[index];
 
        /*
         * First, sync the memory before unmapping the entry
         */
-       if (!swiotlb_orig_addr_null(buffer)
-           && ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL)))
+       if (buffer && ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL)))
                /*
                 * bounce... copy the data back into the original buffer * and
                 * delete the bounce buffer.
                 */
-               __sync_single(buffer, dma_addr, size, DMA_FROM_DEVICE);
+               memcpy(buffer, dma_addr, size);
 
        /*
         * Return the buffer to the free list by setting the corresponding
@@ -482,18 +416,18 @@ sync_single(struct device *hwdev, char *dma_addr, size_t size,
            int dir, int target)
 {
        int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
-       io_tlb_addr_t buffer = io_tlb_orig_addr[index];
+       char *buffer = io_tlb_orig_addr[index];
 
        switch (target) {
        case SYNC_FOR_CPU:
                if (likely(dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL))
-                       __sync_single(buffer, dma_addr, size, DMA_FROM_DEVICE);
+                       memcpy(buffer, dma_addr, size);
                else
                        BUG_ON(dir != DMA_TO_DEVICE);
                break;
        case SYNC_FOR_DEVICE:
                if (likely(dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL))
-                       __sync_single(buffer, dma_addr, size, DMA_TO_DEVICE);
+                       memcpy(dma_addr, buffer, size);
                else
                        BUG_ON(dir != DMA_FROM_DEVICE);
                break;
@@ -502,8 +436,6 @@ sync_single(struct device *hwdev, char *dma_addr, size_t size,
        }
 }
 
-#ifdef SWIOTLB_ARCH_NEED_ALLOC
-
 void *
 swiotlb_alloc_coherent(struct device *hwdev, size_t size,
                       dma_addr_t *dma_handle, gfp_t flags)
@@ -519,10 +451,7 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
         */
        flags |= GFP_DMA;
 
-       if (!order_needs_mapping(order))
-               ret = (void *)__get_free_pages(flags, order);
-       else
-               ret = NULL;
+       ret = (void *)__get_free_pages(flags, order);
        if (ret && address_needs_mapping(hwdev, virt_to_bus(ret))) {
                /*
                 * The allocated memory isn't reachable by the device.
@@ -560,7 +489,6 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
        *dma_handle = dev_addr;
        return ret;
 }
-EXPORT_SYMBOL(swiotlb_alloc_coherent);
 
 void
 swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
@@ -573,9 +501,6 @@ swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
                /* DMA_TO_DEVICE to avoid memcpy in unmap_single */
                swiotlb_unmap_single (hwdev, dma_handle, size, DMA_TO_DEVICE);
 }
-EXPORT_SYMBOL(swiotlb_free_coherent);
-
-#endif
 
 static void
 swiotlb_full(struct device *dev, size_t size, int dir, int do_panic)
@@ -617,14 +542,13 @@ swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir)
         * we can safely return the device addr and not worry about bounce
         * buffering it.
         */
-       if (!range_needs_mapping(ptr, size)
-           && !address_needs_mapping(hwdev, dev_addr))
+       if (!address_needs_mapping(hwdev, dev_addr) && !swiotlb_force)
                return dev_addr;
 
        /*
         * Oh well, have to allocate and map a bounce buffer.
         */
-       map = map_single(hwdev, ptr_to_io_tlb_addr(ptr), size, dir);
+       map = map_single(hwdev, ptr, size, dir);
        if (!map) {
                swiotlb_full(hwdev, size, dir, 1);
                map = io_tlb_overflow_buffer;
@@ -752,16 +676,17 @@ int
 swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems,
               int dir)
 {
+       void *addr;
        dma_addr_t dev_addr;
        int i;
 
        BUG_ON(dir == DMA_NONE);
 
        for (i = 0; i < nelems; i++, sg++) {
-               dev_addr = SG_ENT_PHYS_ADDRESS(sg);
-               if (range_needs_mapping(SG_ENT_VIRT_ADDRESS(sg), sg->length)
-                   || address_needs_mapping(hwdev, dev_addr)) {
-                       void *map = map_single(hwdev, sg_to_io_tlb_addr(sg), sg->length, dir);
+               addr = SG_ENT_VIRT_ADDRESS(sg);
+               dev_addr = virt_to_bus(addr);
+               if (swiotlb_force || address_needs_mapping(hwdev, dev_addr)) {
+                       void *map = map_single(hwdev, addr, sg->length, dir);
                        if (!map) {
                                /* Don't panic here, we expect map_sg users
                                   to do proper error handling. */
@@ -835,44 +760,6 @@ swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
        swiotlb_sync_sg(hwdev, sg, nelems, dir, SYNC_FOR_DEVICE);
 }
 
-#ifdef SWIOTLB_ARCH_NEED_MAP_PAGE
-
-dma_addr_t
-swiotlb_map_page(struct device *hwdev, struct page *page,
-                unsigned long offset, size_t size,
-                enum dma_data_direction direction)
-{
-       dma_addr_t dev_addr;
-       char *map;
-
-       dev_addr = page_to_bus(page) + offset;
-       if (address_needs_mapping(hwdev, dev_addr)) {
-               map = map_single(hwdev, page_to_io_tlb_addr(page, offset), size, direction);
-               if (!map) {
-                       swiotlb_full(hwdev, size, direction, 1);
-                       map = io_tlb_overflow_buffer;
-               }
-               dev_addr = virt_to_bus(map);
-       }
-
-       return dev_addr;
-}
-
-void
-swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
-                  size_t size, enum dma_data_direction direction)
-{
-       char *dma_addr = bus_to_virt(dev_addr);
-
-       BUG_ON(direction == DMA_NONE);
-       if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end)
-               unmap_single(hwdev, dma_addr, size, direction);
-       else if (direction == DMA_FROM_DEVICE)
-               dma_mark_clean(dma_addr, size);
-}
-
-#endif
-
 int
 swiotlb_dma_mapping_error(dma_addr_t dma_addr)
 {
@@ -885,13 +772,10 @@ swiotlb_dma_mapping_error(dma_addr_t dma_addr)
  * during bus mastering, then you would pass 0x00ffffff as the mask to
  * this function.
  */
-#ifndef __swiotlb_dma_supported
-#define __swiotlb_dma_supported(hwdev, mask) (virt_to_bus(io_tlb_end - 1) <= (mask))
-#endif
 int
 swiotlb_dma_supported(struct device *hwdev, u64 mask)
 {
-       return __swiotlb_dma_supported(hwdev, mask);
+       return virt_to_bus(io_tlb_end - 1) <= mask;
 }
 
 EXPORT_SYMBOL(swiotlb_init);
@@ -906,4 +790,6 @@ EXPORT_SYMBOL_GPL(swiotlb_sync_single_range_for_device);
 EXPORT_SYMBOL(swiotlb_sync_sg_for_cpu);
 EXPORT_SYMBOL(swiotlb_sync_sg_for_device);
 EXPORT_SYMBOL(swiotlb_dma_mapping_error);
+EXPORT_SYMBOL(swiotlb_alloc_coherent);
+EXPORT_SYMBOL(swiotlb_free_coherent);
 EXPORT_SYMBOL(swiotlb_dma_supported);
index 259a706bd83ec5d3392b37dcf093b2c3ec953145..d76e8eb342d0df2e0468f014076a720866ae2277 100644 (file)
@@ -144,7 +144,7 @@ static struct zonelist *bind_zonelist(nodemask_t *nodes)
        max++;                  /* space for zlcache_ptr (see mmzone.h) */
        zl = kmalloc(sizeof(struct zone *) * max, GFP_KERNEL);
        if (!zl)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
        zl->zlcache_ptr = NULL;
        num = 0;
        /* First put in the highest zones from all nodes, then all the next 
@@ -162,6 +162,10 @@ static struct zonelist *bind_zonelist(nodemask_t *nodes)
                        break;
                k--;
        }
+       if (num == 0) {
+               kfree(zl);
+               return ERR_PTR(-EINVAL);
+       }
        zl->zones[num] = NULL;
        return zl;
 }
@@ -193,9 +197,10 @@ static struct mempolicy *mpol_new(int mode, nodemask_t *nodes)
                break;
        case MPOL_BIND:
                policy->v.zonelist = bind_zonelist(nodes);
-               if (policy->v.zonelist == NULL) {
+               if (IS_ERR(policy->v.zonelist)) {
+                       void *error_code = policy->v.zonelist;
                        kmem_cache_free(policy_cache, policy);
-                       return ERR_PTR(-ENOMEM);
+                       return error_code;
                }
                break;
        }
@@ -316,15 +321,6 @@ static inline int check_pgd_range(struct vm_area_struct *vma,
        return 0;
 }
 
-/* Check if a vma is migratable */
-static inline int vma_migratable(struct vm_area_struct *vma)
-{
-       if (vma->vm_flags & (
-               VM_LOCKED|VM_IO|VM_HUGETLB|VM_PFNMAP|VM_RESERVED))
-               return 0;
-       return 1;
-}
-
 /*
  * Check if all pages in a range are on a set of nodes.
  * If pagelist != NULL then isolate pages from the LRU and
@@ -1667,7 +1663,7 @@ void mpol_rebind_policy(struct mempolicy *pol, const nodemask_t *newmask)
                 * then zonelist_policy() will "FALL THROUGH" to MPOL_DEFAULT.
                 */
 
-               if (zonelist) {
+               if (!IS_ERR(zonelist)) {
                        /* Good - got mem - substitute new zonelist */
                        kfree(pol->v.zonelist);
                        pol->v.zonelist = zonelist;
index e9b161bde95b4c382092a1c94a8fcfbd4bcf58f0..7a66ca25dc8aa99b77f2a4f041fed0cd8194b6aa 100644 (file)
@@ -781,7 +781,7 @@ static int do_move_pages(struct mm_struct *mm, struct page_to_node *pm,
 
                err = -EFAULT;
                vma = find_vma(mm, pp->addr);
-               if (!vma)
+               if (!vma || !vma_migratable(vma))
                        goto set_status;
 
                page = follow_page(vma, pp->addr, FOLL_GET);
index eb509ae76553260c61a4b17b3b8bc7deca663b25..84f997da78d70e607578afac5a87b64362b12558 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -299,6 +299,8 @@ static int browse_rb(struct rb_root *root)
                        printk("vm_end %lx < vm_start %lx\n", vma->vm_end, vma->vm_start);
                i++;
                pn = nd;
+               prev = vma->vm_start;
+               pend = vma->vm_end;
        }
        j = 0;
        for (nd = pn; nd; nd = rb_prev(nd)) {
index f7e088f5a309eff3a03c8da5ad4ca4b37ecd5518..f469e3cd08e82d47ba3a0aa8d9753081e2c7cc99 100644 (file)
@@ -296,11 +296,21 @@ void balance_dirty_pages_ratelimited_nr(struct address_space *mapping,
 }
 EXPORT_SYMBOL(balance_dirty_pages_ratelimited_nr);
 
-void throttle_vm_writeout(void)
+void throttle_vm_writeout(gfp_t gfp_mask)
 {
        long background_thresh;
        long dirty_thresh;
 
+       if ((gfp_mask & (__GFP_FS|__GFP_IO)) != (__GFP_FS|__GFP_IO)) {
+               /*
+                * The caller might hold locks which can prevent IO completion
+                * or progress in the filesystem.  So we cannot just sit here
+                * waiting for IO to complete.
+                */
+               congestion_wait(WRITE, HZ/10);
+               return;
+       }
+
         for ( ; ; ) {
                get_dirty_limits(&background_thresh, &dirty_thresh, NULL);
 
@@ -317,7 +327,6 @@ void throttle_vm_writeout(void)
         }
 }
 
-
 /*
  * writeback at least _min_pages, and keep writing until the amount of dirty
  * memory is less than the background threshold, or until we're all clean.
index d461b23a27a1176decc9229edf45c8ae1c388472..353ce9039a86f477ac13897bb76ab522c718ab87 100644 (file)
@@ -600,7 +600,7 @@ static int prep_new_page(struct page *page, int order, gfp_t gfp_flags)
 
        page->flags &= ~(1 << PG_uptodate | 1 << PG_error |
                        1 << PG_referenced | 1 << PG_arch_1 |
-                       1 << PG_checked | 1 << PG_mappedtodisk);
+                       1 << PG_owner_priv_1 | 1 << PG_mappedtodisk);
        set_page_private(page, 0);
        set_page_refcounted(page);
 
@@ -664,6 +664,26 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order,
        return i;
 }
 
+#if MAX_NUMNODES > 1
+int nr_node_ids __read_mostly;
+EXPORT_SYMBOL(nr_node_ids);
+
+/*
+ * Figure out the number of possible node ids.
+ */
+static void __init setup_nr_node_ids(void)
+{
+       unsigned int node;
+       unsigned int highest = 0;
+
+       for_each_node_mask(node, node_possible_map)
+               highest = node;
+       nr_node_ids = highest + 1;
+}
+#else
+static void __init setup_nr_node_ids(void) {}
+#endif
+
 #ifdef CONFIG_NUMA
 /*
  * Called from the slab reaper to drain pagesets on a particular node that
@@ -2944,6 +2964,7 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn)
                                                early_node_map[i].end_pfn);
 
        /* Initialise every node */
+       setup_nr_node_ids();
        for_each_online_node(nid) {
                pg_data_t *pgdat = NODE_DATA(nid);
                free_area_init_node(nid, pgdat, NULL,
@@ -3370,18 +3391,4 @@ EXPORT_SYMBOL(pfn_to_page);
 EXPORT_SYMBOL(page_to_pfn);
 #endif /* CONFIG_OUT_OF_LINE_PFN_TO_PAGE */
 
-#if MAX_NUMNODES > 1
-/*
- * Find the highest possible node id.
- */
-int highest_possible_node_id(void)
-{
-       unsigned int node;
-       unsigned int highest = 0;
 
-       for_each_node_mask(node, node_possible_map)
-               highest = node;
-       return highest;
-}
-EXPORT_SYMBOL(highest_possible_node_id);
-#endif
index 669acb22b572190ff2dcc6544c968bbd7516859e..22ed3f71a67421831f12b0deffa915eacf5d1db7 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -183,7 +183,7 @@ void __init anon_vma_init(void)
  */
 static struct anon_vma *page_lock_anon_vma(struct page *page)
 {
-       struct anon_vma *anon_vma = NULL;
+       struct anon_vma *anon_vma;
        unsigned long anon_mapping;
 
        rcu_read_lock();
@@ -195,9 +195,16 @@ static struct anon_vma *page_lock_anon_vma(struct page *page)
 
        anon_vma = (struct anon_vma *) (anon_mapping - PAGE_MAPPING_ANON);
        spin_lock(&anon_vma->lock);
+       return anon_vma;
 out:
        rcu_read_unlock();
-       return anon_vma;
+       return NULL;
+}
+
+static void page_unlock_anon_vma(struct anon_vma *anon_vma)
+{
+       spin_unlock(&anon_vma->lock);
+       rcu_read_unlock();
 }
 
 /*
@@ -333,7 +340,8 @@ static int page_referenced_anon(struct page *page)
                if (!mapcount)
                        break;
        }
-       spin_unlock(&anon_vma->lock);
+
+       page_unlock_anon_vma(anon_vma);
        return referenced;
 }
 
@@ -802,7 +810,8 @@ static int try_to_unmap_anon(struct page *page, int migration)
                if (ret == SWAP_FAIL || !page_mapped(page))
                        break;
        }
-       spin_unlock(&anon_vma->lock);
+
+       page_unlock_anon_vma(anon_vma);
        return ret;
 }
 
index 882053031aa0590b502551783c8902b50461abf1..b8c429a2d271b676d21840f095ec5449000424db 100644 (file)
@@ -175,7 +175,7 @@ static inline void shmem_unacct_blocks(unsigned long flags, long pages)
                vm_unacct_memory(pages * VM_ACCT(PAGE_CACHE_SIZE));
 }
 
-static struct super_operations shmem_ops;
+static const struct super_operations shmem_ops;
 static const struct address_space_operations shmem_aops;
 static const struct file_operations shmem_file_operations;
 static const struct inode_operations shmem_inode_operations;
@@ -1228,7 +1228,8 @@ failed:
        return error;
 }
 
-struct page *shmem_nopage(struct vm_area_struct *vma, unsigned long address, int *type)
+static struct page *shmem_nopage(struct vm_area_struct *vma,
+                                unsigned long address, int *type)
 {
        struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
        struct page *page = NULL;
@@ -1335,7 +1336,7 @@ out_nomem:
        return retval;
 }
 
-int shmem_mmap(struct file *file, struct vm_area_struct *vma)
+static int shmem_mmap(struct file *file, struct vm_area_struct *vma)
 {
        file_accessed(file);
        vma->vm_ops = &shmem_vm_ops;
@@ -2382,7 +2383,7 @@ static const struct inode_operations shmem_special_inode_operations = {
 #endif
 };
 
-static struct super_operations shmem_ops = {
+static const struct super_operations shmem_ops = {
        .alloc_inode    = shmem_alloc_inode,
        .destroy_inode  = shmem_destroy_inode,
 #ifdef CONFIG_TMPFS
index 70784b848b69b475718f0090033770b7c17b511b..57f7aa4200640e78cd1207e2a39dbbd4d310c8ac 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1042,7 +1042,7 @@ static void *alternate_node_alloc(struct kmem_cache *, gfp_t);
 static struct array_cache **alloc_alien_cache(int node, int limit)
 {
        struct array_cache **ac_ptr;
-       int memsize = sizeof(void *) * MAX_NUMNODES;
+       int memsize = sizeof(void *) * nr_node_ids;
        int i;
 
        if (limit > 1)
@@ -4026,7 +4026,7 @@ void drain_array(struct kmem_cache *cachep, struct kmem_list3 *l3,
 
 /**
  * cache_reap - Reclaim memory from caches.
- * @unused: unused parameter
+ * @w: work descriptor
  *
  * Called from workqueue/eventd every few seconds.
  * Purpose:
index c7f6e1914bc4e77264591f02958c32f1f8af1d93..8803471593fd7135ded6359d2a249c39a0d29815 100644 (file)
@@ -126,6 +126,7 @@ int shmem_unuse(swp_entry_t entry, struct page *page)
        return 0;
 }
 
+#if 0
 int shmem_mmap(struct file *file, struct vm_area_struct *vma)
 {
        file_accessed(file);
@@ -135,6 +136,7 @@ int shmem_mmap(struct file *file, struct vm_area_struct *vma)
        return 0;
 #endif
 }
+#endif  /*  0  */
 
 #ifndef CONFIG_MMU
 unsigned long shmem_get_unmapped_area(struct file *file,
index ebf3fcb4115b8c664e54e4c47e02968ed93ab0be..0f4b6d18ab0ed663360e0fba11f46f23e8c6b5b3 100644 (file)
@@ -375,10 +375,10 @@ int invalidate_inode_pages2_range(struct address_space *mapping,
 
        pagevec_init(&pvec, 0);
        next = start;
-       while (next <= end && !ret && !wrapped &&
+       while (next <= end && !wrapped &&
                pagevec_lookup(&pvec, mapping, next,
                        min(end - next, (pgoff_t)PAGEVEC_SIZE - 1) + 1)) {
-               for (i = 0; !ret && i < pagevec_count(&pvec); i++) {
+               for (i = 0; i < pagevec_count(&pvec); i++) {
                        struct page *page = pvec.pages[i];
                        pgoff_t page_index;
 
index 0655d5fe73e82c164043bf99958397602d6846c7..db023e2ff3852f544c6a4b0f8cb3b43ecd0d456b 100644 (file)
@@ -952,7 +952,7 @@ static unsigned long shrink_zone(int priority, struct zone *zone,
                }
        }
 
-       throttle_vm_writeout();
+       throttle_vm_writeout(sc->gfp_mask);
 
        atomic_dec(&zone->reclaim_in_progress);
        return nr_reclaimed;
index c1c205fad4fbc34cde3ba9474a269a42337959af..eb1c71ed7dfe928c80e39701138fd7a0f52160d1 100644 (file)
@@ -184,14 +184,23 @@ struct net_device *__find_vlan_dev(struct net_device *real_dev,
        struct vlan_group *grp = __vlan_find_group(real_dev->ifindex);
 
        if (grp)
-               return grp->vlan_devices[VID];
+               return vlan_group_get_device(grp, VID);
 
        return NULL;
 }
 
+static void vlan_group_free(struct vlan_group *grp)
+{
+       int i;
+
+       for (i=0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++)
+               kfree(grp->vlan_devices_arrays[i]);
+       kfree(grp);
+}
+
 static void vlan_rcu_free(struct rcu_head *rcu)
 {
-       kfree(container_of(rcu, struct vlan_group, rcu));
+       vlan_group_free(container_of(rcu, struct vlan_group, rcu));
 }
 
 
@@ -223,7 +232,7 @@ static int unregister_vlan_dev(struct net_device *real_dev,
        ret = 0;
 
        if (grp) {
-               dev = grp->vlan_devices[vlan_id];
+               dev = vlan_group_get_device(grp, vlan_id);
                if (dev) {
                        /* Remove proc entry */
                        vlan_proc_rem_dev(dev);
@@ -237,7 +246,7 @@ static int unregister_vlan_dev(struct net_device *real_dev,
                                real_dev->vlan_rx_kill_vid(real_dev, vlan_id);
                        }
 
-                       grp->vlan_devices[vlan_id] = NULL;
+                       vlan_group_set_device(grp, vlan_id, NULL);
                        synchronize_net();
 
 
@@ -251,7 +260,7 @@ static int unregister_vlan_dev(struct net_device *real_dev,
                         * group.
                         */
                        for (i = 0; i < VLAN_VID_MASK; i++)
-                               if (grp->vlan_devices[i])
+                               if (vlan_group_get_device(grp, i))
                                        break;
 
                        if (i == VLAN_VID_MASK) {
@@ -379,6 +388,7 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
        struct net_device *new_dev;
        struct net_device *real_dev; /* the ethernet device */
        char name[IFNAMSIZ];
+       int i;
 
 #ifdef VLAN_DEBUG
        printk(VLAN_DBG "%s: if_name -:%s:-     vid: %i\n",
@@ -544,6 +554,15 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
                if (!grp)
                        goto out_free_unregister;
 
+               for (i=0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) {
+                       grp->vlan_devices_arrays[i] = kzalloc(
+                               sizeof(struct net_device *)*VLAN_GROUP_ARRAY_PART_LEN,
+                               GFP_KERNEL);
+
+                       if (!grp->vlan_devices_arrays[i])
+                               goto out_free_arrays;
+               }
+
                /* printk(KERN_ALERT "VLAN REGISTER:  Allocated new group.\n"); */
                grp->real_dev_ifindex = real_dev->ifindex;
 
@@ -554,7 +573,7 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
                        real_dev->vlan_rx_register(real_dev, grp);
        }
 
-       grp->vlan_devices[VLAN_ID] = new_dev;
+       vlan_group_set_device(grp, VLAN_ID, new_dev);
 
        if (vlan_proc_add_dev(new_dev)<0)/* create it's proc entry */
                printk(KERN_WARNING "VLAN: failed to add proc entry for %s\n",
@@ -571,6 +590,9 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
 #endif
        return new_dev;
 
+out_free_arrays:
+       vlan_group_free(grp);
+
 out_free_unregister:
        unregister_netdev(new_dev);
        goto out_unlock;
@@ -606,7 +628,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
        case NETDEV_CHANGE:
                /* Propagate real device state to vlan devices */
                for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
-                       vlandev = grp->vlan_devices[i];
+                       vlandev = vlan_group_get_device(grp, i);
                        if (!vlandev)
                                continue;
 
@@ -617,7 +639,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
        case NETDEV_DOWN:
                /* Put all VLANs for this dev in the down state too.  */
                for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
-                       vlandev = grp->vlan_devices[i];
+                       vlandev = vlan_group_get_device(grp, i);
                        if (!vlandev)
                                continue;
 
@@ -632,7 +654,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
        case NETDEV_UP:
                /* Put all VLANs for this dev in the up state too.  */
                for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
-                       vlandev = grp->vlan_devices[i];
+                       vlandev = vlan_group_get_device(grp, i);
                        if (!vlandev)
                                continue;
 
@@ -649,7 +671,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
                for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
                        int ret;
 
-                       vlandev = grp->vlan_devices[i];
+                       vlandev = vlan_group_get_device(grp, i);
                        if (!vlandev)
                                continue;
 
index f928d2b2a17dac5c81a7660108e895b5640a1263..71f5cfbbebb834ce1ffa3283cde1f00db372b580 100644 (file)
@@ -656,7 +656,7 @@ static int hci_sock_dev_event(struct notifier_block *this, unsigned long event,
                /* Detach sockets from device */
                read_lock(&hci_sk_list.lock);
                sk_for_each(sk, node, &hci_sk_list.head) {
-                       bh_lock_sock(sk);
+                       lock_sock(sk);
                        if (hci_pi(sk)->hdev == hdev) {
                                hci_pi(sk)->hdev = NULL;
                                sk->sk_err = EPIPE;
@@ -665,7 +665,7 @@ static int hci_sock_dev_event(struct notifier_block *this, unsigned long event,
 
                                hci_dev_put(hdev);
                        }
-                       bh_unlock_sock(sk);
+                       release_sock(sk);
                }
                read_unlock(&hci_sk_list.lock);
        }
index c6abf2a5a9326e5a704a8ec5c8c647843033a891..98fdfa1fbddda7054b84e67d3e10bda033e80a4b 100644 (file)
@@ -1,6 +1,7 @@
 config BT_HIDP
        tristate "HIDP protocol support"
        depends on BT && BT_L2CAP && INPUT
+       select HID
        help
          HIDP (Human Interface Device Protocol) is a transport layer
          for HID reports.  HIDP is required for the Bluetooth Human
index 4b99c5e4478da77c099190daea614244ada030d3..4c914df5fd06aa479fbeca16a3b98becc6fda939 100644 (file)
@@ -38,6 +38,7 @@
 #include <net/sock.h>
 
 #include <linux/input.h>
+#include <linux/hid.h>
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
@@ -50,7 +51,7 @@
 #define BT_DBG(D...)
 #endif
 
-#define VERSION "1.1"
+#define VERSION "1.2"
 
 static DECLARE_RWSEM(hidp_session_sem);
 static LIST_HEAD(hidp_session_list);
@@ -124,15 +125,22 @@ static void __hidp_copy_session(struct hidp_session *session, struct hidp_connin
                else
                        strncpy(ci->name, "HID Boot Device", 128);
        }
+
+       if (session->hid) {
+               ci->vendor  = session->hid->vendor;
+               ci->product = session->hid->product;
+               ci->version = session->hid->version;
+               strncpy(ci->name, session->hid->name, 128);
+       }
 }
 
-static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+static inline int hidp_queue_event(struct hidp_session *session, struct input_dev *dev,
+                                       unsigned int type, unsigned int code, int value)
 {
-       struct hidp_session *session = dev->private;
-       struct sk_buff *skb;
        unsigned char newleds;
+       struct sk_buff *skb;
 
-       BT_DBG("input %p type %d code %d value %d", dev, type, code, value);
+       BT_DBG("session %p type %d code %d value %d", session, type, code, value);
 
        if (type != EV_LED)
                return -1;
@@ -164,6 +172,21 @@ static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned i
        return 0;
 }
 
+static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+{
+       struct hid_device *hid = dev->private;
+       struct hidp_session *session = hid->driver_data;
+
+       return hidp_queue_event(session, dev, type, code, value);
+}
+
+static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+{
+       struct hidp_session *session = dev->private;
+
+       return hidp_queue_event(session, dev, type, code, value);
+}
+
 static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
 {
        struct input_dev *dev = session->input;
@@ -219,6 +242,42 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
        input_sync(dev);
 }
 
+static inline int hidp_queue_report(struct hidp_session *session, unsigned char *data, int size)
+{
+       struct sk_buff *skb;
+
+       BT_DBG("session %p hid %p data %p size %d", session, device, data, size);
+
+       if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) {
+               BT_ERR("Can't allocate memory for new frame");
+               return -ENOMEM;
+       }
+
+       *skb_put(skb, 1) = 0xa2;
+       if (size > 0)
+               memcpy(skb_put(skb, size), data, size);
+
+       skb_queue_tail(&session->intr_transmit, skb);
+
+       hidp_schedule(session);
+
+       return 0;
+}
+
+static int hidp_send_report(struct hidp_session *session, struct hid_report *report)
+{
+       unsigned char buf[32];
+       int rsize;
+
+       rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0);
+       if (rsize > sizeof(buf))
+               return -EIO;
+
+       hid_output_report(report, buf);
+
+       return hidp_queue_report(session, buf, rsize);
+}
+
 static void hidp_idle_timeout(unsigned long arg)
 {
        struct hidp_session *session = (struct hidp_session *) arg;
@@ -346,6 +405,10 @@ static inline void hidp_process_data(struct hidp_session *session, struct sk_buf
 
                if (session->input)
                        hidp_input_report(session, skb);
+
+               if (session->hid)
+                       hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
+
                break;
 
        case HIDP_DATA_RTYPE_OTHER:
@@ -404,8 +467,14 @@ static inline void hidp_recv_intr_frame(struct hidp_session *session, struct sk_
 
        if (hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
                hidp_set_timer(session);
+
                if (session->input)
                        hidp_input_report(session, skb);
+
+               if (session->hid) {
+                       hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1);
+                       BT_DBG("report len %d", skb->len);
+               }
        } else {
                BT_DBG("Unsupported protocol header 0x%02x", hdr);
        }
@@ -471,6 +540,11 @@ static int hidp_session(void *arg)
                product = session->input->id.product;
        }
 
+       if (session->hid) {
+               vendor  = session->hid->vendor;
+               product = session->hid->product;
+       }
+
        daemonize("khidpd_%04x%04x", vendor, product);
        set_user_nice(current, -15);
        current->flags |= PF_NOFREEZE;
@@ -521,6 +595,12 @@ static int hidp_session(void *arg)
                session->input = NULL;
        }
 
+       if (session->hid) {
+               if (session->hid->claimed & HID_CLAIMED_INPUT)
+                       hidinput_disconnect(session->hid);
+               hid_free_device(session->hid);
+       }
+
        up_write(&hidp_session_sem);
 
        kfree(session);
@@ -590,6 +670,56 @@ static inline void hidp_setup_input(struct hidp_session *session, struct hidp_co
        input_register_device(input);
 }
 
+static int hidp_open(struct hid_device *hid)
+{
+       return 0;
+}
+
+static void hidp_close(struct hid_device *hid)
+{
+}
+
+static inline void hidp_setup_hid(struct hidp_session *session, struct hidp_connadd_req *req)
+{
+       struct hid_device *hid = session->hid;
+       struct hid_report *report;
+       bdaddr_t src, dst;
+
+       baswap(&src, &bt_sk(session->ctrl_sock->sk)->src);
+       baswap(&dst, &bt_sk(session->ctrl_sock->sk)->dst);
+
+       hid->driver_data = session;
+
+       hid->country = req->country;
+
+       hid->bus     = BUS_BLUETOOTH;
+       hid->vendor  = req->vendor;
+       hid->product = req->product;
+       hid->version = req->version;
+
+       strncpy(hid->name, req->name, 128);
+       strncpy(hid->phys, batostr(&src), 64);
+       strncpy(hid->uniq, batostr(&dst), 64);
+
+       hid->dev = hidp_get_device(session);
+
+       hid->hid_open  = hidp_open;
+       hid->hid_close = hidp_close;
+
+       hid->hidinput_input_event = hidp_hidinput_event;
+
+       list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list)
+               hidp_send_report(session, report);
+
+       list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
+               hidp_send_report(session, report);
+
+       if (hidinput_connect(hid) == 0) {
+               hid->claimed |= HID_CLAIMED_INPUT;
+               hid_ff_init(hid);
+       }
+}
+
 int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
 {
        struct hidp_session *session, *s;
@@ -605,10 +735,38 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
        if (!session)
                return -ENOMEM;
 
-       session->input = input_allocate_device();
-       if (!session->input) {
-               kfree(session);
-               return -ENOMEM;
+       BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size);
+
+       if (req->rd_size > 0) {
+               unsigned char *buf = kmalloc(req->rd_size, GFP_KERNEL);
+
+               if (!buf) {
+                       kfree(session);
+                       return -ENOMEM;
+               }
+
+               if (copy_from_user(buf, req->rd_data, req->rd_size)) {
+                       kfree(buf);
+                       kfree(session);
+                       return -EFAULT;
+               }
+
+               session->hid = hid_parse_report(buf, req->rd_size);
+
+               kfree(buf);
+
+               if (!session->hid) {
+                       kfree(session);
+                       return -EINVAL;
+               }
+       }
+
+       if (!session->hid) {
+               session->input = input_allocate_device();
+               if (!session->input) {
+                       kfree(session);
+                       return -ENOMEM;
+               }
        }
 
        down_write(&hidp_session_sem);
@@ -644,6 +802,9 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
        if (session->input)
                hidp_setup_input(session, req);
 
+       if (session->hid)
+               hidp_setup_hid(session, req);
+
        __hidp_link_session(session);
 
        hidp_set_timer(session);
@@ -677,6 +838,9 @@ unlink:
 failed:
        up_write(&hidp_session_sem);
 
+       if (session->hid)
+               hid_free_device(session->hid);
+
        kfree(session->input);
        kfree(session);
        return err;
index a326601c8f414473a2345404c783003355cdc9d8..343fb0566b3ee73a244a9ce269e482c8578603fe 100644 (file)
@@ -145,6 +145,8 @@ struct hidp_session {
 
        struct input_dev *input;
 
+       struct hid_device *hid;
+
        struct timer_list timer;
 
        struct sk_buff_head ctrl_transmit;
index 8b8a6c1dbd9905534628f492f8d329e03d6f71ff..0c185257e55bbbe65933a57f6991930b149d2c62 100644 (file)
@@ -194,7 +194,7 @@ static int hidp_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigne
                if (put_user(ca.ctrl_sock, &uca->ctrl_sock) ||
                                put_user(ca.intr_sock, &uca->intr_sock) ||
                                put_user(ca.parser, &uca->parser) ||
-                               put_user(ca.rd_size, &uca->parser) ||
+                               put_user(ca.rd_size, &uca->rd_size) ||
                                put_user(compat_ptr(ca.rd_data), &uca->rd_data) ||
                                put_user(ca.country, &uca->country) ||
                                put_user(ca.subclass, &uca->subclass) ||
index 8cd82dce5008cf3e575229026e82281834847656..9a7a44fc721ffd9afb6daba5638f097de4462125 100644 (file)
@@ -74,6 +74,8 @@ struct rfcomm_dev {
        wait_queue_head_t       wait;
        struct tasklet_struct   wakeup_task;
 
+       struct device           *tty_dev;
+
        atomic_t                wmem_alloc;
 };
 
@@ -261,7 +263,7 @@ out:
                return err;
        }
 
-       tty_register_device(rfcomm_tty_driver, dev->id, rfcomm_get_device(dev));
+       dev->tty_dev = tty_register_device(rfcomm_tty_driver, dev->id, NULL);
 
        return dev->id;
 }
@@ -630,6 +632,9 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
        set_current_state(TASK_RUNNING);
        remove_wait_queue(&dev->wait, &wait);
 
+       if (err == 0)
+               device_move(dev->tty_dev, rfcomm_get_device(dev));
+
        return err;
 }
 
@@ -642,6 +647,8 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
        BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc, dev->opened);
 
        if (--dev->opened == 0) {
+               device_move(dev->tty_dev, NULL);
+
                /* Close DLC and dettach TTY */
                rfcomm_dlc_close(dev->dlc, 0);
 
index aff6a779c9c82e1df96417f55d086656fc6274cc..f3a2e29be40c30b173f447bc5ee412cf28c2dcc4 100644 (file)
@@ -77,26 +77,15 @@ static int port_cost(struct net_device *dev)
  * Called from work queue to allow for calling functions that
  * might sleep (such as speed check), and to debounce.
  */
-static void port_carrier_check(struct work_struct *work)
+void br_port_carrier_check(struct net_bridge_port *p)
 {
-       struct net_bridge_port *p;
-       struct net_device *dev;
-       struct net_bridge *br;
-
-       dev = container_of(work, struct net_bridge_port,
-                          carrier_check.work)->dev;
-       work_release(work);
-
-       rtnl_lock();
-       p = dev->br_port;
-       if (!p)
-               goto done;
-       br = p->br;
+       struct net_device *dev = p->dev;
+       struct net_bridge *br = p->br;
 
        if (netif_carrier_ok(dev))
                p->path_cost = port_cost(dev);
 
-       if (br->dev->flags & IFF_UP) {
+       if (netif_running(br->dev)) {
                spin_lock_bh(&br->lock);
                if (netif_carrier_ok(dev)) {
                        if (p->state == BR_STATE_DISABLED)
@@ -107,9 +96,6 @@ static void port_carrier_check(struct work_struct *work)
                }
                spin_unlock_bh(&br->lock);
        }
-done:
-       dev_put(dev);
-       rtnl_unlock();
 }
 
 static void release_nbp(struct kobject *kobj)
@@ -162,9 +148,6 @@ static void del_nbp(struct net_bridge_port *p)
 
        dev_set_promiscuity(dev, -1);
 
-       if (cancel_delayed_work(&p->carrier_check))
-               dev_put(dev);
-
        spin_lock_bh(&br->lock);
        br_stp_disable_port(p);
        spin_unlock_bh(&br->lock);
@@ -282,7 +265,6 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
        p->port_no = index;
        br_init_port(p);
        p->state = BR_STATE_DISABLED;
-       INIT_DELAYED_WORK_NAR(&p->carrier_check, port_carrier_check);
        br_stp_port_timer_init(p);
 
        kobject_init(&p->kobj);
@@ -446,12 +428,14 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
        spin_lock_bh(&br->lock);
        br_stp_recalculate_bridge_id(br);
        br_features_recompute(br);
-       if (schedule_delayed_work(&p->carrier_check, BR_PORT_DEBOUNCE))
-               dev_hold(dev);
 
+       if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) &&
+           (br->dev->flags & IFF_UP))
+               br_stp_enable_port(p);
        spin_unlock_bh(&br->lock);
 
        dev_set_mtu(br->dev, br_min_mtu(br));
+
        kobject_uevent(&p->kobj, KOBJ_ADD);
 
        return 0;
index 3ab153d3c508810007da27fb9ca846a0a2ead0b0..147015fe5c75c910cb3e4c990f104523d24b212c 100644 (file)
@@ -291,12 +291,11 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
 
-               spin_lock_bh(&br->lock);
                if ((p = br_get_port(br, args[1])) == NULL)
                        ret = -EINVAL;
                else
                        br_stp_set_path_cost(p, args[2]);
-               spin_unlock_bh(&br->lock);
+
                return ret;
        }
 
index 3311c4e30829ed93c6e3ce2d004f956eb8e60758..37357ed2149b53056b192930335077ae6510ae25 100644 (file)
@@ -42,51 +42,48 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
 
        br = p->br;
 
-       spin_lock_bh(&br->lock);
        switch (event) {
        case NETDEV_CHANGEMTU:
                dev_set_mtu(br->dev, br_min_mtu(br));
                break;
 
        case NETDEV_CHANGEADDR:
+               spin_lock_bh(&br->lock);
                br_fdb_changeaddr(p, dev->dev_addr);
                br_ifinfo_notify(RTM_NEWLINK, p);
                br_stp_recalculate_bridge_id(br);
+               spin_unlock_bh(&br->lock);
                break;
 
        case NETDEV_CHANGE:
-               if (br->dev->flags & IFF_UP)
-                       if (schedule_delayed_work(&p->carrier_check,
-                                               BR_PORT_DEBOUNCE))
-                               dev_hold(dev);
+               br_port_carrier_check(p);
                break;
 
        case NETDEV_FEAT_CHANGE:
-               if (br->dev->flags & IFF_UP)
+               spin_lock_bh(&br->lock);
+               if (netif_running(br->dev))
                        br_features_recompute(br);
-
-               /* could do recursive feature change notification
-                * but who would care??
-                */
+               spin_unlock_bh(&br->lock);
                break;
 
        case NETDEV_DOWN:
+               spin_lock_bh(&br->lock);
                if (br->dev->flags & IFF_UP)
                        br_stp_disable_port(p);
+               spin_unlock_bh(&br->lock);
                break;
 
        case NETDEV_UP:
+               spin_lock_bh(&br->lock);
                if (netif_carrier_ok(dev) && (br->dev->flags & IFF_UP))
                        br_stp_enable_port(p);
+               spin_unlock_bh(&br->lock);
                break;
 
        case NETDEV_UNREGISTER:
-               spin_unlock_bh(&br->lock);
                br_del_if(br, dev);
-               goto done;
+               break;
        }
-       spin_unlock_bh(&br->lock);
 
- done:
        return NOTIFY_DONE;
 }
index 6a0540e0591e93593d547ff35cafe1e00da50799..cc3f1c99261a94cede4ba05164e6ff9f6f684b85 100644 (file)
@@ -16,7 +16,6 @@
 #define _BR_PRIVATE_H
 
 #include <linux/netdevice.h>
-#include <linux/miscdevice.h>
 #include <linux/if_bridge.h>
 
 #define BR_HASH_BITS 8
@@ -27,8 +26,6 @@
 #define BR_PORT_BITS   10
 #define BR_MAX_PORTS   (1<<BR_PORT_BITS)
 
-#define BR_PORT_DEBOUNCE (HZ/10)
-
 #define BR_VERSION     "2.2"
 
 typedef struct bridge_id bridge_id;
@@ -82,7 +79,6 @@ struct net_bridge_port
        struct timer_list               hold_timer;
        struct timer_list               message_age_timer;
        struct kobject                  kobj;
-       struct delayed_work             carrier_check;
        struct rcu_head                 rcu;
 };
 
@@ -173,6 +169,7 @@ extern void br_flood_forward(struct net_bridge *br,
                      int clone);
 
 /* br_if.c */
+extern void br_port_carrier_check(struct net_bridge_port *p);
 extern int br_add_bridge(const char *name);
 extern int br_del_bridge(const char *name);
 extern void br_cleanup_bridges(void);
index 34c49799f9b303a11d70c3c1f6839fe403a2e43c..ac9984f98e5959b62691f8db87e801768972ee45 100644 (file)
@@ -833,8 +833,7 @@ static int translate_table(char *name, struct ebt_table_info *newinfo)
                /* this will get free'd in do_replace()/ebt_register_table()
                   if an error occurs */
                newinfo->chainstack =
-                       vmalloc((highest_possible_processor_id()+1)
-                                       * sizeof(*(newinfo->chainstack)));
+                       vmalloc(nr_cpu_ids * sizeof(*(newinfo->chainstack)));
                if (!newinfo->chainstack)
                        return -ENOMEM;
                for_each_possible_cpu(i) {
@@ -947,8 +946,7 @@ static int do_replace(void __user *user, unsigned int len)
        if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
                return -ENOMEM;
 
-       countersize = COUNTER_OFFSET(tmp.nentries) *
-                                       (highest_possible_processor_id()+1);
+       countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
        newinfo = vmalloc(sizeof(*newinfo) + countersize);
        if (!newinfo)
                return -ENOMEM;
@@ -1168,8 +1166,7 @@ int ebt_register_table(struct ebt_table *table)
                return -EINVAL;
        }
 
-       countersize = COUNTER_OFFSET(repl->nentries) *
-                                       (highest_possible_processor_id()+1);
+       countersize = COUNTER_OFFSET(repl->nentries) * nr_cpu_ids;
        newinfo = vmalloc(sizeof(*newinfo) + countersize);
        ret = -ENOMEM;
        if (!newinfo)
index f89ff151cfabff32a6436c98fef66e243118bc20..820761f9eeef92df8929a1517e04e81779148d2c 100644 (file)
@@ -2037,7 +2037,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features)
 err:
        while ((skb = segs)) {
                segs = skb->next;
-               kfree(skb);
+               kfree_skb(skb);
        }
        return ERR_PTR(err);
 }
index e9986acdd0ab0920f5283801484619926907542f..8d65d6478dcde0dd52ff1c28958aa2e03ebf160f 100644 (file)
@@ -1597,7 +1597,7 @@ int compat_sock_common_getsockopt(struct socket *sock, int level, int optname,
 {
        struct sock *sk = sock->sk;
 
-       if (sk->sk_prot->compat_setsockopt != NULL)
+       if (sk->sk_prot->compat_getsockopt != NULL)
                return sk->sk_prot->compat_getsockopt(sk, level, optname,
                                                      optval, optlen);
        return sk->sk_prot->getsockopt(sk, level, optname, optval, optlen);
index 5361a4d8e13b54dc8d18ca2ea3fd959745928d06..746f79d104b3557fdb5883d744fe287abde35fd5 100644 (file)
@@ -545,12 +545,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
                /* set idle flag */
                hctx->ccid3hctx_idle = 1;
                break;
-       case TFRC_SSTATE_NO_SENT:
-               /*
-                * XXX when implementing bidirectional rx/tx check this again
-                */
-               DCCP_WARN("Illegal ACK received - no packet sent\n");
-               /* fall through */
+       case TFRC_SSTATE_NO_SENT:       /* fall through */
        case TFRC_SSTATE_TERM:          /* ignore feedback when closing */
                break;
        }
index e33a9edb40363ef7c964de7de3eb55c0c81d7846..a0e7cd183a5d3e648d40bf81b6a3d6420c9931bd 100644 (file)
@@ -191,6 +191,7 @@ extern void dccp_send_sync(struct sock *sk, const u64 seq,
                           const enum dccp_pkt_type pkt_type);
 
 extern void dccp_write_xmit(struct sock *sk, int block);
+extern void dccp_write_xmit_timer(unsigned long data);
 extern void dccp_write_space(struct sock *sk);
 
 extern void dccp_init_xmit_timers(struct sock *sk);
index 4dee462f00db2c11fab14f709e15d8f6cd97432a..78b043c458bf95ac78aab62526408e09a72f8f00 100644 (file)
@@ -248,18 +248,8 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
                            DCCP_ACKVEC_STATE_RECEIVED))
                goto discard;
 
-       /*
-        * Deliver to the CCID module in charge.
-        * FIXME: Currently DCCP operates one-directional only, i.e. a listening
-        *        server is not at the same time a connecting client. There is
-        *        not much sense in delivering to both rx/tx sides at the moment
-        *        (only one is active at a time); when moving to bidirectional
-        *        service, this needs to be revised.
-        */
-       if (dccp_sk(sk)->dccps_role == DCCP_ROLE_SERVER)
-               ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
-       else
-               ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
+       ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
+       ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
 
        return __dccp_rcv_established(sk, skb, dh, len);
 discard:
@@ -494,11 +484,8 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                                    DCCP_ACKVEC_STATE_RECEIVED))
                        goto discard;
 
-               /* XXX see the comments in dccp_rcv_established about this */
-               if (dccp_sk(sk)->dccps_role == DCCP_ROLE_SERVER)
-                       ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
-               else
-                       ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
+               ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
+               ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
        }
 
        /*
index 6656bb497c7bde44aa37520cb5e65781b24179a6..6d235b3013dd3262b8185fa61e06690bad6eccc9 100644 (file)
@@ -103,7 +103,7 @@ struct sock *dccp_create_openreq_child(struct sock *sk,
 
        if (newsk != NULL) {
                const struct dccp_request_sock *dreq = dccp_rsk(req);
-               struct inet_connection_sock *newicsk = inet_csk(sk);
+               struct inet_connection_sock *newicsk = inet_csk(newsk);
                struct dccp_sock *newdp = dccp_sk(newsk);
                struct dccp_minisock *newdmsk = dccp_msk(newsk);
 
index f5c6aca1dfa45557a31ed6f9fe0a9b0d4f109a9f..aa21cc4de37f7b77c84cd38d6d901a1027810471 100644 (file)
@@ -213,19 +213,6 @@ do_interrupted:
        goto out;
 }
 
-static void dccp_write_xmit_timer(unsigned long data) {
-       struct sock *sk = (struct sock *)data;
-       struct dccp_sock *dp = dccp_sk(sk);
-
-       bh_lock_sock(sk);
-       if (sock_owned_by_user(sk))
-               sk_reset_timer(sk, &dp->dccps_xmit_timer, jiffies+1);
-       else
-               dccp_write_xmit(sk, 0);
-       bh_unlock_sock(sk);
-       sock_put(sk);
-}
-
 void dccp_write_xmit(struct sock *sk, int block)
 {
        struct dccp_sock *dp = dccp_sk(sk);
@@ -269,7 +256,7 @@ void dccp_write_xmit(struct sock *sk, int block)
                                         err);
                } else {
                        dccp_pr_debug("packet discarded\n");
-                       kfree(skb);
+                       kfree_skb(skb);
                }
        }
 }
@@ -434,9 +421,6 @@ static inline void dccp_connect_init(struct sock *sk)
        dp->dccps_gar = dp->dccps_iss;
 
        icsk->icsk_retransmits = 0;
-       init_timer(&dp->dccps_xmit_timer);
-       dp->dccps_xmit_timer.data = (unsigned long)sk;
-       dp->dccps_xmit_timer.function = dccp_write_xmit_timer;
 }
 
 int dccp_connect(struct sock *sk)
index 41ea0f6594c4a5b26e82247cddc3539f90f06001..b038a0a3ad40a1fcbc182c6f66e37a2171120144 100644 (file)
@@ -261,8 +261,33 @@ out:
        sock_put(sk);
 }
 
+/* Transmit-delay timer: used by the CCIDs to delay actual send time */
+void dccp_write_xmit_timer(unsigned long data)
+{
+       struct sock *sk = (struct sock *)data;
+       struct dccp_sock *dp = dccp_sk(sk);
+
+       bh_lock_sock(sk);
+       if (sock_owned_by_user(sk))
+               sk_reset_timer(sk, &dp->dccps_xmit_timer, jiffies+1);
+       else
+               dccp_write_xmit(sk, 0);
+       bh_unlock_sock(sk);
+       sock_put(sk);
+}
+
+static void dccp_init_write_xmit_timer(struct sock *sk)
+{
+       struct dccp_sock *dp = dccp_sk(sk);
+
+       init_timer(&dp->dccps_xmit_timer);
+       dp->dccps_xmit_timer.data = (unsigned long)sk;
+       dp->dccps_xmit_timer.function = dccp_write_xmit_timer;
+}
+
 void dccp_init_xmit_timers(struct sock *sk)
 {
+       dccp_init_write_xmit_timer(sk);
        inet_csk_init_xmit_timers(sk, &dccp_write_timer, &dccp_delack_timer,
                                  &dccp_keepalive_timer);
 }
index 4f8c3ef7081950b6e20157245b100dfca7f64065..e9cdc6615ddc7483447d34907205c907a39782a0 100644 (file)
@@ -265,17 +265,10 @@ void ieee80211softmac_init_bss(struct ieee80211softmac_device *mac)
        /* Change the default txrate to the highest possible value.
         * The txrate machine will lower it, if it is too high.
         */
-       /* FIXME: We don't correctly handle backing down to lower
-          rates, so 801.11g devices start off at 11M for now. People
-          can manually change it if they really need to, but 11M is
-          more reliable. Note similar logic in
-          ieee80211softmac_wx_set_rate() */
-       if (ieee->modulation & IEEE80211_CCK_MODULATION) {
+       if (ieee->modulation & IEEE80211_OFDM_MODULATION)
+               txrates->user_rate = IEEE80211_OFDM_RATE_24MB;
+       else
                txrates->user_rate = IEEE80211_CCK_RATE_11MB;
-       } else if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
-               txrates->user_rate = IEEE80211_OFDM_RATE_54MB;
-       } else
-               assert(0);
 
        txrates->default_rate = IEEE80211_CCK_RATE_1MB;
        change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
index c306d52566e0dfda1673b37a089a85dd40ea78a7..f13937bf9e8ce20f3b2c171948593795d082b8ee 100644 (file)
@@ -177,15 +177,10 @@ ieee80211softmac_wx_set_rate(struct net_device *net_dev,
        int err = -EINVAL;
 
        if (in_rate == -1) {
-               /* FIXME: We don't correctly handle backing down to lower
-                  rates, so 801.11g devices start off at 11M for now. People
-                  can manually change it if they really need to, but 11M is
-                  more reliable. Note similar logic in
-                  ieee80211softmac_wx_set_rate() */
-               if (ieee->modulation & IEEE80211_CCK_MODULATION)
-                       in_rate = 11000000;
+               if (ieee->modulation & IEEE80211_OFDM_MODULATION)
+                       in_rate = 24000000;
                else
-                       in_rate = 54000000;
+                       in_rate = 11000000;
        }
 
        switch (in_rate) {
index 91f3a5cdbcf84719034369bb376e904da614cb71..9e8ef509c51dde3ecb9f3941b4750ca44a3f82d7 100644 (file)
@@ -442,7 +442,7 @@ config INET_DIAG
        ---help---
          Support for INET (TCP, DCCP, etc) socket monitoring interface used by
          native Linux tools such as ss. ss is included in iproute2, currently
-         downloadable at <http://developer.osdl.org/dev/iproute2>. 
+         downloadable at <http://linux-net.osdl.org/index.php/Iproute2>.
          
          If unsure, say Y.
 
@@ -550,7 +550,7 @@ config TCP_CONG_SCALABLE
        Scalable TCP is a sender-side only change to TCP which uses a
        MIMD congestion control algorithm which has some nice scaling
        properties, though is known to have fairness issues.
-       See http://www-lce.eng.cam.ac.uk/~ctk21/scalable/
+       See http://www.deneholme.net/tom/scalable/
 
 config TCP_CONG_LP
        tristate "TCP Low Priority"
index 60aafb4a8adff56c8fa3fd54d664fd76e2ee7177..c976dd7e9758f5e4fbf9f0cfe38c0e68002154c1 100644 (file)
@@ -732,11 +732,12 @@ static int cipso_v4_map_lvl_hton(const struct cipso_v4_doi *doi_def,
                *net_lvl = host_lvl;
                return 0;
        case CIPSO_V4_MAP_STD:
-               if (host_lvl < doi_def->map.std->lvl.local_size) {
+               if (host_lvl < doi_def->map.std->lvl.local_size &&
+                   doi_def->map.std->lvl.local[host_lvl] < CIPSO_V4_INV_LVL) {
                        *net_lvl = doi_def->map.std->lvl.local[host_lvl];
                        return 0;
                }
-               break;
+               return -EPERM;
        }
 
        return -EINVAL;
@@ -771,7 +772,7 @@ static int cipso_v4_map_lvl_ntoh(const struct cipso_v4_doi *doi_def,
                        *host_lvl = doi_def->map.std->lvl.cipso[net_lvl];
                        return 0;
                }
-               break;
+               return -EPERM;
        }
 
        return -EINVAL;
index 8a0ec10a13a7370b536a63a20b6c6a4c0fd431c4..98a00d0edc760c658d23675eec194e8cefc79ae0 100644 (file)
@@ -502,8 +502,10 @@ static struct in_ifaddr *rtm_to_ifaddr(struct nlmsghdr *nlh)
                goto errout;
 
        ifm = nlmsg_data(nlh);
-       if (ifm->ifa_prefixlen > 32 || tb[IFA_LOCAL] == NULL)
+       if (ifm->ifa_prefixlen > 32 || tb[IFA_LOCAL] == NULL) {
+               err = -EINVAL;
                goto errout;
+       }
 
        dev = __dev_get_by_index(ifm->ifa_index);
        if (dev == NULL) {
@@ -1054,12 +1056,14 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
        ASSERT_RTNL();
 
        if (!in_dev) {
-               if (event == NETDEV_REGISTER && dev == &loopback_dev) {
+               if (event == NETDEV_REGISTER) {
                        in_dev = inetdev_init(dev);
                        if (!in_dev)
                                panic("devinet: Failed to create loopback\n");
-                       in_dev->cnf.no_xfrm = 1;
-                       in_dev->cnf.no_policy = 1;
+                       if (dev == &loopback_dev) {
+                               in_dev->cnf.no_xfrm = 1;
+                               in_dev->cnf.no_policy = 1;
+                       }
                }
                goto out;
        }
index 063721302ebf24faef796999f3aea0728950c116..1c6a084b5fb7adf9e4a77e9b1227afc97082b117 100644 (file)
@@ -1250,6 +1250,28 @@ out:
        return;
 }
 
+/*
+ *     Resend IGMP JOIN report; used for bonding.
+ */
+void ip_mc_rejoin_group(struct ip_mc_list *im)
+{
+       struct in_device *in_dev = im->interface;
+
+#ifdef CONFIG_IP_MULTICAST
+       if (im->multiaddr == IGMP_ALL_HOSTS)
+               return;
+
+       if (IGMP_V1_SEEN(in_dev) || IGMP_V2_SEEN(in_dev)) {
+               igmp_mod_timer(im, IGMP_Initial_Report_Delay);
+               return;
+       }
+       /* else, v3 */
+       im->crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
+               IGMP_Unsolicited_Report_Count;
+       igmp_ifc_event(in_dev);
+#endif
+}
+
 /*
  *     A socket has left a multicast group on device dev
  */
@@ -2596,3 +2618,4 @@ int __init igmp_mc_proc_init(void)
 EXPORT_SYMBOL(ip_mc_dec_group);
 EXPORT_SYMBOL(ip_mc_inc_group);
 EXPORT_SYMBOL(ip_mc_join_group);
+EXPORT_SYMBOL(ip_mc_rejoin_group);
index 57f481498fbb39d99338187b9a0653efbb692b7a..c312785d14d082af7c30994fa24e2d50f4ac18b4 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/module.h>
 #include <linux/mroute.h>
 #include <linux/init.h>
+#include <linux/random.h>
 #include <net/ip.h>
 #include <net/protocol.h>
 #include <linux/skbuff.h>
 
 #define MULTIPATH_MAX_CANDIDATES 40
 
-/* interface to random number generation */
-static unsigned int RANDOM_SEED = 93186752;
-
-static inline unsigned int random(unsigned int ubound)
-{
-       static unsigned int a = 1588635695,
-               q = 2,
-               r = 1117695901;
-
-       RANDOM_SEED = a*(RANDOM_SEED % q) - r*(RANDOM_SEED / q);
-
-       return RANDOM_SEED % ubound;
-}
-
-
 static void random_select_route(const struct flowi *flp,
                                struct rtable *first,
                                struct rtable **rp)
@@ -84,7 +70,7 @@ static void random_select_route(const struct flowi *flp,
        if (candidate_count > 1) {
                unsigned char i = 0;
                unsigned char candidate_no = (unsigned char)
-                       random(candidate_count);
+                       (random32() % candidate_count);
 
                /* find chosen candidate and adjust GC data for all candidates
                 * to ensure they stay in cache
index 2bdbb92b450adbf859501a5d83008d2521a80818..57c50369453934bb238cc5c98ccd873fd40362df 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/module.h>
 #include <linux/mroute.h>
 #include <linux/init.h>
+#include <linux/random.h>
 #include <net/ip.h>
 #include <net/protocol.h>
 #include <linux/skbuff.h>
@@ -84,18 +85,6 @@ struct multipath_route {
 /* state: primarily weight per route information */
 static struct multipath_bucket state[MULTIPATH_STATE_SIZE];
 
-/* interface to random number generation */
-static unsigned int RANDOM_SEED = 93186752;
-
-static inline unsigned int random(unsigned int ubound)
-{
-       static unsigned int a = 1588635695,
-               q = 2,
-               r = 1117695901;
-       RANDOM_SEED = a*(RANDOM_SEED % q) - r*(RANDOM_SEED / q);
-       return RANDOM_SEED % ubound;
-}
-
 static unsigned char __multipath_lookup_weight(const struct flowi *fl,
                                               const struct rtable *rt)
 {
@@ -193,7 +182,7 @@ static void wrandom_select_route(const struct flowi *flp,
 
        /* choose a weighted random candidate */
        decision = first;
-       selector = random(power);
+       selector = random32() % power;
        last_power = 0;
 
        /* select candidate, adjust GC data and cleanup local state */
index 07ba1dd136b5b2e711336cdb0828291d012edc54..23b99ae2cc37fffd07f5a38d4e6941a6fb44ebe3 100644 (file)
@@ -1254,7 +1254,7 @@ get_next_corpse(int (*iter)(struct ip_conntrack *i, void *data),
        list_for_each_entry(h, &unconfirmed, list) {
                ct = tuplehash_to_ctrack(h);
                if (iter(ct, data))
-                       goto found;
+                       set_bit(IPS_DYING_BIT, &ct->status);
        }
        write_unlock_bh(&ip_conntrack_lock);
        return NULL;
index 170d625fad67d7d7bc51878a937b597f8b8823f6..0a72eab146203e2ee208546638380c3662558578 100644 (file)
@@ -812,8 +812,10 @@ void ip_conntrack_tcp_update(struct sk_buff *skb,
 static const u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] =
 {
        [TH_SYN]                        = 1,
-       [TH_SYN|TH_ACK]                 = 1,
        [TH_SYN|TH_PUSH]                = 1,
+       [TH_SYN|TH_URG]                 = 1,
+       [TH_SYN|TH_PUSH|TH_URG]         = 1,
+       [TH_SYN|TH_ACK]                 = 1,
        [TH_SYN|TH_ACK|TH_PUSH]         = 1,
        [TH_RST]                        = 1,
        [TH_RST|TH_ACK]                 = 1,
index b984db771258f989f7a9499408ea0e4319c54e62..8f3e92d20df82ce0c402f947189025978259a29e 100644 (file)
@@ -379,8 +379,7 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len)
        return -ENOENT;
 }
 
-#if defined(CONFIG_NF_CT_NETLINK) || \
-    defined(CONFIG_NF_CT_NETLINK_MODULE)
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
 
 #include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter/nfnetlink_conntrack.h>
@@ -435,8 +434,7 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = {
        .print_conntrack = ipv4_print_conntrack,
        .prepare         = ipv4_prepare,
        .get_features    = ipv4_get_features,
-#if defined(CONFIG_NF_CT_NETLINK) || \
-    defined(CONFIG_NF_CT_NETLINK_MODULE)
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
        .tuple_to_nfattr = ipv4_tuple_to_nfattr,
        .nfattr_to_tuple = ipv4_nfattr_to_tuple,
 #endif
index 88cfa6aacfc150f81eb9d7d419d2400812aa8515..5fd1e5363c1ab60ed9ec1e3e70505247f79327e3 100644 (file)
@@ -268,8 +268,7 @@ icmp_error(struct sk_buff *skb, unsigned int dataoff,
        return icmp_error_message(skb, ctinfo, hooknum);
 }
 
-#if defined(CONFIG_NF_CT_NETLINK) || \
-    defined(CONFIG_NF_CT_NETLINK_MODULE)
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
 
 #include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter/nfnetlink_conntrack.h>
@@ -368,8 +367,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp =
        .error                  = icmp_error,
        .destroy                = NULL,
        .me                     = NULL,
-#if defined(CONFIG_NF_CT_NETLINK) || \
-    defined(CONFIG_NF_CT_NETLINK_MODULE)
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
        .tuple_to_nfattr        = icmp_tuple_to_nfattr,
        .nfattr_to_tuple        = icmp_nfattr_to_tuple,
 #endif
index 2c01378d35924fb3bfddbebce591a01a7d8502ed..452e9d326684448ddafe00a558e2c3571a61b509 100644 (file)
@@ -546,8 +546,7 @@ void nf_nat_protocol_unregister(struct nf_nat_protocol *proto)
 }
 EXPORT_SYMBOL(nf_nat_protocol_unregister);
 
-#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
-    defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
 int
 nf_nat_port_range_to_nfattr(struct sk_buff *skb,
                            const struct nf_nat_range *range)
index d3de579e09d225e32f2b01693830890c6aab3e70..e5a34c17d9271e21708efda147d7bc079e9f86ab 100644 (file)
@@ -152,8 +152,7 @@ static struct nf_nat_protocol gre __read_mostly = {
        .manip_pkt              = gre_manip_pkt,
        .in_range               = gre_in_range,
        .unique_tuple           = gre_unique_tuple,
-#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
-    defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
        .range_to_nfattr        = nf_nat_port_range_to_nfattr,
        .nfattr_to_range        = nf_nat_port_nfattr_to_range,
 #endif
index 6bc2f06de055952d6bad47434e860620cc0a8fd2..f71ef9b5f4283f5ec08e824e705f858484074b5a 100644 (file)
@@ -78,8 +78,7 @@ struct nf_nat_protocol nf_nat_protocol_icmp = {
        .manip_pkt              = icmp_manip_pkt,
        .in_range               = icmp_in_range,
        .unique_tuple           = icmp_unique_tuple,
-#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
-    defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
        .range_to_nfattr        = nf_nat_port_range_to_nfattr,
        .nfattr_to_range        = nf_nat_port_nfattr_to_range,
 #endif
index 439164c7a62664a0c632ebfa9d3cd0ad4bdf26d2..123c95913f2815aa6f2cde7071634b9de8c2c7dd 100644 (file)
@@ -144,8 +144,7 @@ struct nf_nat_protocol nf_nat_protocol_tcp = {
        .manip_pkt              = tcp_manip_pkt,
        .in_range               = tcp_in_range,
        .unique_tuple           = tcp_unique_tuple,
-#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
-    defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
        .range_to_nfattr        = nf_nat_port_range_to_nfattr,
        .nfattr_to_range        = nf_nat_port_nfattr_to_range,
 #endif
index 8cae6e063bb6331b4ce720af5957b84439983b2d..1c4c70e25cd4bf8135bfd3bcf8b9344ee653bb3b 100644 (file)
@@ -134,8 +134,7 @@ struct nf_nat_protocol nf_nat_protocol_udp = {
        .manip_pkt              = udp_manip_pkt,
        .in_range               = udp_in_range,
        .unique_tuple           = udp_unique_tuple,
-#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
-    defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
        .range_to_nfattr        = nf_nat_port_range_to_nfattr,
        .nfattr_to_range        = nf_nat_port_nfattr_to_range,
 #endif
index ac6516c642a1756fae602cb79e06cb42714df302..74c4d103ebc2f74e919983c53605941356ab21d3 100644 (file)
@@ -2266,12 +2266,12 @@ void tcp_free_md5sig_pool(void)
 {
        struct tcp_md5sig_pool **pool = NULL;
 
-       spin_lock(&tcp_md5sig_pool_lock);
+       spin_lock_bh(&tcp_md5sig_pool_lock);
        if (--tcp_md5sig_users == 0) {
                pool = tcp_md5sig_pool;
                tcp_md5sig_pool = NULL;
        }
-       spin_unlock(&tcp_md5sig_pool_lock);
+       spin_unlock_bh(&tcp_md5sig_pool_lock);
        if (pool)
                __tcp_free_md5sig_pool(pool);
 }
@@ -2314,36 +2314,36 @@ struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(void)
        int alloc = 0;
 
 retry:
-       spin_lock(&tcp_md5sig_pool_lock);
+       spin_lock_bh(&tcp_md5sig_pool_lock);
        pool = tcp_md5sig_pool;
        if (tcp_md5sig_users++ == 0) {
                alloc = 1;
-               spin_unlock(&tcp_md5sig_pool_lock);
+               spin_unlock_bh(&tcp_md5sig_pool_lock);
        } else if (!pool) {
                tcp_md5sig_users--;
-               spin_unlock(&tcp_md5sig_pool_lock);
+               spin_unlock_bh(&tcp_md5sig_pool_lock);
                cpu_relax();
                goto retry;
        } else
-               spin_unlock(&tcp_md5sig_pool_lock);
+               spin_unlock_bh(&tcp_md5sig_pool_lock);
 
        if (alloc) {
                /* we cannot hold spinlock here because this may sleep. */
                struct tcp_md5sig_pool **p = __tcp_alloc_md5sig_pool();
-               spin_lock(&tcp_md5sig_pool_lock);
+               spin_lock_bh(&tcp_md5sig_pool_lock);
                if (!p) {
                        tcp_md5sig_users--;
-                       spin_unlock(&tcp_md5sig_pool_lock);
+                       spin_unlock_bh(&tcp_md5sig_pool_lock);
                        return NULL;
                }
                pool = tcp_md5sig_pool;
                if (pool) {
                        /* oops, it has already been assigned. */
-                       spin_unlock(&tcp_md5sig_pool_lock);
+                       spin_unlock_bh(&tcp_md5sig_pool_lock);
                        __tcp_free_md5sig_pool(p);
                } else {
                        tcp_md5sig_pool = pool = p;
-                       spin_unlock(&tcp_md5sig_pool_lock);
+                       spin_unlock_bh(&tcp_md5sig_pool_lock);
                }
        }
        return pool;
@@ -2354,11 +2354,11 @@ EXPORT_SYMBOL(tcp_alloc_md5sig_pool);
 struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu)
 {
        struct tcp_md5sig_pool **p;
-       spin_lock(&tcp_md5sig_pool_lock);
+       spin_lock_bh(&tcp_md5sig_pool_lock);
        p = tcp_md5sig_pool;
        if (p)
                tcp_md5sig_users++;
-       spin_unlock(&tcp_md5sig_pool_lock);
+       spin_unlock_bh(&tcp_md5sig_pool_lock);
        return (p ? *per_cpu_ptr(p, cpu) : NULL);
 }
 
index 30b1e520ad943442fc76f13cc5d3b6d27aa5d657..6b5c64f3c925ea4c90da5ddd4bae50eb1135dc86 100644 (file)
@@ -381,7 +381,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
        if (newsk != NULL) {
                const struct inet_request_sock *ireq = inet_rsk(req);
                struct tcp_request_sock *treq = tcp_rsk(req);
-               struct inet_connection_sock *newicsk = inet_csk(sk);
+               struct inet_connection_sock *newicsk = inet_csk(newsk);
                struct tcp_sock *newtp;
 
                /* Now setup tcp_sock */
index ce6c46034314b35a3d17d2d18d35b0538cfe5116..fc620a7c1db4d18027ade93bc04c1e9de750f4c7 100644 (file)
@@ -1215,6 +1215,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
 
                if (ulen < sizeof(*uh) || pskb_trim_rcsum(skb, ulen))
                        goto short_packet;
+               uh = skb->h.uh;
 
                udp4_csum_init(skb, uh);
 
index e1cab33fdad1333506ce906b453e11ec8feee6bc..ceb4376f572ae8cd6c7b95845efc38d9820d84bc 100644 (file)
@@ -111,6 +111,7 @@ static int xfrm4_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
            (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
                goto out;
 
+       iph = skb->nh.iph;
        if (iph->protocol == IPPROTO_IPIP) {
                if (x->props.flags & XFRM_STATE_DECAP_DSCP)
                        ipv4_copy_dscp(iph, skb->h.ipiph);
index fef19c6bcb98b89496c3e622041c77efd5ca9423..5d51a2af34c1a0edf334225326de78c384bbeb7c 100644 (file)
@@ -291,7 +291,7 @@ static void xfrm4_dst_destroy(struct dst_entry *dst)
 
        if (likely(xdst->u.rt.idev))
                in_dev_put(xdst->u.rt.idev);
-       if (dst->xfrm->props.family == AF_INET && likely(xdst->u.rt.peer))
+       if (dst->xfrm && dst->xfrm->props.family == AF_INET && likely(xdst->u.rt.peer))
                inet_putpeer(xdst->u.rt.peer);
        xfrm_dst_destroy(xdst);
 }
index 8bacda109b7f00571b610977ff6f8b161339860b..d460017bb3538ef9bf98109b2ef8530ac4d0d679 100644 (file)
@@ -32,6 +32,6 @@ obj-$(CONFIG_NETFILTER)       += netfilter/
 obj-$(CONFIG_IPV6_SIT) += sit.o
 obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
 
-obj-y += exthdrs_core.o
+obj-y += addrconf_core.o exthdrs_core.o
 
 obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o
index 569a37d698f7711fbf2c61aad8b271cce11550c5..a7fee6b273205fb483b284c84f028853d9fffeed 100644 (file)
@@ -211,74 +211,6 @@ const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
 #endif
 const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
 
-#define IPV6_ADDR_SCOPE_TYPE(scope)    ((scope) << 16)
-
-static inline unsigned ipv6_addr_scope2type(unsigned scope)
-{
-       switch(scope) {
-       case IPV6_ADDR_SCOPE_NODELOCAL:
-               return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_NODELOCAL) |
-                       IPV6_ADDR_LOOPBACK);
-       case IPV6_ADDR_SCOPE_LINKLOCAL:
-               return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL) |
-                       IPV6_ADDR_LINKLOCAL);
-       case IPV6_ADDR_SCOPE_SITELOCAL:
-               return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL) |
-                       IPV6_ADDR_SITELOCAL);
-       }
-       return IPV6_ADDR_SCOPE_TYPE(scope);
-}
-
-int __ipv6_addr_type(const struct in6_addr *addr)
-{
-       __be32 st;
-
-       st = addr->s6_addr32[0];
-
-       /* Consider all addresses with the first three bits different of
-          000 and 111 as unicasts.
-        */
-       if ((st & htonl(0xE0000000)) != htonl(0x00000000) &&
-           (st & htonl(0xE0000000)) != htonl(0xE0000000))
-               return (IPV6_ADDR_UNICAST |
-                       IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));
-
-       if ((st & htonl(0xFF000000)) == htonl(0xFF000000)) {
-               /* multicast */
-               /* addr-select 3.1 */
-               return (IPV6_ADDR_MULTICAST |
-                       ipv6_addr_scope2type(IPV6_ADDR_MC_SCOPE(addr)));
-       }
-
-       if ((st & htonl(0xFFC00000)) == htonl(0xFE800000))
-               return (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST |
-                       IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL));               /* addr-select 3.1 */
-       if ((st & htonl(0xFFC00000)) == htonl(0xFEC00000))
-               return (IPV6_ADDR_SITELOCAL | IPV6_ADDR_UNICAST |
-                       IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL));               /* addr-select 3.1 */
-
-       if ((addr->s6_addr32[0] | addr->s6_addr32[1]) == 0) {
-               if (addr->s6_addr32[2] == 0) {
-                       if (addr->s6_addr32[3] == 0)
-                               return IPV6_ADDR_ANY;
-
-                       if (addr->s6_addr32[3] == htonl(0x00000001))
-                               return (IPV6_ADDR_LOOPBACK | IPV6_ADDR_UNICAST |
-                                       IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL));       /* addr-select 3.4 */
-
-                       return (IPV6_ADDR_COMPATv4 | IPV6_ADDR_UNICAST |
-                               IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));  /* addr-select 3.3 */
-               }
-
-               if (addr->s6_addr32[2] == htonl(0x0000ffff))
-                       return (IPV6_ADDR_MAPPED |
-                               IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));  /* addr-select 3.3 */
-       }
-
-       return (IPV6_ADDR_RESERVED |
-               IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));  /* addr-select 3.4 */
-}
-
 static void addrconf_del_timer(struct inet6_ifaddr *ifp)
 {
        if (del_timer(&ifp->timer))
@@ -410,10 +342,6 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
        }
 #endif
 
-       if (netif_carrier_ok(dev))
-               ndev->if_flags |= IF_READY;
-
-
        ipv6_mc_init_dev(ndev);
        ndev->tstamp = jiffies;
 #ifdef CONFIG_SYSCTL
@@ -468,6 +396,8 @@ static void dev_forward_change(struct inet6_dev *idev)
                        ipv6_dev_mc_dec(dev, &addr);
        }
        for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) {
+               if (ifa->flags&IFA_F_TENTATIVE)
+                       continue;
                if (idev->cnf.forwarding)
                        addrconf_join_anycast(ifa);
                else
@@ -1910,6 +1840,7 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen,
        struct inet6_dev *idev;
        struct net_device *dev;
        int scope;
+       u32 flags = RTF_EXPIRES;
 
        ASSERT_RTNL();
 
@@ -1925,9 +1856,10 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen,
 
        scope = ipv6_addr_scope(pfx);
 
-       if (valid_lft == INFINITY_LIFE_TIME)
+       if (valid_lft == INFINITY_LIFE_TIME) {
                ifa_flags |= IFA_F_PERMANENT;
-       else if (valid_lft >= 0x7FFFFFFF/HZ)
+               flags = 0;
+       } else if (valid_lft >= 0x7FFFFFFF/HZ)
                valid_lft = 0x7FFFFFFF/HZ;
 
        if (prefered_lft == 0)
@@ -1945,6 +1877,8 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen,
                ifp->tstamp = jiffies;
                spin_unlock_bh(&ifp->lock);
 
+               addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev,
+                                     jiffies_to_clock_t(valid_lft * HZ), flags);
                addrconf_dad_start(ifp, 0);
                in6_ifa_put(ifp);
                addrconf_verify(0);
@@ -2124,6 +2058,7 @@ static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr
 
        ifp = ipv6_add_addr(idev, addr, 64, IFA_LINK, IFA_F_PERMANENT);
        if (!IS_ERR(ifp)) {
+               addrconf_prefix_route(&ifp->addr, ifp->prefix_len, idev->dev, 0, 0);
                addrconf_dad_start(ifp, 0);
                in6_ifa_put(ifp);
        }
@@ -2240,6 +2175,14 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
        int run_pending = 0;
 
        switch(event) {
+       case NETDEV_REGISTER:
+               if (!idev) {
+                       idev = ipv6_add_dev(dev);
+                       if (!idev)
+                               printk(KERN_WARNING "IPv6: add_dev failed for %s\n",
+                                       dev->name);
+               }
+               break;
        case NETDEV_UP:
        case NETDEV_CHANGE:
                if (event == NETDEV_UP) {
@@ -2538,10 +2481,6 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
 
        addrconf_join_solict(dev, &ifp->addr);
 
-       if (ifp->prefix_len != 128 && (ifp->flags&IFA_F_PERMANENT))
-               addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev, 0,
-                                       flags);
-
        net_srandom(ifp->addr.s6_addr32[3]);
 
        read_lock_bh(&idev->lock);
@@ -2972,12 +2911,15 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
                             u32 prefered_lft, u32 valid_lft)
 {
+       u32 flags = RTF_EXPIRES;
+
        if (!valid_lft || (prefered_lft > valid_lft))
                return -EINVAL;
 
-       if (valid_lft == INFINITY_LIFE_TIME)
+       if (valid_lft == INFINITY_LIFE_TIME) {
                ifa_flags |= IFA_F_PERMANENT;
-       else if (valid_lft >= 0x7FFFFFFF/HZ)
+               flags = 0;
+       } else if (valid_lft >= 0x7FFFFFFF/HZ)
                valid_lft = 0x7FFFFFFF/HZ;
 
        if (prefered_lft == 0)
@@ -2996,6 +2938,8 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
        if (!(ifp->flags&IFA_F_TENTATIVE))
                ipv6_ifa_notify(0, ifp);
 
+       addrconf_prefix_route(&ifp->addr, ifp->prefix_len, ifp->idev->dev,
+                             jiffies_to_clock_t(valid_lft * HZ), flags);
        addrconf_verify(0);
 
        return 0;
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c
new file mode 100644 (file)
index 0000000..faaefb6
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * IPv6 library code, needed by static components when full IPv6 support is
+ * not configured or static.
+ */
+
+#include <net/ipv6.h>
+
+#define IPV6_ADDR_SCOPE_TYPE(scope)    ((scope) << 16)
+
+static inline unsigned ipv6_addr_scope2type(unsigned scope)
+{
+       switch(scope) {
+       case IPV6_ADDR_SCOPE_NODELOCAL:
+               return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_NODELOCAL) |
+                       IPV6_ADDR_LOOPBACK);
+       case IPV6_ADDR_SCOPE_LINKLOCAL:
+               return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL) |
+                       IPV6_ADDR_LINKLOCAL);
+       case IPV6_ADDR_SCOPE_SITELOCAL:
+               return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL) |
+                       IPV6_ADDR_SITELOCAL);
+       }
+       return IPV6_ADDR_SCOPE_TYPE(scope);
+}
+
+int __ipv6_addr_type(const struct in6_addr *addr)
+{
+       __be32 st;
+
+       st = addr->s6_addr32[0];
+
+       /* Consider all addresses with the first three bits different of
+          000 and 111 as unicasts.
+        */
+       if ((st & htonl(0xE0000000)) != htonl(0x00000000) &&
+           (st & htonl(0xE0000000)) != htonl(0xE0000000))
+               return (IPV6_ADDR_UNICAST |
+                       IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));
+
+       if ((st & htonl(0xFF000000)) == htonl(0xFF000000)) {
+               /* multicast */
+               /* addr-select 3.1 */
+               return (IPV6_ADDR_MULTICAST |
+                       ipv6_addr_scope2type(IPV6_ADDR_MC_SCOPE(addr)));
+       }
+
+       if ((st & htonl(0xFFC00000)) == htonl(0xFE800000))
+               return (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST |
+                       IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL));               /* addr-select 3.1 */
+       if ((st & htonl(0xFFC00000)) == htonl(0xFEC00000))
+               return (IPV6_ADDR_SITELOCAL | IPV6_ADDR_UNICAST |
+                       IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL));               /* addr-select 3.1 */
+
+       if ((addr->s6_addr32[0] | addr->s6_addr32[1]) == 0) {
+               if (addr->s6_addr32[2] == 0) {
+                       if (addr->s6_addr32[3] == 0)
+                               return IPV6_ADDR_ANY;
+
+                       if (addr->s6_addr32[3] == htonl(0x00000001))
+                               return (IPV6_ADDR_LOOPBACK | IPV6_ADDR_UNICAST |
+                                       IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL));       /* addr-select 3.4 */
+
+                       return (IPV6_ADDR_COMPATv4 | IPV6_ADDR_UNICAST |
+                               IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));  /* addr-select 3.3 */
+               }
+
+               if (addr->s6_addr32[2] == htonl(0x0000ffff))
+                       return (IPV6_ADDR_MAPPED |
+                               IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));  /* addr-select 3.3 */
+       }
+
+       return (IPV6_ADDR_RESERVED |
+               IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));  /* addr-select 3.4 */
+}
+EXPORT_SYMBOL(__ipv6_addr_type);
+
index 3585d8fa7f029930869ac900ad73ae0f4a442f22..5cac14a5c7784761c09a5ff20fe0561aee070968 100644 (file)
@@ -929,25 +929,28 @@ static void __exit inet6_exit(void)
 {
        /* First of all disallow new sockets creation. */
        sock_unregister(PF_INET6);
+
+       /* Cleanup code parts. */
+       ipv6_packet_cleanup();
+#ifdef CONFIG_IPV6_MIP6
+       mip6_fini();
+#endif
+       addrconf_cleanup();
+       ip6_flowlabel_cleanup();
+       ip6_route_cleanup();
 #ifdef CONFIG_PROC_FS
+
+       /* Cleanup code parts. */
        if6_proc_exit();
        ac6_proc_exit();
        ipv6_misc_proc_exit();
-       udp6_proc_exit();
        udplite6_proc_exit();
+       udp6_proc_exit();
        tcp6_proc_exit();
        raw6_proc_exit();
 #endif
-#ifdef CONFIG_IPV6_MIP6
-       mip6_fini();
-#endif
-       /* Cleanup code parts. */
-       ip6_flowlabel_cleanup();
-       addrconf_cleanup();
-       ip6_route_cleanup();
-       ipv6_packet_cleanup();
-       igmp6_cleanup();
        ipv6_netfilter_fini();
+       igmp6_cleanup();
        ndisc_cleanup();
        icmpv6_cleanup();
 #ifdef CONFIG_SYSCTL
@@ -955,6 +958,7 @@ static void __exit inet6_exit(void)
 #endif
        cleanup_ipv6_mibs();
        proto_unregister(&rawv6_prot);
+       proto_unregister(&udplitev6_prot);
        proto_unregister(&udpv6_prot);
        proto_unregister(&tcpv6_prot);
 }
index e5ef5979ade417e32d2bc11a41979f7fc0056758..09117d63256f6d92e4b5deebfd8bf6ccdb5230cf 100644 (file)
@@ -461,6 +461,7 @@ static inline struct ifacaddr6 *ac6_get_first(struct seq_file *seq)
                        break;
                }
                read_unlock_bh(&idev->lock);
+               in6_dev_put(idev);
        }
        return im;
 }
index 662edb826899e5c78ba6f219699a8c4ac9199f4e..08d944223ec810f78d7357cc6b5c52b77c636b0b 100644 (file)
@@ -727,11 +727,8 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
        }
        if (mtu < IPV6_MIN_MTU)
                mtu = IPV6_MIN_MTU;
-       if (skb->dst && mtu < dst_mtu(skb->dst)) {
-               struct rt6_info *rt = (struct rt6_info *) skb->dst;
-               rt->rt6i_flags |= RTF_MODIFIED;
-               rt->u.dst.metrics[RTAX_MTU-1] = mtu;
-       }
+       if (skb->dst)
+               skb->dst->ops->update_pmtu(skb->dst, mtu);
        if (skb->len > mtu) {
                icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev);
                goto tx_err_dst_release;
index 286c86735aed7772f6851228026d0a633a1d45bd..f5f9582a8d39554c120ed147ddc9f71105d6a889 100644 (file)
@@ -413,7 +413,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
                }
 
                /* routing header option needs extra check */
-               if (optname == IPV6_RTHDR && opt->srcrt) {
+               if (optname == IPV6_RTHDR && opt && opt->srcrt) {
                        struct ipv6_rt_hdr *rthdr = opt->srcrt;
                        switch (rthdr->type) {
                        case IPV6_SRCRT_TYPE_0:
@@ -795,12 +795,16 @@ int compat_ipv6_setsockopt(struct sock *sk, int level, int optname,
 EXPORT_SYMBOL(compat_ipv6_setsockopt);
 #endif
 
-static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr,
+static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt,
                                  char __user *optval, int len)
 {
-       if (!hdr)
+       struct ipv6_opt_hdr *hdr;
+
+       if (!opt || !opt->hopopt)
                return 0;
-       len = min_t(int, len, ipv6_optlen(hdr));
+       hdr = opt->hopopt;
+
+       len = min_t(unsigned int, len, ipv6_optlen(hdr));
        if (copy_to_user(optval, hdr, ipv6_optlen(hdr)))
                return -EFAULT;
        return len;
@@ -940,7 +944,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
        {
 
                lock_sock(sk);
-               len = ipv6_getsockopt_sticky(sk, np->opt->hopopt,
+               len = ipv6_getsockopt_sticky(sk, np->opt,
                                             optval, len);
                release_sock(sk);
                return put_user(len, optlen);
index 0e8e0676a03368029eff4ce70bcdaa4113f2e8fc..e12e3d4fccec0378ac61ee6731ac4ef70374569a 100644 (file)
@@ -6,7 +6,6 @@
 #include <net/ip6_route.h>
 #include <net/xfrm.h>
 
-EXPORT_SYMBOL(__ipv6_addr_type);
 EXPORT_SYMBOL(icmpv6_send);
 EXPORT_SYMBOL(icmpv6_statistics);
 EXPORT_SYMBOL(icmpv6_err_convert);
index 0b2d265e7da746ef6383ba5b8fd2ee5cb008da64..1c405dd30c67b5996483a513009e76e5706137fe 100644 (file)
@@ -15,6 +15,7 @@ int ip6_route_me_harder(struct sk_buff *skb)
        struct dst_entry *dst;
        struct flowi fl = {
                .oif = skb->sk ? skb->sk->sk_bound_dev_if : 0,
+               .mark = skb->mark,
                .nl_u =
                { .ip6_u =
                  { .daddr = iph->daddr,
index 4b7be4bb4d03406f437e08b9d5162aed80fd42fe..d1102455668d43db1ba803253df51bc92b583235 100644 (file)
@@ -257,6 +257,7 @@ static unsigned int ipv6_conntrack_in(unsigned int hooknum,
                }
                nf_conntrack_get(reasm->nfct);
                (*pskb)->nfct = reasm->nfct;
+               (*pskb)->nfctinfo = reasm->nfctinfo;
                return NF_ACCEPT;
        }
 
@@ -353,8 +354,7 @@ static ctl_table nf_ct_ipv6_sysctl_table[] = {
 };
 #endif
 
-#if defined(CONFIG_NF_CT_NETLINK) || \
-    defined(CONFIG_NF_CT_NETLINK_MODULE)
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
 
 #include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter/nfnetlink_conntrack.h>
@@ -403,8 +403,7 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 = {
        .print_tuple            = ipv6_print_tuple,
        .print_conntrack        = ipv6_print_conntrack,
        .prepare                = ipv6_prepare,
-#if defined(CONFIG_NF_CT_NETLINK) || \
-    defined(CONFIG_NF_CT_NETLINK_MODULE)
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
        .tuple_to_nfattr        = ipv6_tuple_to_nfattr,
        .nfattr_to_tuple        = ipv6_nfattr_to_tuple,
 #endif
index 21f19cc719f34d2bd4bcad23808efa95095bd023..075da4f287b84989a92af4e0c08b7e756d837a5e 100644 (file)
@@ -244,8 +244,7 @@ icmpv6_error(struct sk_buff *skb, unsigned int dataoff,
        return icmpv6_error_message(skb, dataoff, ctinfo, hooknum);
 }
 
-#if defined(CONFIG_NF_CT_NETLINK) || \
-    defined(CONFIG_NF_CT_NETLINK_MODULE)
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
 
 #include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter/nfnetlink_conntrack.h>
@@ -327,8 +326,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 =
        .packet                 = icmpv6_packet,
        .new                    = icmpv6_new,
        .error                  = icmpv6_error,
-#if defined(CONFIG_NF_CT_NETLINK) || \
-    defined(CONFIG_NF_CT_NETLINK_MODULE)
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
        .tuple_to_nfattr        = icmpv6_tuple_to_nfattr,
        .nfattr_to_tuple        = icmpv6_nfattr_to_tuple,
 #endif
index b1133f27c8aed0ce5578d0417c0c704bc1650c9b..d8a585bd2cb40654cd16b7593ecabe190eae7f7e 100644 (file)
@@ -189,7 +189,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
                        case AF_INET6:
                                ipv6_addr_copy(&fl_tunnel.fl6_dst, __xfrm6_bundle_addr_remote(xfrm[i], &fl->fl6_dst));
 
-                               ipv6_addr_copy(&fl_tunnel.fl6_src, __xfrm6_bundle_addr_remote(xfrm[i], &fl->fl6_src));
+                               ipv6_addr_copy(&fl_tunnel.fl6_src, __xfrm6_bundle_addr_local(xfrm[i], &fl->fl6_src));
                                break;
                        default:
                                BUG_ON(1);
diff --git a/net/ipx/ChangeLog b/net/ipx/ChangeLog
deleted file mode 100644 (file)
index 3b29763..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
- Revision 0.21:        Uses the new generic socket option code.
-
- Revision 0.22:        Gcc clean ups and drop out device registration. Use the
-               new multi-protocol edition of hard_header
-
- Revision 0.23: IPX /proc by Mark Evans. Adding a route will
-               will overwrite any existing route to the same network.
-
- Revision 0.24:        Supports new /proc with no 4K limit
-
- Revision 0.25:        Add ephemeral sockets, passive local network
-               identification, support for local net 0 and
-               multiple datalinks <Greg Page>
-
- Revision 0.26: Device drop kills IPX routes via it. (needed for module)
-
- Revision 0.27: Autobind <Mark Evans>
-
- Revision 0.28: Small fix for multiple local networks <Thomas Winder>
-
- Revision 0.29: Assorted major errors removed <Mark Evans>
-               Small correction to promisc mode error fix <Alan Cox>
-               Asynchronous I/O support. Changed to use notifiers
-               and the newer packet_type stuff. Assorted major
-               fixes <Alejandro Liu>
-
- Revision 0.30:        Moved to net/ipx/...    <Alan Cox>
-               Don't set address length on recvfrom that errors.
-               Incorrect verify_area.
-
- Revision 0.31:        New sk_buffs. This still needs a lot of 
-               testing. <Alan Cox>
-
- Revision 0.32: Using sock_alloc_send_skb, firewall hooks. <Alan Cox>
-               Supports sendmsg/recvmsg
-
- Revision 0.33:        Internal network support, routing changes, uses a
-               protocol private area for ipx data.
-
- Revision 0.34:        Module support. <Jim Freeman>
-
- Revision 0.35: Checksum support. <Neil Turton>, hooked in by <Alan Cox>
-               Handles WIN95 discovery packets <Volker Lendecke>
-
- Revision 0.36:        Internal bump up for 2.1
-
- Revision 0.37:        Began adding POSIXisms.
-
- Revision 0.38: Asynchronous socket stuff made current.
-
- Revision 0.39: SPX interfaces
-
- Revision 0.40: Tiny SIOCGSTAMP fix (chris@cybernet.co.nz)
-
- Revision 0.41: 802.2TR removed (p.norton@computer.org)
-               Fixed connecting to primary net,
-               Automatic binding on send & receive,
-               Martijn van Oosterhout <kleptogimp@geocities.com>
-
- Revision 042:  Multithreading - use spinlocks and refcounting to
-               protect some structures: ipx_interface sock list, list
-               of ipx interfaces, etc. 
-               Bugfixes - do refcounting on net_devices, check function
-               results, etc. Thanks to davem and freitag for
-               suggestions and guidance.
-               Arnaldo Carvalho de Melo <acme@conectiva.com.br>,
-               November, 2000
-
- Revision 043: Shared SKBs, don't mangle packets, some cleanups
-               Arnaldo Carvalho de Melo <acme@conectiva.com.br>,
-               December, 2000
-
- Revision 044: Call ipxitf_hold on NETDEV_UP - acme
-
- Revision 045: fix PPROP routing bug - acme
-
- Revision 046: Further fixes to PPROP, ipxitf_create_internal was
-               doing an unneeded MOD_INC_USE_COUNT, implement
-               sysctl for ipx_pprop_broacasting, fix the ipx sysctl
-               handling, making it dynamic, some cleanups, thanks to
-               Petr Vandrovec for review and good suggestions. (acme)
-
- Revision 047: Cleanups, CodingStyle changes, move the ncp connection
-               hack out of line - acme
-
- Revision 048: Use sk->protinfo to store the pointer to IPX private
-               area, remove af_ipx from sk->protinfo and move ipx_opt
-               to include/net/ipx.h, use IPX_SK like DecNET, etc - acme
-
- Revision 049: SPX support dropped, see comment in ipx_create - acme
-
- Revision 050: Use seq_file for proc stuff, moving it to ipx_proc.c - acme
-
-Other fixes:
- Protect the module by a MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT pair. Also, now
- usage count is managed this way:
- -Count one if the auto_interface mode is on
- -Count one per configured interface
- Jacques Gelinas (jacques@solucorp.qc.ca)
index 980a826f5d02e01e75fdefb9e527e9b8890e1176..e9ad0062fbb6a8df3e13182597176016657695b6 100644 (file)
@@ -16,8 +16,7 @@ config IPX
          support", below.
 
          IPX is similar in scope to IP, while SPX, which runs on top of IPX,
-         is similar to TCP. There is also experimental support for SPX in
-         Linux (see "SPX networking", below).
+         is similar to TCP.
 
          To turn your Linux box into a fully featured NetWare file server and
          IPX router, say Y here and fetch either lwared from
@@ -26,9 +25,6 @@ config IPX
          information, read the IPX-HOWTO available from
          <http://www.tldp.org/docs.html#howto>.
 
-         General information about how to connect Linux, Windows machines and
-         Macs is on the WWW at <http://www.eats.com/linux_mac_win.html>.
-
          The IPX driver would enlarge your kernel by about 16 KB. To compile
          this driver as a module, choose M here: the module will be called ipx.
          Unless you want to integrate your Linux box with a local Novell
index 826e6c4ca5d510ab3e54e088eeef7f4c458bf3ee..c7fad2c5b9f3508867130646681b5155e7fec108 100644 (file)
 #include <net/irda/irttp.h>            /* irttp_init */
 #include <net/irda/irda_device.h>      /* irda_device_init */
 
-/* irproc.c */
-extern void irda_proc_register(void);
-extern void irda_proc_unregister(void);
-/* irsysctl.c */
-extern int  irda_sysctl_register(void);
-extern void irda_sysctl_unregister(void);
-/* af_irda.c */
-extern int  irsock_init(void);
-extern void irsock_cleanup(void);
-/* irlap_frame.c */
-extern int  irlap_driver_rcv(struct sk_buff *, struct net_device *,
-                            struct packet_type *, struct net_device *);
-
 /*
  * Module parameters
  */
index 1c58204d767e6ad460775b13985833dcbf3d5f95..a4e7e2db0ff35402bbc722d6e977811689e8eeeb 100644 (file)
@@ -1467,9 +1467,6 @@ static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
 
        err = xfrm_state_delete(x);
 
-       xfrm_audit_log(audit_get_loginuid(current->audit_context), 0,
-                      AUDIT_MAC_IPSEC_DELSA, err ? 0 : 1, NULL, x);
-
        if (err < 0)
                goto out;
 
@@ -1478,6 +1475,8 @@ static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
        c.event = XFRM_MSG_DELSA;
        km_state_notify(x, &c);
 out:
+       xfrm_audit_log(audit_get_loginuid(current->audit_context), 0,
+                      AUDIT_MAC_IPSEC_DELSA, err ? 0 : 1, NULL, x);
        xfrm_state_put(x);
 
        return err;
@@ -2294,14 +2293,12 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
        }
 
        xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN, pol->sadb_x_policy_dir-1,
-                                  &sel, tmp.security, 1);
+                                  &sel, tmp.security, 1, &err);
        security_xfrm_policy_free(&tmp);
 
        if (xp == NULL)
                return -ENOENT;
 
-       err = security_xfrm_policy_delete(xp);
-
        xfrm_audit_log(audit_get_loginuid(current->audit_context), 0,
                       AUDIT_MAC_IPSEC_DELSPD, err ? 0 : 1, xp, NULL);
 
@@ -2539,7 +2536,7 @@ static int pfkey_migrate(struct sock *sk, struct sk_buff *skb,
 static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
 {
        unsigned int dir;
-       int err;
+       int err = 0, delete;
        struct sadb_x_policy *pol;
        struct xfrm_policy *xp;
        struct km_event c;
@@ -2551,16 +2548,20 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
        if (dir >= XFRM_POLICY_MAX)
                return -EINVAL;
 
+       delete = (hdr->sadb_msg_type == SADB_X_SPDDELETE2);
        xp = xfrm_policy_byid(XFRM_POLICY_TYPE_MAIN, dir, pol->sadb_x_policy_id,
-                             hdr->sadb_msg_type == SADB_X_SPDDELETE2);
+                             delete, &err);
        if (xp == NULL)
                return -ENOENT;
 
-       err = 0;
+       if (delete) {
+               xfrm_audit_log(audit_get_loginuid(current->audit_context), 0,
+                              AUDIT_MAC_IPSEC_DELSPD, err ? 0 : 1, xp, NULL);
 
-       c.seq = hdr->sadb_msg_seq;
-       c.pid = hdr->sadb_msg_pid;
-       if (hdr->sadb_msg_type == SADB_X_SPDDELETE2) {
+               if (err)
+                       goto out;
+               c.seq = hdr->sadb_msg_seq;
+               c.pid = hdr->sadb_msg_pid;
                c.data.byid = 1;
                c.event = XFRM_MSG_DELPOLICY;
                km_policy_notify(xp, dir, &c);
@@ -2568,6 +2569,7 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
                err = key_pol_get_resp(sk, xp, hdr, dir);
        }
 
+out:
        xfrm_pol_put(xp);
        return err;
 }
index 32891ebc9e68f3f6d657a83faa615548449c36e7..b3a70eb6d42ae8728a5d8803ea230e9d27ecbb10 100644 (file)
@@ -976,8 +976,7 @@ void __nf_ct_refresh_acct(struct nf_conn *ct,
 }
 EXPORT_SYMBOL_GPL(__nf_ct_refresh_acct);
 
-#if defined(CONFIG_NF_CT_NETLINK) || \
-    defined(CONFIG_NF_CT_NETLINK_MODULE)
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
 
 #include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter/nfnetlink_conntrack.h>
@@ -1070,7 +1069,7 @@ get_next_corpse(int (*iter)(struct nf_conn *i, void *data),
        list_for_each_entry(h, &unconfirmed, list) {
                ct = nf_ct_tuplehash_to_ctrack(h);
                if (iter(ct, data))
-                       goto found;
+                       set_bit(IPS_DYING_BIT, &ct->status);
        }
        write_unlock_bh(&nf_conntrack_lock);
        return NULL;
index ac193ce702494f72c98a9c12c6d12be3e2a6e2be..5434472420fe68dc83cc231cbc6436d5d47854d9 100644 (file)
@@ -281,8 +281,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 = {
        .new             = gre_new,
        .destroy         = gre_destroy,
        .me              = THIS_MODULE,
-#if defined(CONFIG_NF_CONNTRACK_NETLINK) || \
-    defined(CONFIG_NF_CONNTRACK_NETLINK_MODULE)
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
        .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
        .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple,
 #endif
index 069b85ca51cd026d2799d24d82e7c5208bd40481..153d6619993ab6795f56d6ac63f7b66ebc3da741 100644 (file)
@@ -769,8 +769,10 @@ EXPORT_SYMBOL_GPL(nf_conntrack_tcp_update);
 static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] =
 {
        [TH_SYN]                        = 1,
-       [TH_SYN|TH_ACK]                 = 1,
        [TH_SYN|TH_PUSH]                = 1,
+       [TH_SYN|TH_URG]                 = 1,
+       [TH_SYN|TH_PUSH|TH_URG]         = 1,
+       [TH_SYN|TH_ACK]                 = 1,
        [TH_SYN|TH_ACK|TH_PUSH]         = 1,
        [TH_RST]                        = 1,
        [TH_RST|TH_ACK]                 = 1,
@@ -1099,8 +1101,7 @@ static int tcp_new(struct nf_conn *conntrack,
        return 1;
 }
 
-#if defined(CONFIG_NF_CT_NETLINK) || \
-    defined(CONFIG_NF_CT_NETLINK_MODULE)
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
 
 #include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter/nfnetlink_conntrack.h>
@@ -1378,8 +1379,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 =
        .packet                 = tcp_packet,
        .new                    = tcp_new,
        .error                  = tcp_error,
-#if defined(CONFIG_NF_CT_NETLINK) || \
-    defined(CONFIG_NF_CT_NETLINK_MODULE)
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
        .to_nfattr              = tcp_to_nfattr,
        .from_nfattr            = nfattr_to_tcp,
        .tuple_to_nfattr        = nf_ct_port_tuple_to_nfattr,
@@ -1408,8 +1408,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 =
        .packet                 = tcp_packet,
        .new                    = tcp_new,
        .error                  = tcp_error,
-#if defined(CONFIG_NF_CT_NETLINK) || \
-    defined(CONFIG_NF_CT_NETLINK_MODULE)
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
        .to_nfattr              = tcp_to_nfattr,
        .from_nfattr            = nfattr_to_tcp,
        .tuple_to_nfattr        = nf_ct_port_tuple_to_nfattr,
index d0a1cee7ee52d765b144a2f53e15e3fbb1627451..a5e5726ec0c7d7cbe4ef2e7101c2e0f3aca9b853 100644 (file)
@@ -208,8 +208,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 =
        .packet                 = udp_packet,
        .new                    = udp_new,
        .error                  = udp_error,
-#if defined(CONFIG_NF_CT_NETLINK) || \
-    defined(CONFIG_NF_CT_NETLINK_MODULE)
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
        .tuple_to_nfattr        = nf_ct_port_tuple_to_nfattr,
        .nfattr_to_tuple        = nf_ct_port_nfattr_to_tuple,
 #endif
@@ -236,8 +235,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 =
        .packet                 = udp_packet,
        .new                    = udp_new,
        .error                  = udp_error,
-#if defined(CONFIG_NF_CT_NETLINK) || \
-    defined(CONFIG_NF_CT_NETLINK_MODULE)
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
        .tuple_to_nfattr        = nf_ct_port_tuple_to_nfattr,
        .nfattr_to_tuple        = nf_ct_port_nfattr_to_tuple,
 #endif
index 11d504d0ac72068d8c88bc794fe4cb8c1284e3d9..bf23e489e4cdc88eec4a81a8c3461ac2cd5008ee 100644 (file)
@@ -197,13 +197,12 @@ EXPORT_SYMBOL_GPL(nfnetlink_has_listeners);
 
 int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo)
 {
-       gfp_t allocation = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
        int err = 0;
 
        NETLINK_CB(skb).dst_group = group;
        if (echo)
                atomic_inc(&skb->users);
-       netlink_broadcast(nfnl, skb, pid, group, allocation);
+       netlink_broadcast(nfnl, skb, pid, group, gfp_any());
        if (echo)
                err = netlink_unicast(nfnl, skb, pid, MSG_DONTWAIT);
 
index b8eab0dbc3dd3f3a93f6af25317dc1c5e7f2f98b..5cb30ebba0f4fd1538c7c3bb36f6902ae8109541 100644 (file)
@@ -133,6 +133,7 @@ instance_put(struct nfulnl_instance *inst)
        if (inst && atomic_dec_and_test(&inst->use)) {
                UDEBUG("kfree(inst=%p)\n", inst);
                kfree(inst);
+               module_put(THIS_MODULE);
        }
 }
 
@@ -217,6 +218,9 @@ _instance_destroy2(struct nfulnl_instance *inst, int lock)
 
        spin_lock_bh(&inst->lock);
        if (inst->skb) {
+               /* timer "holds" one reference (we have one more) */
+               if (del_timer(&inst->timer))
+                       instance_put(inst);
                if (inst->qlen)
                        __nfulnl_send(inst);
                if (inst->skb) {
@@ -228,8 +232,6 @@ _instance_destroy2(struct nfulnl_instance *inst, int lock)
 
        /* and finally put the refcount */
        instance_put(inst);
-
-       module_put(THIS_MODULE);
 }
 
 static inline void
@@ -363,9 +365,6 @@ __nfulnl_send(struct nfulnl_instance *inst)
 {
        int status;
 
-       if (timer_pending(&inst->timer))
-               del_timer(&inst->timer);
-
        if (!inst->skb)
                return 0;
 
@@ -393,8 +392,8 @@ static void nfulnl_timer(unsigned long data)
 
        spin_lock_bh(&inst->lock);
        __nfulnl_send(inst);
-       instance_put(inst);
        spin_unlock_bh(&inst->lock);
+       instance_put(inst);
 }
 
 /* This is an inline function, we don't really care about a long
@@ -487,7 +486,7 @@ __build_packet_message(struct nfulnl_instance *inst,
                         * for physical device (when called from ipv4) */
                        NFA_PUT(inst->skb, NFULA_IFINDEX_OUTDEV,
                                sizeof(tmp_uint), &tmp_uint);
-                       if (skb->nf_bridge) {
+                       if (skb->nf_bridge && skb->nf_bridge->physoutdev) {
                                tmp_uint =
                                    htonl(skb->nf_bridge->physoutdev->ifindex);
                                NFA_PUT(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
@@ -560,6 +559,7 @@ __build_packet_message(struct nfulnl_instance *inst,
        }
 
        nlh->nlmsg_len = inst->skb->tail - old_tail;
+       inst->lastnlh = nlh;
        return 0;
 
 nlmsg_failure:
@@ -615,7 +615,7 @@ nfulnl_log_packet(unsigned int pf,
 
        plen = 0;
        if (prefix)
-               plen = strlen(prefix);
+               plen = strlen(prefix) + 1;
 
        /* all macros expand to constant values at compile time */
        /* FIXME: do we want to make the size calculation conditional based on
@@ -689,6 +689,9 @@ nfulnl_log_packet(unsigned int pf,
                 * enough room in the skb left. flush to userspace. */
                UDEBUG("flushing old skb\n");
 
+               /* timer "holds" one reference (we have another one) */
+               if (del_timer(&inst->timer))
+                       instance_put(inst);
                __nfulnl_send(inst);
 
                if (!(inst->skb = nfulnl_alloc_skb(nlbufsiz, size))) {
@@ -711,15 +714,16 @@ nfulnl_log_packet(unsigned int pf,
                inst->timer.expires = jiffies + (inst->flushtimeout*HZ/100);
                add_timer(&inst->timer);
        }
-       spin_unlock_bh(&inst->lock);
 
+unlock_and_release:
+       spin_unlock_bh(&inst->lock);
+       instance_put(inst);
        return;
 
 alloc_failure:
-       spin_unlock_bh(&inst->lock);
-       instance_put(inst);
        UDEBUG("error allocating skb\n");
        /* FIXME: statistics */
+       goto unlock_and_release;
 }
 
 static int
@@ -856,6 +860,9 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
                        ret = -EINVAL;
                        break;
                }
+
+               if (!inst)
+                       goto out;
        } else {
                if (!inst) {
                        UDEBUG("no config command, and no instance for "
@@ -909,6 +916,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
 
 out_put:
        instance_put(inst);
+out:
        return ret;
 }
 
index 5bc37181662e5e0a51281093c08d590c199cac2e..b931edee4b8be1c3836a200461915a0ed9d4e8a9 100644 (file)
@@ -173,7 +173,7 @@ static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info)
        return 0;
 
 list_failure:
-       kfree(ans_skb);
+       kfree_skb(ans_skb);
        return ret_val;
 }
 
index bf2699074774dc436d53d5276c2375721df58cf1..28d47e8f2873e49403d1d6fe20c6fc298470ea3a 100644 (file)
@@ -227,17 +227,14 @@ struct packet_skb_cb {
 
 #ifdef CONFIG_PACKET_MMAP
 
-static inline char *packet_lookup_frame(struct packet_sock *po, unsigned int position)
+static inline struct tpacket_hdr *packet_lookup_frame(struct packet_sock *po, unsigned int position)
 {
        unsigned int pg_vec_pos, frame_offset;
-       char *frame;
 
        pg_vec_pos = position / po->frames_per_block;
        frame_offset = position % po->frames_per_block;
 
-       frame = po->pg_vec[pg_vec_pos] + (frame_offset * po->frame_size);
-
-       return frame;
+       return (struct tpacket_hdr *)(po->pg_vec[pg_vec_pos] + (frame_offset * po->frame_size));
 }
 #endif
 
@@ -639,7 +636,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
        }
 
        spin_lock(&sk->sk_receive_queue.lock);
-       h = (struct tpacket_hdr *)packet_lookup_frame(po, po->head);
+       h = packet_lookup_frame(po, po->head);
 
        if (h->tp_status)
                goto ring_is_full;
@@ -1473,7 +1470,7 @@ static int packet_notifier(struct notifier_block *this, unsigned long msg, void
 {
        struct sock *sk;
        struct hlist_node *node;
-       struct net_device *dev = (struct net_device*)data;
+       struct net_device *dev = data;
 
        read_lock(&packet_sklist_lock);
        sk_for_each(sk, node, &packet_sklist) {
@@ -1588,7 +1585,7 @@ static unsigned int packet_poll(struct file * file, struct socket *sock,
                unsigned last = po->head ? po->head-1 : po->frame_max;
                struct tpacket_hdr *h;
 
-               h = (struct tpacket_hdr *)packet_lookup_frame(po, last);
+               h = packet_lookup_frame(po, last);
 
                if (h->tp_status)
                        mask |= POLLIN | POLLRDNORM;
index 63fe1093b61635f06ecfc821e2c3caf6e68524eb..0b9c49b3a10000a07b391e164715cae8e322565f 100644 (file)
@@ -360,7 +360,7 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
                return;
        }
 
-       read_lock(&in6_dev->lock);
+       read_lock_bh(&in6_dev->lock);
        for (ifp = in6_dev->addr_list; ifp; ifp = ifp->if_next) {
                /* Add the address to the local list.  */
                addr = t_new(struct sctp_sockaddr_entry, GFP_ATOMIC);
@@ -374,7 +374,7 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
                }
        }
 
-       read_unlock(&in6_dev->lock);
+       read_unlock_bh(&in6_dev->lock);
        rcu_read_unlock();
 }
 
index 5c2ddd10db065629139d0544cc439ffa42e10687..41abfd17627e1a3b0a75029acf1f78031f1c8447 100644 (file)
@@ -396,6 +396,19 @@ void sctp_retransmit_mark(struct sctp_outq *q,
                if (sctp_chunk_abandoned(chunk)) {
                        list_del_init(lchunk);
                        sctp_insert_list(&q->abandoned, lchunk);
+
+                       /* If this chunk has not been previousely acked,
+                        * stop considering it 'outstanding'.  Our peer
+                        * will most likely never see it since it will
+                        * not be retransmitted
+                        */
+                       if (!chunk->tsn_gap_acked) {
+                               chunk->transport->flight_size -=
+                                               sctp_data_size(chunk);
+                               q->outstanding_bytes -= sctp_data_size(chunk);
+                               q->asoc->peer.rwnd += (sctp_data_size(chunk) +
+                                                       sizeof(struct sk_buff));
+                       }
                        continue;
                }
 
@@ -1244,6 +1257,15 @@ static void sctp_check_transmitted(struct sctp_outq *q,
                if (sctp_chunk_abandoned(tchunk)) {
                        /* Move the chunk to abandoned list. */
                        sctp_insert_list(&q->abandoned, lchunk);
+
+                       /* If this chunk has not been acked, stop
+                        * considering it as 'outstanding'.
+                        */
+                       if (!tchunk->tsn_gap_acked) {
+                               tchunk->transport->flight_size -=
+                                               sctp_data_size(tchunk);
+                               q->outstanding_bytes -= sctp_data_size(tchunk);
+                       }
                        continue;
                }
 
@@ -1695,11 +1717,6 @@ static void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 ctsn)
                 */
                if (TSN_lte(tsn, ctsn)) {
                        list_del_init(lchunk);
-                       if (!chunk->tsn_gap_acked) {
-                               chunk->transport->flight_size -=
-                                       sctp_data_size(chunk);
-                               q->outstanding_bytes -= sctp_data_size(chunk);
-                       }
                        sctp_chunk_free(chunk);
                } else {
                        if (TSN_lte(tsn, asoc->adv_peer_ack_point+1)) {
index b3cad8a03736c1a05b34fe6c9264a3b192eb6e19..70c39eac0581c06e2bac8a464630428fc98e3342 100644 (file)
@@ -4605,12 +4605,12 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep,
         * sent as soon as cwnd allows (normally when a SACK arrives).
         */
 
-       /* NB: Rules E4 and F1 are implicit in R1.  */
-       sctp_add_cmd_sf(commands, SCTP_CMD_RETRAN, SCTP_TRANSPORT(transport));
-
        /* Do some failure management (Section 8.2). */
        sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, SCTP_TRANSPORT(transport));
 
+       /* NB: Rules E4 and F1 are implicit in R1.  */
+       sctp_add_cmd_sf(commands, SCTP_CMD_RETRAN, SCTP_TRANSPORT(transport));
+
        return SCTP_DISPOSITION_CONSUME;
 }
 
index 4ab137403e1ac3b0ff075b97dde73308bc843c8c..b4db53ff143577a06fd72d2ef83418b4de194e9d 100644 (file)
 
 #define RPCDBG_FACILITY        RPCDBG_SVCDSP
 
+#define svc_serv_is_pooled(serv)    ((serv)->sv_function)
+
 /*
  * Mode for mapping cpus to pools.
  */
 enum {
-       SVC_POOL_NONE = -1,     /* uninitialised, choose one of the others */
+       SVC_POOL_AUTO = -1,     /* choose one of the others */
        SVC_POOL_GLOBAL,        /* no mapping, just a single global pool
                                 * (legacy & UP mode) */
        SVC_POOL_PERCPU,        /* one pool per cpu */
        SVC_POOL_PERNODE        /* one pool per numa node */
 };
+#define SVC_POOL_DEFAULT       SVC_POOL_GLOBAL
 
 /*
  * Structure for mapping cpus to pools and vice versa.
  * Setup once during sunrpc initialisation.
  */
 static struct svc_pool_map {
+       int count;                      /* How many svc_servs use us */
        int mode;                       /* Note: int not enum to avoid
                                         * warnings about "enumeration value
                                         * not handled in switch" */
@@ -50,9 +54,63 @@ static struct svc_pool_map {
        unsigned int *pool_to;          /* maps pool id to cpu or node */
        unsigned int *to_pool;          /* maps cpu or node to pool id */
 } svc_pool_map = {
-       .mode = SVC_POOL_NONE
+       .count = 0,
+       .mode = SVC_POOL_DEFAULT
 };
+static DEFINE_MUTEX(svc_pool_map_mutex);/* protects svc_pool_map.count only */
+
+static int
+param_set_pool_mode(const char *val, struct kernel_param *kp)
+{
+       int *ip = (int *)kp->arg;
+       struct svc_pool_map *m = &svc_pool_map;
+       int err;
+
+       mutex_lock(&svc_pool_map_mutex);
+
+       err = -EBUSY;
+       if (m->count)
+               goto out;
+
+       err = 0;
+       if (!strncmp(val, "auto", 4))
+               *ip = SVC_POOL_AUTO;
+       else if (!strncmp(val, "global", 6))
+               *ip = SVC_POOL_GLOBAL;
+       else if (!strncmp(val, "percpu", 6))
+               *ip = SVC_POOL_PERCPU;
+       else if (!strncmp(val, "pernode", 7))
+               *ip = SVC_POOL_PERNODE;
+       else
+               err = -EINVAL;
+
+out:
+       mutex_unlock(&svc_pool_map_mutex);
+       return err;
+}
 
+static int
+param_get_pool_mode(char *buf, struct kernel_param *kp)
+{
+       int *ip = (int *)kp->arg;
+
+       switch (*ip)
+       {
+       case SVC_POOL_AUTO:
+               return strlcpy(buf, "auto", 20);
+       case SVC_POOL_GLOBAL:
+               return strlcpy(buf, "global", 20);
+       case SVC_POOL_PERCPU:
+               return strlcpy(buf, "percpu", 20);
+       case SVC_POOL_PERNODE:
+               return strlcpy(buf, "pernode", 20);
+       default:
+               return sprintf(buf, "%d", *ip);
+       }
+}
+
+module_param_call(pool_mode, param_set_pool_mode, param_get_pool_mode,
+                &svc_pool_map.mode, 0644);
 
 /*
  * Detect best pool mapping mode heuristically,
@@ -115,7 +173,7 @@ fail:
 static int
 svc_pool_map_init_percpu(struct svc_pool_map *m)
 {
-       unsigned int maxpools = highest_possible_processor_id()+1;
+       unsigned int maxpools = nr_cpu_ids;
        unsigned int pidx = 0;
        unsigned int cpu;
        int err;
@@ -143,7 +201,7 @@ svc_pool_map_init_percpu(struct svc_pool_map *m)
 static int
 svc_pool_map_init_pernode(struct svc_pool_map *m)
 {
-       unsigned int maxpools = highest_possible_node_id()+1;
+       unsigned int maxpools = nr_node_ids;
        unsigned int pidx = 0;
        unsigned int node;
        int err;
@@ -166,18 +224,25 @@ svc_pool_map_init_pernode(struct svc_pool_map *m)
 
 
 /*
- * Build the global map of cpus to pools and vice versa.
+ * Add a reference to the global map of cpus to pools (and
+ * vice versa).  Initialise the map if we're the first user.
+ * Returns the number of pools.
  */
 static unsigned int
-svc_pool_map_init(void)
+svc_pool_map_get(void)
 {
        struct svc_pool_map *m = &svc_pool_map;
        int npools = -1;
 
-       if (m->mode != SVC_POOL_NONE)
+       mutex_lock(&svc_pool_map_mutex);
+
+       if (m->count++) {
+               mutex_unlock(&svc_pool_map_mutex);
                return m->npools;
+       }
 
-       m->mode = svc_pool_map_choose_mode();
+       if (m->mode == SVC_POOL_AUTO)
+               m->mode = svc_pool_map_choose_mode();
 
        switch (m->mode) {
        case SVC_POOL_PERCPU:
@@ -195,9 +260,36 @@ svc_pool_map_init(void)
        }
        m->npools = npools;
 
+       mutex_unlock(&svc_pool_map_mutex);
        return m->npools;
 }
 
+
+/*
+ * Drop a reference to the global map of cpus to pools.
+ * When the last reference is dropped, the map data is
+ * freed; this allows the sysadmin to change the pool
+ * mode using the pool_mode module option without
+ * rebooting or re-loading sunrpc.ko.
+ */
+static void
+svc_pool_map_put(void)
+{
+       struct svc_pool_map *m = &svc_pool_map;
+
+       mutex_lock(&svc_pool_map_mutex);
+
+       if (!--m->count) {
+               m->mode = SVC_POOL_DEFAULT;
+               kfree(m->to_pool);
+               kfree(m->pool_to);
+               m->npools = 0;
+       }
+
+       mutex_unlock(&svc_pool_map_mutex);
+}
+
+
 /*
  * Set the current thread's cpus_allowed mask so that it
  * will only run on cpus in the given pool.
@@ -212,10 +304,9 @@ svc_pool_map_set_cpumask(unsigned int pidx, cpumask_t *oldmask)
 
        /*
         * The caller checks for sv_nrpools > 1, which
-        * implies that we've been initialized and the
-        * map mode is not NONE.
+        * implies that we've been initialized.
         */
-       BUG_ON(m->mode == SVC_POOL_NONE);
+       BUG_ON(m->count == 0);
 
        switch (m->mode)
        {
@@ -246,18 +337,19 @@ svc_pool_for_cpu(struct svc_serv *serv, int cpu)
        unsigned int pidx = 0;
 
        /*
-        * SVC_POOL_NONE happens in a pure client when
+        * An uninitialised map happens in a pure client when
         * lockd is brought up, so silently treat it the
         * same as SVC_POOL_GLOBAL.
         */
-
-       switch (m->mode) {
-       case SVC_POOL_PERCPU:
-               pidx = m->to_pool[cpu];
-               break;
-       case SVC_POOL_PERNODE:
-               pidx = m->to_pool[cpu_to_node(cpu)];
-               break;
+       if (svc_serv_is_pooled(serv)) {
+               switch (m->mode) {
+               case SVC_POOL_PERCPU:
+                       pidx = m->to_pool[cpu];
+                       break;
+               case SVC_POOL_PERNODE:
+                       pidx = m->to_pool[cpu_to_node(cpu)];
+                       break;
+               }
        }
        return &serv->sv_pools[pidx % serv->sv_nrpools];
 }
@@ -347,7 +439,7 @@ svc_create_pooled(struct svc_program *prog, unsigned int bufsize,
                  svc_thread_fn func, int sig, struct module *mod)
 {
        struct svc_serv *serv;
-       unsigned int npools = svc_pool_map_init();
+       unsigned int npools = svc_pool_map_get();
 
        serv = __svc_create(prog, bufsize, npools, shutdown);
 
@@ -367,6 +459,7 @@ void
 svc_destroy(struct svc_serv *serv)
 {
        struct svc_sock *svsk;
+       struct svc_sock *tmp;
 
        dprintk("svc: svc_destroy(%s, %d)\n",
                                serv->sv_program->pg_name,
@@ -382,24 +475,23 @@ svc_destroy(struct svc_serv *serv)
 
        del_timer_sync(&serv->sv_temptimer);
 
-       while (!list_empty(&serv->sv_tempsocks)) {
-               svsk = list_entry(serv->sv_tempsocks.next,
-                                 struct svc_sock,
-                                 sk_list);
-               svc_close_socket(svsk);
-       }
+       list_for_each_entry_safe(svsk, tmp, &serv->sv_tempsocks, sk_list)
+               svc_force_close_socket(svsk);
+
        if (serv->sv_shutdown)
                serv->sv_shutdown(serv);
 
-       while (!list_empty(&serv->sv_permsocks)) {
-               svsk = list_entry(serv->sv_permsocks.next,
-                                 struct svc_sock,
-                                 sk_list);
-               svc_close_socket(svsk);
-       }
+       list_for_each_entry_safe(svsk, tmp, &serv->sv_permsocks, sk_list)
+               svc_force_close_socket(svsk);
+
+       BUG_ON(!list_empty(&serv->sv_permsocks));
+       BUG_ON(!list_empty(&serv->sv_tempsocks));
 
        cache_clean_deferred(serv);
 
+       if (svc_serv_is_pooled(serv))
+               svc_pool_map_put();
+
        /* Unregister service with the portmapper */
        svc_register(serv, 0, 0);
        kfree(serv->sv_pools);
index 63ae94771b8e589e851eb94fc154599b5fc0754f..f6e1eb1ea7201dc3796b0058701af81627f7761d 100644 (file)
@@ -82,6 +82,7 @@ static void           svc_delete_socket(struct svc_sock *svsk);
 static void            svc_udp_data_ready(struct sock *, int);
 static int             svc_udp_recvfrom(struct svc_rqst *);
 static int             svc_udp_sendto(struct svc_rqst *);
+static void            svc_close_socket(struct svc_sock *svsk);
 
 static struct svc_deferred_req *svc_deferred_dequeue(struct svc_sock *svsk);
 static int svc_deferred_recv(struct svc_rqst *rqstp);
@@ -131,13 +132,13 @@ static char *__svc_print_addr(struct sockaddr *addr, char *buf, size_t len)
                        NIPQUAD(((struct sockaddr_in *) addr)->sin_addr),
                        htons(((struct sockaddr_in *) addr)->sin_port));
                break;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+
        case AF_INET6:
                snprintf(buf, len, "%x:%x:%x:%x:%x:%x:%x:%x, port=%u",
                        NIP6(((struct sockaddr_in6 *) addr)->sin6_addr),
                        htons(((struct sockaddr_in6 *) addr)->sin6_port));
                break;
-#endif
+
        default:
                snprintf(buf, len, "unknown address type: %d", addr->sa_family);
                break;
@@ -449,9 +450,7 @@ svc_wake_up(struct svc_serv *serv)
 
 union svc_pktinfo_u {
        struct in_pktinfo pkti;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
        struct in6_pktinfo pkti6;
-#endif
 };
 
 static void svc_set_cmsg_data(struct svc_rqst *rqstp, struct cmsghdr *cmh)
@@ -467,7 +466,7 @@ static void svc_set_cmsg_data(struct svc_rqst *rqstp, struct cmsghdr *cmh)
                        cmh->cmsg_len = CMSG_LEN(sizeof(*pki));
                }
                break;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+
        case AF_INET6: {
                        struct in6_pktinfo *pki = CMSG_DATA(cmh);
 
@@ -479,7 +478,6 @@ static void svc_set_cmsg_data(struct svc_rqst *rqstp, struct cmsghdr *cmh)
                        cmh->cmsg_len = CMSG_LEN(sizeof(*pki));
                }
                break;
-#endif
        }
        return;
 }
@@ -721,45 +719,21 @@ svc_write_space(struct sock *sk)
        }
 }
 
-static void svc_udp_get_sender_address(struct svc_rqst *rqstp,
-                                       struct sk_buff *skb)
+static inline void svc_udp_get_dest_address(struct svc_rqst *rqstp,
+                                           struct cmsghdr *cmh)
 {
        switch (rqstp->rq_sock->sk_sk->sk_family) {
        case AF_INET: {
-               /* this seems to come from net/ipv4/udp.c:udp_recvmsg */
-                       struct sockaddr_in *sin = svc_addr_in(rqstp);
-
-                       sin->sin_family = AF_INET;
-                       sin->sin_port = skb->h.uh->source;
-                       sin->sin_addr.s_addr = skb->nh.iph->saddr;
-                       rqstp->rq_addrlen = sizeof(struct sockaddr_in);
-                       /* Remember which interface received this request */
-                       rqstp->rq_daddr.addr.s_addr = skb->nh.iph->daddr;
-               }
+               struct in_pktinfo *pki = CMSG_DATA(cmh);
+               rqstp->rq_daddr.addr.s_addr = pki->ipi_spec_dst.s_addr;
                break;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-       case AF_INET6: {
-               /* this is derived from net/ipv6/udp.c:udpv6_recvmesg */
-                       struct sockaddr_in6 *sin6 = svc_addr_in6(rqstp);
-
-                       sin6->sin6_family = AF_INET6;
-                       sin6->sin6_port = skb->h.uh->source;
-                       sin6->sin6_flowinfo = 0;
-                       sin6->sin6_scope_id = 0;
-                       if (ipv6_addr_type(&sin6->sin6_addr) &
-                                                       IPV6_ADDR_LINKLOCAL)
-                               sin6->sin6_scope_id = IP6CB(skb)->iif;
-                       ipv6_addr_copy(&sin6->sin6_addr,
-                                                       &skb->nh.ipv6h->saddr);
-                       rqstp->rq_addrlen = sizeof(struct sockaddr_in);
-                       /* Remember which interface received this request */
-                       ipv6_addr_copy(&rqstp->rq_daddr.addr6,
-                                                       &skb->nh.ipv6h->saddr);
                }
+       case AF_INET6: {
+               struct in6_pktinfo *pki = CMSG_DATA(cmh);
+               ipv6_addr_copy(&rqstp->rq_daddr.addr6, &pki->ipi6_addr);
                break;
-#endif
+               }
        }
-       return;
 }
 
 /*
@@ -771,7 +745,15 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
        struct svc_sock *svsk = rqstp->rq_sock;
        struct svc_serv *serv = svsk->sk_server;
        struct sk_buff  *skb;
+       char            buffer[CMSG_SPACE(sizeof(union svc_pktinfo_u))];
+       struct cmsghdr *cmh = (struct cmsghdr *)buffer;
        int             err, len;
+       struct msghdr msg = {
+               .msg_name = svc_addr(rqstp),
+               .msg_control = cmh,
+               .msg_controllen = sizeof(buffer),
+               .msg_flags = MSG_DONTWAIT,
+       };
 
        if (test_and_clear_bit(SK_CHNGBUF, &svsk->sk_flags))
            /* udp sockets need large rcvbuf as all pending
@@ -797,7 +779,9 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
        }
 
        clear_bit(SK_DATA, &svsk->sk_flags);
-       while ((skb = skb_recv_datagram(svsk->sk_sk, 0, 1, &err)) == NULL) {
+       while ((err == kernel_recvmsg(svsk->sk_sock, &msg, NULL,
+                                     0, 0, MSG_PEEK | MSG_DONTWAIT)) < 0 ||
+              (skb = skb_recv_datagram(svsk->sk_sk, 0, 1, &err)) == NULL) {
                if (err == -EAGAIN) {
                        svc_sock_received(svsk);
                        return err;
@@ -805,6 +789,7 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
                /* possibly an icmp error */
                dprintk("svc: recvfrom returned error %d\n", -err);
        }
+       rqstp->rq_addrlen = sizeof(rqstp->rq_addr);
        if (skb->tstamp.off_sec == 0) {
                struct timeval tv;
 
@@ -827,7 +812,16 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
 
        rqstp->rq_prot = IPPROTO_UDP;
 
-       svc_udp_get_sender_address(rqstp, skb);
+       if (cmh->cmsg_level != IPPROTO_IP ||
+           cmh->cmsg_type != IP_PKTINFO) {
+               if (net_ratelimit())
+                       printk("rpcsvc: received unknown control message:"
+                              "%d/%d\n",
+                              cmh->cmsg_level, cmh->cmsg_type);
+               skb_free_datagram(svsk->sk_sk, skb);
+               return 0;
+       }
+       svc_udp_get_dest_address(rqstp, cmh);
 
        if (skb_is_nonlinear(skb)) {
                /* we have to copy */
@@ -884,6 +878,9 @@ svc_udp_sendto(struct svc_rqst *rqstp)
 static void
 svc_udp_init(struct svc_sock *svsk)
 {
+       int one = 1;
+       mm_segment_t oldfs;
+
        svsk->sk_sk->sk_data_ready = svc_udp_data_ready;
        svsk->sk_sk->sk_write_space = svc_write_space;
        svsk->sk_recvfrom = svc_udp_recvfrom;
@@ -899,6 +896,13 @@ svc_udp_init(struct svc_sock *svsk)
 
        set_bit(SK_DATA, &svsk->sk_flags); /* might have come in before data_ready set up */
        set_bit(SK_CHNGBUF, &svsk->sk_flags);
+
+       oldfs = get_fs();
+       set_fs(KERNEL_DS);
+       /* make sure we get destination address info */
+       svsk->sk_sock->ops->setsockopt(svsk->sk_sock, IPPROTO_IP, IP_PKTINFO,
+                                      (char __user *)&one, sizeof(one));
+       set_fs(oldfs);
 }
 
 /*
@@ -977,11 +981,9 @@ static inline int svc_port_is_privileged(struct sockaddr *sin)
        case AF_INET:
                return ntohs(((struct sockaddr_in *)sin)->sin_port)
                        < PROT_SOCK;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
        case AF_INET6:
                return ntohs(((struct sockaddr_in6 *)sin)->sin6_port)
                        < PROT_SOCK;
-#endif
        default:
                return 0;
        }
@@ -1786,7 +1788,7 @@ svc_delete_socket(struct svc_sock *svsk)
        spin_unlock_bh(&serv->sv_lock);
 }
 
-void svc_close_socket(struct svc_sock *svsk)
+static void svc_close_socket(struct svc_sock *svsk)
 {
        set_bit(SK_CLOSE, &svsk->sk_flags);
        if (test_and_set_bit(SK_BUSY, &svsk->sk_flags))
@@ -1799,6 +1801,19 @@ void svc_close_socket(struct svc_sock *svsk)
        svc_sock_put(svsk);
 }
 
+void svc_force_close_socket(struct svc_sock *svsk)
+{
+       set_bit(SK_CLOSE, &svsk->sk_flags);
+       if (test_bit(SK_BUSY, &svsk->sk_flags)) {
+               /* Waiting to be processed, but no threads left,
+                * So just remove it from the waiting list
+                */
+               list_del_init(&svsk->sk_ready);
+               clear_bit(SK_BUSY, &svsk->sk_flags);
+       }
+       svc_close_socket(svsk);
+}
+
 /**
  * svc_makesock - Make a socket for nfsd and lockd
  * @serv: RPC server structure
index 946b715db5ec8c708287d8d5ae51a2eb4d77ab8e..0c3a70ac507545e6afef5d282c0460560e0ecdb5 100644 (file)
@@ -735,12 +735,14 @@ EXPORT_SYMBOL(xfrm_policy_insert);
 
 struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
                                          struct xfrm_selector *sel,
-                                         struct xfrm_sec_ctx *ctx, int delete)
+                                         struct xfrm_sec_ctx *ctx, int delete,
+                                         int *err)
 {
        struct xfrm_policy *pol, *ret;
        struct hlist_head *chain;
        struct hlist_node *entry;
 
+       *err = 0;
        write_lock_bh(&xfrm_policy_lock);
        chain = policy_hash_bysel(sel, sel->family, dir);
        ret = NULL;
@@ -750,6 +752,11 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
                    xfrm_sec_ctx_match(ctx, pol->security)) {
                        xfrm_pol_hold(pol);
                        if (delete) {
+                               *err = security_xfrm_policy_delete(pol);
+                               if (*err) {
+                                       write_unlock_bh(&xfrm_policy_lock);
+                                       return pol;
+                               }
                                hlist_del(&pol->bydst);
                                hlist_del(&pol->byidx);
                                xfrm_policy_count[dir]--;
@@ -768,12 +775,14 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
 }
 EXPORT_SYMBOL(xfrm_policy_bysel_ctx);
 
-struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete)
+struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete,
+                                    int *err)
 {
        struct xfrm_policy *pol, *ret;
        struct hlist_head *chain;
        struct hlist_node *entry;
 
+       *err = 0;
        write_lock_bh(&xfrm_policy_lock);
        chain = xfrm_policy_byidx + idx_hash(id);
        ret = NULL;
@@ -781,6 +790,11 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete)
                if (pol->type == type && pol->index == id) {
                        xfrm_pol_hold(pol);
                        if (delete) {
+                               *err = security_xfrm_policy_delete(pol);
+                               if (*err) {
+                                       write_unlock_bh(&xfrm_policy_lock);
+                                       return pol;
+                               }
                                hlist_del(&pol->bydst);
                                hlist_del(&pol->byidx);
                                xfrm_policy_count[dir]--;
index 2567453216113fdd5e23a51e856f1a6526abfc7b..96789952f6a3ff24b41a1301a5095a3fdd791997 100644 (file)
@@ -530,9 +530,6 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
 
        err = xfrm_state_delete(x);
 
-       xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid,
-                      AUDIT_MAC_IPSEC_DELSA, err ? 0 : 1, NULL, x);
-
        if (err < 0)
                goto out;
 
@@ -542,6 +539,8 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
        km_state_notify(x, &c);
 
 out:
+       xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid,
+                      AUDIT_MAC_IPSEC_DELSA, err ? 0 : 1, NULL, x);
        xfrm_state_put(x);
        return err;
 }
@@ -1254,7 +1253,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
                return err;
 
        if (p->index)
-               xp = xfrm_policy_byid(type, p->dir, p->index, delete);
+               xp = xfrm_policy_byid(type, p->dir, p->index, delete, &err);
        else {
                struct rtattr *rt = xfrma[XFRMA_SEC_CTX-1];
                struct xfrm_policy tmp;
@@ -1270,7 +1269,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
                        if ((err = security_xfrm_policy_alloc(&tmp, uctx)))
                                return err;
                }
-               xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, delete);
+               xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security,
+                                          delete, &err);
                security_xfrm_policy_free(&tmp);
        }
        if (xp == NULL)
@@ -1288,8 +1288,6 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
                                              MSG_DONTWAIT);
                }
        } else {
-               err = security_xfrm_policy_delete(xp);
-
                xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid,
                               AUDIT_MAC_IPSEC_DELSPD, err ? 0 : 1, xp, NULL);
 
@@ -1303,9 +1301,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
                km_policy_notify(xp, p->dir, &c);
        }
 
-       xfrm_pol_put(xp);
-
 out:
+       xfrm_pol_put(xp);
        return err;
 }
 
@@ -1401,7 +1398,7 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
 
        x = xfrm_state_lookup(&id->daddr, id->spi, id->proto, id->family);
        if (x == NULL) {
-               kfree(r_skb);
+               kfree_skb(r_skb);
                return -ESRCH;
        }
 
@@ -1502,7 +1499,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
                return err;
 
        if (p->index)
-               xp = xfrm_policy_byid(type, p->dir, p->index, 0);
+               xp = xfrm_policy_byid(type, p->dir, p->index, 0, &err);
        else {
                struct rtattr *rt = xfrma[XFRMA_SEC_CTX-1];
                struct xfrm_policy tmp;
@@ -1518,13 +1515,14 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
                        if ((err = security_xfrm_policy_alloc(&tmp, uctx)))
                                return err;
                }
-               xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, 0);
+               xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security,
+                                          0, &err);
                security_xfrm_policy_free(&tmp);
        }
 
        if (xp == NULL)
-               return err;
-                                                                                       read_lock(&xp->lock);
+               return -ENOENT;
+       read_lock(&xp->lock);
        if (xp->dead) {
                read_unlock(&xp->lock);
                goto out;
@@ -1557,14 +1555,13 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
        struct xfrm_usersa_info *p = &ue->state;
 
        x = xfrm_state_lookup(&p->id.daddr, p->id.spi, p->id.proto, p->family);
-               err = -ENOENT;
 
+       err = -ENOENT;
        if (x == NULL)
                return err;
 
-       err = -EINVAL;
-
        spin_lock_bh(&x->lock);
+       err = -EINVAL;
        if (x->km.state != XFRM_STATE_VALID)
                goto out;
        km_state_expired(x, ue->hard, current->pid);
@@ -1574,6 +1571,7 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
                xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid,
                               AUDIT_MAC_IPSEC_DELSA, 1, NULL, x);
        }
+       err = 0;
 out:
        spin_unlock_bh(&x->lock);
        xfrm_state_put(x);
index 4d928b859845d02ba63cf128c7165bc4896b0fac..8be269ffbf9d4f8159ca7a49a589f879a3d38583 100755 (executable)
@@ -452,7 +452,7 @@ sub output_struct_html(%) {
     my %args = %{$_[0]};
     my ($parameter);
 
-    print "<h2>".$args{'type'}." ".$args{'struct'}."</h2>\n";
+    print "<h2>".$args{'type'}." ".$args{'struct'}. " - " .$args{'purpose'}."</h2>\n";
     print "<b>".$args{'type'}." ".$args{'struct'}."</b> {<br>\n";
     foreach $parameter (@{$args{'parameterlist'}}) {
        if ($parameter =~ /^#/) {
@@ -498,8 +498,8 @@ sub output_function_html(%) {
     my %args = %{$_[0]};
     my ($parameter, $section);
     my $count;
-    print "<h2>Function</h2>\n";
 
+    print "<h2>" .$args{'function'}." - ".$args{'purpose'}."</h2>\n";
     print "<i>".$args{'functiontype'}."</i>\n";
     print "<b>".$args{'function'}."</b>\n";
     print "(";
@@ -1547,7 +1547,7 @@ sub dump_function($$) {
     $prototype =~ s/^noinline +//;
     $prototype =~ s/__devinit +//;
     $prototype =~ s/^#define\s+//; #ak added
-    $prototype =~ s/__attribute__ \(\([a-z,]*\)\)//;
+    $prototype =~ s/__attribute__\s*\(\([a-z,]*\)\)//;
 
     # Yes, this truly is vile.  We are looking for:
     # 1. Return type (may be nothing if we're looking at a macro)
index f61c9ccef6aa562889a2a8c867730c7d05de0f91..b2f73ffb40bde5e790c2a93fb68b9d215bbcf86a 100644 (file)
@@ -452,6 +452,24 @@ static int do_eisa_entry(const char *filename, struct eisa_device_id *eisa,
        return 1;
 }
 
+/* Looks like: parisc:tNhvNrevNsvN */
+static int do_parisc_entry(const char *filename, struct parisc_device_id *id,
+               char *alias)
+{
+       id->hw_type = TO_NATIVE(id->hw_type);
+       id->hversion = TO_NATIVE(id->hversion);
+       id->hversion_rev = TO_NATIVE(id->hversion_rev);
+       id->sversion = TO_NATIVE(id->sversion);
+
+       strcpy(alias, "parisc:");
+       ADD(alias, "t", id->hw_type != PA_HWTYPE_ANY_ID, id->hw_type);
+       ADD(alias, "hv", id->hversion != PA_HVERSION_ANY_ID, id->hversion);
+       ADD(alias, "rev", id->hversion_rev != PA_HVERSION_REV_ANY_ID, id->hversion_rev);
+       ADD(alias, "sv", id->sversion != PA_SVERSION_ANY_ID, id->sversion);
+
+       return 1;
+}
+
 /* Ignore any prefix, eg. v850 prepends _ */
 static inline int sym_is(const char *symbol, const char *name)
 {
@@ -559,6 +577,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
                do_table(symval, sym->st_size,
                         sizeof(struct eisa_device_id), "eisa",
                         do_eisa_entry, mod);
+       else if (sym_is(symname, "__mod_parisc_device_table"))
+               do_table(symval, sym->st_size,
+                        sizeof(struct parisc_device_id), "parisc",
+                        do_parisc_entry, mod);
 }
 
 /* Now add out buffered information to the generated C source */
index 569e68410d7a96a78f2673d4fdaf12bfc65136af..65bdfdb56877ee0297d9e605384caedbcbed286c 100644 (file)
@@ -686,6 +686,30 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf_Addr addr,
        return NULL;
 }
 
+static inline int is_arm_mapping_symbol(const char *str)
+{
+       return str[0] == '$' && strchr("atd", str[1])
+              && (str[2] == '\0' || str[2] == '.');
+}
+
+/*
+ * If there's no name there, ignore it; likewise, ignore it if it's
+ * one of the magic symbols emitted used by current ARM tools.
+ *
+ * Otherwise if find_symbols_between() returns those symbols, they'll
+ * fail the whitelist tests and cause lots of false alarms ... fixable
+ * only by merging __exit and __init sections into __text, bloating
+ * the kernel (which is especially evil on embedded platforms).
+ */
+static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym)
+{
+       const char *name = elf->strtab + sym->st_name;
+
+       if (!name || !strlen(name))
+               return 0;
+       return !is_arm_mapping_symbol(name);
+}
+
 /*
  * Find symbols before or equal addr and after addr - in the section sec.
  * If we find two symbols with equal offset prefer one with a valid name.
@@ -714,16 +738,15 @@ static void find_symbols_between(struct elf_info *elf, Elf_Addr addr,
                symsec = secstrings + elf->sechdrs[sym->st_shndx].sh_name;
                if (strcmp(symsec, sec) != 0)
                        continue;
+               if (!is_valid_name(elf, sym))
+                       continue;
                if (sym->st_value <= addr) {
                        if ((addr - sym->st_value) < beforediff) {
                                beforediff = addr - sym->st_value;
                                *before = sym;
                        }
                        else if ((addr - sym->st_value) == beforediff) {
-                               /* equal offset, valid name? */
-                               const char *name = elf->strtab + sym->st_name;
-                               if (name && strlen(name))
-                                       *before = sym;
+                               *before = sym;
                        }
                }
                else
@@ -733,10 +756,7 @@ static void find_symbols_between(struct elf_info *elf, Elf_Addr addr,
                                *after = sym;
                        }
                        else if ((sym->st_value - addr) == afterdiff) {
-                               /* equal offset, valid name? */
-                               const char *name = elf->strtab + sym->st_name;
-                               if (name && strlen(name))
-                                       *after = sym;
+                               *after = sym;
                        }
                }
        }
@@ -941,7 +961,7 @@ static int init_section_ref_ok(const char *name)
                ".opd",   /* see comment [OPD] at exit_section_ref_ok() */
                ".toc1",  /* used by ppc64 */
                ".stab",
-               ".rodata",
+               ".data.rel.ro", /* used by parisc64 */
                ".parainstructions",
                ".text.lock",
                "__bug_table", /* used by powerpc for BUG() */
@@ -964,6 +984,7 @@ static int init_section_ref_ok(const char *name)
                ".eh_frame",
                ".debug",
                ".parainstructions",
+               ".rodata",
                NULL
        };
        /* part of section name */
index b1ac22d231954bc5e900c07da670962c953ba1c2..19a385e9968e2c1eabcbdab8eec41bab8be4869b 100644 (file)
@@ -653,11 +653,11 @@ static int superblock_doinit(struct super_block *sb, void *data)
        sbsec->initialized = 1;
 
        if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) {
-               printk(KERN_INFO "SELinux: initialized (dev %s, type %s), unknown behavior\n",
+               printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
                       sb->s_id, sb->s_type->name);
        }
        else {
-               printk(KERN_INFO "SELinux: initialized (dev %s, type %s), %s\n",
+               printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
                       sb->s_id, sb->s_type->name,
                       labeling_behaviors[sbsec->behavior-1]);
        }
@@ -4434,7 +4434,7 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
 static int selinux_register_security (const char *name, struct security_operations *ops)
 {
        if (secondary_ops != original_ops) {
-               printk(KERN_INFO "%s:  There is already a secondary security "
+               printk(KERN_ERR "%s:  There is already a secondary security "
                       "module registered.\n", __FUNCTION__);
                return -EINVAL;
        }
@@ -4451,7 +4451,7 @@ static int selinux_register_security (const char *name, struct security_operatio
 static int selinux_unregister_security (const char *name, struct security_operations *ops)
 {
        if (ops != secondary_ops) {
-               printk (KERN_INFO "%s:  trying to unregister a security module "
+               printk(KERN_ERR "%s:  trying to unregister a security module "
                        "that is not registered.\n", __FUNCTION__);
                return -EINVAL;
        }
@@ -4889,9 +4889,9 @@ static __init int selinux_init(void)
                panic("SELinux: Unable to register with kernel.\n");
 
        if (selinux_enforcing) {
-               printk(KERN_INFO "SELinux:  Starting in enforcing mode\n");
+               printk(KERN_DEBUG "SELinux:  Starting in enforcing mode\n");
        } else {
-               printk(KERN_INFO "SELinux:  Starting in permissive mode\n");
+               printk(KERN_DEBUG "SELinux:  Starting in permissive mode\n");
        }
 
 #ifdef CONFIG_KEYS
@@ -4907,10 +4907,10 @@ static __init int selinux_init(void)
 
 void selinux_complete_init(void)
 {
-       printk(KERN_INFO "SELinux:  Completing initialization.\n");
+       printk(KERN_DEBUG "SELinux:  Completing initialization.\n");
 
        /* Set up any superblocks initialized prior to the policy load. */
-       printk(KERN_INFO "SELinux:  Setting up existing superblocks.\n");
+       printk(KERN_DEBUG "SELinux:  Setting up existing superblocks.\n");
        spin_lock(&sb_lock);
        spin_lock(&sb_security_lock);
 next_sb:
@@ -4968,9 +4968,9 @@ static int __init selinux_nf_ip_init(void)
 
        if (!selinux_enabled)
                goto out;
-               
-       printk(KERN_INFO "SELinux:  Registering netfilter hooks\n");
-       
+
+       printk(KERN_DEBUG "SELinux:  Registering netfilter hooks\n");
+
        err = nf_register_hook(&selinux_ipv4_op);
        if (err)
                panic("SELinux: nf_register_hook for IPv4: error %d\n", err);
@@ -4992,7 +4992,7 @@ __initcall(selinux_nf_ip_init);
 #ifdef CONFIG_SECURITY_SELINUX_DISABLE
 static void selinux_nf_ip_exit(void)
 {
-       printk(KERN_INFO "SELinux:  Unregistering netfilter hooks\n");
+       printk(KERN_DEBUG "SELinux:  Unregistering netfilter hooks\n");
 
        nf_unregister_hook(&selinux_ipv4_op);
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
index 9142073319c0085fcd07f87291510f3033f20bf2..3122908afdc1484d495faf7f4c92cc0e1cb2e31a 100644 (file)
@@ -277,7 +277,7 @@ void avtab_hash_eval(struct avtab *h, char *tag)
                }
        }
 
-       printk(KERN_INFO "%s:  %d entries and %d/%d buckets used, longest "
+       printk(KERN_DEBUG "%s:  %d entries and %d/%d buckets used, longest "
               "chain length %d\n", tag, h->nel, slots_used, AVTAB_SIZE,
               max_chain_len);
 }
index cd79c6338aa060df5af08643f50b767c5fa56b61..0ac1021734c01118a012b38ab7335b8eeeb2f4fa 100644 (file)
@@ -374,7 +374,7 @@ static void symtab_hash_eval(struct symtab *s)
                struct hashtab_info info;
 
                hashtab_stat(h, &info);
-               printk(KERN_INFO "%s:  %d entries and %d/%d buckets used, "
+               printk(KERN_DEBUG "%s:  %d entries and %d/%d buckets used, "
                       "longest chain length %d\n", symtab_name[i], h->nel,
                       info.slots_used, h->size, info.max_chain_len);
        }
@@ -391,14 +391,14 @@ static int policydb_index_others(struct policydb *p)
 {
        int i, rc = 0;
 
-       printk(KERN_INFO "security:  %d users, %d roles, %d types, %d bools",
+       printk(KERN_DEBUG "security:  %d users, %d roles, %d types, %d bools",
               p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim);
        if (selinux_mls_enabled)
                printk(", %d sens, %d cats", p->p_levels.nprim,
                       p->p_cats.nprim);
        printk("\n");
 
-       printk(KERN_INFO "security:  %d classes, %d rules\n",
+       printk(KERN_DEBUG "security:  %d classes, %d rules\n",
               p->p_classes.nprim, p->te_avtab.nel);
 
 #ifdef DEBUG_HASHES
index ca9154dc5d825bea7f680de2f42b0979e4a930a6..1e52356664d6866ed2b24ad753088b8349a167ba 100644 (file)
@@ -609,6 +609,9 @@ int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
        struct context *context;
        int rc = 0;
 
+       *scontext = NULL;
+       *scontext_len  = 0;
+
        if (!ss_initialized) {
                if (sid <= SECINITSID_NUM) {
                        char *scontextp;
index d78f9ff30da906bb30edefcc9f63aaccf2fce5aa..53a54a77f1f8ca806a65becc6e5464e394d48dbc 100644 (file)
@@ -253,7 +253,7 @@ void sidtab_hash_eval(struct sidtab *h, char *tag)
                }
        }
 
-       printk(KERN_INFO "%s:  %d entries and %d/%d buckets used, longest "
+       printk(KERN_DEBUG "%s:  %d entries and %d/%d buckets used, longest "
               "chain length %d\n", tag, h->nel, slots_used, SIDTAB_SIZE,
               max_chain_len);
 }
index 5190d7acdb9fd6306761c8a7da2a689d561e1f0c..b9eca9f3dd252cd44d29d4aa1215c713347a8d81 100644 (file)
@@ -726,8 +726,8 @@ static struct snd_pcm_ops aaci_playback_ops = {
        .mmap           = aaci_pcm_mmap,
 };
 
-static int aaci_pcm_capture_hw_params(snd_pcm_substream_t *substream,
-                                     snd_pcm_hw_params_t *params)
+static int aaci_pcm_capture_hw_params(struct snd_pcm_substream *substream,
+                                     struct snd_pcm_hw_params *params)
 {
        struct aaci *aaci = substream->private_data;
        struct aaci_runtime *aacirun = substream->runtime->private_data;
@@ -783,8 +783,8 @@ static void aaci_pcm_capture_start(struct aaci_runtime *aacirun)
        writel(ie, aacirun->base + AACI_IE);
 }
 
-static int aaci_pcm_capture_trigger(snd_pcm_substream_t *substream, int cmd){
-
+static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
+{
        struct aaci *aaci = substream->private_data;
        struct aaci_runtime *aacirun = substream->runtime->private_data;
        unsigned long flags;
@@ -824,7 +824,7 @@ static int aaci_pcm_capture_trigger(snd_pcm_substream_t *substream, int cmd){
        return ret;
 }
 
-static int aaci_pcm_capture_prepare(snd_pcm_substream_t *substream)
+static int aaci_pcm_capture_prepare(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct aaci *aaci = substream->private_data;
@@ -842,7 +842,7 @@ static int aaci_pcm_capture_prepare(snd_pcm_substream_t *substream)
        return 0;
 }
 
-static snd_pcm_ops_t aaci_capture_ops = {
+static struct snd_pcm_ops aaci_capture_ops = {
        .open           = aaci_pcm_open,
        .close          = aaci_pcm_close,
        .ioctl          = snd_pcm_lib_ioctl,
index cf603337b321d01bba027480e29fc5abbe593b98..ff705c63a03a2f0292438a380e11b2f76212de22 100644 (file)
@@ -854,7 +854,7 @@ static struct snd_kcontrol_new snd_harmony_controls[] = {
                       HARMONY_GAIN_HE_SHIFT, 1, 0),
 };
 
-static void __init 
+static void __devinit
 snd_harmony_mixer_reset(struct snd_harmony *h)
 {
        harmony_mute(h);
@@ -863,7 +863,7 @@ snd_harmony_mixer_reset(struct snd_harmony *h)
        harmony_unmute(h);
 }
 
-static int __init 
+static int __devinit
 snd_harmony_mixer_init(struct snd_harmony *h)
 {
        struct snd_card *card = h->card;
index bfc2fed16da3a0208a6a5be3d146a81032ecffd1..37fabf75daa7291d148d30d141562ddcf0d9f69a 100644 (file)
@@ -1790,6 +1790,8 @@ static const struct snd_kcontrol_new snd_ac97_ad1981x_jack_sense[] = {
  * (SS vendor << 16 | device)
  */
 static unsigned int ad1981_jacks_blacklist[] = {
+       0x10140523, /* Thinkpad R40 */
+       0x10140534, /* Thinkpad X31 */
        0x10140537, /* Thinkpad T41p */
        0x10140554, /* Thinkpad T42p/R50p */
        0 /* end */
index 9327ab2eccb0c704a951a2a59b51f1c5eb28e2df..ba7fa22b285dd837c881f61d1856205dba58fb13 100644 (file)
@@ -2312,6 +2312,8 @@ static int __devinit snd_ali_create(struct snd_card *card,
                return err;
        }
 
+       snd_card_set_dev(card, &pci->dev);
+
        /* initialise synth voices*/
        for (i = 0; i < ALI_CHANNELS; i++ ) {
                codec->synth.voices[i].number = i;
index c3f3da21123454f3e8df27d0212c5eb084b2a93c..e9b029e1cd6dd626d4fb8586695acc3813c53950 100644 (file)
@@ -804,6 +804,7 @@ static struct {
        {0x1822, 0x0001}, /* Twinhan VisionPlus DVB-T */
        {0x18ac, 0xd500}, /* DVICO FusionHDTV 5 Lite */
        {0x18ac, 0xdb10}, /* DVICO FusionHDTV DVB-T Lite */
+       {0x18ac, 0xdb11}, /* Ultraview DVB-T Lite */
        {0x270f, 0xfc00}, /* Chaintech Digitop DST-1000 DVB-S */
        {0x7063, 0x2000}, /* pcHDTV HD-2000 TV */
 };
index 70face7e104862b38cf7545136e4a26141b32d23..7d3c5ee0005cc0bf81fe805fe08cdfe932bb26d8 100644 (file)
@@ -57,7 +57,7 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;    /* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;      /* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;     /* Enable switches */
 static long mpu_port[SNDRV_CARDS];
-static long fm_port[SNDRV_CARDS];
+static long fm_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)]=1};
 static int soft_ac3[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)]=1};
 #ifdef SUPPORT_JOYSTICK
 static int joystick_port[SNDRV_CARDS];
@@ -2779,6 +2779,9 @@ static int __devinit snd_cmipci_create_fm(struct cmipci *cm, long fm_port)
        struct snd_opl3 *opl3;
        int err;
 
+       if (!fm_port)
+               goto disable_fm;
+
        /* first try FM regs in PCI port range */
        iosynth = cm->iobase + CM_REG_FM_PCI;
        err = snd_opl3_create(cm->card, iosynth, iosynth + 2,
@@ -2793,7 +2796,7 @@ static int __devinit snd_cmipci_create_fm(struct cmipci *cm, long fm_port)
                case 0x3C8: val |= CM_FMSEL_3C8; break;
                case 0x388: val |= CM_FMSEL_388; break;
                default:
-                           return 0;
+                       goto disable_fm;
                }
                snd_cmipci_write(cm, CM_REG_LEGACY_CTRL, val);
                /* enable FM */
@@ -2803,11 +2806,7 @@ static int __devinit snd_cmipci_create_fm(struct cmipci *cm, long fm_port)
                                    OPL3_HW_OPL3, 0, &opl3) < 0) {
                        printk(KERN_ERR "cmipci: no OPL device at %#lx, "
                               "skipping...\n", iosynth);
-                       /* disable FM */
-                       snd_cmipci_write(cm, CM_REG_LEGACY_CTRL,
-                                        val & ~CM_FMSEL_MASK);
-                       snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_FM_EN);
-                       return 0;
+                       goto disable_fm;
                }
        }
        if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
@@ -2815,6 +2814,11 @@ static int __devinit snd_cmipci_create_fm(struct cmipci *cm, long fm_port)
                return err;
        }
        return 0;
+
+ disable_fm:
+       snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_FMSEL_MASK);
+       snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_FM_EN);
+       return 0;
 }
 
 static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
index 6a428b81dba65e4719980a5dee6f3922b83a431b..e413da00759bcbe3cc2e67086b41866d12e4bc4a 100644 (file)
@@ -2033,6 +2033,8 @@ static int __devinit snd_echo_probe(struct pci_dev *pci,
        if (card == NULL)
                return -ENOMEM;
 
+       snd_card_set_dev(card, &pci->dev);
+
        if ((err = snd_echo_create(card, pci, &chip)) < 0) {
                snd_card_free(card);
                return err;
index 38977bce70e2f6f0d33aab76923087068d6de66e..00ace59b05c982f9867fa40886604f1c5f44192b 100644 (file)
@@ -523,6 +523,7 @@ static struct snd_kcontrol_new ad1986a_mixers[] = {
        HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
        HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
        HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
        HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT),
        HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT),
        HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
@@ -570,6 +571,7 @@ static struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
        HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
        HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
        HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
        /* HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT),
           HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT),
           HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
@@ -658,6 +660,7 @@ static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
        HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x0, HDA_OUTPUT),
        HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
        HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
        HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
        HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
        {
index 23a1c75085b58fcd742a0e015003005a43a72931..46e93c6b9a425cb543367dd34f7e94d2f43a3f27 100644 (file)
@@ -629,10 +629,12 @@ static int cxt5045_hp_master_vol_put(struct snd_kcontrol *kcontrol,
 static void cxt5045_hp_automute(struct hda_codec *codec)
 {
        struct conexant_spec *spec = codec->spec;
-       unsigned int bits = (spec->hp_present || !spec->cur_eapd) ? 0x80 : 0;
+       unsigned int bits;
 
        spec->hp_present = snd_hda_codec_read(codec, 0x11, 0,
                                     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+
+       bits = (spec->hp_present || !spec->cur_eapd) ? 0x80 : 0;
        snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits);
        snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits);
 }
@@ -979,10 +981,12 @@ static int cxt5047_hp_master_vol_put(struct snd_kcontrol *kcontrol,
 static void cxt5047_hp_automute(struct hda_codec *codec)
 {
        struct conexant_spec *spec = codec->spec;
-       unsigned int bits = spec->hp_present || !spec->cur_eapd ? 0x80 : 0;
+       unsigned int bits;
 
        spec->hp_present = snd_hda_codec_read(codec, 0x13, 0,
                                     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+
+       bits = (spec->hp_present || !spec->cur_eapd) ? 0x80 : 0;
        snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0, 0x80, bits);
        snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0, 0x80, bits);
        /* Mute/Unmute PCM 2 for good measure - some systems need this */
index 145682b7807124430dbcec680668a2f01b64b7a2..84d005ef30eed3a044c7041881cf056384553e51 100644 (file)
@@ -4942,9 +4942,16 @@ static int patch_alc882(struct hda_codec *codec)
                                                  alc882_cfg_tbl);
 
        if (board_config < 0 || board_config >= ALC882_MODEL_LAST) {
-               printk(KERN_INFO "hda_codec: Unknown model for ALC882, "
-                      "trying auto-probe from BIOS...\n");
-               board_config = ALC882_AUTO;
+               /* Pick up systems that don't supply PCI SSID */
+               switch (codec->subsystem_id) {
+               case 0x106b0c00: /* Mac Pro */
+                       board_config = ALC885_MACPRO;
+                       break;
+               default:
+                       printk(KERN_INFO "hda_codec: Unknown model for ALC882, "
+                                        "trying auto-probe from BIOS...\n");
+                       board_config = ALC882_AUTO;
+               }
        }
 
        if (board_config == ALC882_AUTO) {
@@ -5917,8 +5924,10 @@ static struct snd_kcontrol_new alc262_base_mixer[] = {
        HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
        HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
        HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
        HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
        HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+       HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
        /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
           HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */
        HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),
@@ -5937,8 +5946,10 @@ static struct snd_kcontrol_new alc262_hippo1_mixer[] = {
        HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
        HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
        HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
        HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
        HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+       HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
        /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
           HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */
        /*HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),*/
@@ -5955,8 +5966,10 @@ static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
 
        HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
        HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
        HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
        HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+       HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
        HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
        HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
        HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
@@ -5977,6 +5990,7 @@ static struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = {
        HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
        HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x02, HDA_INPUT),
        HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x02, HDA_INPUT),
+       HDA_CODEC_VOLUME("Front Mic Boost", 0x1a, 0, HDA_INPUT),
        HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
        HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
        HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
@@ -5989,6 +6003,7 @@ static struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = {
 static struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = {
        HDA_CODEC_VOLUME("Rear Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
        HDA_CODEC_MUTE("Rear Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Rear Mic Boost", 0x18, 0, HDA_INPUT),
        { } /* end */
 };
 
index f7ef9c5afe8732d70d98b6191df4dc1b00f6571a..4c7b03996be99b773f5ff84ca9c9ae2b1a3bbf8c 100644 (file)
@@ -59,6 +59,8 @@ enum {
        STAC_D945GTP3,
        STAC_D945GTP5,
        STAC_MACMINI,
+       STAC_MACBOOK,
+       STAC_MACBOOK_PRO,
        STAC_922X_MODELS
 };
 
@@ -461,6 +463,8 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = {
                      "Dell Inspiron E1705/9400", STAC_REF),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ce,
                      "Dell XPS M1710", STAC_REF),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cf,
+                     "Dell Precision M90", STAC_REF),
        {} /* terminator */
 };
 
@@ -519,11 +523,25 @@ static unsigned int d945gtp5_pin_configs[10] = {
        0x02a19320, 0x40000100,
 };
 
+static unsigned int macbook_pin_configs[10] = {
+       0x0321e230, 0x03a1e020, 0x400000fd, 0x9017e110,
+       0x400000fe, 0x0381e021, 0x1345e240, 0x13c5e22e,
+       0x400000fc, 0x400000fb,
+};
+
+static unsigned int macbook_pro_pin_configs[10] = {
+       0x0221401f, 0x90a70120, 0x01813024, 0x01014010,
+       0x400000fd, 0x01016011, 0x1345e240, 0x13c5e22e,
+       0x400000fc, 0x400000fb,
+};
+
 static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = {
        [STAC_D945_REF] = ref922x_pin_configs,
        [STAC_D945GTP3] = d945gtp3_pin_configs,
        [STAC_D945GTP5] = d945gtp5_pin_configs,
        [STAC_MACMINI] = d945gtp5_pin_configs,
+       [STAC_MACBOOK] = macbook_pin_configs,
+       [STAC_MACBOOK_PRO] = macbook_pro_pin_configs,
 };
 
 static const char *stac922x_models[STAC_922X_MODELS] = {
@@ -531,6 +549,8 @@ static const char *stac922x_models[STAC_922X_MODELS] = {
        [STAC_D945GTP5] = "5stack",
        [STAC_D945GTP3] = "3stack",
        [STAC_MACMINI]  = "macmini",
+       [STAC_MACBOOK]  = "macbook",
+       [STAC_MACBOOK_PRO]      = "macbook-pro",
 };
 
 static struct snd_pci_quirk stac922x_cfg_tbl[] = {
@@ -1864,6 +1884,18 @@ static int patch_stac922x(struct hda_codec *codec)
        spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS,
                                                        stac922x_models,
                                                        stac922x_cfg_tbl);
+       if (spec->board_config == STAC_MACMINI) {
+               spec->gpio_mute = 1;
+               /* Intel Macs have all same PCI SSID, so we need to check
+                * codec SSID to distinguish the exact models
+                */
+               switch (codec->subsystem_id) {
+               case 0x106b1e00:
+                       spec->board_config = STAC_MACBOOK_PRO;
+                       break;
+               }
+       }
+
  again:
        if (spec->board_config < 0) {
                snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, "
@@ -1904,9 +1936,6 @@ static int patch_stac922x(struct hda_codec *codec)
                return err;
        }
 
-       if (spec->board_config == STAC_MACMINI)
-               spec->gpio_mute = 1;
-
        codec->patch_ops = stac92xx_patch_ops;
 
        return 0;
index 5e1d5d2b285030be51f42d7cee4e3654a20f50b0..952625dead58ef56973f48fbbe122cc63fd8a58e 100644 (file)
@@ -1919,6 +1919,8 @@ snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
                return err;
        }
 
+       snd_card_set_dev(card, &pci->dev);
+
        *rchip = chip;
        return 0;
 }
index e0215aca119364eff28261ab238a01e84a840963..6e95857e4e67a4cd10f5843312cae93ed661237b 100644 (file)
@@ -4468,6 +4468,8 @@ static int __devinit snd_hdspm_probe(struct pci_dev *pci,
        hdspm->dev = dev;
        hdspm->pci = pci;
 
+       snd_card_set_dev(card, &pci->dev);
+
        if ((err =
             snd_hdspm_create(card, hdspm, precise_ptr[dev],
                              enable_monitor[dev])) < 0) {
index 92a64871bcd079788d19c41547fd46354bfd2075..ee7a691a9ba163b0fff87a07aad33ea3cf9d84ca 100644 (file)
@@ -39,7 +39,7 @@ static int ac97_write(struct snd_soc_codec *codec,
  */
 static const u16 wm9712_reg[] = {
        0x6174, 0x8000, 0x8000, 0x8000, // 6
-       0xf0f0, 0xaaa0, 0xc008, 0x6808, // e
+       0x0f0f, 0xaaa0, 0xc008, 0x6808, // e
        0xe808, 0xaaa0, 0xad00, 0x8000, // 16
        0xe808, 0x3000, 0x8000, 0x0000, // 1e
        0x0000, 0x0000, 0x0000, 0x000f, // 26
@@ -96,6 +96,7 @@ SOC_DOUBLE("Speaker Playback Volume", AC97_MASTER, 8, 0, 31, 1),
 SOC_SINGLE("Speaker Playback Switch", AC97_MASTER, 15, 1, 1),
 SOC_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1),
 SOC_SINGLE("Headphone Playback Switch", AC97_HEADPHONE,15, 1, 1),
+SOC_DOUBLE("PCM Playback Volume", AC97_PCM, 8, 0, 31, 1),
 
 SOC_SINGLE("Speaker Playback ZC Switch", AC97_MASTER, 7, 1, 0),
 SOC_SINGLE("Speaker Playback Invert Switch", AC97_MASTER, 6, 1, 0),