]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'common/fbdev-mipi' of master.kernel.org:/pub/scm/linux/kernel/git/letha...
authorPaul Mundt <lethal@linux-sh.org>
Wed, 5 Jan 2011 08:30:20 +0000 (17:30 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Wed, 5 Jan 2011 08:30:20 +0000 (17:30 +0900)
1171 files changed:
Documentation/ABI/testing/sysfs-bus-rbd [new file with mode: 0644]
Documentation/ABI/testing/sysfs-platform-asus-laptop
Documentation/ABI/testing/sysfs-platform-eeepc-wmi [new file with mode: 0644]
Documentation/DocBook/sh.tmpl
Documentation/DocBook/uio-howto.tmpl
Documentation/development-process/2.Process
Documentation/driver-model/interface.txt [deleted file]
Documentation/edac.txt
Documentation/fb/00-INDEX
Documentation/filesystems/Locking
Documentation/filesystems/configfs/configfs_example_explicit.c
Documentation/filesystems/vfs.txt
Documentation/gpio.txt
Documentation/hwmon/lm93
Documentation/hwmon/max6650
Documentation/kernel-parameters.txt
Documentation/networking/ip-sysctl.txt
Documentation/power/runtime_pm.txt
Documentation/sh/clk.txt [deleted file]
MAINTAINERS
Makefile
arch/arm/Kconfig
arch/arm/boot/Makefile
arch/arm/boot/bootp/init.S
arch/arm/boot/compressed/head.S
arch/arm/boot/compressed/vmlinux.lds.in
arch/arm/common/gic.c
arch/arm/configs/at91rm9200_defconfig [new file with mode: 0644]
arch/arm/configs/at91rm9200dk_defconfig [deleted file]
arch/arm/configs/at91rm9200ek_defconfig [deleted file]
arch/arm/configs/ateb9200_defconfig [deleted file]
arch/arm/configs/carmeva_defconfig [deleted file]
arch/arm/configs/cpuat91_defconfig [deleted file]
arch/arm/configs/csb337_defconfig [deleted file]
arch/arm/configs/csb637_defconfig [deleted file]
arch/arm/configs/ecbat91_defconfig [deleted file]
arch/arm/configs/kafa_defconfig [deleted file]
arch/arm/configs/kb9202_defconfig [deleted file]
arch/arm/configs/onearm_defconfig [deleted file]
arch/arm/configs/picotux200_defconfig [deleted file]
arch/arm/configs/yl9200_defconfig [deleted file]
arch/arm/include/asm/assembler.h
arch/arm/include/asm/mmu.h
arch/arm/include/asm/pgtable.h
arch/arm/kernel/entry-armv.S
arch/arm/kernel/head.S
arch/arm/kernel/relocate_kernel.S
arch/arm/lib/findbit.S
arch/arm/mach-aaec2000/include/mach/vmalloc.h
arch/arm/mach-at91/Makefile
arch/arm/mach-at91/at91rm9200_devices.c
arch/arm/mach-at91/board-1arm.c
arch/arm/mach-at91/board-kafa.c
arch/arm/mach-at91/board-pcontrol-g20.c
arch/arm/mach-at91/board-picotux200.c
arch/arm/mach-at91/board-rm9200dk.c [moved from arch/arm/mach-at91/board-dk.c with 98% similarity]
arch/arm/mach-at91/board-rm9200ek.c [moved from arch/arm/mach-at91/board-ek.c with 98% similarity]
arch/arm/mach-at91/board-stamp9g20.c
arch/arm/mach-at91/board-yl-9200.c
arch/arm/mach-at91/clock.c
arch/arm/mach-at91/include/mach/board.h
arch/arm/mach-at91/include/mach/stamp9g20.h [new file with mode: 0644]
arch/arm/mach-bcmring/include/mach/vmalloc.h
arch/arm/mach-clps711x/include/mach/vmalloc.h
arch/arm/mach-cns3xxx/pcie.c
arch/arm/mach-davinci/dm355.c
arch/arm/mach-davinci/dm365.c
arch/arm/mach-davinci/dm644x.c
arch/arm/mach-ebsa110/include/mach/vmalloc.h
arch/arm/mach-footbridge/include/mach/vmalloc.h
arch/arm/mach-h720x/include/mach/vmalloc.h
arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
arch/arm/mach-integrator/include/mach/vmalloc.h
arch/arm/mach-mmp/mmp2.c
arch/arm/mach-msm/include/mach/vmalloc.h
arch/arm/mach-mx25/devices-imx25.h
arch/arm/mach-mx3/mach-pcm037_eet.c
arch/arm/mach-netx/include/mach/vmalloc.h
arch/arm/mach-omap1/include/mach/vmalloc.h
arch/arm/mach-omap2/board-zoom-peripherals.c
arch/arm/mach-omap2/include/mach/vmalloc.h
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/pm-debug.c
arch/arm/mach-omap2/pm24xx.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/prcm-common.h
arch/arm/mach-omap2/serial.c
arch/arm/mach-pnx4008/include/mach/vmalloc.h
arch/arm/mach-pxa/palmtx.c
arch/arm/mach-realview/headsmp.S
arch/arm/mach-rpc/include/mach/vmalloc.h
arch/arm/mach-s3c2410/h1940-bluetooth.c
arch/arm/mach-s3c2412/Kconfig
arch/arm/mach-s3c2412/Makefile
arch/arm/mach-s3c2416/Kconfig
arch/arm/mach-s3c2416/irq.c
arch/arm/mach-s3c2440/Kconfig
arch/arm/mach-s3c2440/s3c2440.c
arch/arm/mach-s3c2440/s3c2442.c
arch/arm/mach-s3c2443/Kconfig
arch/arm/mach-s3c2443/irq.c
arch/arm/mach-s3c64xx/mach-mini6410.c
arch/arm/mach-s3c64xx/mach-real6410.c
arch/arm/mach-s5pv210/mach-aquila.c
arch/arm/mach-s5pv210/mach-goni.c
arch/arm/mach-s5pv210/mach-smdkc110.c
arch/arm/mach-s5pv210/mach-smdkv210.c
arch/arm/mach-shark/include/mach/vmalloc.h
arch/arm/mach-shmobile/board-ap4evb.c
arch/arm/mach-shmobile/clock-sh7372.c
arch/arm/mach-shmobile/include/mach/entry-macro.S
arch/arm/mach-shmobile/include/mach/vmalloc.h
arch/arm/mach-tegra/include/mach/debug-macro.S
arch/arm/mach-ux500/cpu.c
arch/arm/mach-versatile/include/mach/vmalloc.h
arch/arm/mach-vexpress/headsmp.S
arch/arm/mm/cache-v6.S
arch/arm/mm/cache-v7.S
arch/arm/mm/ioremap.c
arch/arm/mm/proc-macros.S
arch/arm/mm/proc-v7.S
arch/arm/plat-iop/time.c
arch/arm/plat-mxc/devices/platform-imx-dma.c
arch/arm/plat-mxc/devices/platform-spi_imx.c
arch/arm/plat-nomadik/timer.c
arch/arm/plat-omap/counter_32k.c
arch/arm/plat-omap/sram.c
arch/arm/plat-pxa/include/plat/sdhci.h
arch/arm/plat-s3c24xx/Kconfig
arch/arm/plat-s3c24xx/cpu.c
arch/arm/plat-s3c24xx/gpiolib.c
arch/arm/plat-s3c24xx/include/plat/s3c244x.h
arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c
arch/arm/plat-s3c24xx/spi-bus1-gpd8_9_10.c
arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c
arch/arm/plat-samsung/gpio-config.c
arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
arch/arm/tools/mach-types
arch/arm/vfp/vfphw.S
arch/mips/Kconfig
arch/mips/alchemy/common/platform.c
arch/mips/alchemy/devboards/prom.c
arch/mips/ar7/clock.c
arch/mips/ar7/time.c
arch/mips/bcm47xx/setup.c
arch/mips/include/asm/cpu.h
arch/mips/include/asm/elf.h
arch/mips/include/asm/io.h
arch/mips/include/asm/mach-ar7/ar7.h
arch/mips/include/asm/mach-bcm47xx/nvram.h
arch/mips/jz4740/board-qi_lb60.c
arch/mips/jz4740/platform.c
arch/mips/jz4740/prom.c
arch/mips/kernel/cevt-r4k.c
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/linux32.c
arch/mips/kernel/process.c
arch/mips/kernel/prom.c
arch/mips/kernel/smp-mt.c
arch/mips/kernel/traps.c
arch/mips/kernel/vpe.c
arch/mips/lib/memset.S
arch/mips/loongson/common/env.c
arch/mips/math-emu/cp1emu.c
arch/mips/mm/dma-default.c
arch/mips/mm/sc-mips.c
arch/mips/pmc-sierra/yosemite/py-console.c
arch/mips/sibyte/swarm/setup.c
arch/mn10300/include/asm/syscall.h [new file with mode: 0644]
arch/mn10300/kernel/gdb-io-serial.c
arch/mn10300/kernel/gdb-io-ttysm.c
arch/mn10300/kernel/gdb-stub.c
arch/mn10300/kernel/time.c
arch/parisc/kernel/irq.c
arch/parisc/kernel/signal.c
arch/powerpc/Kconfig
arch/powerpc/boot/div64.S
arch/powerpc/kernel/kgdb.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/pgtable.c
arch/powerpc/mm/tlb_low_64e.S
arch/powerpc/mm/tlb_nohash.c
arch/powerpc/platforms/pseries/Kconfig
arch/powerpc/platforms/pseries/eeh.c
arch/powerpc/platforms/pseries/pci_dlpar.c
arch/s390/kernel/nmi.c
arch/s390/kernel/vtime.c
arch/s390/lib/delay.c
arch/sh/Kconfig
arch/sh/boards/mach-ecovec24/setup.c
arch/sh/boards/mach-se/7724/setup.c
arch/sh/include/asm/cacheflush.h
arch/sh/include/asm/processor_32.h
arch/sh/include/asm/unistd_32.h
arch/sh/include/cpu-sh4/cpu/sh7724.h
arch/sh/kernel/cpu/sh4/clock-sh4-202.c
arch/sh/kernel/cpu/sh4a/clock-sh7724.c
arch/sh/kernel/sys_sh.c
arch/sh/kernel/syscalls_32.S
arch/sh/kernel/vsyscall/vsyscall-trapa.S
arch/sh/mm/cache-sh4.c
arch/sh/mm/cache-sh7705.c
arch/sh/mm/cache.c
arch/sh/mm/kmap.c
arch/sparc/include/asm/openprom.h
arch/sparc/include/asm/oplib_32.h
arch/sparc/include/asm/oplib_64.h
arch/sparc/kernel/leon_kernel.c
arch/sparc/prom/Makefile
arch/sparc/prom/console_32.c
arch/sparc/prom/console_64.c
arch/sparc/prom/devops_32.c [deleted file]
arch/sparc/prom/devops_64.c [deleted file]
arch/sparc/prom/misc_64.c
arch/sparc/prom/printf.c
arch/sparc/prom/tree_32.c
arch/sparc/prom/tree_64.c
arch/tile/Kconfig
arch/tile/include/asm/cacheflush.h
arch/tile/include/asm/io.h
arch/tile/include/asm/pci-bridge.h [deleted file]
arch/tile/include/asm/pci.h
arch/tile/include/asm/processor.h
arch/tile/include/asm/signal.h
arch/tile/include/hv/drv_xgbe_impl.h [new file with mode: 0644]
arch/tile/include/hv/drv_xgbe_intf.h [new file with mode: 0644]
arch/tile/include/hv/netio_errors.h [new file with mode: 0644]
arch/tile/include/hv/netio_intf.h [new file with mode: 0644]
arch/tile/kernel/Makefile
arch/tile/kernel/compat_signal.c
arch/tile/kernel/intvec_32.S
arch/tile/kernel/pci.c [new file with mode: 0644]
arch/tile/kernel/process.c
arch/tile/kernel/setup.c
arch/tile/kernel/signal.c
arch/tile/lib/memchr_32.c
arch/tile/lib/spinlock_32.c
arch/um/drivers/line.c
arch/x86/Kconfig
arch/x86/boot/compressed/misc.c
arch/x86/crypto/ghash-clmulni-intel_glue.c
arch/x86/include/asm/e820.h
arch/x86/include/asm/fixmap.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/msr-index.h
arch/x86/include/asm/paravirt.h
arch/x86/include/asm/pvclock.h
arch/x86/include/asm/uv/uv_hub.h
arch/x86/include/asm/uv/uv_mmrs.h
arch/x86/include/asm/xen/interface.h
arch/x86/include/asm/xen/interface_32.h
arch/x86/include/asm/xen/interface_64.h
arch/x86/include/asm/xen/page.h
arch/x86/kernel/Makefile
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/hw_nmi.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apic/probe_64.c
arch/x86/kernel/apic/x2apic_uv_x.c
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
arch/x86/kernel/head_32.S
arch/x86/kernel/hpet.c
arch/x86/kernel/hw_breakpoint.c
arch/x86/kernel/kgdb.c
arch/x86/kernel/mmconf-fam10h_64.c
arch/x86/kernel/pvclock.c
arch/x86/kernel/resource.c [new file with mode: 0644]
arch/x86/kernel/setup.c
arch/x86/kernel/xsave.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/kvm/x86.h
arch/x86/lguest/boot.c
arch/x86/lguest/i386_head.S
arch/x86/mm/tlb.c
arch/x86/pci/i386.c
arch/x86/pci/xen.c
arch/x86/platform/uv/tlb_uv.c
arch/x86/platform/uv/uv_time.c
arch/x86/vdso/Makefile
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
arch/x86/xen/platform-pci-unplug.c
arch/x86/xen/setup.c
arch/x86/xen/suspend.c
arch/x86/xen/time.c
arch/x86/xen/xen-ops.h
block/blk-map.c
block/blk-merge.c
block/blk-settings.c
block/blk-sysfs.c
block/blk-throttle.c
block/bsg.c
drivers/acpi/ac.c
drivers/acpi/apei/erst.c
drivers/acpi/apei/hest.c
drivers/acpi/battery.c
drivers/acpi/ec.c
drivers/acpi/osl.c
drivers/acpi/power.c
drivers/acpi/processor_thermal.c
drivers/acpi/sleep.c
drivers/ata/libata-scsi.c
drivers/ata/sata_via.c
drivers/atm/adummy.c
drivers/atm/ambassador.c
drivers/atm/atmtcp.c
drivers/atm/eni.c
drivers/atm/firestream.c
drivers/atm/fore200e.c
drivers/atm/he.c
drivers/atm/horizon.c
drivers/atm/idt77252.c
drivers/atm/iphase.c
drivers/atm/lanai.c
drivers/atm/nicstar.c
drivers/atm/solos-pci.c
drivers/atm/zatm.c
drivers/block/amiflop.c
drivers/block/ataflop.c
drivers/block/cciss.c
drivers/block/drbd/drbd_receiver.c
drivers/block/drbd/drbd_req.h
drivers/block/drbd/drbd_worker.c
drivers/block/rbd.c
drivers/block/xen-blkfront.c
drivers/bluetooth/ath3k.c
drivers/bluetooth/btusb.c
drivers/char/agp/intel-gtt.c
drivers/char/tpm/tpm_tis.c
drivers/char/virtio_console.c
drivers/clocksource/sh_cmt.c
drivers/connector/connector.c
drivers/dma/Makefile
drivers/dma/at_hdmac.c
drivers/dma/fsldma.c
drivers/dma/fsldma.h
drivers/dma/imx-dma.c
drivers/dma/imx-sdma.c
drivers/dma/intel_mid_dma.c
drivers/dma/ioat/Makefile
drivers/dma/pch_dma.c
drivers/dma/ppc4xx/adma.c
drivers/dma/shdma.c
drivers/edac/Makefile
drivers/edac/amd64_edac.c
drivers/edac/edac_core.h
drivers/edac/edac_mc.c
drivers/edac/mce_amd_inj.c
drivers/firewire/net.c
drivers/firewire/ohci.c
drivers/gpio/cs5535-gpio.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_suspend.c
drivers/gpu/drm/i915/intel_acpi.c
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_i2c.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/nouveau/nouveau_backlight.c
drivers/gpu/drm/nouveau/nouveau_bios.c
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_connector.h
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_fence.c
drivers/gpu/drm/nouveau/nouveau_gem.c
drivers/gpu/drm/nouveau/nouveau_hw.c
drivers/gpu/drm/nouveau/nouveau_hw.h
drivers/gpu/drm/nouveau/nouveau_i2c.c
drivers/gpu/drm/nouveau/nouveau_irq.c
drivers/gpu/drm/nouveau/nouveau_mem.c
drivers/gpu/drm/nouveau/nouveau_object.c
drivers/gpu/drm/nouveau/nouveau_pm.c
drivers/gpu/drm/nouveau/nouveau_ramht.c
drivers/gpu/drm/nouveau/nouveau_sgdma.c
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/nouveau/nouveau_temp.c
drivers/gpu/drm/nouveau/nv04_crtc.c
drivers/gpu/drm/nouveau/nv04_dfp.c
drivers/gpu/drm/nouveau/nv04_pm.c
drivers/gpu/drm/nouveau/nv50_calc.c
drivers/gpu/drm/nouveau/nv50_crtc.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/nouveau/nv50_fifo.c
drivers/gpu/drm/nouveau/nv50_graph.c
drivers/gpu/drm/nouveau/nv50_instmem.c
drivers/gpu/drm/radeon/atom.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_blit_kms.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_blit_kms.c
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/r600_reg.h
drivers/gpu/drm/radeon/r600d.h
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_benchmark.c
drivers/gpu/drm/radeon/radeon_bios.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_encoders.c
drivers/gpu/drm/radeon/radeon_gart.c
drivers/gpu/drm/radeon/radeon_gem.c
drivers/gpu/drm/radeon/radeon_i2c.c
drivers/gpu/drm/radeon/radeon_irq.c
drivers/gpu/drm/radeon/radeon_legacy_encoders.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/radeon_object.h
drivers/gpu/drm/radeon/radeon_ring.c
drivers/gpu/drm/radeon/radeon_test.c
drivers/gpu/drm/radeon/radeon_ttm.c
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
drivers/hid/hid-core.c
drivers/hid/hid-egalax.c
drivers/hid/hid-input.c
drivers/hid/hid-tmff.c
drivers/hwmon/adm1026.c
drivers/hwmon/i5k_amb.c
drivers/hwmon/it87.c
drivers/hwmon/lis3lv02d_i2c.c
drivers/hwmon/ltc4215.c
drivers/i2c/Kconfig
drivers/i2c/algos/Kconfig
drivers/i2c/busses/i2c-intel-mid.c
drivers/idle/intel_idle.c
drivers/infiniband/core/ud_header.c
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_marshall.c
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/hw/mlx4/qp.c
drivers/input/evdev.c
drivers/input/input.c
drivers/input/joystick/turbografx.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Makefile
drivers/input/keyboard/gpio_keys_polled.c [new file with mode: 0644]
drivers/input/mouse/synaptics.h
drivers/input/serio/gscps2.c
drivers/input/tablet/aiptek.c
drivers/input/tablet/wacom_wac.c
drivers/input/touchscreen/usbtouchscreen.c
drivers/isdn/icn/icn.c
drivers/leds/Kconfig
drivers/leds/leds-lp5521.c
drivers/leds/leds-lp5523.c
drivers/leds/leds-ss4200.c
drivers/macintosh/Kconfig
drivers/md/dm-table.c
drivers/md/md.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/media/common/saa7146_hlp.c
drivers/media/common/saa7146_video.c
drivers/media/common/tuners/Kconfig
drivers/media/dvb/frontends/Kconfig
drivers/media/radio/radio-aimslab.c
drivers/media/radio/radio-aztech.c
drivers/media/radio/radio-cadet.c
drivers/media/radio/radio-gemtek-pci.c
drivers/media/radio/radio-gemtek.c
drivers/media/radio/radio-maestro.c
drivers/media/radio/radio-maxiradio.c
drivers/media/radio/radio-miropcm20.c
drivers/media/radio/radio-rtrack2.c
drivers/media/radio/radio-sf16fmi.c
drivers/media/radio/radio-sf16fmr2.c
drivers/media/radio/radio-si4713.c
drivers/media/radio/radio-tea5764.c
drivers/media/radio/radio-terratec.c
drivers/media/radio/radio-timb.c
drivers/media/radio/radio-trust.c
drivers/media/radio/radio-typhoon.c
drivers/media/radio/radio-zoltrix.c
drivers/media/video/Kconfig
drivers/media/video/arv.c
drivers/media/video/au0828/au0828-cards.c
drivers/media/video/bt8xx/bttv-cards.c
drivers/media/video/bt8xx/bttv-driver.c
drivers/media/video/bw-qcam.c
drivers/media/video/c-qcam.c
drivers/media/video/cafe_ccic.c
drivers/media/video/cx18/cx18-alsa-pcm.c
drivers/media/video/cx18/cx18-i2c.c
drivers/media/video/cx18/cx18-streams.c
drivers/media/video/cx231xx/cx231xx-cards.c
drivers/media/video/cx23885/cx23885-cards.c
drivers/media/video/cx23885/cx23885-video.c
drivers/media/video/cx88/cx88-cards.c
drivers/media/video/cx88/cx88-video.c
drivers/media/video/davinci/vpfe_capture.c
drivers/media/video/davinci/vpif_capture.c
drivers/media/video/davinci/vpif_display.c
drivers/media/video/em28xx/em28xx-cards.c
drivers/media/video/et61x251/et61x251_core.c
drivers/media/video/fsl-viu.c
drivers/media/video/gspca/sonixj.c
drivers/media/video/ivtv/ivtv-i2c.c
drivers/media/video/meye.c
drivers/media/video/mxb.c
drivers/media/video/pms.c
drivers/media/video/pvrusb2/pvrusb2-hdw.c
drivers/media/video/s5p-fimc/fimc-capture.c
drivers/media/video/saa7134/saa7134-cards.c
drivers/media/video/saa7134/saa7134-core.c
drivers/media/video/sh_vou.c
drivers/media/video/sn9c102/sn9c102_core.c
drivers/media/video/soc_camera.c
drivers/media/video/usbvision/usbvision-i2c.c
drivers/media/video/uvc/uvc_ctrl.c
drivers/media/video/uvc/uvc_queue.c
drivers/media/video/uvc/uvc_v4l2.c
drivers/media/video/uvc/uvc_video.c
drivers/media/video/uvc/uvcvideo.h
drivers/media/video/v4l2-common.c
drivers/media/video/v4l2-dev.c
drivers/media/video/v4l2-device.c
drivers/media/video/via-camera.c
drivers/media/video/vino.c
drivers/media/video/w9966.c
drivers/media/video/zoran/zoran_card.c
drivers/misc/isl29020.c
drivers/misc/sgi-xp/xpc_partition.c
drivers/mmc/core/core.c
drivers/mmc/core/mmc.c
drivers/mmc/core/sdio.c
drivers/mmc/core/sdio_bus.c
drivers/mmc/host/omap_hsmmc.c
drivers/mmc/host/sdhci-esdhc-imx.c
drivers/mmc/host/sdhci-pci.c
drivers/mmc/host/sdhci-pxa.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h
drivers/mmc/host/ushc.c
drivers/mtd/maps/pxa2xx-flash.c
drivers/mtd/nand/omap2.c
drivers/mtd/ubi/io.c
drivers/mtd/ubi/scan.c
drivers/net/3c59x.c
drivers/net/8139cp.c
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/atl1c/atl1c_hw.c
drivers/net/au1000_eth.c
drivers/net/b44.c
drivers/net/benet/be_cmds.c
drivers/net/benet/be_main.c
drivers/net/bnx2x/bnx2x.h
drivers/net/bnx2x/bnx2x_cmn.c
drivers/net/bnx2x/bnx2x_init_ops.h
drivers/net/bnx2x/bnx2x_main.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bonding.h
drivers/net/caif/caif_shm_u5500.c
drivers/net/caif/caif_shmcore.c
drivers/net/caif/caif_spi.c
drivers/net/cxgb4/t4_hw.c
drivers/net/cxgb4vf/cxgb4vf_main.c
drivers/net/cxgb4vf/t4vf_hw.c
drivers/net/e1000/e1000_main.c
drivers/net/ehea/ehea_ethtool.c
drivers/net/ehea/ehea_main.c
drivers/net/enic/enic_main.c
drivers/net/gianfar.c
drivers/net/ifb.c
drivers/net/ipg.c
drivers/net/irda/sh_sir.c
drivers/net/ixgbe/ixgbe_main.c
drivers/net/mlx4/fw.c
drivers/net/pch_gbe/pch_gbe_main.c
drivers/net/pch_gbe/pch_gbe_param.c
drivers/net/phy/Kconfig
drivers/net/phy/icplus.c
drivers/net/phy/marvell.c
drivers/net/ppp_generic.c
drivers/net/pppoe.c
drivers/net/qlge/qlge.h
drivers/net/qlge/qlge_main.c
drivers/net/qlge/qlge_mpi.c
drivers/net/r8169.c
drivers/net/sfc/efx.c
drivers/net/sfc/net_driver.h
drivers/net/sfc/nic.c
drivers/net/stmmac/stmmac_main.c
drivers/net/tile/Makefile [new file with mode: 0644]
drivers/net/tile/tilepro.c [new file with mode: 0644]
drivers/net/tulip/dmfe.c
drivers/net/ucc_geth.h
drivers/net/usb/hso.c
drivers/net/wan/hd64572.c
drivers/net/wan/x25_asy.c
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/eeprom.c
drivers/net/wireless/ath/ath9k/eeprom.h
drivers/net/wireless/ath/ath9k/eeprom_9287.c
drivers/net/wireless/ath/ath9k/eeprom_def.c
drivers/net/wireless/ath/ath9k/hif_usb.c
drivers/net/wireless/ath/ath9k/htc.h
drivers/net/wireless/ath/ath9k/htc_drv_init.c
drivers/net/wireless/ath/ath9k/htc_drv_main.c
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/mac.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/ath9k/reg.h
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/ath/carl9170/fw.c
drivers/net/wireless/ath/carl9170/main.c
drivers/net/wireless/ath/carl9170/tx.c
drivers/net/wireless/ath/carl9170/usb.c
drivers/net/wireless/b43/sdio.c
drivers/net/wireless/libertas/if_sdio.c
drivers/net/wireless/libertas/if_spi.c
drivers/net/wireless/libertas/main.c
drivers/net/wireless/orinoco/main.c
drivers/net/wireless/orinoco/orinoco_cs.c
drivers/net/wireless/orinoco/scan.c
drivers/net/wireless/orinoco/scan.h
drivers/net/wireless/orinoco/spectrum_cs.c
drivers/net/wireless/orinoco/wext.c
drivers/net/xen-netfront.c
drivers/parisc/dino.c
drivers/parisc/eisa.c
drivers/parisc/gsc.c
drivers/parisc/iosapic.c
drivers/parisc/led.c
drivers/parisc/superio.c
drivers/pci/Makefile
drivers/pci/bus.c
drivers/pci/dmar.c
drivers/pci/quirks.c
drivers/pcmcia/soc_common.c
drivers/platform/x86/asus-laptop.c
drivers/platform/x86/eeepc-wmi.c
drivers/platform/x86/hp-wmi.c
drivers/platform/x86/ibm_rtl.c
drivers/platform/x86/msi-wmi.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/toshiba_acpi.c
drivers/platform/x86/wmi.c
drivers/pnp/pnpacpi/core.c
drivers/regulator/core.c
drivers/regulator/mc13783-regulator.c
drivers/regulator/tps6586x-regulator.c
drivers/regulator/twl-regulator.c
drivers/s390/cio/css.c
drivers/s390/cio/qdio_thinint.c
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_scsi.c
drivers/scsi/arm/fas216.h
drivers/scsi/hpsa.c
drivers/scsi/osd/osd_initiator.c
drivers/scsi/pmcraid.c
drivers/scsi/pmcraid.h
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_iocb.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_nx.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_version.h
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/serial/8250.c
drivers/serial/kgdboc.c
drivers/serial/mfd.c
drivers/sh/clk/core.c
drivers/sh/clk/cpg.c
drivers/spi/atmel_spi.c
drivers/spi/dw_spi.c
drivers/ssb/b43_pci_bridge.c
drivers/staging/asus_oled/asus_oled.c
drivers/staging/batman-adv/hard-interface.c
drivers/staging/batman-adv/soft-interface.c
drivers/staging/brcm80211/README
drivers/staging/brcm80211/TODO
drivers/staging/comedi/drivers/usbdux.c
drivers/staging/cx25821/cx25821-video.c
drivers/staging/cx25821/cx25821-video.h
drivers/staging/cx25821/cx25821.h
drivers/staging/easycap/easycap.h
drivers/staging/frontier/tranzport.c
drivers/staging/go7007/go7007-driver.c
drivers/staging/iio/accel/adis16220_core.c
drivers/staging/intel_sst/intel_sst_stream_encoded.c
drivers/staging/line6/control.c
drivers/staging/line6/midi.c
drivers/staging/line6/pcm.c
drivers/staging/line6/pod.c
drivers/staging/line6/toneport.c
drivers/staging/line6/variax.c
drivers/staging/quickstart/quickstart.c
drivers/staging/rt2860/usb_main_dev.c
drivers/staging/rtl8187se/r8185b_init.c
drivers/staging/rtl8712/usb_halinit.c
drivers/staging/samsung-laptop/samsung-laptop.c
drivers/staging/speakup/fakekey.c
drivers/staging/spectra/ffsport.c
drivers/staging/tm6000/tm6000-cards.c
drivers/staging/udlfb/udlfb.c
drivers/staging/winbond/sysdef.h
drivers/staging/zram/zram_sysfs.c
drivers/tty/n_gsm.c
drivers/tty/sysrq.c
drivers/tty/tty_io.c
drivers/tty/tty_ldisc.c
drivers/uio/uio.c
drivers/uio/uio_cif.c
drivers/uio/uio_netx.c
drivers/usb/atm/ueagle-atm.c
drivers/usb/atm/usbatm.c
drivers/usb/core/Kconfig
drivers/usb/core/hcd.c
drivers/usb/gadget/atmel_usba_udc.c
drivers/usb/gadget/composite.c
drivers/usb/host/ehci-dbg.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-mem.c
drivers/usb/host/ehci-pci.c
drivers/usb/host/ehci-sched.c
drivers/usb/host/ehci.h
drivers/usb/host/isp1362-hcd.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/misc/cypress_cy7c63.c
drivers/usb/misc/trancevibrator.c
drivers/usb/misc/usbled.c
drivers/usb/misc/usbsevseg.c
drivers/usb/misc/uss720.c
drivers/usb/misc/yurex.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_gadget.c
drivers/usb/otg/langwell_otg.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/usb-serial.c
drivers/usb/storage/sierra_ms.c
drivers/usb/storage/unusual_devs.h
drivers/vhost/net.c
drivers/vhost/vhost.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/backlight/backlight.c
drivers/video/bf537-lq035.c [new file with mode: 0644]
drivers/video/bfin_adv7393fb.c [new file with mode: 0644]
drivers/video/bfin_adv7393fb.h [new file with mode: 0644]
drivers/video/da8xx-fb.c
drivers/video/fbcmap.c
drivers/video/fbmon.c
drivers/video/geode/lxfb.h
drivers/video/geode/lxfb_ops.c
drivers/video/modedb.c
drivers/video/mx3fb.c
drivers/video/omap/Kconfig
drivers/video/omap2/vram.c
drivers/video/s1d13xxxfb.c
drivers/video/s3c-fb.c
drivers/video/sh_mobile_hdmi.c
drivers/video/sh_mobile_lcdcfb.c
drivers/video/sis/init.c
drivers/video/sis/init.h
drivers/video/sis/init301.c
drivers/video/sis/init301.h
drivers/video/sis/initextlfb.c
drivers/video/sis/osdef.h [deleted file]
drivers/video/sis/sis.h
drivers/video/sis/sis_main.c
drivers/video/sis/vgatypes.h
drivers/video/sis/vstruct.h
drivers/video/via/via-core.c
drivers/video/via/via-gpio.c
drivers/video/via/viafbdev.c
drivers/video/via/viafbdev.h
drivers/video/vt8500lcdfb.c [new file with mode: 0644]
drivers/video/vt8500lcdfb.h [new file with mode: 0644]
drivers/video/wm8505fb.c [new file with mode: 0644]
drivers/video/wm8505fb_regs.h [new file with mode: 0644]
drivers/video/wmt_ge_rops.c [new file with mode: 0644]
drivers/video/wmt_ge_rops.h [new file with mode: 0644]
drivers/virtio/virtio.c
drivers/virtio/virtio_ring.c
drivers/watchdog/Kconfig
drivers/watchdog/bcm63xx_wdt.c
drivers/watchdog/gef_wdt.c
drivers/watchdog/iTCO_wdt.c
drivers/xen/Makefile
drivers/xen/balloon.c
drivers/xen/events.c
drivers/xen/evtchn.c
drivers/xen/manage.c
drivers/xen/xenfs/privcmd.c
drivers/xen/xenfs/super.c
fs/autofs4/root.c
fs/btrfs/compression.c
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/export.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/extent_io.h
fs/btrfs/file.c
fs/btrfs/free-space-cache.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/ioctl.h
fs/btrfs/ordered-data.c
fs/btrfs/ordered-data.h
fs/btrfs/orphan.c
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/btrfs/volumes.h
fs/ceph/addr.c
fs/ceph/caps.c
fs/ceph/dir.c
fs/ceph/file.c
fs/ceph/inode.c
fs/ceph/ioctl.h
fs/ceph/locks.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/ceph/super.h
fs/cifs/Kconfig
fs/cifs/Makefile
fs/cifs/README
fs/cifs/cifs_fs_sb.h
fs/cifs/cifsacl.c
fs/cifs/cifsacl.h
fs/cifs/cifsfs.c
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/dns_resolve.c
fs/cifs/file.c
fs/cifs/fscache.c
fs/cifs/inode.c
fs/cifs/readdir.c
fs/cifs/xattr.c
fs/compat.c
fs/exec.c
fs/ext4/ext4.h
fs/ext4/inode.c
fs/ext4/ioctl.c
fs/ext4/namei.c
fs/ext4/page-io.c
fs/ext4/super.c
fs/fuse/file.c
fs/gfs2/quota.c
fs/ioctl.c
fs/ioprio.c
fs/jbd2/journal.c
fs/namei.c
fs/nfs/dir.c
fs/nfs/direct.c
fs/nfs/file.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/mount_clnt.c
fs/nfs/nfs2xdr.c
fs/nfs/nfs3xdr.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4xdr.c
fs/nfs/pagelist.c
fs/nfs/read.c
fs/nfs/super.c
fs/nfs/write.c
fs/nfsd/nfs3xdr.c
fs/nfsd/xdr4.h
fs/nilfs2/dat.c
fs/nilfs2/gcinode.c
fs/nilfs2/ioctl.c
fs/notify/fanotify/fanotify.c
fs/notify/fanotify/fanotify_user.c
fs/notify/inotify/inotify_user.c
fs/ocfs2/cluster/heartbeat.c
fs/ocfs2/dcache.c
fs/ocfs2/dlm/dlmdomain.c
fs/ocfs2/ocfs2.h
fs/ocfs2/stack_user.c
fs/pipe.c
fs/proc/base.c
fs/proc/task_mmu.c
fs/reiserfs/ioctl.c
fs/reiserfs/xattr_acl.c
fs/splice.c
fs/xfs/linux-2.6/xfs_aops.c
fs/xfs/linux-2.6/xfs_buf.c
fs/xfs/xfs_bmap.c
fs/xfs/xfs_bmap.h
fs/xfs/xfs_dfrag.c
fs/xfs/xfs_error.c
fs/xfs/xfs_error.h
fs/xfs/xfs_inode_item.c
fs/xfs/xfs_rename.c
include/acpi/video.h
include/drm/i915_drm.h
include/drm/nouveau_drm.h
include/linux/acpi.h
include/linux/atmdev.h
include/linux/binfmts.h
include/linux/blkdev.h
include/linux/bootmem.h
include/linux/ceph/libceph.h
include/linux/ceph/messenger.h
include/linux/ceph/osd_client.h
include/linux/cnt32_to_63.h
include/linux/cpu.h
include/linux/dmar.h
include/linux/fanotify.h
include/linux/fb.h
include/linux/fs.h
include/linux/fsnotify.h
include/linux/fsnotify_backend.h
include/linux/gfp.h
include/linux/gpio_keys.h
include/linux/hardirq.h
include/linux/hw_breakpoint.h
include/linux/input.h
include/linux/ioport.h
include/linux/marvell_phy.h
include/linux/memory_hotplug.h
include/linux/mfd/wm8350/audio.h
include/linux/mfd/wm8994/pdata.h
include/linux/mmc/host.h
include/linux/module.h
include/linux/nfs_fs.h
include/linux/nfs_page.h
include/linux/nfs_xdr.h
include/linux/node.h
include/linux/page_cgroup.h
include/linux/pci_ids.h
include/linux/perf_event.h
include/linux/pipe_fs_i.h
include/linux/pm_runtime.h
include/linux/rtnetlink.h
include/linux/sched.h
include/linux/sh_clk.h
include/linux/snmp.h
include/linux/ssb/ssb_driver_gige.h
include/linux/tty.h
include/linux/uio_driver.h
include/linux/usb.h
include/linux/via-core.h
include/linux/video_output.h
include/linux/vmalloc.h
include/media/saa7146.h
include/media/v4l2-common.h
include/media/v4l2-device.h
include/net/af_unix.h
include/net/cfg80211.h
include/net/neighbour.h
include/net/sock.h
include/sound/sh_fsi.h
include/video/da8xx-fb.h
include/video/s1d13xxxfb.h
include/video/sh_mobile_hdmi.h
include/xen/events.h
include/xen/interface/io/ring.h
include/xen/interface/memory.h
include/xen/interface/physdev.h
include/xen/page.h
include/xen/privcmd.h
init/Kconfig
kernel/debug/kdb/kdb_main.c
kernel/exit.c
kernel/fork.c
kernel/hw_breakpoint.c
kernel/irq/proc.c
kernel/irq_work.c
kernel/kallsyms.c
kernel/module.c
kernel/perf_event.c
kernel/posix-cpu-timers.c
kernel/power/hibernate.c
kernel/power/suspend.c
kernel/power/swap.c
kernel/power/user.c
kernel/printk.c
kernel/resource.c
kernel/sched.c
kernel/sched_fair.c
kernel/timer.c
kernel/trace/trace.c
kernel/workqueue.c
lib/debug_locks.c
mm/filemap.c
mm/hugetlb.c
mm/ksm.c
mm/memcontrol.c
mm/memory-failure.c
mm/memory_hotplug.c
mm/mempolicy.c
mm/mmap.c
mm/nommu.c
mm/page_alloc.c
mm/pagewalk.c
mm/slub.c
mm/truncate.c
mm/vmalloc.c
mm/vmscan.c
mm/vmstat.c
net/atm/atm_sysfs.c
net/atm/resources.c
net/atm/resources.h
net/bluetooth/sco.c
net/ceph/Makefile
net/ceph/buffer.c
net/ceph/messenger.c
net/ceph/osd_client.c
net/ceph/pagevec.c
net/core/filter.c
net/core/net-sysfs.c
net/core/request_sock.c
net/core/timestamping.c
net/dccp/input.c
net/decnet/af_decnet.c
net/econet/af_econet.c
net/ipv4/fib_trie.c
net/ipv4/icmp.c
net/ipv4/inet_hashtables.c
net/ipv4/proc.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_minisocks.c
net/ipv4/tcp_output.c
net/ipv6/addrconf.c
net/ipv6/ip6_tunnel.c
net/ipv6/sit.c
net/irda/irttp.c
net/l2tp/l2tp_ip.c
net/llc/af_llc.c
net/mac80211/Kconfig
net/mac80211/rx.c
net/mac80211/tx.c
net/netfilter/ipvs/Kconfig
net/rds/rdma.c
net/sctp/socket.c
net/socket.c
net/sunrpc/clnt.c
net/sunrpc/svc_xprt.c
net/unix/af_unix.c
net/unix/garbage.c
net/wireless/chan.c
net/x25/x25_link.c
net/xfrm/xfrm_hash.c
net/xfrm/xfrm_state.c
scripts/gfp-translate
scripts/kconfig/expr.h
scripts/kconfig/lkc.h
scripts/kconfig/menu.c
scripts/kconfig/zconf.gperf
scripts/kconfig/zconf.hash.c_shipped
scripts/kconfig/zconf.tab.c_shipped
scripts/kconfig/zconf.y
scripts/kernel-doc
scripts/recordmcount.h
scripts/tags.sh
sound/atmel/abdac.c
sound/core/oss/pcm_oss.c
sound/core/pcm_lib.c
sound/oss/dev_table.c
sound/oss/midibuf.c
sound/oss/pss.c
sound/oss/sequencer.c
sound/pci/asihpi/hpioctl.c
sound/pci/azt3328.c
sound/pci/ctxfi/ctpcm.c
sound/pci/hda/hda_eld.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/intel8x0.c
sound/pci/mixart/mixart_hwdep.h
sound/ppc/pmac.c
sound/soc/atmel/Kconfig
sound/soc/atmel/sam9g20_wm8731.c
sound/soc/atmel/snd-soc-afeb9260.c
sound/soc/codecs/max98088.c
sound/soc/codecs/stac9766.c
sound/soc/codecs/tlv320aic3x.c
sound/soc/codecs/tpa6130a2.c
sound/soc/codecs/uda134x.c
sound/soc/codecs/wm8350.c
sound/soc/codecs/wm8523.c
sound/soc/codecs/wm8580.c
sound/soc/codecs/wm8731.c
sound/soc/codecs/wm8776.c
sound/soc/codecs/wm8904.c
sound/soc/codecs/wm8955.c
sound/soc/codecs/wm8960.c
sound/soc/codecs/wm8961.c
sound/soc/codecs/wm8962.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm_hubs.c
sound/soc/davinci/davinci-evm.c
sound/soc/davinci/davinci-i2s.c
sound/soc/davinci/davinci-mcasp.c
sound/soc/davinci/davinci-sffsdr.c
sound/soc/davinci/davinci-vcif.c
sound/soc/ep93xx/simone.c
sound/soc/fsl/efika-audio-fabric.c
sound/soc/fsl/mpc5200_dma.c
sound/soc/fsl/mpc5200_psc_i2s.c
sound/soc/fsl/mpc8610_hpcd.c
sound/soc/fsl/p1022_ds.c
sound/soc/fsl/pcm030-audio-fabric.c
sound/soc/imx/eukrea-tlv320.c
sound/soc/imx/imx-pcm-dma-mx2.c
sound/soc/imx/imx-ssi.c
sound/soc/imx/imx-ssi.h
sound/soc/imx/phycore-ac97.c
sound/soc/nuc900/nuc900-ac97.c
sound/soc/nuc900/nuc900-audio.h
sound/soc/nuc900/nuc900-pcm.c
sound/soc/omap/Kconfig
sound/soc/omap/omap-mcbsp.c
sound/soc/omap/omap3pandora.c
sound/soc/omap/osk5912.c
sound/soc/pxa/Kconfig
sound/soc/pxa/corgi.c
sound/soc/pxa/magician.c
sound/soc/pxa/poodle.c
sound/soc/pxa/spitz.c
sound/soc/pxa/tosa.c
sound/soc/s3c24xx/Kconfig
sound/soc/s3c24xx/rx1950_uda1380.c
sound/soc/s3c24xx/smdk_spdif.c
sound/soc/s6000/s6000-i2s.c
sound/soc/s6000/s6000-pcm.c
sound/soc/s6000/s6105-ipcam.c
sound/soc/sh/fsi.c
sound/soc/sh/ssi.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/spi/at73c213.c
tools/perf/builtin-record.c
tools/perf/util/header.c
tools/perf/util/symbol.c
usr/initramfs_data.S

diff --git a/Documentation/ABI/testing/sysfs-bus-rbd b/Documentation/ABI/testing/sysfs-bus-rbd
new file mode 100644 (file)
index 0000000..90a87e2
--- /dev/null
@@ -0,0 +1,83 @@
+What:          /sys/bus/rbd/
+Date:          November 2010
+Contact:       Yehuda Sadeh <yehuda@hq.newdream.net>,
+               Sage Weil <sage@newdream.net>
+Description:
+
+Being used for adding and removing rbd block devices.
+
+Usage: <mon ip addr> <options> <pool name> <rbd image name> [snap name]
+
+ $ echo "192.168.0.1 name=admin rbd foo" > /sys/bus/rbd/add
+
+The snapshot name can be "-" or omitted to map the image read/write. A <dev-id>
+will be assigned for any registered block device. If snapshot is used, it will
+be mapped read-only.
+
+Removal of a device:
+
+  $ echo <dev-id> > /sys/bus/rbd/remove
+
+Entries under /sys/bus/rbd/devices/<dev-id>/
+--------------------------------------------
+
+client_id
+
+       The ceph unique client id that was assigned for this specific session.
+
+major
+
+       The block device major number.
+
+name
+
+       The name of the rbd image.
+
+pool
+
+       The pool where this rbd image resides. The pool-name pair is unique
+       per rados system.
+
+size
+
+       The size (in bytes) of the mapped block device.
+
+refresh
+
+       Writing to this file will reread the image header data and set
+       all relevant datastructures accordingly.
+
+current_snap
+
+       The current snapshot for which the device is mapped.
+
+create_snap
+
+       Create a snapshot:
+
+        $ echo <snap-name> > /sys/bus/rbd/devices/<dev-id>/snap_create
+
+rollback_snap
+
+       Rolls back data to the specified snapshot. This goes over the entire
+       list of rados blocks and sends a rollback command to each.
+
+        $ echo <snap-name> > /sys/bus/rbd/devices/<dev-id>/snap_rollback
+
+snap_*
+
+       A directory per each snapshot
+
+
+Entries under /sys/bus/rbd/devices/<dev-id>/snap_<snap-name>
+-------------------------------------------------------------
+
+id
+
+       The rados internal snapshot id assigned for this snapshot
+
+size
+
+       The size of the image when this snapshot was taken.
+
+
index 1d775390e8562dae8e4eb53d1db9959edff4b943..41ff8ae4dee0f852380f9e4007025293501b10c0 100644 (file)
@@ -47,6 +47,20 @@ Date:                January 2007
 KernelVersion: 2.6.20
 Contact:       "Corentin Chary" <corentincj@iksaif.net>
 Description:
-               Control the bluetooth device. 1 means on, 0 means off.
+               Control the wlan device. 1 means on, 0 means off.
                This may control the led, the device or both.
 Users:         Lapsus
+
+What:          /sys/devices/platform/asus_laptop/wimax
+Date:          October 2010
+KernelVersion: 2.6.37
+Contact:       "Corentin Chary" <corentincj@iksaif.net>
+Description:
+               Control the wimax device. 1 means on, 0 means off.
+
+What:          /sys/devices/platform/asus_laptop/wwan
+Date:          October 2010
+KernelVersion: 2.6.37
+Contact:       "Corentin Chary" <corentincj@iksaif.net>
+Description:
+               Control the wwan (3G) device. 1 means on, 0 means off.
diff --git a/Documentation/ABI/testing/sysfs-platform-eeepc-wmi b/Documentation/ABI/testing/sysfs-platform-eeepc-wmi
new file mode 100644 (file)
index 0000000..e4b5fef
--- /dev/null
@@ -0,0 +1,10 @@
+What:          /sys/devices/platform/eeepc-wmi/cpufv
+Date:          Oct 2010
+KernelVersion: 2.6.37
+Contact:       "Corentin Chary" <corentincj@iksaif.net>
+Description:
+               Change CPU clock configuration (write-only).
+               There are three available clock configuration:
+                   * 0 -> Super Performance Mode
+                   * 1 -> High Performance Mode
+                   * 2 -> Power Saving Mode
index d858d92cf6d9528a6122a1404589ec884c40ca9a..4a38f604fa661fe3b2383746b67f59bc45ed619c 100644 (file)
       </sect2>
     </sect1>
   </chapter>
-  <chapter id="clk">
-    <title>Clock Framework Extensions</title>
-!Iinclude/linux/sh_clk.h
-  </chapter>
   <chapter id="mach">
     <title>Machine Specific Interfaces</title>
     <sect1 id="dreamcast">
index 4d4ce0e61e424708a94db666e0496d7c0f3fc253..b4665b9c40b0ec46253b9ae6cf9bb1bbd06ec563 100644 (file)
@@ -16,7 +16,7 @@
        </orgname>
 
        <address>
-          <email>hjk@linutronix.de</email>
+          <email>hjk@hansjkoch.de</email>
        </address>
     </affiliation>
 </author>
@@ -114,7 +114,7 @@ GPL version 2.
 
 <para>If you know of any translations for this document, or you are
 interested in translating it, please email me
-<email>hjk@linutronix.de</email>.
+<email>hjk@hansjkoch.de</email>.
 </para>
 </sect1>
 
@@ -171,7 +171,7 @@ interested in translating it, please email me
 <title>Feedback</title>
        <para>Find something wrong with this document? (Or perhaps something
        right?) I would love to hear from you. Please email me at
-       <email>hjk@linutronix.de</email>.</para>
+       <email>hjk@hansjkoch.de</email>.</para>
 </sect1>
 </chapter>
 
index 97726eba6102ca31410028391d8f637b3d7a01c5..911a4518634048d9098a02865d328c18824c8248 100644 (file)
@@ -154,7 +154,7 @@ The stages that a patch goes through are, generally:
    inclusion, it should be accepted by a relevant subsystem maintainer -
    though this acceptance is not a guarantee that the patch will make it
    all the way to the mainline.  The patch will show up in the maintainer's
-   subsystem tree and into the staging trees (described below).  When the
+   subsystem tree and into the -next trees (described below).  When the
    process works, this step leads to more extensive review of the patch and
    the discovery of any problems resulting from the integration of this
    patch with work being done by others.
@@ -236,7 +236,7 @@ finding the right maintainer.  Sending patches directly to Linus is not
 normally the right way to go.
 
 
-2.4: STAGING TREES
+2.4: NEXT TREES
 
 The chain of subsystem trees guides the flow of patches into the kernel,
 but it also raises an interesting question: what if somebody wants to look
@@ -250,7 +250,7 @@ changes land in the mainline kernel.  One could pull changes from all of
 the interesting subsystem trees, but that would be a big and error-prone
 job.
 
-The answer comes in the form of staging trees, where subsystem trees are
+The answer comes in the form of -next trees, where subsystem trees are
 collected for testing and review.  The older of these trees, maintained by
 Andrew Morton, is called "-mm" (for memory management, which is how it got
 started).  The -mm tree integrates patches from a long list of subsystem
@@ -275,7 +275,7 @@ directory at:
 Use of the MMOTM tree is likely to be a frustrating experience, though;
 there is a definite chance that it will not even compile.
 
-The other staging tree, started more recently, is linux-next, maintained by
+The other -next tree, started more recently, is linux-next, maintained by
 Stephen Rothwell.  The linux-next tree is, by design, a snapshot of what
 the mainline is expected to look like after the next merge window closes.
 Linux-next trees are announced on the linux-kernel and linux-next mailing
@@ -303,12 +303,25 @@ volatility of linux-next tends to make it a difficult development target.
 See http://lwn.net/Articles/289013/ for more information on this topic, and
 stay tuned; much is still in flux where linux-next is involved.
 
-Besides the mmotm and linux-next trees, the kernel source tree now contains
-the drivers/staging/ directory and many sub-directories for drivers or
-filesystems that are on their way to being added to the kernel tree
-proper, but they remain in drivers/staging/ while they still need more
-work.
-
+2.4.1: STAGING TREES
+
+The kernel source tree now contains the drivers/staging/ directory, where
+many sub-directories for drivers or filesystems that are on their way to
+being added to the kernel tree live.  They remain in drivers/staging while
+they still need more work; once complete, they can be moved into the
+kernel proper.  This is a way to keep track of drivers that aren't
+up to Linux kernel coding or quality standards, but people may want to use
+them and track development.
+
+Greg Kroah-Hartman currently (as of 2.6.36) maintains the staging tree.
+Drivers that still need work are sent to him, with each driver having
+its own subdirectory in drivers/staging/.  Along with the driver source
+files, a TODO file should be present in the directory as well.  The TODO
+file lists the pending work that the driver needs for acceptance into
+the kernel proper, as well as a list of people that should be Cc'd for any
+patches to the driver.  Staging drivers that don't currently build should
+have their config entries depend upon CONFIG_BROKEN.  Once they can
+be successfully built without outside patches, CONFIG_BROKEN can be removed.
 
 2.5: TOOLS
 
diff --git a/Documentation/driver-model/interface.txt b/Documentation/driver-model/interface.txt
deleted file mode 100644 (file)
index c66912b..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-
-Device Interfaces
-
-Introduction
-~~~~~~~~~~~~
-
-Device interfaces are the logical interfaces of device classes that correlate
-directly to userspace interfaces, like device nodes. 
-   
-Each device class may have multiple interfaces through which you can 
-access the same device. An input device may support the mouse interface, 
-the 'evdev' interface, and the touchscreen interface. A SCSI disk would 
-support the disk interface, the SCSI generic interface, and possibly a raw 
-device interface. 
-
-Device interfaces are registered with the class they belong to. As devices
-are added to the class, they are added to each interface registered with
-the class. The interface is responsible for determining whether the device
-supports the interface or not. 
-
-
-Programming Interface
-~~~~~~~~~~~~~~~~~~~~~
-
-struct device_interface {
-       char                    * name;
-       rwlock_t                lock;
-       u32                     devnum;
-       struct device_class     * devclass;
-
-       struct list_head        node;
-       struct driver_dir_entry dir;
-
-       int (*add_device)(struct device *);
-       int (*add_device)(struct intf_data *);
-};
-
-int interface_register(struct device_interface *);
-void interface_unregister(struct device_interface *);
-
-
-An interface must specify the device class it belongs to. It is added
-to that class's list of interfaces on registration.
-
-
-Interfaces can be added to a device class at any time. Whenever it is
-added, each device in the class is passed to the interface's
-add_device callback. When an interface is removed, each device is
-removed from the interface.
-
-
-Devices
-~~~~~~~
-Once a device is added to a device class, it is added to each
-interface that is registered with the device class. The class
-is expected to place a class-specific data structure in 
-struct device::class_data. The interface can use that (along with
-other fields of struct device) to determine whether or not the driver
-and/or device support that particular interface.
-
-
-Data
-~~~~
-
-struct intf_data {
-       struct list_head        node;
-       struct device_interface * intf;
-       struct device           * dev;
-       u32                     intf_num;
-};
-
-int interface_add_data(struct interface_data *);
-
-The interface is responsible for allocating and initializing a struct 
-intf_data and calling interface_add_data() to add it to the device's list
-of interfaces it belongs to. This list will be iterated over when the device
-is removed from the class (instead of all possible interfaces for a class).
-This structure should probably be embedded in whatever per-device data 
-structure the interface is allocating anyway.
-   
-Devices are enumerated within the interface. This happens in interface_add_data()
-and the enumerated value is stored in the struct intf_data for that device. 
-
-sysfs
-~~~~~
-Each interface is given a directory in the directory of the device
-class it belongs to:
-
-Interfaces get a directory in the class's directory as well:
-
-   class/
-   `-- input
-       |-- devices
-       |-- drivers
-       |-- mouse
-       `-- evdev
-
-When a device is added to the interface, a symlink is created that points 
-to the device's directory in the physical hierarchy:
-
-   class/
-   `-- input
-       |-- devices
-       |   `-- 1 -> ../../../root/pci0/00:1f.0/usb_bus/00:1f.2-1:0/
-       |-- drivers
-       |   `-- usb:usb_mouse -> ../../../bus/drivers/usb_mouse/
-       |-- mouse
-       |   `-- 1 -> ../../../root/pci0/00:1f.0/usb_bus/00:1f.2-1:0/
-       `-- evdev
-           `-- 1 -> ../../../root/pci0/00:1f.0/usb_bus/00:1f.2-1:0/
-
-
-Future Plans
-~~~~~~~~~~~~
-A device interface is correlated directly with a userspace interface
-for a device, specifically a device node. For instance, a SCSI disk
-exposes at least two interfaces to userspace: the standard SCSI disk
-interface and the SCSI generic interface. It might also export a raw
-device interface. 
-
-Many interfaces have a major number associated with them and each
-device gets a minor number. Or, multiple interfaces might share one
-major number, and each will receive a range of minor numbers (like in
-the case of input devices).
-
-These major and minor numbers could be stored in the interface
-structure. Major and minor allocations could happen when the interface
-is registered with the class, or via a helper function. 
-
index 0b875e8da96965316d0bca49185d5a28b6d25649..9ee774de57cda04609dbf41b105c01069f0b2bcf 100644 (file)
@@ -196,7 +196,7 @@ csrow3.
 The representation of the above is reflected in the directory tree
 in EDAC's sysfs interface. Starting in directory
 /sys/devices/system/edac/mc each memory controller will be represented
-by its own 'mcX' directory, where 'X" is the index of the MC.
+by its own 'mcX' directory, where 'X' is the index of the MC.
 
 
        ..../edac/mc/
@@ -207,7 +207,7 @@ by its own 'mcX' directory, where 'X" is the index of the MC.
                   ....
 
 Under each 'mcX' directory each 'csrowX' is again represented by a
-'csrowX', where 'X" is the csrow index:
+'csrowX', where 'X' is the csrow index:
 
 
        .../mc/mc0/
@@ -232,7 +232,7 @@ EDAC control and attribute files.
 
 
 In 'mcX' directories are EDAC control and attribute files for
-this 'X" instance of the memory controllers:
+this 'X' instance of the memory controllers:
 
 
 Counter reset control file:
@@ -343,7 +343,7 @@ Sdram memory scrubbing rate:
 'csrowX' DIRECTORIES
 
 In the 'csrowX' directories are EDAC control and attribute files for
-this 'X" instance of csrow:
+this 'X' instance of csrow:
 
 
 Total Uncorrectable Errors count attribute file:
index a618fd99c9f0164298cd343ce404d04f3d38cd40..30a70542e8235d5939056e311dd933597ef49e2a 100644 (file)
@@ -4,33 +4,41 @@ please mail me.
                                    Geert Uytterhoeven <geert@linux-m68k.org>
 
 00-INDEX
-       - this file
+       - this file.
 arkfb.txt
        - info on the fbdev driver for ARK Logic chips.
 aty128fb.txt
        - info on the ATI Rage128 frame buffer driver.
 cirrusfb.txt
        - info on the driver for Cirrus Logic chipsets.
+cmap_xfbdev.txt
+       - an introduction to fbdev's cmap structures.
 deferred_io.txt
        - an introduction to deferred IO.
+efifb.txt
+       - info on the EFI platform driver for Intel based Apple computers.
+ep93xx-fb.txt
+       - info on the driver for EP93xx LCD controller.
 fbcon.txt
        - intro to and usage guide for the framebuffer console (fbcon).
 framebuffer.txt
        - introduction to frame buffer devices.
-imacfb.txt
-       - info on the generic EFI platform driver for Intel based Macs.
+gxfb.txt
+       - info on the framebuffer driver for AMD Geode GX2 based processors.
 intel810.txt
        - documentation for the Intel 810/815 framebuffer driver.
 intelfb.txt
        - docs for Intel 830M/845G/852GM/855GM/865G/915G/945G fb driver.
 internals.txt
        - quick overview of frame buffer device internals.
+lxfb.txt
+       - info on the framebuffer driver for AMD Geode LX based processors.
 matroxfb.txt
        - info on the Matrox framebuffer driver for Alpha, Intel and PPC.
+metronomefb.txt
+       - info on the driver for the Metronome display controller.
 modedb.txt
        - info on the video mode database.
-matroxfb.txt
-       - info on the Matrox frame buffer driver.
 pvr2fb.txt
        - info on the PowerVR 2 frame buffer driver.
 pxafb.txt
@@ -39,13 +47,23 @@ s3fb.txt
        - info on the fbdev driver for S3 Trio/Virge chips.
 sa1100fb.txt
        - information about the driver for the SA-1100 LCD controller.
+sh7760fb.txt
+       - info on the SH7760/SH7763 integrated LCDC Framebuffer driver.
 sisfb.txt
        - info on the framebuffer device driver for various SiS chips.
 sstfb.txt
        - info on the frame buffer driver for 3dfx' Voodoo Graphics boards.
 tgafb.txt
-       - info on the TGA (DECChip 21030) frame buffer driver
+       - info on the TGA (DECChip 21030) frame buffer driver.
+tridentfb.txt
+       info on the framebuffer driver for some Trident chip based cards.
+uvesafb.txt
+       - info on the userspace VESA (VBE2+ compliant) frame buffer device.
 vesafb.txt
-       - info on the VESA frame buffer device
+       - info on the VESA frame buffer device.
+viafb.modes
+       - list of modes for VIA Integration Graphic Chip.
+viafb.txt
+       - info on the VIA Integration Graphic Chip console framebuffer driver.
 vt8623fb.txt
        - info on the fb driver for the graphics core in VIA VT8623 chipsets.
index a91f30890011ddf69ba9b859484966c943db7fb5..b6426f15b4ae85f5469b962806004237b9b5607e 100644 (file)
@@ -173,12 +173,13 @@ prototypes:
        sector_t (*bmap)(struct address_space *, sector_t);
        int (*invalidatepage) (struct page *, unsigned long);
        int (*releasepage) (struct page *, int);
+       void (*freepage)(struct page *);
        int (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
                        loff_t offset, unsigned long nr_segs);
        int (*launder_page) (struct page *);
 
 locking rules:
-       All except set_page_dirty may block
+       All except set_page_dirty and freepage may block
 
                        BKL     PageLocked(page)        i_mutex
 writepage:             no      yes, unlocks (see below)
@@ -193,6 +194,7 @@ perform_write:              no      n/a                     yes
 bmap:                  no
 invalidatepage:                no      yes
 releasepage:           no      yes
+freepage:              no      yes
 direct_IO:             no
 launder_page:          no      yes
 
@@ -288,6 +290,9 @@ buffers from the page in preparation for freeing it.  It returns zero to
 indicate that the buffers are (or may be) freeable.  If ->releasepage is zero,
 the kernel assumes that the fs has no private interest in the buffers.
 
+       ->freepage() is called when the kernel is done dropping the page
+from the page cache.
+
        ->launder_page() may be called prior to releasing a page if
 it is still found to be dirty. It returns zero if the page was successfully
 cleaned, or an error value if not. Note that in order to prevent the page
index d428cc9f07f399141e643fc6d8df8ce88433365b..fd53869f5633f2994fe06365fe53c1754747dc6a 100644 (file)
@@ -89,7 +89,7 @@ static ssize_t childless_storeme_write(struct childless *childless,
        char *p = (char *) page;
 
        tmp = simple_strtoul(p, &p, 10);
-       if (!p || (*p && (*p != '\n')))
+       if ((*p != '\0') && (*p != '\n'))
                return -EINVAL;
 
        if (tmp > INT_MAX)
index ed7e5efc06d8fe33dc54a2122a059fdbec874092..20899e095e7e6879580b53aa9aa0282fb4b5ce63 100644 (file)
@@ -534,6 +534,7 @@ struct address_space_operations {
        sector_t (*bmap)(struct address_space *, sector_t);
        int (*invalidatepage) (struct page *, unsigned long);
        int (*releasepage) (struct page *, int);
+       void (*freepage)(struct page *);
        ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
                        loff_t offset, unsigned long nr_segs);
        struct page* (*get_xip_page)(struct address_space *, sector_t,
@@ -660,11 +661,10 @@ struct address_space_operations {
   releasepage: releasepage is called on PagePrivate pages to indicate
         that the page should be freed if possible.  ->releasepage
         should remove any private data from the page and clear the
-        PagePrivate flag.  It may also remove the page from the
-        address_space.  If this fails for some reason, it may indicate
-        failure with a 0 return value.
-       This is used in two distinct though related cases.  The first
-        is when the VM finds a clean page with no active users and
+        PagePrivate flag. If releasepage() fails for some reason, it must
+       indicate failure with a 0 return value.
+       releasepage() is used in two distinct though related cases.  The
+       first is when the VM finds a clean page with no active users and
         wants to make it a free page.  If ->releasepage succeeds, the
         page will be removed from the address_space and become free.
 
@@ -679,6 +679,12 @@ struct address_space_operations {
         need to ensure this.  Possibly it can clear the PageUptodate
         bit if it cannot free private data yet.
 
+  freepage: freepage is called once the page is no longer visible in
+        the page cache in order to allow the cleanup of any private
+       data. Since it may be called by the memory reclaimer, it
+       should not assume that the original address_space mapping still
+       exists, and it should not block.
+
   direct_IO: called by the generic read/write routines to perform
         direct_IO - that is IO requests which bypass the page cache
         and transfer data directly between the storage and the
index 9633da01ff46afb008566ccb53aa381606654e85..792faa3c06cf7ccda5ab081dbf568276324538e5 100644 (file)
@@ -617,6 +617,16 @@ and have the following read/write attributes:
                is configured as an output, this value may be written;
                any nonzero value is treated as high.
 
+               If the pin can be configured as interrupt-generating interrupt
+               and if it has been configured to generate interrupts (see the
+               description of "edge"), you can poll(2) on that file and
+               poll(2) will return whenever the interrupt was triggered. If
+               you use poll(2), set the events POLLPRI and POLLERR. If you
+               use select(2), set the file descriptor in exceptfds. After
+               poll(2) returns, either lseek(2) to the beginning of the sysfs
+               file and read the new value or close the file and re-open it
+               to read the value.
+
        "edge" ... reads as either "none", "rising", "falling", or
                "both". Write these strings to select the signal edge(s)
                that will make poll(2) on the "value" file return.
index ac711f357fafb0793d10c3cb31d2cd882647f767..7a10616d0b441c473e82d8c2c31489d7dd5e80c2 100644 (file)
@@ -11,7 +11,7 @@ Authors:
        Mark M. Hoffman <mhoffman@lightlink.com>
        Ported to 2.6 by Eric J. Bowersox <ericb@aspsys.com>
        Adapted to 2.6.20 by Carsten Emde <ce@osadl.org>
-       Modified for mainline integration by Hans J. Koch <hjk@linutronix.de>
+       Modified for mainline integration by Hans J. Koch <hjk@hansjkoch.de>
 
 Module Parameters
 -----------------
index 8be7beb9e3e81122d015a3eab8f634d22562bd91..c565650fcfc6f6949c8a24ae1bd2002ae9da86fa 100644 (file)
@@ -8,7 +8,7 @@ Supported chips:
     Datasheet: http://pdfserv.maxim-ic.com/en/ds/MAX6650-MAX6651.pdf
 
 Authors:
-    Hans J. Koch <hjk@linutronix.de>
+    Hans J. Koch <hjk@hansjkoch.de>
     John Morris <john.morris@spirentcom.com>
     Claus Gindhart <claus.gindhart@kontron.com>
 
index 92e83e53148fe8b1d4848af9a8fd7442cc5624ba..8b61c93609994dd91e36c25e1b29647ad084eaff 100644 (file)
@@ -2175,11 +2175,6 @@ and is between 256 and 4096 characters. It is defined in the file
        reset_devices   [KNL] Force drivers to reset the underlying device
                        during initialization.
 
-       resource_alloc_from_bottom
-                       Allocate new resources from the beginning of available
-                       space, not the end.  If you need to use this, please
-                       report a bug.
-
        resume=         [SWSUSP]
                        Specify the partition device for software suspend
 
@@ -2385,6 +2380,11 @@ and is between 256 and 4096 characters. It is defined in the file
                        improve throughput, but will also increase the
                        amount of memory reserved for use by the client.
 
+       swapaccount[=0|1]
+                       [KNL] Enable accounting of swap in memory resource
+                       controller if no parameter or 1 is given or disable
+                       it if 0 is given (See Documentation/cgroups/memory.txt)
+
        swiotlb=        [IA-64] Number of I/O TLB slabs
 
        switches=       [HW,M68k]
index fe95105992c57f1c81248dd8d3c1c38c3272e0f9..3c5e465296e146b3089adfcec06f6c96c9805ddb 100644 (file)
@@ -144,6 +144,7 @@ tcp_adv_win_scale - INTEGER
        Count buffering overhead as bytes/2^tcp_adv_win_scale
        (if tcp_adv_win_scale > 0) or bytes-bytes/2^(-tcp_adv_win_scale),
        if it is <= 0.
+       Possible values are [-31, 31], inclusive.
        Default: 2
 
 tcp_allowed_congestion_control - STRING
index 489e9bacd165ad4a354130edcf7e03d97471b52b..41cc7b30d7ddaff700a198b590eb91047d90d0d0 100644 (file)
@@ -379,8 +379,8 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
       zero)
 
   bool pm_runtime_suspended(struct device *dev);
-    - return true if the device's runtime PM status is 'suspended', or false
-      otherwise
+    - return true if the device's runtime PM status is 'suspended' and its
+      'power.disable_depth' field is equal to zero, or false otherwise
 
   void pm_runtime_allow(struct device *dev);
     - set the power.runtime_auto flag for the device and decrease its usage
diff --git a/Documentation/sh/clk.txt b/Documentation/sh/clk.txt
deleted file mode 100644 (file)
index 114b595..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-Clock framework on SuperH architecture
-
-The framework on SH extends existing API by the function clk_set_rate_ex,
-which prototype is as follows:
-
-    clk_set_rate_ex (struct clk *clk, unsigned long rate, int algo_id)
-
-The algo_id parameter is used to specify algorithm used to recalculate clocks,
-adjanced to clock, specified as first argument. It is assumed that algo_id==0
-means no changes to adjanced clock
-
-Internally, the clk_set_rate_ex forwards request to clk->ops->set_rate method,
-if it is present in ops structure. The method should set the clock rate and adjust
-all needed clocks according to the passed algo_id.
-Exact values for algo_id are machine-dependent. For the sh7722, the following
-values are defined:
-
-       NO_CHANGE       = 0,
-       IUS_N1_N1,      /* I:U = N:1, U:Sh = N:1 */
-       IUS_322,        /* I:U:Sh = 3:2:2        */
-       IUS_522,        /* I:U:Sh = 5:2:2        */
-       IUS_N11,        /* I:U:Sh = N:1:1        */
-       SB_N1,          /* Sh:B = N:1            */
-       SB3_N1,         /* Sh:B3 = N:1           */
-       SB3_32,         /* Sh:B3 = 3:2           */
-       SB3_43,         /* Sh:B3 = 4:3           */
-       SB3_54,         /* Sh:B3 = 5:4           */
-       BP_N1,          /* B:P   = N:1           */
-       IP_N1           /* I:P   = N:1           */
-
-Each of these constants means relation between clocks that can be set via the FRQCR
-register
index 8e6548dbd5db50c4e80f24fd9ae4bdd4597bd6c3..6a588873cf8d2da8b00f803a1dcd8d96841292bd 100644 (file)
@@ -559,14 +559,14 @@ W:        http://maxim.org.za/at91_26.html
 S:     Maintained
 
 ARM/BCMRING ARM ARCHITECTURE
-M:     Leo Chen <leochen@broadcom.com>
+M:     Jiandong Zheng <jdzheng@broadcom.com>
 M:     Scott Branden <sbranden@broadcom.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/mach-bcmring
 
 ARM/BCMRING MTD NAND DRIVER
-M:     Leo Chen <leochen@broadcom.com>
+M:     Jiandong Zheng <jdzheng@broadcom.com>
 M:     Scott Branden <sbranden@broadcom.com>
 L:     linux-mtd@lists.infradead.org
 S:     Maintained
@@ -815,7 +815,7 @@ F:  drivers/mmc/host/msm_sdcc.c
 F:     drivers/mmc/host/msm_sdcc.h
 F:     drivers/serial/msm_serial.h
 F:     drivers/serial/msm_serial.c
-T:     git git://codeaurora.org/quic/kernel/dwalker/linux-msm.git
+T:     git git://codeaurora.org/quic/kernel/davidb/linux-msm.git
 S:     Maintained
 
 ARM/TOSA MACHINE SUPPORT
@@ -1359,7 +1359,7 @@ F:        include/net/bluetooth/
 
 BONDING DRIVER
 M:     Jay Vosburgh <fubar@us.ibm.com>
-L:     bonding-devel@lists.sourceforge.net
+L:     netdev@vger.kernel.org
 W:     http://sourceforge.net/projects/bonding/
 S:     Supported
 F:     drivers/net/bonding/
@@ -1829,6 +1829,13 @@ W:       http://www.chelsio.com
 S:     Supported
 F:     drivers/net/cxgb4vf/
 
+STMMAC ETHERNET DRIVER
+M:     Giuseppe Cavallaro <peppe.cavallaro@st.com>
+L:     netdev@vger.kernel.org
+W:     http://www.stlinux.com
+S:     Supported
+F:     drivers/net/stmmac/
+
 CYBERPRO FB DRIVER
 M:     Russell King <linux@arm.linux.org.uk>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -2008,6 +2015,7 @@ F:        drivers/hwmon/dme1737.c
 DOCBOOK FOR DOCUMENTATION
 M:     Randy Dunlap <rdunlap@xenotime.net>
 S:     Maintained
+F:     scripts/kernel-doc
 
 DOCKING STATION DRIVER
 M:     Shaohua Li <shaohua.li@intel.com>
@@ -2018,6 +2026,7 @@ F:        drivers/acpi/dock.c
 DOCUMENTATION
 M:     Randy Dunlap <rdunlap@xenotime.net>
 L:     linux-doc@vger.kernel.org
+T:     quilt oss.oracle.com/~rdunlap/kernel-doc-patches/current/
 S:     Maintained
 F:     Documentation/
 
@@ -2051,7 +2060,7 @@ F:        Documentation/blockdev/drbd/
 
 DRIVER CORE, KOBJECTS, DEBUGFS AND SYSFS
 M:     Greg Kroah-Hartman <gregkh@suse.de>
-T:     quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6.git
 S:     Supported
 F:     Documentation/kobject.txt
 F:     drivers/base/
@@ -2071,7 +2080,7 @@ F:        include/drm/
 
 INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
 M:     Chris Wilson <chris@chris-wilson.co.uk>
-L:     intel-gfx@lists.freedesktop.org
+L:     intel-gfx@lists.freedesktop.org (subscribers-only)
 L:     dri-devel@lists.freedesktop.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/ickle/drm-intel.git
 S:     Supported
@@ -2435,10 +2444,12 @@ F:      drivers/net/wan/sdla.c
 FRAMEBUFFER LAYER
 L:     linux-fbdev@vger.kernel.org
 W:     http://linux-fbdev.sourceforge.net/
+Q:     http://patchwork.kernel.org/project/linux-fbdev/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/fbdev-2.6.git
 S:     Orphan
 F:     Documentation/fb/
-F:     drivers/video/fb*
+F:     drivers/video/
+F:     include/video/
 F:     include/linux/fb.h
 
 FREESCALE DMA DRIVER
@@ -4053,9 +4064,8 @@ F:        drivers/scsi/NCR_D700.*
 
 NETEFFECT IWARP RNIC DRIVER (IW_NES)
 M:     Faisal Latif <faisal.latif@intel.com>
-M:     Chien Tung <chien.tin.tung@intel.com>
 L:     linux-rdma@vger.kernel.org
-W:     http://www.neteffect.com
+W:     http://www.intel.com/Products/Server/Adapters/Server-Cluster/Server-Cluster-overview.htm
 S:     Supported
 F:     drivers/infiniband/hw/nes/
 
@@ -5828,6 +5838,8 @@ M:        Chris Metcalf <cmetcalf@tilera.com>
 W:     http://www.tilera.com/scm/
 S:     Supported
 F:     arch/tile/
+F:     drivers/char/hvc_tile.c
+F:     drivers/net/tile/
 
 TLAN NETWORK DRIVER
 M:     Samuel Chessman <chessman@tux.org>
@@ -5920,7 +5932,6 @@ F:        include/linux/tty.h
 
 TULIP NETWORK DRIVERS
 M:     Grant Grundler <grundler@parisc-linux.org>
-M:     Kyle McMartin <kyle@mcmartin.ca>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/tulip/
@@ -6572,6 +6583,15 @@ F:       include/linux/mfd/wm8400*
 F:     include/sound/wm????.h
 F:     sound/soc/codecs/wm*
 
+WORKQUEUE
+M:     Tejun Heo <tj@kernel.org>
+L:     linux-kernel@vger.kernel.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git
+S:     Maintained
+F:     include/linux/workqueue.h
+F:     kernel/workqueue.c
+F:     Documentation/workqueue.txt
+
 X.25 NETWORK LAYER
 M:     Andrew Hendry <andrew.hendry@gmail.com>
 L:     linux-x25@vger.kernel.org
index ab5359db3d177b2e4a83823baa15da908e5b395b..77044b7918a5cbe8439d9000175ca0b7f0ea4717 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 37
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc7
 NAME = Flesh-Eating Bats with Fangs
 
 # *DOCUMENTATION*
index db524e75c4a21e4f45bc4b72e459adcdaf1dda4b..d56d21c0573ba519b36d7f1e4012eb609dfbb664 100644 (file)
@@ -9,7 +9,7 @@ config ARM
        select GENERIC_ATOMIC64 if (!CPU_32v6K || !AEABI)
        select HAVE_OPROFILE if (HAVE_PERF_EVENTS)
        select HAVE_ARCH_KGDB
-       select HAVE_KPROBES if (!XIP_KERNEL)
+       select HAVE_KPROBES if (!XIP_KERNEL && !THUMB2_KERNEL)
        select HAVE_KRETPROBES if (HAVE_KPROBES)
        select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
        select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
@@ -1311,7 +1311,7 @@ config HZ
 
 config THUMB2_KERNEL
        bool "Compile the kernel in Thumb-2 mode"
-       depends on CPU_V7 && EXPERIMENTAL
+       depends on CPU_V7 && !CPU_V6 && EXPERIMENTAL
        select AEABI
        select ARM_ASM_UNIFIED
        help
@@ -1759,7 +1759,7 @@ comment "At least one emulation must be selected"
 
 config FPE_NWFPE
        bool "NWFPE math emulation"
-       depends on !AEABI || OABI_COMPAT
+       depends on (!AEABI || OABI_COMPAT) && !THUMB2_KERNEL
        ---help---
          Say Y to include the NWFPE floating point emulator in the kernel.
          This is necessary to run most binaries. Linux does not currently
index 4a590f4113e2af044ea1764aeb0681ad7f50a74c..4d26f2c52a7553c1f0c6f387c2e7f5ad9a25328c 100644 (file)
@@ -70,12 +70,7 @@ else
 $(obj)/uImage: LOADADDR=$(ZRELADDR)
 endif
 
-ifeq ($(CONFIG_THUMB2_KERNEL),y)
-# Set bit 0 to 1 so that "mov pc, rx" switches to Thumb-2 mode
-$(obj)/uImage: STARTADDR=$(shell echo $(LOADADDR) | sed -e "s/.$$/1/")
-else
 $(obj)/uImage: STARTADDR=$(LOADADDR)
-endif
 
 $(obj)/uImage: $(obj)/zImage FORCE
        $(call if_changed,uimage)
index 8b0de41c3dcbbe646877a9f31635bb5e48b8b4bd..78b508075161fd4967bdbb3821eab162aa9dd5bc 100644 (file)
@@ -73,6 +73,8 @@ move:         ldmia   r4!, {r7 - r10}         @ move 32-bytes at a time
 
                .size   _start, . - _start
 
+               .align
+
                .type   data,#object
 data:          .word   initrd_start            @ source initrd address
                .word   initrd_phys             @ destination initrd address
index 6825c34646d4e02f24b0eefe7ab4e012bca05208..7193884ed8b06c4452b6fe57f3c38821013d0af0 100644 (file)
@@ -125,9 +125,13 @@ wait:              mrc     p14, 0, pc, c0, c1, 0
  * sort out different calling conventions
  */
                .align
+               .arm                            @ Always enter in ARM state
 start:
                .type   start,#function
-               .rept   8
+ THUMB(                adr     r12, BSYM(1f)   )
+ THUMB(                bx      r12             )
+ THUMB(                .rept   6               )
+ ARM(          .rept   8               )
                mov     r0, r0
                .endr
 
@@ -135,6 +139,7 @@ start:
                .word   0x016f2818              @ Magic numbers to help the loader
                .word   start                   @ absolute load/run zImage address
                .word   _edata                  @ zImage end address
+ THUMB(                .thumb                  )
 1:             mov     r7, r1                  @ save architecture ID
                mov     r8, r2                  @ save atags pointer
 
@@ -174,7 +179,8 @@ not_angel:
                ldr     sp, [r0, #28]
 #ifdef CONFIG_AUTO_ZRELADDR
                @ determine final kernel image address
-               and     r4, pc, #0xf8000000
+               mov     r4, pc
+               and     r4, r4, #0xf8000000
                add     r4, r4, #TEXT_OFFSET
 #else
                ldr     r4, =zreladdr
@@ -445,7 +451,8 @@ __setup_mmu:        sub     r3, r4, #16384          @ Page directory size
  */
                mov     r1, #0x1e
                orr     r1, r1, #3 << 10
-               mov     r2, pc, lsr #20
+               mov     r2, pc
+               mov     r2, r2, lsr #20
                orr     r1, r1, r2, lsl #20
                add     r0, r3, r2, lsl #2
                str     r1, [r0], #4
@@ -1084,6 +1091,6 @@ memdump:  mov     r12, r0
 reloc_end:
 
                .align
-               .section ".stack", "w"
+               .section ".stack", "aw", %nobits
 user_stack:    .space  4096
 user_stack_end:
index d08168941bd686b6f7a112f0668e96503c2ba667..366a924019ac6dcf1ccaad07b605f6c6ec1b74c6 100644 (file)
@@ -57,7 +57,7 @@ SECTIONS
   .bss                 : { *(.bss) }
   _end = .;
 
-  .stack (NOLOAD)      : { *(.stack) }
+  .stack               : { *(.stack) }
 
   .stab 0              : { *(.stab) }
   .stabstr 0           : { *(.stabstr) }
index 772f95f1aecddf49ada9ceea0caa5295d22c9613..e6388dcd8cfa2cf5f7a31ee59a6728bda377f89c 100644 (file)
@@ -146,9 +146,15 @@ static int gic_set_cpu(unsigned int irq, const struct cpumask *mask_val)
        unsigned int shift = (irq % 4) * 8;
        unsigned int cpu = cpumask_first(mask_val);
        u32 val;
+       struct irq_desc *desc;
 
        spin_lock(&irq_controller_lock);
-       irq_desc[irq].node = cpu;
+       desc = irq_to_desc(irq);
+       if (desc == NULL) {
+               spin_unlock(&irq_controller_lock);
+               return -EINVAL;
+       }
+       desc->node = cpu;
        val = readl(reg) & ~(0xff << shift);
        val |= 1 << (cpu + shift);
        writel(val, reg);
@@ -210,7 +216,7 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
 void __init gic_dist_init(unsigned int gic_nr, void __iomem *base,
                          unsigned int irq_start)
 {
-       unsigned int max_irq, i;
+       unsigned int gic_irqs, irq_limit, i;
        u32 cpumask = 1 << smp_processor_id();
 
        if (gic_nr >= MAX_GIC_NR)
@@ -226,47 +232,49 @@ void __init gic_dist_init(unsigned int gic_nr, void __iomem *base,
 
        /*
         * Find out how many interrupts are supported.
-        */
-       max_irq = readl(base + GIC_DIST_CTR) & 0x1f;
-       max_irq = (max_irq + 1) * 32;
-
-       /*
         * The GIC only supports up to 1020 interrupt sources.
-        * Limit this to either the architected maximum, or the
-        * platform maximum.
         */
-       if (max_irq > max(1020, NR_IRQS))
-               max_irq = max(1020, NR_IRQS);
+       gic_irqs = readl(base + GIC_DIST_CTR) & 0x1f;
+       gic_irqs = (gic_irqs + 1) * 32;
+       if (gic_irqs > 1020)
+               gic_irqs = 1020;
 
        /*
         * Set all global interrupts to be level triggered, active low.
         */
-       for (i = 32; i < max_irq; i += 16)
+       for (i = 32; i < gic_irqs; i += 16)
                writel(0, base + GIC_DIST_CONFIG + i * 4 / 16);
 
        /*
         * Set all global interrupts to this CPU only.
         */
-       for (i = 32; i < max_irq; i += 4)
+       for (i = 32; i < gic_irqs; i += 4)
                writel(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
 
        /*
         * Set priority on all global interrupts.
         */
-       for (i = 32; i < max_irq; i += 4)
+       for (i = 32; i < gic_irqs; i += 4)
                writel(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4);
 
        /*
         * Disable all interrupts.  Leave the PPI and SGIs alone
         * as these enables are banked registers.
         */
-       for (i = 32; i < max_irq; i += 32)
+       for (i = 32; i < gic_irqs; i += 32)
                writel(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
 
+       /*
+        * Limit number of interrupts registered to the platform maximum
+        */
+       irq_limit = gic_data[gic_nr].irq_offset + gic_irqs;
+       if (WARN_ON(irq_limit > NR_IRQS))
+               irq_limit = NR_IRQS;
+
        /*
         * Setup the Linux IRQ subsystem.
         */
-       for (i = irq_start; i < gic_data[gic_nr].irq_offset + max_irq; i++) {
+       for (i = irq_start; i < irq_limit; i++) {
                set_irq_chip(i, &gic_chip);
                set_irq_chip_data(i, &gic_data[gic_nr]);
                set_irq_handler(i, handle_level_irq);
diff --git a/arch/arm/configs/at91rm9200_defconfig b/arch/arm/configs/at91rm9200_defconfig
new file mode 100644 (file)
index 0000000..38cb7c9
--- /dev/null
@@ -0,0 +1,341 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_AT91=y
+CONFIG_MACH_ONEARM=y
+CONFIG_ARCH_AT91RM9200DK=y
+CONFIG_MACH_AT91RM9200EK=y
+CONFIG_MACH_CSB337=y
+CONFIG_MACH_CSB637=y
+CONFIG_MACH_CARMEVA=y
+CONFIG_MACH_ATEB9200=y
+CONFIG_MACH_KB9200=y
+CONFIG_MACH_PICOTUX2XX=y
+CONFIG_MACH_KAFA=y
+CONFIG_MACH_ECBAT91=y
+CONFIG_MACH_YL9200=y
+CONFIG_MACH_CPUAT91=y
+CONFIG_MACH_ECO920=y
+CONFIG_MTD_AT91_DATAFLASH_CARD=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+CONFIG_AT91_TIMER_HZ=100
+# CONFIG_ARM_THUMB is not set
+CONFIG_PCCARD=y
+CONFIG_AT91_CF=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_LEDS=y
+CONFIG_LEDS_CPU=y
+CONFIG_ZBOOT_ROM_TEXT=0x10000000
+CONFIG_ZBOOT_ROM_BSS=0x20040000
+CONFIG_KEXEC=y
+CONFIG_FPE_NWFPE=y
+CONFIG_BINFMT_MISC=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_AFS_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PLATRAM=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_MTD_NAND_PLATFORM=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_GLUEBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_NBD=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_ATMEL_TCLIB=y
+CONFIG_EEPROM_LEGACY=m
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_TUN=m
+CONFIG_PHYLIB=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_SMSC_PHY=y
+CONFIG_MICREL_PHY=y
+CONFIG_NET_ETHERNET=y
+CONFIG_ARM_AT91_ETHER=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_EPSON2888=y
+CONFIG_PPP=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_LEGACY_PTY_COUNT=32
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_GPIO=y
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=y
+CONFIG_SPI_BITBANG=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_HWMON=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1029=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM73=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83793=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_AT91RM9200_WATCHDOG=y
+CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_S1D13XXX=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_DISPLAY_SUPPORT=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_MINI_4x6=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_MON=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=y
+CONFIG_USB_SERIAL=y
+CONFIG_USB_SERIAL_CONSOLE=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_FTDI_SIO=y
+CONFIG_USB_SERIAL_KEYSPAN=y
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_MCT_U232=y
+CONFIG_USB_SERIAL_PL2303=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ETH=m
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_MMC=y
+CONFIG_MMC_AT91=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_HCTOSYS is not set
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_PCF8563=y
+CONFIG_RTC_DRV_AT91RM9200=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_REISERFS_FS=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_TMPFS=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RUBIN=y
+CONFIG_CRAMFS=y
+CONFIG_MINIX_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=y
+CONFIG_SMB_FS=m
+CONFIG_CIFS=m
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_FTRACE is not set
+CONFIG_CRYPTO_PCBC=y
+CONFIG_CRYPTO_SHA1=y
diff --git a/arch/arm/configs/at91rm9200dk_defconfig b/arch/arm/configs/at91rm9200dk_defconfig
deleted file mode 100644 (file)
index 4438e64..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91RM9200DK=y
-CONFIG_MACH_ECO920=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_PCCARD=y
-CONFIG_AT91_CF=y
-CONFIG_LEDS=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20410000,3145728 root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IPV6 is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_ARM_AT91_ETHER=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_AT91RM9200_WATCHDOG=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_USB_HID is not set
-CONFIG_USB=y
-CONFIG_USB_DEBUG=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_GADGET=y
-CONFIG_MMC=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91RM9200=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_TMPFS=y
-CONFIG_CRAMFS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
diff --git a/arch/arm/configs/at91rm9200ek_defconfig b/arch/arm/configs/at91rm9200ek_defconfig
deleted file mode 100644 (file)
index ccd517c..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_MACH_AT91RM9200EK=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_LEDS=y
-CONFIG_LEDS_CPU=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20410000,3145728 root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IPV6 is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_ARM_AT91_ETHER=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_AT91RM9200_WATCHDOG=y
-CONFIG_FB=y
-CONFIG_FB_S1D13XXX=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_USB_HID is not set
-CONFIG_USB=y
-CONFIG_USB_DEBUG=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_GADGET=y
-CONFIG_MMC=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91RM9200=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_TMPFS=y
-CONFIG_CRAMFS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
diff --git a/arch/arm/configs/ateb9200_defconfig b/arch/arm/configs/ateb9200_defconfig
deleted file mode 100644 (file)
index 1b0e9a1..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
-CONFIG_SLAB=y
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=m
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_ARCH_AT91=y
-CONFIG_MACH_ATEB9200=y
-CONFIG_PCCARD=m
-CONFIG_AT91_CF=m
-CONFIG_PREEMPT=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_FPE_NWFPE=y
-CONFIG_PM=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IPV6 is not set
-CONFIG_BRIDGE=m
-CONFIG_VLAN_8021Q=m
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK_RO=y
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_NBD=m
-CONFIG_SCSI=m
-CONFIG_BLK_DEV_SD=m
-CONFIG_BLK_DEV_SR=m
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_CHR_DEV_SG=m
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=m
-CONFIG_TUN=m
-CONFIG_PHYLIB=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_ARM_AT91_ETHER=y
-CONFIG_USB_USBNET=y
-CONFIG_USB_NET_GL620A=y
-CONFIG_USB_NET_PLUSB=y
-CONFIG_USB_NET_RNDIS_HOST=y
-CONFIG_USB_ALI_M5632=y
-CONFIG_USB_AN2720=y
-CONFIG_USB_EPSON2888=y
-CONFIG_PPP=m
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPPOE=m
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_I2C=m
-CONFIG_I2C_CHARDEV=m
-CONFIG_I2C_GPIO=m
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_SOUND=y
-CONFIG_USB_HID=m
-CONFIG_HID_PID=y
-CONFIG_USB_HIDDEV=y
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_ACM=m
-CONFIG_USB_PRINTER=m
-CONFIG_USB_STORAGE=m
-CONFIG_USB_STORAGE_DATAFAB=m
-CONFIG_USB_STORAGE_FREECOM=m
-CONFIG_USB_STORAGE_USBAT=m
-CONFIG_USB_STORAGE_SDDR09=m
-CONFIG_USB_STORAGE_SDDR55=m
-CONFIG_USB_STORAGE_JUMPSHOT=m
-CONFIG_USB_SERIAL=m
-CONFIG_USB_SERIAL_GENERIC=y
-CONFIG_USB_SERIAL_FTDI_SIO=m
-CONFIG_USB_SERIAL_PL2303=m
-CONFIG_USB_GADGET=m
-CONFIG_USB_ETH=m
-CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_USB_G_SERIAL=m
-CONFIG_MMC=m
-CONFIG_MMC_DEBUG=y
-CONFIG_RTC_CLASS=y
-# CONFIG_RTC_HCTOSYS is not set
-CONFIG_RTC_DRV_AT91RM9200=y
-CONFIG_EXT2_FS=m
-CONFIG_EXT3_FS=m
-CONFIG_REISERFS_FS=m
-CONFIG_INOTIFY=y
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_NTFS_FS=m
-CONFIG_NTFS_RW=y
-CONFIG_TMPFS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=m
-CONFIG_NFS_V3=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-CONFIG_NFSD=m
-CONFIG_NFSD_V4=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAC_PARTITION=y
-CONFIG_BSD_DISKLABEL=y
-CONFIG_MINIX_SUBPARTITION=y
-CONFIG_SOLARIS_X86_PARTITION=y
-CONFIG_UNIXWARE_DISKLABEL=y
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_ASCII=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_UTF8=m
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRC16=m
-CONFIG_LIBCRC32C=m
diff --git a/arch/arm/configs/carmeva_defconfig b/arch/arm/configs/carmeva_defconfig
deleted file mode 100644 (file)
index ac64dbd..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
-# CONFIG_HOTPLUG is not set
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_ARCH_AT91=y
-CONFIG_MACH_CARMEVA=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-# CONFIG_IPV6 is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_ARM_AT91_ETHER=y
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIO=m
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_MMC=m
-CONFIG_MMC_DEBUG=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-# CONFIG_DNOTIFY is not set
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_COMPRESSION_OPTIONS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_NFSD=y
diff --git a/arch/arm/configs/cpuat91_defconfig b/arch/arm/configs/cpuat91_defconfig
deleted file mode 100644 (file)
index 022aeb5..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_MACH_CPUAT91=y
-CONFIG_AT91_TIMER_HZ=100
-# CONFIG_ARM_THUMB is not set
-CONFIG_PREEMPT=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PLATRAM=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_NBD=y
-CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_NETDEVICES=y
-CONFIG_PHYLIB=y
-CONFIG_NET_ETHERNET=y
-CONFIG_ARM_AT91_ETHER=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-CONFIG_PPP=y
-CONFIG_PPP_ASYNC=y
-CONFIG_PPP_DEFLATE=y
-CONFIG_PPP_BSDCOMP=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_LEGACY_PTY_COUNT=32
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-CONFIG_GPIO_SYSFS=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_AT91RM9200_WATCHDOG=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_HID_SUPPORT is not set
-CONFIG_USB=y
-# CONFIG_USB_DEVICE_CLASS is not set
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ETH=m
-CONFIG_MMC=y
-CONFIG_MMC_AT91=m
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_LEDS_TRIGGER_GPIO=y
-CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
-CONFIG_RTC_CLASS=y
-# CONFIG_RTC_HCTOSYS is not set
-CONFIG_RTC_DRV_DS1307=y
-CONFIG_RTC_DRV_PCF8563=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_INOTIFY=y
-CONFIG_AUTOFS4_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_CRAMFS=y
-CONFIG_MINIX_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_UTF8=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
diff --git a/arch/arm/configs/csb337_defconfig b/arch/arm/configs/csb337_defconfig
deleted file mode 100644 (file)
index a24c448..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_AT91=y
-CONFIG_MACH_CSB337=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_PCCARD=y
-CONFIG_AT91_CF=y
-CONFIG_LEDS=y
-CONFIG_LEDS_CPU=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=32M console=ttyS0,38400 initrd=0x20410000,3145728 root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_ATMEL_SSC=y
-CONFIG_SCSI=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_ARM_AT91_ETHER=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_AT91RM9200_WATCHDOG=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_USB_HID is not set
-CONFIG_USB=y
-CONFIG_USB_DEBUG=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_SERIAL=y
-CONFIG_USB_SERIAL_CONSOLE=y
-CONFIG_USB_SERIAL_GENERIC=y
-CONFIG_USB_SERIAL_FTDI_SIO=y
-CONFIG_USB_SERIAL_KEYSPAN=y
-CONFIG_USB_SERIAL_KEYSPAN_MPR=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19=y
-CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
-CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
-CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
-CONFIG_USB_SERIAL_MCT_U232=y
-CONFIG_USB_GADGET=y
-CONFIG_MMC=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_HCTOSYS_DEVICE="rtc1"
-# CONFIG_RTC_INTF_SYSFS is not set
-CONFIG_RTC_DRV_DS1307=y
-CONFIG_RTC_DRV_AT91RM9200=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_TMPFS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
diff --git a/arch/arm/configs/csb637_defconfig b/arch/arm/configs/csb637_defconfig
deleted file mode 100644 (file)
index 98552ad..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_AT91=y
-CONFIG_MACH_CSB637=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_PCCARD=y
-CONFIG_AT91_CF=y
-CONFIG_LEDS=y
-CONFIG_LEDS_CPU=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=32M console=ttyS0,38400 initrd=0x20410000,3145728 root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_SCSI=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_ARM_AT91_ETHER=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_AT91RM9200_WATCHDOG=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_USB_HID is not set
-CONFIG_USB=y
-CONFIG_USB_DEBUG=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_SERIAL=y
-CONFIG_USB_SERIAL_CONSOLE=y
-CONFIG_USB_SERIAL_GENERIC=y
-CONFIG_USB_SERIAL_FTDI_SIO=y
-CONFIG_USB_SERIAL_KEYSPAN=y
-CONFIG_USB_SERIAL_KEYSPAN_MPR=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19=y
-CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
-CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
-CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
-CONFIG_USB_SERIAL_MCT_U232=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_TMPFS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
diff --git a/arch/arm/configs/ecbat91_defconfig b/arch/arm/configs/ecbat91_defconfig
deleted file mode 100644 (file)
index 6bb6abd..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_MACH_ECBAT91=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-CONFIG_PCCARD=y
-CONFIG_AT91_CF=y
-CONFIG_PREEMPT=y
-CONFIG_LEDS=y
-CONFIG_LEDS_CPU=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="rootfstype=reiserfs root=/dev/mmcblk0p1 console=ttyS0,115200n8 rootdelay=1"
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IPV6 is not set
-CONFIG_CFG80211=y
-CONFIG_MAC80211=y
-# CONFIG_STANDALONE is not set
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_AFS_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_DATAFLASH=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_ARM_AT91_ETHER=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-CONFIG_PPP=y
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_SPI=y
-CONFIG_SPI_BITBANG=y
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_USB_HID is not set
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_DEVICE_CLASS is not set
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_PRINTER=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_GADGET=y
-CONFIG_MMC=y
-CONFIG_MMC_DEBUG=y
-CONFIG_MMC_AT91=m
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_RTC_CLASS=y
-# CONFIG_RTC_HCTOSYS is not set
-CONFIG_RTC_DRV_AT91RM9200=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_REISERFS_FS=y
-CONFIG_INOTIFY=y
-CONFIG_TMPFS=y
-CONFIG_CONFIGFS_FS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_DEBUG_USER=y
-CONFIG_CRYPTO_PCBC=y
-CONFIG_CRYPTO_SHA1=y
diff --git a/arch/arm/configs/kafa_defconfig b/arch/arm/configs/kafa_defconfig
deleted file mode 100644 (file)
index 896dbe0..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_MACH_KAFA=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_PREEMPT=y
-CONFIG_LEDS=y
-CONFIG_LEDS_CPU=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20800000,10M root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_BINFMT_MISC=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK_RO=y
-CONFIG_NETDEVICES=y
-CONFIG_PHYLIB=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_ARM_AT91_ETHER=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_LEGACY_PTY_COUNT=32
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_AT91RM9200_WATCHDOG=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_RTC_CLASS=y
-# CONFIG_RTC_HCTOSYS is not set
-CONFIG_RTC_DRV_AT91RM9200=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_TMPFS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=m
-CONFIG_NFS_V3=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_DES=y
diff --git a/arch/arm/configs/kb9202_defconfig b/arch/arm/configs/kb9202_defconfig
deleted file mode 100644 (file)
index 9f906a8..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_AUDIT=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-CONFIG_ARCH_AT91=y
-CONFIG_MACH_KB9200=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x10000000
-CONFIG_ZBOOT_ROM_BSS=0x20040000
-CONFIG_CMDLINE="noinitrd root=/dev/mtdblock0 rootfstype=jffs2 mem=64M"
-CONFIG_KEXEC=y
-CONFIG_FPE_NWFPE=y
-CONFIG_BINFMT_MISC=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_FIRMWARE_IN_KERNEL is not set
-CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_COMPLEX_MAPPINGS=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_MTD_UBI=y
-CONFIG_MTD_UBI_GLUEBI=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=16384
-CONFIG_ATMEL_TCLIB=y
-CONFIG_ATMEL_SSC=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_SPI_ATTRS=m
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_ARM_AT91_ETHER=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_AT91RM9200_WATCHDOG=y
-CONFIG_FB=y
-CONFIG_FB_MODE_HELPERS=y
-CONFIG_FB_TILEBLITTING=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-# CONFIG_LCD_CLASS_DEVICE is not set
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-# CONFIG_BACKLIGHT_GENERIC is not set
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FONTS=y
-CONFIG_FONT_MINI_4x6=y
-# CONFIG_HID_SUPPORT is not set
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_LIBUSUAL=y
-CONFIG_MMC=y
-CONFIG_MMC_AT91=m
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91RM9200=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_DNOTIFY is not set
-CONFIG_INOTIFY=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_CONFIGFS_FS=y
-CONFIG_JFFS2_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_UTF8=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_SCHED_DEBUG is not set
-# CONFIG_DEBUG_PREEMPT is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
diff --git a/arch/arm/configs/onearm_defconfig b/arch/arm/configs/onearm_defconfig
deleted file mode 100644 (file)
index 1579857..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_MACH_ONEARM=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_PCCARD=y
-CONFIG_AT91_CF=y
-CONFIG_LEDS=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp mem=64M"
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IPV6=y
-# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET6_XFRM_MODE_BEET is not set
-# CONFIG_IPV6_SIT is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_BLK_DEV_NBD=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_ARM_AT91_ETHER=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_AT91RM9200_WATCHDOG=y
-# CONFIG_USB_HID is not set
-CONFIG_USB=y
-CONFIG_USB_DEBUG=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_GADGET=y
-CONFIG_MMC=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_TMPFS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_ROOT_NFS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
diff --git a/arch/arm/configs/picotux200_defconfig b/arch/arm/configs/picotux200_defconfig
deleted file mode 100644 (file)
index 4c9afa4..0000000
+++ /dev/null
@@ -1,242 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_IKCONFIG=m
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
-# CONFIG_KALLSYMS is not set
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_MACH_PICOTUX2XX=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_KEXEC=y
-CONFIG_FPE_NWFPE=y
-CONFIG_BINFMT_MISC=m
-CONFIG_NET=y
-CONFIG_PACKET=m
-CONFIG_UNIX=y
-CONFIG_XFRM_USER=m
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_NET_IPIP=m
-CONFIG_NET_IPGRE=m
-CONFIG_INET_AH=m
-CONFIG_INET_ESP=m
-CONFIG_INET_IPCOMP=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
-CONFIG_INET_DIAG=m
-CONFIG_IPV6_PRIVACY=y
-CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
-CONFIG_INET6_AH=m
-CONFIG_INET6_ESP=m
-CONFIG_INET6_IPCOMP=m
-CONFIG_IPV6_MIP6=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_TUNNEL=m
-CONFIG_BRIDGE=m
-CONFIG_VLAN_8021Q=m
-CONFIG_BT=m
-CONFIG_BT_L2CAP=m
-CONFIG_BT_SCO=m
-CONFIG_BT_RFCOMM=m
-CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=m
-CONFIG_BT_BNEP_MC_FILTER=y
-CONFIG_BT_BNEP_PROTO_FILTER=y
-CONFIG_BT_HIDP=m
-CONFIG_FW_LOADER=m
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_EEPROM_LEGACY=m
-CONFIG_SCSI=m
-CONFIG_BLK_DEV_SD=m
-CONFIG_BLK_DEV_SR=m
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_CHR_DEV_SG=m
-CONFIG_NETDEVICES=y
-CONFIG_TUN=m
-CONFIG_NET_ETHERNET=y
-CONFIG_ARM_AT91_ETHER=y
-CONFIG_USB_CATC=m
-CONFIG_USB_KAWETH=m
-CONFIG_USB_PEGASUS=m
-CONFIG_USB_RTL8150=m
-CONFIG_USB_USBNET=m
-CONFIG_USB_NET_DM9601=m
-CONFIG_USB_NET_GL620A=m
-CONFIG_USB_NET_PLUSB=m
-CONFIG_USB_NET_MCS7830=m
-CONFIG_USB_NET_RNDIS_HOST=m
-CONFIG_USB_ALI_M5632=y
-CONFIG_USB_AN2720=y
-CONFIG_USB_EPSON2888=y
-CONFIG_USB_KC2190=y
-CONFIG_PPP=m
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPP_MPPE=m
-CONFIG_PPPOE=m
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-CONFIG_SLIP_MODE_SLIP6=y
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_I2C=m
-CONFIG_I2C_CHARDEV=m
-CONFIG_I2C_GPIO=m
-CONFIG_HWMON=m
-CONFIG_SENSORS_ADM1021=m
-CONFIG_SENSORS_ADM1025=m
-CONFIG_SENSORS_ADM1026=m
-CONFIG_SENSORS_ADM1029=m
-CONFIG_SENSORS_ADM1031=m
-CONFIG_SENSORS_ADM9240=m
-CONFIG_SENSORS_DS1621=m
-CONFIG_SENSORS_GL518SM=m
-CONFIG_SENSORS_GL520SM=m
-CONFIG_SENSORS_IT87=m
-CONFIG_SENSORS_LM63=m
-CONFIG_SENSORS_LM75=m
-CONFIG_SENSORS_LM77=m
-CONFIG_SENSORS_LM78=m
-CONFIG_SENSORS_LM80=m
-CONFIG_SENSORS_LM83=m
-CONFIG_SENSORS_LM85=m
-CONFIG_SENSORS_LM87=m
-CONFIG_SENSORS_LM90=m
-CONFIG_SENSORS_LM92=m
-CONFIG_SENSORS_MAX1619=m
-CONFIG_SENSORS_PCF8591=m
-CONFIG_SENSORS_SMSC47B397=m
-CONFIG_SENSORS_W83781D=m
-CONFIG_SENSORS_W83791D=m
-CONFIG_SENSORS_W83792D=m
-CONFIG_SENSORS_W83793=m
-CONFIG_SENSORS_W83L785TS=m
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_AT91RM9200_WATCHDOG=m
-CONFIG_HID=m
-CONFIG_USB=m
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_OHCI_HCD=m
-CONFIG_USB_ACM=m
-CONFIG_USB_PRINTER=m
-CONFIG_USB_STORAGE=m
-CONFIG_USB_SERIAL=m
-CONFIG_USB_SERIAL_GENERIC=y
-CONFIG_USB_SERIAL_PL2303=m
-CONFIG_MMC=m
-CONFIG_MMC_AT91=m
-CONFIG_RTC_CLASS=m
-CONFIG_RTC_DRV_AT91RM9200=m
-CONFIG_EXT2_FS=m
-CONFIG_EXT3_FS=m
-# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_INOTIFY=y
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_NTFS_FS=m
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_JFFS2_COMPRESSION_OPTIONS=y
-CONFIG_NFS_FS=m
-CONFIG_SMB_FS=m
-CONFIG_CIFS=m
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_AMIGA_PARTITION=y
-CONFIG_NLS_DEFAULT="utf-8"
-CONFIG_NLS_CODEPAGE_437=m
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-CONFIG_NLS_CODEPAGE_1250=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ASCII=m
-CONFIG_NLS_ISO8859_1=m
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_NLS_UTF8=m
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_DEBUG_LL=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_TEST=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_CAMELLIA=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_LIBCRC32C=m
diff --git a/arch/arm/configs/yl9200_defconfig b/arch/arm/configs/yl9200_defconfig
deleted file mode 100644 (file)
index 30c537f..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91RM9200DK=y
-CONFIG_MACH_YL9200=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20410000,3145728 root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_COMPLEX_MAPPINGS=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PLATRAM=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_MTD_NAND_PLATFORM=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=3
-CONFIG_BLK_DEV_RAM_SIZE=8192
-# CONFIG_MISC_DEVICES is not set
-CONFIG_BLK_DEV_SD=y
-CONFIG_ATA=y
-CONFIG_NETDEVICES=y
-CONFIG_PHYLIB=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_ARM_AT91_ETHER=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
-CONFIG_INPUT_EVDEV=y
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_GPIO=y
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_ADS7846=y
-# CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_SPI=y
-CONFIG_SPI_DEBUG=y
-CONFIG_SPI_ATMEL=y
-CONFIG_FB=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_LCD_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_DISPLAY_SUPPORT=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_VGA16 is not set
-CONFIG_USB=y
-CONFIG_USB_DEBUG=y
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_DEVICE_CLASS is not set
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_M66592=y
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_MMC=y
-CONFIG_MMC_DEBUG=y
-# CONFIG_MMC_BLOCK_BOUNCE is not set
-CONFIG_MMC_AT91=m
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91RM9200=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT3_FS=y
-CONFIG_REISERFS_FS=y
-CONFIG_INOTIFY=y
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_UDF_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=1
-CONFIG_JFFS2_COMPRESSION_OPTIONS=y
-CONFIG_JFFS2_RUBIN=y
-CONFIG_CRAMFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAC_PARTITION=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ISO8859_1=y
-# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_SLUB_DEBUG_ON=y
-CONFIG_DEBUG_KOBJECT=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_LIST=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_DEBUG_LL=y
index 062b58c029ab92ceb23cf0616568a76d3ec3a6b1..749bb6622404b3aed8e9234d2c8ff67e13a731b1 100644 (file)
        @ Slightly optimised to avoid incrementing the pointer twice
        usraccoff \instr, \reg, \ptr, \inc, 0, \cond, \abort
        .if     \rept == 2
-       usraccoff \instr, \reg, \ptr, \inc, 4, \cond, \abort
+       usraccoff \instr, \reg, \ptr, \inc, \inc, \cond, \abort
        .endif
 
        add\cond \ptr, #\rept * \inc
index 68870c7766712a4778b32278e64f82484d12f5e5..b4ffe9d5b5262bbdf01f82218144d74d0823005c 100644 (file)
@@ -13,6 +13,10 @@ typedef struct {
 
 #ifdef CONFIG_CPU_HAS_ASID
 #define ASID(mm)       ((mm)->context.id & 255)
+
+/* init_mm.context.id_lock should be initialized. */
+#define INIT_MM_CONTEXT(name)                                                 \
+       .context.id_lock    = __SPIN_LOCK_UNLOCKED(name.context.id_lock),
 #else
 #define ASID(mm)       (0)
 #endif
index b155414192daea110acf0f890a6f3d139ceef182..53d1d5deb1115b1fe11a52846e62679573534d24 100644 (file)
@@ -374,6 +374,9 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd)
 
 #define pmd_page(pmd)          pfn_to_page(__phys_to_pfn(pmd_val(pmd)))
 
+/* we don't need complex calculations here as the pmd is folded into the pgd */
+#define pmd_addr_end(addr,end) (end)
+
 /*
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
index c09e3573c5deb5795042eb1073f210472b0eadbc..bb96a7d4bbf55464a4069830657334e23fa72449 100644 (file)
@@ -911,7 +911,7 @@ __kuser_cmpxchg:                            @ 0xffff0fc0
         * A special ghost syscall is used for that (see traps.c).
         */
        stmfd   sp!, {r7, lr}
-       ldr     r7, =1f                 @ it's 20 bits
+       ldr     r7, 1f                  @ it's 20 bits
        swi     __ARM_NR_cmpxchg
        ldmfd   sp!, {r7, pc}
 1:     .word   __ARM_NR_cmpxchg
index dd6b369ac69cae5c86dca1e30edd4574b80a2052..6bd82d25683c3a81946d072825cef42f25628643 100644 (file)
@@ -85,9 +85,11 @@ ENTRY(stext)
        mrc     p15, 0, r9, c0, c0              @ get processor id
        bl      __lookup_processor_type         @ r5=procinfo r9=cpuid
        movs    r10, r5                         @ invalid processor (r5=0)?
+ THUMB( it     eq )            @ force fixup-able long branch encoding
        beq     __error_p                       @ yes, error 'p'
        bl      __lookup_machine_type           @ r5=machinfo
        movs    r8, r5                          @ invalid machine (r5=0)?
+ THUMB( it     eq )            @ force fixup-able long branch encoding
        beq     __error_a                       @ yes, error 'a'
        bl      __vet_atags
 #ifdef CONFIG_SMP_ON_UP
@@ -262,6 +264,7 @@ __create_page_tables:
        mov     pc, lr
 ENDPROC(__create_page_tables)
        .ltorg
+       .align
 __enable_mmu_loc:
        .long   .
        .long   __enable_mmu
@@ -282,6 +285,7 @@ ENTRY(secondary_startup)
        bl      __lookup_processor_type
        movs    r10, r5                         @ invalid processor?
        moveq   r0, #'p'                        @ yes, error 'p'
+ THUMB( it     eq )            @ force fixup-able long branch encoding
        beq     __error_p
 
        /*
@@ -308,6 +312,8 @@ ENTRY(__secondary_switched)
        b       secondary_start_kernel
 ENDPROC(__secondary_switched)
 
+       .align
+
        .type   __secondary_data, %object
 __secondary_data:
        .long   .
@@ -413,6 +419,7 @@ __fixup_smp_on_up:
        mov     pc, lr
 ENDPROC(__fixup_smp)
 
+       .align
 1:     .word   .
        .word   __smpalt_begin
        .word   __smpalt_end
index fd26f8d65151a949e6ecff394f0146258882b9d6..9cf4cbf8f95b8ca9eef1baf1d8f49054999304f8 100644 (file)
@@ -59,6 +59,8 @@ relocate_new_kernel:
        ldr r2,kexec_boot_atags
        mov pc,lr
 
+       .align
+
        .globl kexec_start_address
 kexec_start_address:
        .long   0x0
index 1e4cbd4e7be930f2515bece2a19c23f2f2a07845..64f6bc1a91326c79800bbb9205645a7d0e7e5e0c 100644 (file)
@@ -174,8 +174,8 @@ ENDPROC(_find_next_bit_be)
  */
 .L_found:
 #if __LINUX_ARM_ARCH__ >= 5
-               rsb     r1, r3, #0
-               and     r3, r3, r1
+               rsb     r0, r3, #0
+               and     r3, r3, r0
                clz     r3, r3
                rsb     r3, r3, #31
                add     r0, r2, r3
@@ -190,5 +190,7 @@ ENDPROC(_find_next_bit_be)
                addeq   r2, r2, #1
                mov     r0, r2
 #endif
+               cmp     r1, r0                  @ Clamp to maxbit
+               movlo   r0, r1
                mov     pc, lr
 
index cff4e0a996ce992953780bc1af4f11d72aff34f3..a6299e8321bd9258772cb96c80b4fddb170fa047 100644 (file)
@@ -11,6 +11,6 @@
 #ifndef __ASM_ARCH_VMALLOC_H
 #define __ASM_ARCH_VMALLOC_H
 
-#define VMALLOC_END            0xd0000000
+#define VMALLOC_END            0xd0000000UL
 
 #endif /* __ASM_ARCH_VMALLOC_H */
index 821eb842795f137d94a2904ffe5d1db827dca4bf..d13add71f72accab27ae6abade209d8fad2259f9 100644 (file)
@@ -24,8 +24,8 @@ obj-$(CONFIG_ARCH_AT91X40)    += at91x40.o at91x40_time.o
 
 # AT91RM9200 board-specific support
 obj-$(CONFIG_MACH_ONEARM)      += board-1arm.o
-obj-$(CONFIG_ARCH_AT91RM9200DK)        += board-dk.o
-obj-$(CONFIG_MACH_AT91RM9200EK)        += board-ek.o
+obj-$(CONFIG_ARCH_AT91RM9200DK)        += board-rm9200dk.o
+obj-$(CONFIG_MACH_AT91RM9200EK)        += board-rm9200ek.o
 obj-$(CONFIG_MACH_CSB337)      += board-csb337.o
 obj-$(CONFIG_MACH_CSB637)      += board-csb637.o
 obj-$(CONFIG_MACH_CARMEVA)     += board-carmeva.o
@@ -65,7 +65,7 @@ obj-$(CONFIG_MACH_AT91SAM9G20EK) += board-sam9g20ek.o
 obj-$(CONFIG_MACH_CPU9G20)     += board-cpu9krea.o
 obj-$(CONFIG_MACH_STAMP9G20)   += board-stamp9g20.o
 obj-$(CONFIG_MACH_PORTUXG20)   += board-stamp9g20.o
-obj-$(CONFIG_MACH_PCONTROL_G20)        += board-pcontrol-g20.o
+obj-$(CONFIG_MACH_PCONTROL_G20)        += board-pcontrol-g20.o board-stamp9g20.o
 
 # AT91SAM9260/AT91SAM9G20 board-specific support
 obj-$(CONFIG_MACH_SNAPPER_9260)        += board-snapper9260.o
index 9338825cfcd7c1613337738ca4145e884a88a7ec..7b539228e0efb324b258d8e247c1e14c060fb30a 100644 (file)
@@ -1106,51 +1106,6 @@ static inline void configure_usart3_pins(unsigned pins)
 static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART];  /* the UARTs to use */
 struct platform_device *atmel_default_console_device;  /* the serial console device */
 
-void __init __deprecated at91_init_serial(struct at91_uart_config *config)
-{
-       int i;
-
-       /* Fill in list of supported UARTs */
-       for (i = 0; i < config->nr_tty; i++) {
-               switch (config->tty_map[i]) {
-                       case 0:
-                               configure_usart0_pins(ATMEL_UART_CTS | ATMEL_UART_RTS);
-                               at91_uarts[i] = &at91rm9200_uart0_device;
-                               at91_clock_associate("usart0_clk", &at91rm9200_uart0_device.dev, "usart");
-                               break;
-                       case 1:
-                               configure_usart1_pins(ATMEL_UART_CTS | ATMEL_UART_RTS | ATMEL_UART_DSR | ATMEL_UART_DTR | ATMEL_UART_DCD | ATMEL_UART_RI);
-                               at91_uarts[i] = &at91rm9200_uart1_device;
-                               at91_clock_associate("usart1_clk", &at91rm9200_uart1_device.dev, "usart");
-                               break;
-                       case 2:
-                               configure_usart2_pins(0);
-                               at91_uarts[i] = &at91rm9200_uart2_device;
-                               at91_clock_associate("usart2_clk", &at91rm9200_uart2_device.dev, "usart");
-                               break;
-                       case 3:
-                               configure_usart3_pins(0);
-                               at91_uarts[i] = &at91rm9200_uart3_device;
-                               at91_clock_associate("usart3_clk", &at91rm9200_uart3_device.dev, "usart");
-                               break;
-                       case 4:
-                               configure_dbgu_pins();
-                               at91_uarts[i] = &at91rm9200_dbgu_device;
-                               at91_clock_associate("mck", &at91rm9200_dbgu_device.dev, "usart");
-                               break;
-                       default:
-                               continue;
-               }
-               at91_uarts[i]->id = i;          /* update ID number to mapped ID */
-       }
-
-       /* Set serial console device */
-       if (config->console_tty < ATMEL_MAX_UART)
-               atmel_default_console_device = at91_uarts[config->console_tty];
-       if (!atmel_default_console_device)
-               printk(KERN_INFO "AT91: No default serial console defined.\n");
-}
-
 void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
 {
        struct platform_device *pdev;
index 46bdc82d3fbf9985310db451bb2cf8a6eb4b81f7..8a3fc84847c120b42980298067f74d8b3abc00fc 100644 (file)
 #include "generic.h"
 
 
-/*
- * Serial port configuration.
- *    0 .. 3 = USART0 .. USART3
- *    4      = DBGU
- */
-static struct at91_uart_config __initdata onearm_uart_config = {
-       .console_tty    = 0,                            /* ttyS0 */
-       .nr_tty         = 3,
-       .tty_map        = { 4, 0, 1, -1, -1 },          /* ttyS0, ..., ttyS4 */
-};
-
 static void __init onearm_map_io(void)
 {
        /* Initialize processor: 18.432 MHz crystal */
        at91rm9200_initialize(18432000, AT91RM9200_PQFP);
 
-       /* Setup the serial ports and console */
-       at91_init_serial(&onearm_uart_config);
+       /* DBGU on ttyS0. (Rx & Tx only) */
+       at91_register_uart(0, 0, 0);
+
+       /* USART0 on ttyS1 (Rx, Tx, CTS, RTS) */
+       at91_register_uart(AT91RM9200_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
+
+       /* USART1 on ttyS2 (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+       at91_register_uart(AT91RM9200_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS
+                          | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
+                          | ATMEL_UART_RI);
+
+       /* set serial console to ttyS0 (ie, DBGU) */
+       at91_set_serial_console(0);
 }
 
 static void __init onearm_init_irq(void)
index c0ce79d431a0c1f3424b232e6a746b40c9f5dc5c..d2e1f4ec1fcc87dcc6aca97d6a664af6ed637d36 100644 (file)
 #include "generic.h"
 
 
-/*
- * Serial port configuration.
- *    0 .. 3 = USART0 .. USART3
- *    4      = DBGU
- */
-static struct at91_uart_config __initdata kafa_uart_config = {
-       .console_tty    = 0,                            /* ttyS0 */
-       .nr_tty         = 2,
-       .tty_map        = { 4, 0, -1, -1, -1 }          /* ttyS0, ..., ttyS4 */
-};
-
 static void __init kafa_map_io(void)
 {
        /* Initialize processor: 18.432 MHz crystal */
@@ -58,8 +47,14 @@ static void __init kafa_map_io(void)
        /* Set up the LEDs */
        at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4);
 
-       /* Setup the serial ports and console */
-       at91_init_serial(&kafa_uart_config);
+       /* DBGU on ttyS0. (Rx & Tx only) */
+       at91_register_uart(0, 0, 0);
+
+       /* USART0 on ttyS1 (Rx, Tx, CTS, RTS) */
+       at91_register_uart(AT91RM9200_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
+
+       /* set serial console to ttyS0 (ie, DBGU) */
+       at91_set_serial_console(0);
 }
 
 static void __init kafa_init_irq(void)
index bba5a560e02b8c829304ffdded29038760167cdd..feb65787c30be5502985a112e4b200d0f7de8ac0 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <mach/board.h>
 #include <mach/at91sam9_smc.h>
+#include <mach/stamp9g20.h>
 
 #include "sam9_smc.h"
 #include "generic.h"
 
 static void __init pcontrol_g20_map_io(void)
 {
-       /* Initialize processor: 18.432 MHz crystal */
-       at91sam9260_initialize(18432000);
-
-       /* DGBU on ttyS0. (Rx, Tx) only TTL -> JTAG connector X7 17,19 ) */
-       at91_register_uart(0, 0, 0);
+       stamp9g20_map_io();
 
        /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) piggyback  A2 */
        at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS
@@ -54,9 +51,6 @@ static void __init pcontrol_g20_map_io(void)
 
        /* USART2 on ttyS3. (Rx, Tx)  9bit-Bus  Multidrop-mode  X4 */
        at91_register_uart(AT91SAM9260_ID_US4, 3, 0);
-
-       /* set serial console to ttyS0 (ie, DBGU) */
-       at91_set_serial_console(0);
 }
 
 
@@ -66,38 +60,6 @@ static void __init init_irq(void)
 }
 
 
-/*
- * NAND flash 512MiB 1,8V 8-bit, sector size 128 KiB
- */
-static struct atmel_nand_data __initdata nand_data = {
-       .ale            = 21,
-       .cle            = 22,
-       .rdy_pin        = AT91_PIN_PC13,
-       .enable_pin     = AT91_PIN_PC14,
-};
-
-/*
- * Bus timings; unit = 7.57ns
- */
-static struct sam9_smc_config __initdata nand_smc_config = {
-       .ncs_read_setup         = 0,
-       .nrd_setup              = 2,
-       .ncs_write_setup        = 0,
-       .nwe_setup              = 2,
-
-       .ncs_read_pulse         = 4,
-       .nrd_pulse              = 4,
-       .ncs_write_pulse        = 4,
-       .nwe_pulse              = 4,
-
-       .read_cycle             = 7,
-       .write_cycle            = 7,
-
-       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE
-                       | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
-       .tdf_cycles             = 3,
-};
-
 static struct sam9_smc_config __initdata pcontrol_smc_config[2] = { {
        .ncs_read_setup         = 16,
        .nrd_setup              = 18,
@@ -138,14 +100,6 @@ static struct sam9_smc_config __initdata pcontrol_smc_config[2] = { {
        .tdf_cycles             = 1,
 } };
 
-static void __init add_device_nand(void)
-{
-       /* configure chip-select 3 (NAND) */
-       sam9_smc_configure(3, &nand_smc_config);
-       at91_add_device_nand(&nand_data);
-}
-
-
 static void __init add_device_pcontrol(void)
 {
        /* configure chip-select 4 (IO compatible to 8051  X4 ) */
@@ -155,23 +109,6 @@ static void __init add_device_pcontrol(void)
 }
 
 
-/*
- * MCI (SD/MMC)
- * det_pin, wp_pin and vcc_pin are not connected
- */
-#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
-static struct mci_platform_data __initdata mmc_data = {
-       .slot[0] = {
-               .bus_width      = 4,
-       },
-};
-#else
-static struct at91_mmc_data __initdata mmc_data = {
-       .wire4          = 1,
-};
-#endif
-
-
 /*
  * USB Host port
  */
@@ -265,42 +202,13 @@ static struct spi_board_info pcontrol_g20_spi_devices[] = {
 };
 
 
-/*
- * Dallas 1-Wire  DS2431
- */
-static struct w1_gpio_platform_data w1_gpio_pdata = {
-       .pin            = AT91_PIN_PA29,
-       .is_open_drain  = 1,
-};
-
-static struct platform_device w1_device = {
-       .name                   = "w1-gpio",
-       .id                     = -1,
-       .dev.platform_data      = &w1_gpio_pdata,
-};
-
-static void add_wire1(void)
-{
-       at91_set_GPIO_periph(w1_gpio_pdata.pin, 1);
-       at91_set_multi_drive(w1_gpio_pdata.pin, 1);
-       platform_device_register(&w1_device);
-}
-
-
 static void __init pcontrol_g20_board_init(void)
 {
-       at91_add_device_serial();
-       add_device_nand();
-#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
-       at91_add_device_mci(0, &mmc_data);
-#else
-       at91_add_device_mmc(0, &mmc_data);
-#endif
+       stamp9g20_board_init();
        at91_add_device_usbh(&usbh_data);
        at91_add_device_eth(&macb_data);
        at91_add_device_i2c(pcontrol_g20_i2c_devices,
                ARRAY_SIZE(pcontrol_g20_i2c_devices));
-       add_wire1();
        add_device_pcontrol();
        at91_add_device_spi(pcontrol_g20_spi_devices,
                ARRAY_SIZE(pcontrol_g20_spi_devices));
index 9d833bbc592dcf3c10cfd4233140dd0ec34db8ff..55dad3a46547288cba52ed6debc5d384f55bc8e1 100644 (file)
 #include "generic.h"
 
 
-/*
- * Serial port configuration.
- *    0 .. 3 = USART0 .. USART3
- *    4      = DBGU
- */
-static struct at91_uart_config __initdata picotux200_uart_config = {
-       .console_tty    = 0,                            /* ttyS0 */
-       .nr_tty         = 2,
-       .tty_map        = { 4, 1, -1, -1, -1 }          /* ttyS0, ..., ttyS4 */
-};
-
 static void __init picotux200_map_io(void)
 {
        /* Initialize processor: 18.432 MHz crystal */
        at91rm9200_initialize(18432000, AT91RM9200_BGA);
 
-       /* Setup the serial ports and console */
-       at91_init_serial(&picotux200_uart_config);
+       /* DBGU on ttyS0. (Rx & Tx only) */
+       at91_register_uart(0, 0, 0);
+
+       /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+       at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+                         | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
+                         | ATMEL_UART_RI);
+
+       /* set serial console to ttyS0 (ie, DBGU) */
+       at91_set_serial_console(0);
 }
 
 static void __init picotux200_init_irq(void)
@@ -77,11 +74,6 @@ static struct at91_usbh_data __initdata picotux200_usbh_data = {
        .ports          = 1,
 };
 
-// static struct at91_udc_data __initdata picotux200_udc_data = {
-//     .vbus_pin       = AT91_PIN_PD4,
-//     .pullup_pin     = AT91_PIN_PD5,
-// };
-
 static struct at91_mmc_data __initdata picotux200_mmc_data = {
        .det_pin        = AT91_PIN_PB27,
        .slot_b         = 0,
@@ -89,21 +81,6 @@ static struct at91_mmc_data __initdata picotux200_mmc_data = {
        .wp_pin         = AT91_PIN_PA17,
 };
 
-// static struct spi_board_info picotux200_spi_devices[] = {
-//     {       /* DataFlash chip */
-//             .modalias       = "mtd_dataflash",
-//             .chip_select    = 0,
-//             .max_speed_hz   = 15 * 1000 * 1000,
-//     },
-// #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
-//     {       /* DataFlash card */
-//             .modalias       = "mtd_dataflash",
-//             .chip_select    = 3,
-//             .max_speed_hz   = 15 * 1000 * 1000,
-//     },
-// #endif
-// };
-
 #define PICOTUX200_FLASH_BASE  AT91_CHIPSELECT_0
 #define PICOTUX200_FLASH_SIZE  SZ_4M
 
@@ -135,21 +112,11 @@ static void __init picotux200_board_init(void)
        at91_add_device_eth(&picotux200_eth_data);
        /* USB Host */
        at91_add_device_usbh(&picotux200_usbh_data);
-       /* USB Device */
-       // at91_add_device_udc(&picotux200_udc_data);
-       // at91_set_multi_drive(picotux200_udc_data.pullup_pin, 1);     /* pullup_pin is connected to reset */
        /* I2C */
        at91_add_device_i2c(NULL, 0);
-       /* SPI */
-       // at91_add_device_spi(picotux200_spi_devices, ARRAY_SIZE(picotux200_spi_devices));
-#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
-       /* DataFlash card */
-       at91_set_gpio_output(AT91_PIN_PB22, 0);
-#else
        /* MMC */
        at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */
        at91_add_device_mmc(0, &picotux200_mmc_data);
-#endif
        /* NOR Flash */
        platform_device_register(&picotux200_flash);
 }
similarity index 98%
rename from arch/arm/mach-at91/board-dk.c
rename to arch/arm/mach-at91/board-rm9200dk.c
index e14f0e165680ed39b5a9be326e661b9b415cb1bd..4c1047c8200df94466a81337779a4cfcfb1c7d7a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-at91/board-dk.c
+ * linux/arch/arm/mach-at91/board-rm9200dk.c
  *
  *  Copyright (C) 2005 SAN People
  *
@@ -91,10 +91,12 @@ static struct at91_cf_data __initdata dk_cf_data = {
        // .vcc_pin     = ... always powered
 };
 
+#ifndef CONFIG_MTD_AT91_DATAFLASH_CARD
 static struct at91_mmc_data __initdata dk_mmc_data = {
        .slot_b         = 0,
        .wire4          = 1,
 };
+#endif
 
 static struct spi_board_info dk_spi_devices[] = {
        {       /* DataFlash chip */
similarity index 98%
rename from arch/arm/mach-at91/board-ek.c
rename to arch/arm/mach-at91/board-rm9200ek.c
index 56e92c4bbc2a3222c87ddda4c178b13b33bb75dc..9df1be8818c0bdf8eb9ff47086e0a68ee7c21294 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-at91/board-ek.c
+ * linux/arch/arm/mach-at91/board-rm9200ek.c
  *
  *  Copyright (C) 2005 SAN People
  *
@@ -84,12 +84,14 @@ static struct at91_udc_data __initdata ek_udc_data = {
        .pullup_pin     = AT91_PIN_PD5,
 };
 
+#ifndef CONFIG_MTD_AT91_DATAFLASH_CARD
 static struct at91_mmc_data __initdata ek_mmc_data = {
        .det_pin        = AT91_PIN_PB27,
        .slot_b         = 0,
        .wire4          = 1,
        .wp_pin         = AT91_PIN_PA17,
 };
+#endif
 
 static struct spi_board_info ek_spi_devices[] = {
        {       /* DataFlash chip */
index 5206eef4a67eba12e1b22bd7ae0faa48ce29271a..f8902b118960d84f4d9bf6c57d3a28e9c302df64 100644 (file)
@@ -32,7 +32,7 @@
 #include "generic.h"
 
 
-static void __init portuxg20_map_io(void)
+void __init stamp9g20_map_io(void)
 {
        /* Initialize processor: 18.432 MHz crystal */
        at91sam9260_initialize(18432000);
@@ -40,6 +40,24 @@ static void __init portuxg20_map_io(void)
        /* DGBU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
 
+       /* set serial console to ttyS0 (ie, DBGU) */
+       at91_set_serial_console(0);
+}
+
+static void __init stamp9g20evb_map_io(void)
+{
+       stamp9g20_map_io();
+
+       /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+       at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+                                               | ATMEL_UART_DTR | ATMEL_UART_DSR
+                                               | ATMEL_UART_DCD | ATMEL_UART_RI);
+}
+
+static void __init portuxg20_map_io(void)
+{
+       stamp9g20_map_io();
+
        /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
        at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
                                                | ATMEL_UART_DTR | ATMEL_UART_DSR
@@ -56,26 +74,6 @@ static void __init portuxg20_map_io(void)
 
        /* USART5 on ttyS6. (Rx, Tx only) */
        at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
-
-       /* set serial console to ttyS0 (ie, DBGU) */
-       at91_set_serial_console(0);
-}
-
-static void __init stamp9g20_map_io(void)
-{
-       /* Initialize processor: 18.432 MHz crystal */
-       at91sam9260_initialize(18432000);
-
-       /* DGBU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-
-       /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-       at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-                                               | ATMEL_UART_DTR | ATMEL_UART_DSR
-                                               | ATMEL_UART_DCD | ATMEL_UART_RI);
-
-       /* set serial console to ttyS0 (ie, DBGU) */
-       at91_set_serial_console(0);
 }
 
 static void __init init_irq(void)
@@ -156,7 +154,7 @@ static struct at91_udc_data __initdata portuxg20_udc_data = {
        .pullup_pin     = 0,            /* pull-up driven by UDC */
 };
 
-static struct at91_udc_data __initdata stamp9g20_udc_data = {
+static struct at91_udc_data __initdata stamp9g20evb_udc_data = {
        .vbus_pin       = AT91_PIN_PA22,
        .pullup_pin     = 0,            /* pull-up driven by UDC */
 };
@@ -190,7 +188,7 @@ static struct gpio_led portuxg20_leds[] = {
        }
 };
 
-static struct gpio_led stamp9g20_leds[] = {
+static struct gpio_led stamp9g20evb_leds[] = {
        {
                .name                   = "D8",
                .gpio                   = AT91_PIN_PB18,
@@ -250,7 +248,7 @@ void add_w1(void)
 }
 
 
-static void __init generic_board_init(void)
+void __init stamp9g20_board_init(void)
 {
        /* Serial */
        at91_add_device_serial();
@@ -262,34 +260,40 @@ static void __init generic_board_init(void)
 #else
        at91_add_device_mmc(0, &mmc_data);
 #endif
-       /* USB Host */
-       at91_add_device_usbh(&usbh_data);
-       /* Ethernet */
-       at91_add_device_eth(&macb_data);
-       /* I2C */
-       at91_add_device_i2c(NULL, 0);
        /* W1 */
        add_w1();
 }
 
 static void __init portuxg20_board_init(void)
 {
-       generic_board_init();
-       /* SPI */
-       at91_add_device_spi(portuxg20_spi_devices, ARRAY_SIZE(portuxg20_spi_devices));
+       stamp9g20_board_init();
+       /* USB Host */
+       at91_add_device_usbh(&usbh_data);
        /* USB Device */
        at91_add_device_udc(&portuxg20_udc_data);
+       /* Ethernet */
+       at91_add_device_eth(&macb_data);
+       /* I2C */
+       at91_add_device_i2c(NULL, 0);
+       /* SPI */
+       at91_add_device_spi(portuxg20_spi_devices, ARRAY_SIZE(portuxg20_spi_devices));
        /* LEDs */
        at91_gpio_leds(portuxg20_leds, ARRAY_SIZE(portuxg20_leds));
 }
 
-static void __init stamp9g20_board_init(void)
+static void __init stamp9g20evb_board_init(void)
 {
-       generic_board_init();
+       stamp9g20_board_init();
+       /* USB Host */
+       at91_add_device_usbh(&usbh_data);
        /* USB Device */
-       at91_add_device_udc(&stamp9g20_udc_data);
+       at91_add_device_udc(&stamp9g20evb_udc_data);
+       /* Ethernet */
+       at91_add_device_eth(&macb_data);
+       /* I2C */
+       at91_add_device_i2c(NULL, 0);
        /* LEDs */
-       at91_gpio_leds(stamp9g20_leds, ARRAY_SIZE(stamp9g20_leds));
+       at91_gpio_leds(stamp9g20evb_leds, ARRAY_SIZE(stamp9g20evb_leds));
 }
 
 MACHINE_START(PORTUXG20, "taskit PortuxG20")
@@ -305,7 +309,7 @@ MACHINE_START(STAMP9G20, "taskit Stamp9G20")
        /* Maintainer: taskit GmbH */
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91sam926x_timer,
-       .map_io         = stamp9g20_map_io,
+       .map_io         = stamp9g20evb_map_io,
        .init_irq       = init_irq,
-       .init_machine   = stamp9g20_board_init,
+       .init_machine   = stamp9g20evb_board_init,
 MACHINE_END
index 89df00a9d2f72bfd768df2986db8d792fcd3c3d2..e0f0080eb639f30137d8aca6631271ad82dc639e 100644 (file)
@@ -387,7 +387,7 @@ static struct spi_board_info yl9200_spi_devices[] = {
  * EPSON S1D13806 FB (discontinued chip)
  * EPSON S1D13506 FB
  */
-#if defined(CONFIG_FB_S1D135XX) || defined(CONFIG_FB_S1D13XXX_MODULE)
+#if defined(CONFIG_FB_S1D13XXX) || defined(CONFIG_FB_S1D13XXX_MODULE)
 #include <video/s1d13xxxfb.h>
 
 
index 7525cee3983f7252fac0542be5955a490ca6869b..9113da6845f17482437ed984bd978b9b28378dfe 100644 (file)
@@ -658,7 +658,7 @@ static void __init at91_upll_usbfs_clock_init(unsigned long main_clock)
        /* Now set uhpck values */
        uhpck.parent = &utmi_clk;
        uhpck.pmc_mask = AT91SAM926x_PMC_UHP;
-       uhpck.rate_hz = utmi_clk.parent->rate_hz;
+       uhpck.rate_hz = utmi_clk.rate_hz;
        uhpck.rate_hz /= 1 + ((at91_sys_read(AT91_PMC_USB) & AT91_PMC_OHCIUSBDIV) >> 8);
 }
 
index 58528aa9c8a86ddea8286cfb9ebdac7e26ed6942..2b499eb343a12a082ad5d0a862c0fb3fb9e722a5 100644 (file)
@@ -137,13 +137,7 @@ extern void __init at91_add_device_spi(struct spi_board_info *devices, int nr_de
 extern void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins);
 extern void __init at91_set_serial_console(unsigned portnr);
 
-struct at91_uart_config {
-       unsigned short  console_tty;    /* tty number of serial console */
-       unsigned short  nr_tty;         /* number of serial tty's */
-       short           tty_map[];      /* map UART to tty number */
-};
 extern struct platform_device *atmel_default_console_device;
-extern void __init __deprecated at91_init_serial(struct at91_uart_config *config);
 
 struct atmel_uart_data {
        short                   use_dma_tx;     /* use transmit DMA? */
diff --git a/arch/arm/mach-at91/include/mach/stamp9g20.h b/arch/arm/mach-at91/include/mach/stamp9g20.h
new file mode 100644 (file)
index 0000000..6120f9c
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __MACH_STAMP9G20_H
+#define __MACH_STAMP9G20_H
+
+void stamp9g20_map_io(void);
+void stamp9g20_board_init(void);
+
+#endif
index 3db3a09fd3986e7ee452997e75a13180a38475b1..7397bd7817d977db8283291d4544aeb2f3d9833d 100644 (file)
@@ -22,4 +22,4 @@
  * 0xe0000000 to 0xefffffff. This gives us 256 MB of vm space and handles
  * larger physical memory designs better.
  */
-#define VMALLOC_END       0xf0000000
+#define VMALLOC_END       0xf0000000UL
index 30b3a287ed8865d897adccbfb2f318cfa4212e9b..467b96137e47fabddd4cafd9463a0d0abcac1a37 100644 (file)
@@ -17,4 +17,4 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#define VMALLOC_END       0xd0000000
+#define VMALLOC_END       0xd0000000UL
index 38088c36936c7d97960ababadc2716050238f055..78defd71a8295423775d9316670491cb0031b2ca 100644 (file)
@@ -369,7 +369,7 @@ static int __init cns3xxx_pcie_init(void)
 {
        int i;
 
-       hook_fault_code(16 + 6, cns3xxx_pcie_abort_handler, SIGBUS,
+       hook_fault_code(16 + 6, cns3xxx_pcie_abort_handler, SIGBUS, 0,
                        "imprecise external abort");
 
        for (i = 0; i < ARRAY_SIZE(cns3xxx_pcie); i++) {
index 9be261beae7ddb2a72e2e9a76d9dbf2e2bf51316..2652af124acd941bcb2f7d5bcefa88fe8a0721a2 100644 (file)
@@ -359,8 +359,8 @@ static struct clk_lookup dm355_clks[] = {
        CLK(NULL, "uart1", &uart1_clk),
        CLK(NULL, "uart2", &uart2_clk),
        CLK("i2c_davinci.1", NULL, &i2c_clk),
-       CLK("davinci-asp.0", NULL, &asp0_clk),
-       CLK("davinci-asp.1", NULL, &asp1_clk),
+       CLK("davinci-mcbsp.0", NULL, &asp0_clk),
+       CLK("davinci-mcbsp.1", NULL, &asp1_clk),
        CLK("davinci_mmc.0", NULL, &mmcsd0_clk),
        CLK("davinci_mmc.1", NULL, &mmcsd1_clk),
        CLK("spi_davinci.0", NULL, &spi0_clk),
@@ -664,7 +664,7 @@ static struct resource dm355_asp1_resources[] = {
 };
 
 static struct platform_device dm355_asp1_device = {
-       .name           = "davinci-asp",
+       .name           = "davinci-mcbsp",
        .id             = 1,
        .num_resources  = ARRAY_SIZE(dm355_asp1_resources),
        .resource       = dm355_asp1_resources,
index a12065e87266669a9d66f72bb21a9b4207aca4d2..c466d710d3c103cef9f64445f2e994bcdb4551ca 100644 (file)
@@ -459,7 +459,7 @@ static struct clk_lookup dm365_clks[] = {
        CLK(NULL, "usb", &usb_clk),
        CLK("davinci_emac.1", NULL, &emac_clk),
        CLK("davinci_voicecodec", NULL, &voicecodec_clk),
-       CLK("davinci-asp.0", NULL, &asp0_clk),
+       CLK("davinci-mcbsp", NULL, &asp0_clk),
        CLK(NULL, "rto", &rto_clk),
        CLK(NULL, "mjcp", &mjcp_clk),
        CLK(NULL, NULL, NULL),
@@ -922,8 +922,8 @@ static struct resource dm365_asp_resources[] = {
 };
 
 static struct platform_device dm365_asp_device = {
-       .name           = "davinci-asp",
-       .id             = 0,
+       .name           = "davinci-mcbsp",
+       .id             = -1,
        .num_resources  = ARRAY_SIZE(dm365_asp_resources),
        .resource       = dm365_asp_resources,
 };
index 0608dd776a16ca3fd966e02b22f93804f812e618..9a2376b3137ccd57532d0d5d6c1432d3e7c23801 100644 (file)
@@ -302,7 +302,7 @@ static struct clk_lookup dm644x_clks[] = {
        CLK("davinci_emac.1", NULL, &emac_clk),
        CLK("i2c_davinci.1", NULL, &i2c_clk),
        CLK("palm_bk3710", NULL, &ide_clk),
-       CLK("davinci-asp", NULL, &asp_clk),
+       CLK("davinci-mcbsp", NULL, &asp_clk),
        CLK("davinci_mmc.0", NULL, &mmcsd_clk),
        CLK(NULL, "spi", &spi_clk),
        CLK(NULL, "gpio", &gpio_clk),
@@ -580,7 +580,7 @@ static struct resource dm644x_asp_resources[] = {
 };
 
 static struct platform_device dm644x_asp_device = {
-       .name           = "davinci-asp",
+       .name           = "davinci-mcbsp",
        .id             = -1,
        .num_resources  = ARRAY_SIZE(dm644x_asp_resources),
        .resource       = dm644x_asp_resources,
index 60bde56fba4cf3e4ef90cea65ceb2bf8e2db3111..ea141b7a3e03369978934c837153d8da060074a2 100644 (file)
@@ -7,4 +7,4 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#define VMALLOC_END       0xdf000000
+#define VMALLOC_END       0xdf000000UL
index 0ffbb7c85e59e738ce5d1966788ae72f52252ffe..40ba78e5782bb7b236647d53a80722b36c20972c 100644 (file)
@@ -7,4 +7,4 @@
  */
 
 
-#define VMALLOC_END       0xf0000000
+#define VMALLOC_END       0xf0000000UL
index a45915b88756d4e8e786e653bba677c5e36488b0..8520b4a4d4e6f3cd642c1a4b4aa44591f17c7787 100644 (file)
@@ -5,6 +5,6 @@
 #ifndef __ARCH_ARM_VMALLOC_H
 #define __ARCH_ARM_VMALLOC_H
 
-#define VMALLOC_END       0xd0000000
+#define VMALLOC_END       0xd0000000UL
 
 #endif
index 026263c665cae060cfca17ca86ad2fb36c8c2cad..7e1e9dc2c8fcefed05cd1d118d6f1fd16802917c 100644 (file)
@@ -250,9 +250,6 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
        .flags = IMXUART_HAVE_RTSCTS,
 };
 
-#if defined(CONFIG_TOUCHSCREEN_ADS7846) \
-       || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
-
 #define ADS7846_PENDOWN (GPIO_PORTD | 25)
 
 static void ads7846_dev_init(void)
@@ -273,9 +270,7 @@ static struct ads7846_platform_data ads7846_config __initdata = {
        .get_pendown_state      = ads7846_get_pendown_state,
        .keep_vref_on           = 1,
 };
-#endif
 
-#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
 static struct spi_board_info eukrea_mbimx27_spi_board_info[] __initdata = {
        [0] = {
                .modalias       = "ads7846",
@@ -294,7 +289,6 @@ static const struct spi_imx_master eukrea_mbimx27_spi0_data __initconst = {
        .chipselect     = eukrea_mbimx27_spi_cs,
        .num_chipselect = ARRAY_SIZE(eukrea_mbimx27_spi_cs),
 };
-#endif
 
 static struct i2c_board_info eukrea_mbimx27_i2c_devices[] = {
        {
index e056e7cf5645f8c936f4144f8d584f2772ae9bf2..2f5a2bafb11f144340d66e7fa823e1725ef0739a 100644 (file)
@@ -17,4 +17,4 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#define VMALLOC_END       0xd0000000
+#define VMALLOC_END       0xd0000000UL
index daf3993349f81986fa8f5b90ca0c4bcb4e7acc8a..2e3dd08ccc3f3f1d062eaac583b92109e39c31f4 100644 (file)
@@ -126,7 +126,6 @@ static APBC_CLK(twsi3, MMP2_TWSI3, 0, 26000000);
 static APBC_CLK(twsi4, MMP2_TWSI4, 0, 26000000);
 static APBC_CLK(twsi5, MMP2_TWSI5, 0, 26000000);
 static APBC_CLK(twsi6, MMP2_TWSI6, 0, 26000000);
-static APBC_CLK(rtc, MMP2_RTC, 0, 32768);
 
 static APMU_CLK(nand, NAND, 0xbf, 100000000);
 
index 31a32ad062dcd7eee3c280aa91e63c55ea11cf64..d138448eff16dd9720502c922b47a6ba617e2d81 100644 (file)
@@ -16,7 +16,7 @@
 #ifndef __ASM_ARCH_MSM_VMALLOC_H
 #define __ASM_ARCH_MSM_VMALLOC_H
 
-#define VMALLOC_END      0xd0000000
+#define VMALLOC_END      0xd0000000UL
 
 #endif
 
index 93afa10b13cf929de543f5f3eea3b51dead77629..d94d282fa6763c08bf09a2f0128e9de97099a92f 100644 (file)
@@ -42,9 +42,9 @@ extern const struct imx_mxc_nand_data imx25_mxc_nand_data __initconst;
 #define imx25_add_mxc_nand(pdata)      \
        imx_add_mxc_nand(&imx25_mxc_nand_data, pdata)
 
-extern const struct imx_spi_imx_data imx25_spi_imx_data[] __initconst;
+extern const struct imx_spi_imx_data imx25_cspi_data[] __initconst;
 #define imx25_add_spi_imx(id, pdata)   \
-       imx_add_spi_imx(&imx25_spi_imx_data[id], pdata)
+       imx_add_spi_imx(&imx25_cspi_data[id], pdata)
 #define imx25_add_spi_imx0(pdata)      imx25_add_spi_imx(0, pdata)
 #define imx25_add_spi_imx1(pdata)      imx25_add_spi_imx(1, pdata)
 #define imx25_add_spi_imx2(pdata)      imx25_add_spi_imx(2, pdata)
index 99e0894e07db320f3e4bbd668768b24803b62f1c..fda56545d2fd0e49de9b733477efff7d936593c0 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <mach/common.h>
 #include <mach/iomux-mx3.h>
+#include <mach/spi.h>
 
 #include <asm/mach-types.h>
 
@@ -59,14 +60,12 @@ static struct spi_board_info pcm037_spi_dev[] = {
 };
 
 /* Platform Data for MXC CSPI */
-#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
 static int pcm037_spi1_cs[] = {MXC_SPI_CS(1), IOMUX_TO_GPIO(MX31_PIN_KEY_COL7)};
 
 static const struct spi_imx_master pcm037_spi1_pdata __initconst = {
        .chipselect = pcm037_spi1_cs,
        .num_chipselect = ARRAY_SIZE(pcm037_spi1_cs),
 };
-#endif
 
 /* GPIO-keys input device */
 static struct gpio_keys_button pcm037_gpio_keys[] = {
@@ -171,7 +170,7 @@ static struct platform_device pcm037_gpio_keys_device = {
        },
 };
 
-static int eet_init_devices(void)
+static int __init eet_init_devices(void)
 {
        if (!machine_is_pcm037() || pcm037_variant() != PCM037_EET)
                return 0;
index 7cca3574308f0403a07c93edf6e427e6d29f0299..871f1ef7bff58ad30be02182a1547f0d9c761624 100644 (file)
@@ -16,4 +16,4 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#define VMALLOC_END       0xd0000000
+#define VMALLOC_END       0xd0000000UL
index b001f67d695b28e3ff6f10f16fd1842d7f3742fc..22ec4a4795777a711c1e19d2ba408c36ae136146 100644 (file)
@@ -17,4 +17,4 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
-#define VMALLOC_END    0xd8000000
+#define VMALLOC_END    0xd8000000UL
index 86c9b210295214c175638df2997745d2643cd447..9db9203667df504c5b5731680b3f75077ae79b6d 100644 (file)
@@ -216,7 +216,7 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
        {
                .name           = "wl1271",
                .mmc            = 3,
-               .caps           = MMC_CAP_4_BIT_DATA,
+               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD,
                .gpio_wp        = -EINVAL,
                .gpio_cd        = -EINVAL,
                .nonremovable   = true,
index 4da31e997efead8da47b602699a210f9127231b7..866319947760e179674331c6cb83f94e64670320 100644 (file)
@@ -17,4 +17,4 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
-#define VMALLOC_END      0xf8000000
+#define VMALLOC_END      0xf8000000UL
index 40562ddd3ee4fe29ea1e173a61d778225d28b01d..a1939b1e6f82e0d30ca77b8b4156c27eb6f1c4ce 100644 (file)
@@ -297,7 +297,7 @@ static int __init _omap2_init_reprogram_sdrc(void)
                return 0;
 
        dpll3_m2_ck = clk_get(NULL, "dpll3_m2_ck");
-       if (!dpll3_m2_ck)
+       if (IS_ERR(dpll3_m2_ck))
                return -EINVAL;
 
        rate = clk_get_rate(dpll3_m2_ck);
index 5e81517a7af2040a8bff6a2e2eabc9a96e300b76..a8afb610c7d83fa7a500445ea4647d4935d26e09 100644 (file)
@@ -161,6 +161,23 @@ void omap2_pm_dump(int mode, int resume, unsigned int us)
                printk(KERN_INFO "%-20s: 0x%08x\n", regs[i].name, regs[i].val);
 }
 
+void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds)
+{
+       u32 tick_rate, cycles;
+
+       if (!seconds && !milliseconds)
+               return;
+
+       tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer_wakeup));
+       cycles = tick_rate * seconds + tick_rate * milliseconds / 1000;
+       omap_dm_timer_stop(gptimer_wakeup);
+       omap_dm_timer_set_load_start(gptimer_wakeup, 0, 0xffffffff - cycles);
+
+       pr_info("PM: Resume timer in %u.%03u secs"
+               " (%d ticks at %d ticks/sec.)\n",
+               seconds, milliseconds, cycles, tick_rate);
+}
+
 #ifdef CONFIG_DEBUG_FS
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
@@ -354,23 +371,6 @@ void pm_dbg_update_time(struct powerdomain *pwrdm, int prev)
        pwrdm->timer = t;
 }
 
-void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds)
-{
-       u32 tick_rate, cycles;
-
-       if (!seconds && !milliseconds)
-               return;
-
-       tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer_wakeup));
-       cycles = tick_rate * seconds + tick_rate * milliseconds / 1000;
-       omap_dm_timer_stop(gptimer_wakeup);
-       omap_dm_timer_set_load_start(gptimer_wakeup, 0, 0xffffffff - cycles);
-
-       pr_info("PM: Resume timer in %u.%03u secs"
-               " (%d ticks at %d ticks/sec.)\n",
-               seconds, milliseconds, cycles, tick_rate);
-}
-
 static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user)
 {
        struct seq_file *s = (struct seq_file *)user;
index a40457d81927e256ec1f6af538acf038c7e11eb1..aaeea49b9bdd80f6e51affaee9c3a38ff6e2368f 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/irq.h>
 #include <linux/time.h>
 #include <linux/gpio.h>
+#include <linux/console.h>
 
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
 #include <plat/powerdomain.h>
 #include <plat/clockdomain.h>
 
+#ifdef CONFIG_SUSPEND
+static suspend_state_t suspend_state = PM_SUSPEND_ON;
+static inline bool is_suspending(void)
+{
+       return (suspend_state != PM_SUSPEND_ON);
+}
+#else
+static inline bool is_suspending(void)
+{
+       return false;
+}
+#endif
+
 static void (*omap2_sram_idle)(void);
 static void (*omap2_sram_suspend)(u32 dllctrl, void __iomem *sdrc_dlla_ctrl,
                                  void __iomem *sdrc_power);
@@ -118,6 +132,11 @@ static void omap2_enter_full_retention(void)
        if (omap_irq_pending())
                goto no_sleep;
 
+       /* Block console output in case it is on one of the OMAP UARTs */
+       if (!is_suspending())
+               if (try_acquire_console_sem())
+                       goto no_sleep;
+
        omap_uart_prepare_idle(0);
        omap_uart_prepare_idle(1);
        omap_uart_prepare_idle(2);
@@ -131,6 +150,9 @@ static void omap2_enter_full_retention(void)
        omap_uart_resume_idle(1);
        omap_uart_resume_idle(0);
 
+       if (!is_suspending())
+               release_console_sem();
+
 no_sleep:
        if (omap2_pm_debug) {
                unsigned long long tmp;
@@ -277,6 +299,12 @@ out:
        local_irq_enable();
 }
 
+static int omap2_pm_begin(suspend_state_t state)
+{
+       suspend_state = state;
+       return 0;
+}
+
 static int omap2_pm_prepare(void)
 {
        /* We cannot sleep in idle until we have resumed */
@@ -326,10 +354,17 @@ static void omap2_pm_finish(void)
        enable_hlt();
 }
 
+static void omap2_pm_end(void)
+{
+       suspend_state = PM_SUSPEND_ON;
+}
+
 static struct platform_suspend_ops omap_pm_ops = {
+       .begin          = omap2_pm_begin,
        .prepare        = omap2_pm_prepare,
        .enter          = omap2_pm_enter,
        .finish         = omap2_pm_finish,
+       .end            = omap2_pm_end,
        .valid          = suspend_valid_only_mem,
 };
 
index 75c0cd13ad8e0e78ca9686f35d9ec18b370cb6db..648b8c50d02422eeda2146cf3d3ebbe4b44d5a75 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/console.h>
 
 #include <plat/sram.h>
 #include <plat/clockdomain.h>
 #include "sdrc.h"
 #include "control.h"
 
+#ifdef CONFIG_SUSPEND
+static suspend_state_t suspend_state = PM_SUSPEND_ON;
+static inline bool is_suspending(void)
+{
+       return (suspend_state != PM_SUSPEND_ON);
+}
+#else
+static inline bool is_suspending(void)
+{
+       return false;
+}
+#endif
+
 /* Scratchpad offsets */
 #define OMAP343X_TABLE_ADDRESS_OFFSET     0xc4
 #define OMAP343X_TABLE_VALUE_OFFSET       0xc0
@@ -385,6 +399,13 @@ void omap_sram_idle(void)
                omap3_enable_io_chain();
        }
 
+       /* Block console output in case it is on one of the OMAP UARTs */
+       if (!is_suspending())
+               if (per_next_state < PWRDM_POWER_ON ||
+                   core_next_state < PWRDM_POWER_ON)
+                       if (try_acquire_console_sem())
+                               goto console_still_active;
+
        /* PER */
        if (per_next_state < PWRDM_POWER_ON) {
                omap_uart_prepare_idle(2);
@@ -463,6 +484,10 @@ void omap_sram_idle(void)
                omap_uart_resume_idle(3);
        }
 
+       if (!is_suspending())
+               release_console_sem();
+
+console_still_active:
        /* Disable IO-PAD and IO-CHAIN wakeup */
        if (omap3_has_io_wakeup() &&
            (per_next_state < PWRDM_POWER_ON ||
@@ -504,8 +529,6 @@ out:
 }
 
 #ifdef CONFIG_SUSPEND
-static suspend_state_t suspend_state;
-
 static int omap3_pm_prepare(void)
 {
        disable_hlt();
index 298a22a754e20a56e428aeaed051cdd7b2b923f7..f81acee4738dea03f64576b6a6288282002def39 100644 (file)
 #define OMAP24XX_EN_GPT1_MASK                          (1 << 0)
 
 /* PM_WKST_WKUP, CM_IDLEST_WKUP shared bits */
-#define OMAP24XX_ST_GPIOS_SHIFT                                (1 << 2)
-#define OMAP24XX_ST_GPIOS_MASK                         2
-#define OMAP24XX_ST_GPT1_SHIFT                         (1 << 0)
-#define OMAP24XX_ST_GPT1_MASK                          0
+#define OMAP24XX_ST_GPIOS_SHIFT                                2
+#define OMAP24XX_ST_GPIOS_MASK                         (1 << 2)
+#define OMAP24XX_ST_GPT1_SHIFT                         0
+#define OMAP24XX_ST_GPT1_MASK                          (1 << 0)
 
 /* CM_IDLEST_MDM and PM_WKST_MDM shared bits */
-#define OMAP2430_ST_MDM_SHIFT                          (1 << 0)
+#define OMAP2430_ST_MDM_SHIFT                          0
+#define OMAP2430_ST_MDM_MASK                           (1 << 0)
 
 
 /* 3430 register bits shared between CM & PRM registers */
index becf0e38ef7ed58a293588ef0b294a02c560e972..d17960a1be25814e25750270beefc4af35d1c70f 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/serial_8250.h>
 #include <linux/pm_runtime.h>
+#include <linux/console.h>
 
 #ifdef CONFIG_SERIAL_OMAP
 #include <plat/omap-serial.h>
@@ -406,7 +407,7 @@ void omap_uart_resume_idle(int num)
        struct omap_uart_state *uart;
 
        list_for_each_entry(uart, &uart_list, node) {
-               if (num == uart->num) {
+               if (num == uart->num && uart->can_sleep) {
                        omap_uart_enable_clocks(uart);
 
                        /* Check for IO pad wakeup */
@@ -807,6 +808,8 @@ void __init omap_serial_init_port(int port)
 
        oh->dev_attr = uart;
 
+       acquire_console_sem(); /* in case the earlycon is on the UART */
+
        /*
         * Because of early UART probing, UART did not get idled
         * on init.  Now that omap_device is ready, ensure full idle
@@ -831,6 +834,8 @@ void __init omap_serial_init_port(int port)
        omap_uart_block_sleep(uart);
        uart->timeout = DEFAULT_TIMEOUT;
 
+       release_console_sem();
+
        if ((cpu_is_omap34xx() && uart->padconf) ||
            (uart->wk_en && uart->wk_mask)) {
                device_init_wakeup(&od->pdev.dev, true);
index 31b65ee07b0b17f498e9796c2704ff6f427f5662..184913c71141d7c448f7ebcd8f700789064390ef 100644 (file)
@@ -17,4 +17,4 @@
  * The vmalloc() routines leaves a hole of 4kB between each vmalloced
  * area for the same reason. ;)
  */
-#define VMALLOC_END       0xd0000000
+#define VMALLOC_END       0xd0000000UL
index d2060a1d1d6820bcaf796e1a256a92989ce45365..e5c9932b75887914ec1c95b94692322b98f0e4b1 100644 (file)
@@ -241,7 +241,8 @@ static inline void palmtx_keys_init(void) {}
 /******************************************************************************
  * NAND Flash
  ******************************************************************************/
-#if defined(CONFIG_MTD_NAND_GPIO) || defined(CONFIG_MTD_NAND_GPIO_MODULE)
+#if defined(CONFIG_MTD_NAND_PLATFORM) || \
+       defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
 static void palmtx_nand_cmd_ctl(struct mtd_info *mtd, int cmd,
                                 unsigned int ctrl)
 {
index 4075473cf68a1b061a05860ffd4f5da35e92e1e3..b34be4554d40dd0d29809b6b256253e97ec51c56 100644 (file)
@@ -35,5 +35,6 @@ pen:  ldr     r7, [r6]
         */
        b       secondary_startup
 
+       .align
 1:     .long   .
        .long   pen_release
index 3bcd86fadb81ad994e771c27441eeb851c0b3d70..fb700228637a96dceb50a62175307049303de521 100644 (file)
@@ -7,4 +7,4 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#define VMALLOC_END       0xdc000000
+#define VMALLOC_END       0xdc000000UL
index 8aa2f1902a94092e0379d5d46fb1de734a3c0eb9..6b86a722a7db22343f4bf8226f680964c7620ff7 100644 (file)
@@ -77,13 +77,13 @@ static int __devinit h1940bt_probe(struct platform_device *pdev)
 
        /* Configures BT serial port GPIOs */
        s3c_gpio_cfgpin(S3C2410_GPH(0), S3C2410_GPH0_nCTS0);
-       s3c_gpio_cfgpull(S3C2410_GPH(0), S3C_GPIO_PULL_NONE);
+       s3c_gpio_setpull(S3C2410_GPH(0), S3C_GPIO_PULL_NONE);
        s3c_gpio_cfgpin(S3C2410_GPH(1), S3C2410_GPIO_OUTPUT);
-       s3c_gpio_cfgpull(S3C2410_GPH(1), S3C_GPIO_PULL_NONE);
+       s3c_gpio_setpull(S3C2410_GPH(1), S3C_GPIO_PULL_NONE);
        s3c_gpio_cfgpin(S3C2410_GPH(2), S3C2410_GPH2_TXD0);
-       s3c_gpio_cfgpull(S3C2410_GPH(2), S3C_GPIO_PULL_NONE);
+       s3c_gpio_setpull(S3C2410_GPH(2), S3C_GPIO_PULL_NONE);
        s3c_gpio_cfgpin(S3C2410_GPH(3), S3C2410_GPH3_RXD0);
-       s3c_gpio_cfgpull(S3C2410_GPH(3), S3C_GPIO_PULL_NONE);
+       s3c_gpio_setpull(S3C2410_GPH(3), S3C_GPIO_PULL_NONE);
 
 
        rfk = rfkill_alloc(DRV_NAME, &pdev->dev, RFKILL_TYPE_BLUETOOTH,
index cef6a65637bd946c31e12691ba51d2d05f554f6a..6983cb4d4cae81b4791e877e07018f4fe170a531 100644 (file)
@@ -16,7 +16,7 @@ config CPU_S3C2412
 config CPU_S3C2412_ONLY
        bool
        depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \
-                  !CPU_2416 && !CPU_S3C2440 && !CPU_S3C2442 && \
+                  !CPU_S3C2416 && !CPU_S3C2440 && !CPU_S3C2442 && \
                   !CPU_S3C2443 && CPU_S3C2412
        default y if CPU_S3C2412
 
@@ -28,9 +28,16 @@ config S3C2412_DMA
 
 config S3C2412_PM
        bool
+       select S3C2412_PM_SLEEP
        help
          Internal config node to apply S3C2412 power management
 
+config S3C2412_PM_SLEEP
+       bool
+       help
+         Internal config node to apply sleep for S3C2412 power management.
+         Can be selected by another SoCs with similar sleep procedure.
+
 # Note, the S3C2412 IOtiming support is in plat-s3c24xx
 
 config S3C2412_CPUFREQ
index 530ec46cbaea52d9a4ff16c6047450c4029195e4..6c48a91ea39e75a00e29b88a968553fc1e796fbb 100644 (file)
@@ -14,7 +14,8 @@ obj-$(CONFIG_CPU_S3C2412)     += irq.o
 obj-$(CONFIG_CPU_S3C2412)      += clock.o
 obj-$(CONFIG_CPU_S3C2412)      += gpio.o
 obj-$(CONFIG_S3C2412_DMA)      += dma.o
-obj-$(CONFIG_S3C2412_PM)       += pm.o sleep.o
+obj-$(CONFIG_S3C2412_PM)       += pm.o
+obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep.o
 obj-$(CONFIG_S3C2412_CPUFREQ)  += cpu-freq.o
 
 # Machine support
index 87b9c9f003bd503dec247cfa3f51b6a43fd97f36..df8d14974c90876b31d16ab2a2d2367ef1f7af89 100644 (file)
@@ -27,6 +27,7 @@ config S3C2416_DMA
 
 config S3C2416_PM
        bool
+       select S3C2412_PM_SLEEP
        help
          Internal config node to apply S3C2416 power management
 
@@ -35,9 +36,12 @@ menu "S3C2416 Machines"
 config MACH_SMDK2416
        bool "SMDK2416"
        select CPU_S3C2416
+       select MACH_SMDK
        select S3C_DEV_FB
        select S3C_DEV_HSMMC
        select S3C_DEV_HSMMC1
+       select S3C_DEV_NAND
+       select S3C_DEV_USB_HOST
        select S3C2416_PM if PM
        help
          Say Y here if you are using an SMDK2416
index 084d121f368cc87d2dfcd6bce0cf6281ab12ba51..00174daf15265024fccbf6063dc56614e827fafd 100644 (file)
@@ -168,12 +168,11 @@ static struct irq_chip s3c2416_irq_dma = {
 
 static void s3c2416_irq_demux_uart3(unsigned int irq, struct irq_desc *desc)
 {
-       s3c2416_irq_demux(IRQ_S3C2443_UART3, 3);
+       s3c2416_irq_demux(IRQ_S3C2443_RX3, 3);
 }
 
 #define INTMSK_UART3   (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0))
-#define SUBMSK_UART3   (0xf << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0)))
-
+#define SUBMSK_UART3   (0x7 << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0)))
 
 static void s3c2416_irq_uart3_mask(unsigned int irqno)
 {
index ff024a6c0f85cd46ca45959dc7137cdb5f20693e..a0cb2581894fa9fbe322347de25781e7b9a4ba81 100644 (file)
@@ -18,6 +18,7 @@ config CPU_S3C2440
 config CPU_S3C2442
        bool
        select CPU_ARM920T
+       select S3C_GPIO_PULL_DOWN
        select S3C2410_CLOCK
        select S3C2410_GPIO
        select S3C2410_PM if PM
@@ -178,6 +179,9 @@ config MACH_MINI2440
        bool "MINI2440 development board"
        select CPU_S3C2440
        select EEPROM_AT24
+       select NEW_LEDS
+       select LEDS_CLASS
+       select LEDS_TRIGGER
        select LEDS_TRIGGER_BACKLIGHT
        select S3C_DEV_NAND
        select S3C_DEV_USB_HOST
index d50f3ae6173d72a27d71ddefc941e0d1adc6bbec..f7663f731ea0728137700c3ada958800a54296db 100644 (file)
@@ -46,9 +46,6 @@ int __init s3c2440_init(void)
 {
        printk("S3C2440: Initialising architecture\n");
 
-       s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1up;
-       s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1up;
-
        /* change irq for watchdog */
 
        s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT;
@@ -58,3 +55,11 @@ int __init s3c2440_init(void)
 
        return sysdev_register(&s3c2440_sysdev);
 }
+
+void __init s3c2440_map_io(void)
+{
+       s3c244x_map_io();
+
+       s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1up;
+       s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1up;
+}
index 188ad1e57dc0321a1f63254f1f1e2a7c04820a17..ecf813546554739e4d329114a0896c6d49a37288 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/mutex.h>
+#include <linux/gpio.h>
 #include <linux/clk.h>
 #include <linux/io.h>
 
 
 #include <plat/clock.h>
 #include <plat/cpu.h>
+#include <plat/s3c244x.h>
+
+#include <plat/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
 
 /* S3C2442 extended clock support */
 
@@ -163,3 +169,11 @@ int __init s3c2442_init(void)
 
        return sysdev_register(&s3c2442_sysdev);
 }
+
+void __init s3c2442_map_io(void)
+{
+       s3c244x_map_io();
+
+       s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1down;
+       s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1down;
+}
index 4fef723126fa3223e4c45711d80e610907208f19..31babec90cecc9b92ff4a08b00da33c8a8446833 100644 (file)
@@ -5,6 +5,7 @@
 config CPU_S3C2443
        bool
        depends on ARCH_S3C2410
+       select CPU_ARM920T
        select S3C2443_DMA if S3C2410_DMA
        select CPU_LLSERIAL_S3C2440
        select SAMSUNG_CLKSRC
index 0e0d693f397449139f8fd9e790a1f4693e3f661b..893424767ce10b68b4420ff40d3026df331639a7 100644 (file)
@@ -166,12 +166,11 @@ static struct irq_chip s3c2443_irq_dma = {
 
 static void s3c2443_irq_demux_uart3(unsigned int irq, struct irq_desc *desc)
 {
-       s3c2443_irq_demux(IRQ_S3C2443_UART3, 3);
+       s3c2443_irq_demux(IRQ_S3C2443_RX3, 3);
 }
 
 #define INTMSK_UART3   (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0))
-#define SUBMSK_UART3   (0xf << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0)))
-
+#define SUBMSK_UART3   (0x7 << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0)))
 
 static void s3c2443_irq_uart3_mask(unsigned int irqno)
 {
index 249c62956471a04b970c082fb7eaf011373de9af..89f35e02e88367aacfe5d2a60187859c1ecd3be1 100644 (file)
@@ -45,7 +45,7 @@
 
 #include <video/platform_lcd.h>
 
-#define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK)
+#define UCON S3C2410_UCON_DEFAULT
 #define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB)
 #define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
 
index f9ef9b5c5f5a09f9aa692e3b705e14905ad4cae9..4957ab0a0d4a371effa85505fcc40b5957294485 100644 (file)
@@ -46,7 +46,7 @@
 
 #include <video/platform_lcd.h>
 
-#define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK)
+#define UCON S3C2410_UCON_DEFAULT
 #define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB)
 #define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
 
index 28677caf3613cca0ec00bf02862ba01c049fd6fd..461aa035afc05956a6262ea53921a941bf757b84 100644 (file)
@@ -378,6 +378,12 @@ static struct max8998_regulator_data aquila_regulators[] = {
 static struct max8998_platform_data aquila_max8998_pdata = {
        .num_regulators = ARRAY_SIZE(aquila_regulators),
        .regulators     = aquila_regulators,
+       .buck1_set1     = S5PV210_GPH0(3),
+       .buck1_set2     = S5PV210_GPH0(4),
+       .buck2_set3     = S5PV210_GPH0(5),
+       .buck1_max_voltage1 = 1200000,
+       .buck1_max_voltage2 = 1200000,
+       .buck2_max_voltage = 1200000,
 };
 #endif
 
index b1dcf964a768773772659b7a01b9e3b6cb8de545..e22d5112fd44aa3267c3bee3a23b023331b951cd 100644 (file)
@@ -518,6 +518,12 @@ static struct max8998_regulator_data goni_regulators[] = {
 static struct max8998_platform_data goni_max8998_pdata = {
        .num_regulators = ARRAY_SIZE(goni_regulators),
        .regulators     = goni_regulators,
+       .buck1_set1     = S5PV210_GPH0(3),
+       .buck1_set2     = S5PV210_GPH0(4),
+       .buck2_set3     = S5PV210_GPH0(5),
+       .buck1_max_voltage1 = 1200000,
+       .buck1_max_voltage2 = 1200000,
+       .buck2_max_voltage = 1200000,
 };
 #endif
 
index 0ad7924fe62e8faa12c54f5aafc07c2aa81474dc..5dd1681c069e582f0f6cb7a61f26e5f6f041ca7c 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/serial_core.h>
 #include <linux/i2c.h>
+#include <linux/sysdev.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
index bcd7a5d53401ae37d751cc59418f6aa74f2eab42..1fbc45b2a4326e89c3de305c9c6a33840b99351b 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/i2c.h>
 #include <linux/init.h>
 #include <linux/serial_core.h>
+#include <linux/sysdev.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
index 8e845b6a7cb57a3f74b9f00c16ba12b2bc0dd6f9..b10df988526d3d710577838a37401d11164ee13a 100644 (file)
@@ -1,4 +1,4 @@
 /*
  * arch/arm/mach-shark/include/mach/vmalloc.h
  */
-#define VMALLOC_END       0xd0000000
+#define VMALLOC_END       0xd0000000UL
index acbb4f0579abf75190999e6e5b1248de29ae48b5..b1222dc43380f9dd6e99081a2080c8dd56d7ef8b 100644 (file)
@@ -535,38 +535,127 @@ static struct platform_device *qhd_devices[] __initdata = {
 
 /* FSI */
 #define IRQ_FSI                evt2irq(0x1840)
+static int __fsi_set_rate(struct clk *clk, long rate, int enable)
+{
+       int ret = 0;
+
+       if (rate <= 0)
+               return ret;
+
+       if (enable) {
+               ret = clk_set_rate(clk, rate);
+               if (0 == ret)
+                       ret = clk_enable(clk);
+       } else {
+               clk_disable(clk);
+       }
+
+       return ret;
+}
+
+static int __fsi_set_round_rate(struct clk *clk, long rate, int enable)
+{
+       return __fsi_set_rate(clk, clk_round_rate(clk, rate), enable);
+}
+
+static int fsi_ak4642_set_rate(struct device *dev, int rate, int enable)
+{
+       struct clk *fsia_ick;
+       struct clk *fsiack;
+       int ret = -EIO;
+
+       fsia_ick = clk_get(dev, "icka");
+       if (IS_ERR(fsia_ick))
+               return PTR_ERR(fsia_ick);
+
+       /*
+        * FSIACK is connected to AK4642,
+        * and use external clock pin from it.
+        * it is parent of fsia_ick now.
+        */
+       fsiack = clk_get_parent(fsia_ick);
+       if (!fsiack)
+               goto fsia_ick_out;
+
+       /*
+        * we get 1/1 divided clock by setting same rate to fsiack and fsia_ick
+        *
+        ** FIXME **
+        * Because the freq_table of external clk (fsiack) are all 0,
+        * the return value of clk_round_rate became 0.
+        * So, it use __fsi_set_rate here.
+        */
+       ret = __fsi_set_rate(fsiack, rate, enable);
+       if (ret < 0)
+               goto fsiack_out;
+
+       ret = __fsi_set_round_rate(fsia_ick, rate, enable);
+       if ((ret < 0) && enable)
+               __fsi_set_round_rate(fsiack, rate, 0); /* disable FSI ACK */
+
+fsiack_out:
+       clk_put(fsiack);
+
+fsia_ick_out:
+       clk_put(fsia_ick);
 
-static int fsi_set_rate(int is_porta, int rate)
+       return 0;
+}
+
+static int fsi_hdmi_set_rate(struct device *dev, int rate, int enable)
 {
        struct clk *fsib_clk;
        struct clk *fdiv_clk = &sh7372_fsidivb_clk;
+       long fsib_rate = 0;
+       long fdiv_rate = 0;
+       int ackmd_bpfmd;
        int ret;
 
-       /* set_rate is not needed if port A */
-       if (is_porta)
-               return 0;
-
-       fsib_clk = clk_get(NULL, "fsib_clk");
-       if (IS_ERR(fsib_clk))
-               return -EINVAL;
-
        switch (rate) {
        case 44100:
-               clk_set_rate(fsib_clk, clk_round_rate(fsib_clk, 11283000));
-               ret = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
+               fsib_rate       = rate * 256;
+               ackmd_bpfmd     = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
                break;
        case 48000:
-               clk_set_rate(fsib_clk, clk_round_rate(fsib_clk, 85428000));
-               clk_set_rate(fdiv_clk, clk_round_rate(fdiv_clk, 12204000));
-               ret = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
+               fsib_rate       = 85428000; /* around 48kHz x 256 x 7 */
+               fdiv_rate       = rate * 256;
+               ackmd_bpfmd     = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
                break;
        default:
                pr_err("unsupported rate in FSI2 port B\n");
-               ret = -EINVAL;
-               break;
+               return -EINVAL;
        }
 
+       /* FSI B setting */
+       fsib_clk = clk_get(dev, "ickb");
+       if (IS_ERR(fsib_clk))
+               return -EIO;
+
+       ret = __fsi_set_round_rate(fsib_clk, fsib_rate, enable);
        clk_put(fsib_clk);
+       if (ret < 0)
+               return ret;
+
+       /* FSI DIV setting */
+       ret = __fsi_set_round_rate(fdiv_clk, fdiv_rate, enable);
+       if (ret < 0) {
+               /* disable FSI B */
+               if (enable)
+                       __fsi_set_round_rate(fsib_clk, fsib_rate, 0);
+               return ret;
+       }
+
+       return ackmd_bpfmd;
+}
+
+static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable)
+{
+       int ret;
+
+       if (is_porta)
+               ret = fsi_ak4642_set_rate(dev, rate, enable);
+       else
+               ret = fsi_hdmi_set_rate(dev, rate, enable);
 
        return ret;
 }
@@ -643,10 +732,15 @@ static struct platform_device lcdc1_device = {
        },
 };
 
+static long ap4evb_clk_optimize(unsigned long target, unsigned long *best_freq,
+                               unsigned long *parent_freq);
+
+
 static struct sh_mobile_hdmi_info hdmi_info = {
        .lcd_chan = &sh_mobile_lcdc1_info.ch[0],
        .lcd_dev = &lcdc1_device.dev,
        .flags = HDMI_SND_SRC_SPDIF,
+       .clk_optimize_parent = ap4evb_clk_optimize,
 };
 
 static struct resource hdmi_resources[] = {
@@ -673,6 +767,25 @@ static struct platform_device hdmi_device = {
        },
 };
 
+static long ap4evb_clk_optimize(unsigned long target, unsigned long *best_freq,
+                               unsigned long *parent_freq)
+{
+       struct clk *hdmi_ick = clk_get(&hdmi_device.dev, "ick");
+       long error;
+
+       if (IS_ERR(hdmi_ick)) {
+               int ret = PTR_ERR(hdmi_ick);
+               pr_err("Cannot get HDMI ICK: %d\n", ret);
+               return ret;
+       }
+
+       error = clk_round_parent(hdmi_ick, target, best_freq, parent_freq, 1, 64);
+
+       clk_put(hdmi_ick);
+
+       return error;
+}
+
 static struct gpio_led ap4evb_leds[] = {
        {
                .name                   = "led4",
@@ -848,6 +961,11 @@ static int __init hdmi_init_pm_clock(void)
                goto out;
        }
 
+       ret = clk_enable(&sh7372_pllc2_clk);
+       if (ret < 0) {
+               pr_err("Cannot enable pllc2 clock\n");
+               goto out;
+       }
        pr_debug("PLLC2 set frequency %lu\n", rate);
 
        ret = clk_set_parent(hdmi_ick, &sh7372_pllc2_clk);
@@ -864,23 +982,11 @@ out:
 
 device_initcall(hdmi_init_pm_clock);
 
-#define FSIACK_DUMMY_RATE 48000
 static int __init fsi_init_pm_clock(void)
 {
        struct clk *fsia_ick;
        int ret;
 
-       /*
-        * FSIACK is connected to AK4642,
-        * and the rate is depend on playing sound rate.
-        * So, set dummy rate (= 48k) here
-        */
-       ret = clk_set_rate(&sh7372_fsiack_clk, FSIACK_DUMMY_RATE);
-       if (ret < 0) {
-               pr_err("Cannot set FSIACK dummy rate: %d\n", ret);
-               return ret;
-       }
-
        fsia_ick = clk_get(&fsi_device.dev, "icka");
        if (IS_ERR(fsia_ick)) {
                ret = PTR_ERR(fsia_ick);
@@ -889,16 +995,9 @@ static int __init fsi_init_pm_clock(void)
        }
 
        ret = clk_set_parent(fsia_ick, &sh7372_fsiack_clk);
-       if (ret < 0) {
-               pr_err("Cannot set FSI-A parent: %d\n", ret);
-               goto out;
-       }
-
-       ret = clk_set_rate(fsia_ick, FSIACK_DUMMY_RATE);
        if (ret < 0)
-               pr_err("Cannot set FSI-A rate: %d\n", ret);
+               pr_err("Cannot set FSI-A parent: %d\n", ret);
 
-out:
        clk_put(fsia_ick);
 
        return ret;
index f4b9ae211566e1d59205f324b54d6fcf68a75e57..66663adb21f83ea51bcc9f282d32b8d20c6dae1b 100644 (file)
@@ -220,8 +220,7 @@ static void pllc2_disable(struct clk *clk)
        __raw_writel(__raw_readl(PLLC2CR) & ~0x80000000, PLLC2CR);
 }
 
-static int pllc2_set_rate(struct clk *clk,
-                         unsigned long rate, int algo_id)
+static int pllc2_set_rate(struct clk *clk, unsigned long rate)
 {
        unsigned long value;
        int idx;
@@ -230,21 +229,13 @@ static int pllc2_set_rate(struct clk *clk,
        if (idx < 0)
                return idx;
 
-       if (rate == clk->parent->rate) {
-               pllc2_disable(clk);
-               return 0;
-       }
+       if (rate == clk->parent->rate)
+               return -EINVAL;
 
        value = __raw_readl(PLLC2CR) & ~(0x3f << 24);
 
-       if (value & 0x80000000)
-               pllc2_disable(clk);
-
        __raw_writel((value & ~0x80000000) | ((idx + 19) << 24), PLLC2CR);
 
-       if (value & 0x80000000)
-               return pllc2_enable(clk);
-
        return 0;
 }
 
@@ -453,32 +444,24 @@ static int fsidiv_enable(struct clk *clk)
        unsigned long value;
 
        value  = __raw_readl(clk->mapping->base) >> 16;
-       if (value < 2) {
-               fsidiv_disable(clk);
-               return -ENOENT;
-       }
+       if (value < 2)
+               return -EIO;
 
        __raw_writel((value << 16) | 0x3, clk->mapping->base);
 
        return 0;
 }
 
-static int fsidiv_set_rate(struct clk *clk,
-                          unsigned long rate, int algo_id)
+static int fsidiv_set_rate(struct clk *clk, unsigned long rate)
 {
        int idx;
 
-       if (clk->parent->rate == rate) {
-               fsidiv_disable(clk);
-               return 0;
-       }
-
        idx = (clk->parent->rate / rate) & 0xffff;
        if (idx < 2)
-               return -ENOENT;
+               return -EINVAL;
 
        __raw_writel(idx << 16, clk->mapping->base);
-       return fsidiv_enable(clk);
+       return 0;
 }
 
 static struct clk_ops fsidiv_clk_ops = {
@@ -610,8 +593,6 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]),
        CLKDEV_CON_ID("fmsi_clk", &div6_clks[DIV6_FMSI]),
        CLKDEV_CON_ID("fmso_clk", &div6_clks[DIV6_FMSO]),
-       CLKDEV_CON_ID("fsia_clk", &div6_reparent_clks[DIV6_FSIA]),
-       CLKDEV_CON_ID("fsib_clk", &div6_reparent_clks[DIV6_FSIB]),
        CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]),
        CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]),
        CLKDEV_CON_ID("vou_clk", &div6_clks[DIV6_VOU]),
@@ -649,8 +630,8 @@ static struct clk_lookup lookups[] = {
        CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */
        CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI2 */
        CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */
-       CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP323]), /* USB0 */
-       CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[MSTP323]), /* USB0 */
+       CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP322]), /* USB0 */
+       CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[MSTP322]), /* USB0 */
        CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */
        CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */
        CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMC */
index a285d13c74165a2e73a3941a7d1d47d03b91b8ac..f428c4db2b60e60f2c21761859aaec3e4401eea3 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2010 Magnus Damm
  * Copyright (C) 2008 Renesas Solutions Corp.
  *
  * This program is free software; you can redistribute it and/or modify
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
-#include <mach/hardware.h>
 #include <mach/irqs.h>
 
+#define INTCA_BASE     0xe6980000
+#define INTFLGA_OFFS   0x00000018 /* accept pending interrupt */
+#define INTEVTA_OFFS   0x00000020 /* vector number of accepted interrupt */
+#define INTLVLA_OFFS   0x00000030 /* priority level of accepted interrupt */
+#define INTLVLB_OFFS   0x00000034 /* previous priority level */
+
        .macro  disable_fiq
        .endm
 
        .macro  get_irqnr_preamble, base, tmp
-       ldr     \base, =INTFLGA
+       ldr     \base, =INTCA_BASE
        .endm
 
        .macro  arch_ret_to_user, tmp1, tmp2
        .endm
 
        .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-       ldr     \irqnr, [\base]
+       /* The single INTFLGA read access below results in the following:
+        *
+        * 1. INTLVLB is updated with old priority value from INTLVLA
+        * 2. Highest priority interrupt is accepted
+        * 3. INTLVLA is updated to contain priority of accepted interrupt
+        * 4. Accepted interrupt vector is stored in INTFLGA and INTEVTA
+        */
+       ldr     \irqnr, [\base, #INTFLGA_OFFS]
+
+       /* Restore INTLVLA with the value saved in INTLVLB.
+        * This is required to support interrupt priorities properly.
+        */
+       ldrb    \tmp, [\base, #INTLVLB_OFFS]
+       strb    \tmp, [\base, #INTLVLA_OFFS]
+
+       /* Handle invalid vector number case */
        cmp     \irqnr, #0
        beq     1000f
-       /* intevt to irq number */
+
+       /* Convert vector to irq number, same as the evt2irq() macro */
        lsr     \irqnr, \irqnr, #0x5
        subs    \irqnr, \irqnr, #16
 
index 4aecf6e3a859f801111fafa328a44b3d0de3b311..2b8fd8b942feca160e61fe513d8856ffcb0d83a7 100644 (file)
@@ -2,6 +2,6 @@
 #define __ASM_MACH_VMALLOC_H
 
 /* Vmalloc at ... - 0xe5ffffff */
-#define VMALLOC_END 0xe6000000
+#define VMALLOC_END 0xe6000000UL
 
 #endif /* __ASM_MACH_VMALLOC_H */
index 8ea3bffb4e009f39b56b2262a762b8b28131c814..a0e7c12868bdf3caf69f504924e461181858060a 100644 (file)
@@ -21,8 +21,8 @@
 #include <mach/io.h>
 
        .macro  addruart, rp, rv
-        ldreq   \rp, =IO_APB_PHYS       @ physical
-        ldrne   \rv, =IO_APB_VIRT        @ virtual
+        ldr     \rp, =IO_APB_PHYS       @ physical
+        ldr     \rv, =IO_APB_VIRT        @ virtual
 #if defined(CONFIG_TEGRA_DEBUG_UART_NONE)
 #error "A debug UART must be selected in the kernel config to use DEBUG_LL"
 #elif defined(CONFIG_TEGRA_DEBUG_UARTA)
index 73fb1a551ec64338b136b73fb1548a9b87bd85e0..608a1372b172267170aaab6ecb2e0276fd5d49be 100644 (file)
@@ -75,14 +75,14 @@ void __init ux500_init_irq(void)
 static inline void ux500_cache_wait(void __iomem *reg, unsigned long mask)
 {
        /* wait for the operation to complete */
-       while (readl(reg) & mask)
+       while (readl_relaxed(reg) & mask)
                ;
 }
 
 static inline void ux500_cache_sync(void)
 {
        void __iomem *base = __io_address(UX500_L2CC_BASE);
-       writel(0, base + L2X0_CACHE_SYNC);
+       writel_relaxed(0, base + L2X0_CACHE_SYNC);
        ux500_cache_wait(base + L2X0_CACHE_SYNC, 1);
 }
 
@@ -107,7 +107,7 @@ static void ux500_l2x0_inv_all(void)
        uint32_t l2x0_way_mask = (1<<16) - 1;   /* Bitmask of active ways */
 
        /* invalidate all ways */
-       writel(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
+       writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
        ux500_cache_wait(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
        ux500_cache_sync();
 }
index ebd8a2543d3b811f5be94118e1c9c9798f134275..7d8e069ad51b98fb0ba6f8f6284276277062c1a0 100644 (file)
@@ -18,4 +18,4 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#define VMALLOC_END            0xd8000000
+#define VMALLOC_END            0xd8000000UL
index 8a78ff68e1eea106a5730d1a32746535b6adcdf1..7a3f0632947c7f19352bb93479eae6a7b2127d92 100644 (file)
@@ -35,5 +35,6 @@ pen:  ldr     r7, [r6]
         */
        b       secondary_startup
 
+       .align
 1:     .long   .
        .long   pen_release
index 99fa688dfadd305113670aa48ea185a9899f8e5b..c96fa1b3f49f5d78b670289a1d8fc8ccf3b38b30 100644 (file)
@@ -203,6 +203,10 @@ ENTRY(v6_flush_kern_dcache_area)
  *     - end     - virtual end address of region
  */
 v6_dma_inv_range:
+#ifdef CONFIG_DMA_CACHE_RWFO
+       ldrb    r2, [r0]                        @ read for ownership
+       strb    r2, [r0]                        @ write for ownership
+#endif
        tst     r0, #D_CACHE_LINE_SIZE - 1
        bic     r0, r0, #D_CACHE_LINE_SIZE - 1
 #ifdef HARVARD_CACHE
@@ -211,6 +215,10 @@ v6_dma_inv_range:
        mcrne   p15, 0, r0, c7, c11, 1          @ clean unified line
 #endif
        tst     r1, #D_CACHE_LINE_SIZE - 1
+#ifdef CONFIG_DMA_CACHE_RWFO
+       ldrneb  r2, [r1, #-1]                   @ read for ownership
+       strneb  r2, [r1, #-1]                   @ write for ownership
+#endif
        bic     r1, r1, #D_CACHE_LINE_SIZE - 1
 #ifdef HARVARD_CACHE
        mcrne   p15, 0, r1, c7, c14, 1          @ clean & invalidate D line
@@ -218,10 +226,6 @@ v6_dma_inv_range:
        mcrne   p15, 0, r1, c7, c15, 1          @ clean & invalidate unified line
 #endif
 1:
-#ifdef CONFIG_DMA_CACHE_RWFO
-       ldr     r2, [r0]                        @ read for ownership
-       str     r2, [r0]                        @ write for ownership
-#endif
 #ifdef HARVARD_CACHE
        mcr     p15, 0, r0, c7, c6, 1           @ invalidate D line
 #else
@@ -229,6 +233,10 @@ v6_dma_inv_range:
 #endif
        add     r0, r0, #D_CACHE_LINE_SIZE
        cmp     r0, r1
+#ifdef CONFIG_DMA_CACHE_RWFO
+       ldrlo   r2, [r0]                        @ read for ownership
+       strlo   r2, [r0]                        @ write for ownership
+#endif
        blo     1b
        mov     r0, #0
        mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
@@ -263,12 +271,12 @@ v6_dma_clean_range:
  *     - end     - virtual end address of region
  */
 ENTRY(v6_dma_flush_range)
-       bic     r0, r0, #D_CACHE_LINE_SIZE - 1
-1:
 #ifdef CONFIG_DMA_CACHE_RWFO
-       ldr     r2, [r0]                        @ read for ownership
-       str     r2, [r0]                        @ write for ownership
+       ldrb    r2, [r0]                @ read for ownership
+       strb    r2, [r0]                @ write for ownership
 #endif
+       bic     r0, r0, #D_CACHE_LINE_SIZE - 1
+1:
 #ifdef HARVARD_CACHE
        mcr     p15, 0, r0, c7, c14, 1          @ clean & invalidate D line
 #else
@@ -276,6 +284,10 @@ ENTRY(v6_dma_flush_range)
 #endif
        add     r0, r0, #D_CACHE_LINE_SIZE
        cmp     r0, r1
+#ifdef CONFIG_DMA_CACHE_RWFO
+       ldrlob  r2, [r0]                        @ read for ownership
+       strlob  r2, [r0]                        @ write for ownership
+#endif
        blo     1b
        mov     r0, #0
        mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
index a3ebf7a4f49b2b404da115a58e7fdf6923792625..6136e68ce953d038ef0fa92b8211a3c477ef8e83 100644 (file)
@@ -173,15 +173,22 @@ ENTRY(v7_coherent_user_range)
  UNWIND(.fnstart               )
        dcache_line_size r2, r3
        sub     r3, r2, #1
-       bic     r0, r0, r3
+       bic     r12, r0, r3
 1:
- USER( mcr     p15, 0, r0, c7, c11, 1  )       @ clean D line to the point of unification
+ USER( mcr     p15, 0, r12, c7, c11, 1 )       @ clean D line to the point of unification
+       add     r12, r12, r2
+       cmp     r12, r1
+       blo     1b
        dsb
- USER( mcr     p15, 0, r0, c7, c5, 1   )       @ invalidate I line
-       add     r0, r0, r2
+       icache_line_size r2, r3
+       sub     r3, r2, #1
+       bic     r12, r0, r3
 2:
-       cmp     r0, r1
-       blo     1b
+ USER( mcr     p15, 0, r12, c7, c5, 1  )       @ invalidate I line
+       add     r12, r12, r2
+       cmp     r12, r1
+       blo     2b
+3:
        mov     r0, #0
        ALT_SMP(mcr     p15, 0, r0, c7, c1, 6)  @ invalidate BTB Inner Shareable
        ALT_UP(mcr      p15, 0, r0, c7, c5, 6)  @ invalidate BTB
@@ -194,10 +201,10 @@ ENTRY(v7_coherent_user_range)
  * isn't mapped, just try the next page.
  */
 9001:
-       mov     r0, r0, lsr #12
-       mov     r0, r0, lsl #12
-       add     r0, r0, #4096
-       b       2b
+       mov     r12, r12, lsr #12
+       mov     r12, r12, lsl #12
+       add     r12, r12, #4096
+       b       3b
  UNWIND(.fnend         )
 ENDPROC(v7_coherent_kern_range)
 ENDPROC(v7_coherent_user_range)
index 17e7b0b57e49f80e6e30c8bbe65ea9d1ebcf14a6..55c17a6fb22fba2450ebce975a467f6c33ddf0ea 100644 (file)
@@ -206,8 +206,8 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn,
         */
        if (pfn_valid(pfn)) {
                printk(KERN_WARNING "BUG: Your driver calls ioremap() on system memory.  This leads\n"
-                      KERN_WARNING "to architecturally unpredictable behaviour on ARMv6+, and ioremap()\n"
-                      KERN_WARNING "will fail in the next kernel release.  Please fix your driver.\n");
+                      "to architecturally unpredictable behaviour on ARMv6+, and ioremap()\n"
+                      "will fail in the next kernel release.  Please fix your driver.\n");
                WARN_ON(1);
        }
 
index 7d63beaf97456541c0718c84b475b844194156e6..b795afd0a2c620ad1e8f774b1c166bc8639b2847 100644 (file)
        .endm
 
 /*
- * cache_line_size - get the cache line size from the CSIDR register
- * (available on ARMv7+). It assumes that the CSSR register was configured
- * to access the L1 data cache CSIDR.
+ * dcache_line_size - get the minimum D-cache line size from the CTR register
+ * on ARMv7.
  */
        .macro  dcache_line_size, reg, tmp
-       mrc     p15, 1, \tmp, c0, c0, 0         @ read CSIDR
-       and     \tmp, \tmp, #7                  @ cache line size encoding
-       mov     \reg, #16                       @ size offset
+       mrc     p15, 0, \tmp, c0, c0, 1         @ read ctr
+       lsr     \tmp, \tmp, #16
+       and     \tmp, \tmp, #0xf                @ cache line size encoding
+       mov     \reg, #4                        @ bytes per word
        mov     \reg, \reg, lsl \tmp            @ actual cache line size
        .endm
 
+/*
+ * icache_line_size - get the minimum I-cache line size from the CTR register
+ * on ARMv7.
+ */
+       .macro  icache_line_size, reg, tmp
+       mrc     p15, 0, \tmp, c0, c0, 1         @ read ctr
+       and     \tmp, \tmp, #0xf                @ cache line size encoding
+       mov     \reg, #4                        @ bytes per word
+       mov     \reg, \reg, lsl \tmp            @ actual cache line size
+       .endm
 
 /*
  * Sanity check the PTE configuration for the code below - which makes
index 53cbe2225153de55cf6848394d63d1fb1ea00a18..9b9ff5d949fdd08d73d37351b0e3c580a7533b83 100644 (file)
@@ -381,7 +381,7 @@ __v7_ca9mp_proc_info:
                PMD_SECT_XN | \
                PMD_SECT_AP_WRITE | \
                PMD_SECT_AP_READ
-       b       __v7_ca9mp_setup
+       W(b)    __v7_ca9mp_setup
        .long   cpu_arch_name
        .long   cpu_elf_name
        .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_TLS
@@ -413,7 +413,7 @@ __v7_proc_info:
                PMD_SECT_XN | \
                PMD_SECT_AP_WRITE | \
                PMD_SECT_AP_READ
-       b       __v7_setup
+       W(b)    __v7_setup
        .long   cpu_arch_name
        .long   cpu_elf_name
        .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_TLS
index 85d3e55ca4a9c293c67d4b2557bb52d90f93d22f..558cdfaf76b6a22a4ff6ff3a5190263c662a3268 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/time.h>
 #include <linux/init.h>
 #include <linux/timex.h>
+#include <linux/sched.h>
 #include <linux/io.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
@@ -36,7 +37,7 @@
 /*
  * IOP clocksource (free-running timer 1).
  */
-static cycle_t iop_clocksource_read(struct clocksource *unused)
+static cycle_t notrace iop_clocksource_read(struct clocksource *unused)
 {
        return 0xffffffffu - read_tcr1();
 }
index 02d989018059361c84077f1b80d49aba6d65b38b..3a705c7877dd1040121d6abd17a251c105259715 100644 (file)
 
 #include <mach/hardware.h>
 #include <mach/devices-common.h>
-#ifdef SDMA_IS_MERGED
 #include <mach/sdma.h>
-#else
-struct sdma_platform_data {
-       int sdma_version;
-       char *cpu_name;
-       int to_version;
-};
-#endif
 
 struct imx_imx_sdma_data {
        resource_size_t iobase;
index e48340ec331e4a8ca376b96c25b36faa0a7eafe0..17f724c9452d3d5520f451bfd8a198216b4fd503 100644 (file)
@@ -27,6 +27,7 @@ const struct imx_spi_imx_data imx21_cspi_data[] __initconst = {
        imx_spi_imx_data_entry(MX21, CSPI, "imx21-cspi", _id, _hwid, SZ_4K)
        imx21_cspi_data_entry(0, 1),
        imx21_cspi_data_entry(1, 2),
+};
 #endif
 
 #ifdef CONFIG_ARCH_MX25
index aedf9c1d645e4a820c8f1f9dd884fdf5fd1cebf5..63cdc6025bd74dfaf46bc93ec49125e9f75bb49d 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2008 STMicroelectronics
  * Copyright (C) 2010 Alessandro Rubini
+ * Copyright (C) 2010 Linus Walleij for ST-Ericsson
  *
  * 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
 #include <linux/clk.h>
 #include <linux/jiffies.h>
 #include <linux/err.h>
+#include <linux/cnt32_to_63.h>
+#include <linux/timer.h>
 #include <asm/mach/time.h>
 
 #include <plat/mtu.h>
 
-void __iomem *mtu_base; /* ssigned by machine code */
+void __iomem *mtu_base; /* Assigned by machine code */
 
 /*
  * Kernel assumes that sched_clock can be called early
@@ -48,16 +51,82 @@ static struct clocksource nmdk_clksrc = {
 /*
  * Override the global weak sched_clock symbol with this
  * local implementation which uses the clocksource to get some
- * better resolution when scheduling the kernel. We accept that
- * this wraps around for now, since it is just a relative time
- * stamp. (Inspired by OMAP implementation.)
+ * better resolution when scheduling the kernel.
+ *
+ * Because the hardware timer period may be quite short
+ * (32.3 secs on the 133 MHz MTU timer selection on ux500)
+ * and because cnt32_to_63() needs to be called at least once per
+ * half period to work properly, a kernel keepwarm() timer is set up
+ * to ensure this requirement is always met.
+ *
+ * Also the sched_clock timer will wrap around at some point,
+ * here we set it to run continously for a year.
  */
+#define SCHED_CLOCK_MIN_WRAP 3600*24*365
+static struct timer_list cnt32_to_63_keepwarm_timer;
+static u32 sched_mult;
+static u32 sched_shift;
+
 unsigned long long notrace sched_clock(void)
 {
-       return clocksource_cyc2ns(nmdk_clksrc.read(
-                                 &nmdk_clksrc),
-                                 nmdk_clksrc.mult,
-                                 nmdk_clksrc.shift);
+       u64 cycles;
+
+       if (unlikely(!mtu_base))
+               return 0;
+
+       cycles = cnt32_to_63(-readl(mtu_base + MTU_VAL(0)));
+       /*
+        * sched_mult is guaranteed to be even so will
+        * shift out bit 63
+        */
+       return (cycles * sched_mult) >> sched_shift;
+}
+
+/* Just kick sched_clock every so often */
+static void cnt32_to_63_keepwarm(unsigned long data)
+{
+       mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + data));
+       (void) sched_clock();
+}
+
+/*
+ * Set up a timer to keep sched_clock():s 32_to_63 algorithm warm
+ * once in half a 32bit timer wrap interval.
+ */
+static void __init nmdk_sched_clock_init(unsigned long rate)
+{
+       u32 v;
+       unsigned long delta;
+       u64 days;
+
+       /* Find the apropriate mult and shift factors */
+       clocks_calc_mult_shift(&sched_mult, &sched_shift,
+                              rate, NSEC_PER_SEC, SCHED_CLOCK_MIN_WRAP);
+       /* We need to multiply by an even number to get rid of bit 63 */
+       if (sched_mult & 1)
+               sched_mult++;
+
+       /* Let's see what we get, take max counter and scale it */
+       days = (0xFFFFFFFFFFFFFFFFLLU * sched_mult) >> sched_shift;
+       do_div(days, NSEC_PER_SEC);
+       do_div(days, (3600*24));
+
+       pr_info("sched_clock: using %d bits @ %lu Hz wrap in %lu days\n",
+               (64 - sched_shift), rate, (unsigned long) days);
+
+       /*
+        * Program a timer to kick us at half 32bit wraparound
+        * Formula: seconds per wrap = (2^32) / f
+        */
+       v = 0xFFFFFFFFUL / rate;
+       /* We want half of the wrap time to keep cnt32_to_63 warm */
+       v /= 2;
+       pr_debug("sched_clock: prescaled timer rate: %lu Hz, "
+                "initialize keepwarm timer every %d seconds\n", rate, v);
+       /* Convert seconds to jiffies */
+       delta = msecs_to_jiffies(v*1000);
+       setup_timer(&cnt32_to_63_keepwarm_timer, cnt32_to_63_keepwarm, delta);
+       mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + delta));
 }
 
 /* Clockevent device: use one-shot mode */
@@ -161,13 +230,15 @@ void __init nmdk_timer_init(void)
        writel(0, mtu_base + MTU_BGLR(0));
        writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0));
 
-       /* Now the scheduling clock is ready */
+       /* Now the clock source is ready */
        nmdk_clksrc.read = nmdk_read_timer;
 
        if (clocksource_register(&nmdk_clksrc))
                pr_err("timer: failed to initialize clock source %s\n",
                       nmdk_clksrc.name);
 
+       nmdk_sched_clock_init(rate);
+
        /* Timer 1 is used for events */
 
        clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE);
index 155fe43a672bc47fde734dc76e10fb844e9b22e5..8722a136f3a5bee844f5643dd195c95f077db666 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/err.h>
 
 #include <plat/common.h>
 #include <plat/board.h>
@@ -164,7 +165,7 @@ static int __init omap_init_clocksource_32k(void)
                        return -ENODEV;
 
                sync_32k_ick = clk_get(NULL, "omap_32ksync_ick");
-               if (sync_32k_ick)
+               if (!IS_ERR(sync_32k_ick))
                        clk_enable(sync_32k_ick);
 
                clocksource_32k.mult = clocksource_hz2mult(32768,
index e2c8eebe6b3a54a1ab7c0a9ffa25f280117ceb04..74dac419d328297a4347b8a29ce1d5c150af1480 100644 (file)
@@ -166,7 +166,7 @@ static void __init omap_detect_sram(void)
                     cpu_is_omap1710())
                        omap_sram_size = 0x4000;        /* 16K */
                else if (cpu_is_omap1611())
-                       omap_sram_size = 0x3e800;       /* 250K */
+                       omap_sram_size = SZ_256K;
                else {
                        printk(KERN_ERR "Could not detect SRAM size\n");
                        omap_sram_size = 0x4000;
index e49c5b6fc4e2efe3eb310e061d2e5d8d7ca8cd88..1ab332e37d7d578336a6d5979b6ea7f7e05ddb20 100644 (file)
@@ -17,6 +17,9 @@
 /* Require clock free running */
 #define PXA_FLAG_DISABLE_CLOCK_GATING (1<<0)
 
+/* Board design supports 8-bit data on SD/SDIO BUS */
+#define PXA_FLAG_SD_8_BIT_CAPABLE_SLOT (1<<2)
+
 /*
  * struct pxa_sdhci_platdata() - Platform device data for PXA SDHCI
  * @max_speed: the maximum speed supported
index 5a27b1b538f2885eab6cd6ccdfd670834607f665..eb105e61c746750f716cb0f8d392da560f8f1332 100644 (file)
@@ -8,7 +8,7 @@ config PLAT_S3C24XX
        default y
        select NO_IOPORT
        select ARCH_REQUIRE_GPIOLIB
-       select S3C_DEVICE_NAND
+       select S3C_DEV_NAND
        select S3C_GPIO_CFG_S3C24XX
        help
          Base platform code for any Samsung S3C24XX device
index 76d0858c3cbba1f1cbe4482af23a43a41a8aa019..4a10c0f684b2952cdb0ebf3fe6e33914f0eca9fb 100644 (file)
@@ -88,7 +88,7 @@ static struct cpu_table cpu_ids[] __initdata = {
        {
                .idcode         = 0x32440000,
                .idmask         = 0xffffffff,
-               .map_io         = s3c244x_map_io,
+               .map_io         = s3c2440_map_io,
                .init_clocks    = s3c244x_init_clocks,
                .init_uarts     = s3c244x_init_uarts,
                .init           = s3c2440_init,
@@ -97,7 +97,7 @@ static struct cpu_table cpu_ids[] __initdata = {
        {
                .idcode         = 0x32440001,
                .idmask         = 0xffffffff,
-               .map_io         = s3c244x_map_io,
+               .map_io         = s3c2440_map_io,
                .init_clocks    = s3c244x_init_clocks,
                .init_uarts     = s3c244x_init_uarts,
                .init           = s3c2440_init,
@@ -106,7 +106,7 @@ static struct cpu_table cpu_ids[] __initdata = {
        {
                .idcode         = 0x32440aaa,
                .idmask         = 0xffffffff,
-               .map_io         = s3c244x_map_io,
+               .map_io         = s3c2442_map_io,
                .init_clocks    = s3c244x_init_clocks,
                .init_uarts     = s3c244x_init_uarts,
                .init           = s3c2442_init,
@@ -115,7 +115,7 @@ static struct cpu_table cpu_ids[] __initdata = {
        {
                .idcode         = 0x32440aab,
                .idmask         = 0xffffffff,
-               .map_io         = s3c244x_map_io,
+               .map_io         = s3c2442_map_io,
                .init_clocks    = s3c244x_init_clocks,
                .init_uarts     = s3c244x_init_uarts,
                .init           = s3c2442_init,
index 24c6f5a30596b3d8206ab16d711ab202e5d99ad8..243b6411050d5edfdd587535a65173f9b1343aa7 100644 (file)
@@ -82,8 +82,6 @@ static struct s3c_gpio_cfg s3c24xx_gpiocfg_banka = {
 struct s3c_gpio_cfg s3c24xx_gpiocfg_default = {
        .set_config     = s3c_gpio_setcfg_s3c24xx,
        .get_config     = s3c_gpio_getcfg_s3c24xx,
-       .set_pull       = s3c_gpio_setpull_1up,
-       .get_pull       = s3c_gpio_getpull_1up,
 };
 
 struct s3c_gpio_chip s3c24xx_gpios[] = {
index 307248d1ccbbdd052e0b1fc34e69923ed7e104df..89e8d0a25f87454c6672429bd793557acda0fe74 100644 (file)
@@ -21,17 +21,22 @@ extern void s3c244x_init_clocks(int xtal);
 #else
 #define s3c244x_init_clocks NULL
 #define s3c244x_init_uarts NULL
-#define s3c244x_map_io NULL
 #endif
 
 #ifdef CONFIG_CPU_S3C2440
 extern  int s3c2440_init(void);
+
+extern void s3c2440_map_io(void);
 #else
 #define s3c2440_init NULL
+#define s3c2440_map_io NULL
 #endif
 
 #ifdef CONFIG_CPU_S3C2442
 extern  int s3c2442_init(void);
+
+extern void s3c2442_map_io(void);
 #else
 #define s3c2442_init NULL
+#define s3c2442_map_io NULL
 #endif
index 9793544a6aceb84bd6613fb040971a17788d41f6..704175b0573f45739d4020bddf3e4ce441604315 100644 (file)
@@ -29,8 +29,8 @@ void s3c24xx_spi_gpiocfg_bus0_gpe11_12_13(struct s3c2410_spi_info *spi,
        } else {
                s3c_gpio_cfgpin(S3C2410_GPE(13), S3C2410_GPIO_INPUT);
                s3c_gpio_cfgpin(S3C2410_GPE(11), S3C2410_GPIO_INPUT);
-               s3c_gpio_cfgpull(S3C2410_GPE(11), S3C_GPIO_PULL_NONE);
-               s3c_gpio_cfgpull(S3C2410_GPE(12), S3C_GPIO_PULL_NONE);
-               s3c_gpio_cfgpull(S3C2410_GPE(13), S3C_GPIO_PULL_NONE);
+               s3c_gpio_setpull(S3C2410_GPE(11), S3C_GPIO_PULL_NONE);
+               s3c_gpio_setpull(S3C2410_GPE(12), S3C_GPIO_PULL_NONE);
+               s3c_gpio_setpull(S3C2410_GPE(13), S3C_GPIO_PULL_NONE);
        }
 }
index db9e9e477ec18a1b71b8cf2c584642aa7314c841..72457afd6255119d3192f3fc8fcdd6dfc616cb37 100644 (file)
@@ -31,8 +31,8 @@ void s3c24xx_spi_gpiocfg_bus1_gpd8_9_10(struct s3c2410_spi_info *spi,
        } else {
                s3c_gpio_cfgpin(S3C2410_GPD(8), S3C2410_GPIO_INPUT);
                s3c_gpio_cfgpin(S3C2410_GPD(9), S3C2410_GPIO_INPUT);
-               s3c_gpio_cfgpull(S3C2410_GPD(10), S3C_GPIO_PULL_NONE);
-               s3c_gpio_cfgpull(S3C2410_GPD(9), S3C_GPIO_PULL_NONE);
-               s3c_gpio_cfgpull(S3C2410_GPD(8), S3C_GPIO_PULL_NONE);
+               s3c_gpio_setpull(S3C2410_GPD(10), S3C_GPIO_PULL_NONE);
+               s3c_gpio_setpull(S3C2410_GPD(9), S3C_GPIO_PULL_NONE);
+               s3c_gpio_setpull(S3C2410_GPD(8), S3C_GPIO_PULL_NONE);
        }
 }
index 8ea663a438bb8cd8e6a69ee87b53ace02d36bb65..c3972b645d13c03d7e1a405d9967f1eec09fe218 100644 (file)
@@ -29,8 +29,8 @@ void s3c24xx_spi_gpiocfg_bus1_gpg5_6_7(struct s3c2410_spi_info *spi,
        } else {
                s3c_gpio_cfgpin(S3C2410_GPG(7), S3C2410_GPIO_INPUT);
                s3c_gpio_cfgpin(S3C2410_GPG(5), S3C2410_GPIO_INPUT);
-               s3c_gpio_cfgpull(S3C2410_GPG(5), S3C_GPIO_PULL_NONE);
-               s3c_gpio_cfgpull(S3C2410_GPG(6), S3C_GPIO_PULL_NONE);
-               s3c_gpio_cfgpull(S3C2410_GPG(7), S3C_GPIO_PULL_NONE);
+               s3c_gpio_setpull(S3C2410_GPG(5), S3C_GPIO_PULL_NONE);
+               s3c_gpio_setpull(S3C2410_GPG(6), S3C_GPIO_PULL_NONE);
+               s3c_gpio_setpull(S3C2410_GPG(7), S3C_GPIO_PULL_NONE);
        }
 }
index b732b773b9aff13fcc4a661b5405618aed363756..0aa32f242ee43097a477a5494f8068723a9386ad 100644 (file)
@@ -280,18 +280,17 @@ s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
 }
 #endif
 
-#ifdef CONFIG_S3C_GPIO_PULL_UP
-int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
-                        unsigned int off, s3c_gpio_pull_t pull)
+#if defined(CONFIG_S3C_GPIO_PULL_UP) || defined(CONFIG_S3C_GPIO_PULL_DOWN)
+static int s3c_gpio_setpull_1(struct s3c_gpio_chip *chip,
+                        unsigned int off, s3c_gpio_pull_t pull,
+                        s3c_gpio_pull_t updown)
 {
        void __iomem *reg = chip->base + 0x08;
        u32 pup = __raw_readl(reg);
 
-       pup = __raw_readl(reg);
-
-       if (pup == S3C_GPIO_PULL_UP)
+       if (pull == updown)
                pup &= ~(1 << off);
-       else if (pup == S3C_GPIO_PULL_NONE)
+       else if (pull == S3C_GPIO_PULL_NONE)
                pup |= (1 << off);
        else
                return -EINVAL;
@@ -300,17 +299,45 @@ int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
        return 0;
 }
 
-s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip,
-                                    unsigned int off)
+static s3c_gpio_pull_t s3c_gpio_getpull_1(struct s3c_gpio_chip *chip,
+                                    unsigned int off, s3c_gpio_pull_t updown)
 {
        void __iomem *reg = chip->base + 0x08;
        u32 pup = __raw_readl(reg);
 
        pup &= (1 << off);
-       return pup ? S3C_GPIO_PULL_NONE : S3C_GPIO_PULL_UP;
+       return pup ? S3C_GPIO_PULL_NONE : updown;
+}
+#endif /* CONFIG_S3C_GPIO_PULL_UP || CONFIG_S3C_GPIO_PULL_DOWN */
+
+#ifdef CONFIG_S3C_GPIO_PULL_UP
+s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip,
+                                    unsigned int off)
+{
+       return s3c_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
+}
+
+int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
+                        unsigned int off, s3c_gpio_pull_t pull)
+{
+       return s3c_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
 }
 #endif /* CONFIG_S3C_GPIO_PULL_UP */
 
+#ifdef CONFIG_S3C_GPIO_PULL_DOWN
+s3c_gpio_pull_t s3c_gpio_getpull_1down(struct s3c_gpio_chip *chip,
+                                    unsigned int off)
+{
+       return s3c_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
+}
+
+int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip,
+                        unsigned int off, s3c_gpio_pull_t pull)
+{
+       return s3c_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
+}
+#endif /* CONFIG_S3C_GPIO_PULL_DOWN */
+
 #ifdef CONFIG_S5P_GPIO_DRVSTR
 s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
 {
index 8fd65d8b5863121192fa4eff36fcd33f5413a88a..0d2c5703f1eeba843726d1c3511e774d2c94e844 100644 (file)
@@ -209,6 +209,17 @@ extern s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
 extern s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip,
                                            unsigned int off);
 
+/**
+ * s3c_gpio_getpull_1down() - Get configuration for choice of down or none
+ * @chip: The gpio chip that the GPIO pin belongs to
+ * @off: The offset to the pin to get the configuration of.
+ *
+ * This helper function reads the state of the pull-down resistor for the
+ * given GPIO in the same case as s3c_gpio_setpull_1down.
+*/
+extern s3c_gpio_pull_t s3c_gpio_getpull_1down(struct s3c_gpio_chip *chip,
+                                           unsigned int off);
+
 /**
  * s3c_gpio_setpull_s3c2443() - Pull configuration for s3c2443.
  * @chip: The gpio chip that is being configured.
index 55590a4d87c932984404d1df13ca4c296c9d7117..2fea897ebeb12959415120a7c1cdcaf5d8ac8fee 100644 (file)
@@ -12,7 +12,7 @@
 #
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #
-# Last update: Thu Sep 9 22:43:01 2010
+# Last update: Sun Dec 12 23:24:27 2010
 #
 # machine_is_xxx       CONFIG_xxxx             MACH_TYPE_xxx           number
 #
@@ -2321,7 +2321,7 @@ mx31txtr          MACH_MX31TXTR           MX31TXTR                2332
 u380                   MACH_U380               U380                    2333
 oamp3_hualu            MACH_HUALU_BOARD        HUALU_BOARD             2334
 npcmx50                        MACH_NPCMX50            NPCMX50                 2335
-mx51_lange51           MACH_MX51_LANGE51       MX51_LANGE51            2336
+mx51_efikamx           MACH_MX51_EFIKAMX       MX51_EFIKAMX            2336
 mx51_lange52           MACH_MX51_LANGE52       MX51_LANGE52            2337
 riom                   MACH_RIOM               RIOM                    2338
 comcas                 MACH_COMCAS             COMCAS                  2339
@@ -2355,7 +2355,7 @@ at91sam9263cs             MACH_AT91SAM9263CS      AT91SAM9263CS           2366
 csb732                 MACH_CSB732             CSB732                  2367
 u8500                  MACH_U8500              U8500                   2368
 huqiu                  MACH_HUQIU              HUQIU                   2369
-mx51_kunlun            MACH_MX51_KUNLUN        MX51_KUNLUN             2370
+mx51_efikasb           MACH_MX51_EFIKASB       MX51_EFIKASB            2370
 pmt1g                  MACH_PMT1G              PMT1G                   2371
 htcelf                 MACH_HTCELF             HTCELF                  2372
 armadillo420           MACH_ARMADILLO420       ARMADILLO420            2373
@@ -2971,7 +2971,7 @@ premierwave_en            MACH_PREMIERWAVE_EN     PREMIERWAVE_EN          2985
 wasabi                 MACH_WASABI             WASABI                  2986
 vivow                  MACH_VIVOW              VIVOW                   2987
 mx50_rdp               MACH_MX50_RDP           MX50_RDP                2988
-universal              MACH_UNIVERSAL          UNIVERSAL               2989
+universal_c210         MACH_UNIVERSAL_C210     UNIVERSAL_C210          2989
 real6410               MACH_REAL6410           REAL6410                2990
 spx_sakura             MACH_SPX_SAKURA         SPX_SAKURA              2991
 ij3k_2440              MACH_IJ3K_2440          IJ3K_2440               2992
@@ -3044,3 +3044,178 @@ harvest_desoto          MACH_HARVEST_DESOTO     HARVEST_DESOTO          3059
 msm8x60_qrdc           MACH_MSM8X60_QRDC       MSM8X60_QRDC            3060
 spear900               MACH_SPEAR900           SPEAR900                3061
 pcontrol_g20           MACH_PCONTROL_G20       PCONTROL_G20            3062
+rdstor                 MACH_RDSTOR             RDSTOR                  3063
+usdloader              MACH_USDLOADER          USDLOADER               3064
+tsoploader             MACH_TSOPLOADER         TSOPLOADER              3065
+kronos                 MACH_KRONOS             KRONOS                  3066
+ffcore                 MACH_FFCORE             FFCORE                  3067
+mone                   MACH_MONE               MONE                    3068
+unit2s                 MACH_UNIT2S             UNIT2S                  3069
+acer_a5                        MACH_ACER_A5            ACER_A5                 3070
+etherpro_isp           MACH_ETHERPRO_ISP       ETHERPRO_ISP            3071
+stretchs7000           MACH_STRETCHS7000       STRETCHS7000            3072
+p87_smartsim           MACH_P87_SMARTSIM       P87_SMARTSIM            3073
+tulip                  MACH_TULIP              TULIP                   3074
+sunflower              MACH_SUNFLOWER          SUNFLOWER               3075
+rib                    MACH_RIB                RIB                     3076
+clod                   MACH_CLOD               CLOD                    3077
+rump                   MACH_RUMP               RUMP                    3078
+tenderloin             MACH_TENDERLOIN         TENDERLOIN              3079
+shortloin              MACH_SHORTLOIN          SHORTLOIN               3080
+crespo                 MACH_CRESPO             CRESPO                  3081
+antares                        MACH_ANTARES            ANTARES                 3082
+wb40n                  MACH_WB40N              WB40N                   3083
+herring                        MACH_HERRING            HERRING                 3084
+naxy400                        MACH_NAXY400            NAXY400                 3085
+naxy1200               MACH_NAXY1200           NAXY1200                3086
+vpr200                 MACH_VPR200             VPR200                  3087
+bug20                  MACH_BUG20              BUG20                   3088
+goflexnet              MACH_GOFLEXNET          GOFLEXNET               3089
+torbreck               MACH_TORBRECK           TORBRECK                3090
+saarb_mg1              MACH_SAARB_MG1          SAARB_MG1               3091
+callisto               MACH_CALLISTO           CALLISTO                3092
+multhsu                        MACH_MULTHSU            MULTHSU                 3093
+saluda                 MACH_SALUDA             SALUDA                  3094
+pemp_omap3_apollo      MACH_PEMP_OMAP3_APOLLO  PEMP_OMAP3_APOLLO       3095
+vc0718                 MACH_VC0718             VC0718                  3096
+mvblx                  MACH_MVBLX              MVBLX                   3097
+inhand_apeiron         MACH_INHAND_APEIRON     INHAND_APEIRON          3098
+inhand_fury            MACH_INHAND_FURY        INHAND_FURY             3099
+inhand_siren           MACH_INHAND_SIREN       INHAND_SIREN            3100
+hdnvp                  MACH_HDNVP              HDNVP                   3101
+softwinner             MACH_SOFTWINNER         SOFTWINNER              3102
+prima2_evb             MACH_PRIMA2_EVB         PRIMA2_EVB              3103
+nas6210                        MACH_NAS6210            NAS6210                 3104
+unisdev                        MACH_UNISDEV            UNISDEV                 3105
+sbca11                 MACH_SBCA11             SBCA11                  3106
+saga                   MACH_SAGA               SAGA                    3107
+ns_k330                        MACH_NS_K330            NS_K330                 3108
+tanna                  MACH_TANNA              TANNA                   3109
+imate8502              MACH_IMATE8502          IMATE8502               3110
+aspen                  MACH_ASPEN              ASPEN                   3111
+daintree_cwac          MACH_DAINTREE_CWAC      DAINTREE_CWAC           3112
+zmx25                  MACH_ZMX25              ZMX25                   3113
+maple1                 MACH_MAPLE1             MAPLE1                  3114
+qsd8x72_surf           MACH_QSD8X72_SURF       QSD8X72_SURF            3115
+qsd8x72_ffa            MACH_QSD8X72_FFA        QSD8X72_FFA             3116
+abilene                        MACH_ABILENE            ABILENE                 3117
+eigen_ttr              MACH_EIGEN_TTR          EIGEN_TTR               3118
+iomega_ix2_200         MACH_IOMEGA_IX2_200     IOMEGA_IX2_200          3119
+coretec_vcx7400                MACH_CORETEC_VCX7400    CORETEC_VCX7400         3120
+santiago               MACH_SANTIAGO           SANTIAGO                3121
+mx257sol               MACH_MX257SOL           MX257SOL                3122
+strasbourg             MACH_STRASBOURG         STRASBOURG              3123
+msm8x60_fluid          MACH_MSM8X60_FLUID      MSM8X60_FLUID           3124
+smartqv5               MACH_SMARTQV5           SMARTQV5                3125
+smartqv3               MACH_SMARTQV3           SMARTQV3                3126
+smartqv7               MACH_SMARTQV7           SMARTQV7                3127
+paz00                  MACH_PAZ00              PAZ00                   3128
+acmenetusfoxg20                MACH_ACMENETUSFOXG20    ACMENETUSFOXG20         3129
+htcwillow              MACH_HTCWILLOW          HTCWILLOW               3130
+fwbd_0404              MACH_FWBD_0404          FWBD_0404               3131
+hdgu                   MACH_HDGU               HDGU                    3132
+pyramid                        MACH_PYRAMID            PYRAMID                 3133
+epiphan                        MACH_EPIPHAN            EPIPHAN                 3134
+omap_bender            MACH_OMAP_BENDER        OMAP_BENDER             3135
+gurnard                        MACH_GURNARD            GURNARD                 3136
+gtl_it5100             MACH_GTL_IT5100         GTL_IT5100              3137
+bcm2708                        MACH_BCM2708            BCM2708                 3138
+mx51_ggc               MACH_MX51_GGC           MX51_GGC                3139
+sharespace             MACH_SHARESPACE         SHARESPACE              3140
+haba_knx_explorer      MACH_HABA_KNX_EXPLORER  HABA_KNX_EXPLORER       3141
+simtec_kirkmod         MACH_SIMTEC_KIRKMOD     SIMTEC_KIRKMOD          3142
+crux                   MACH_CRUX               CRUX                    3143
+mx51_bravo             MACH_MX51_BRAVO         MX51_BRAVO              3144
+charon                 MACH_CHARON             CHARON                  3145
+picocom3               MACH_PICOCOM3           PICOCOM3                3146
+picocom4               MACH_PICOCOM4           PICOCOM4                3147
+serrano                        MACH_SERRANO            SERRANO                 3148
+doubleshot             MACH_DOUBLESHOT         DOUBLESHOT              3149
+evsy                   MACH_EVSY               EVSY                    3150
+huashan                        MACH_HUASHAN            HUASHAN                 3151
+lausanne               MACH_LAUSANNE           LAUSANNE                3152
+emerald                        MACH_EMERALD            EMERALD                 3153
+tqma35                 MACH_TQMA35             TQMA35                  3154
+marvel                 MACH_MARVEL             MARVEL                  3155
+manuae                 MACH_MANUAE             MANUAE                  3156
+chacha                 MACH_CHACHA             CHACHA                  3157
+lemon                  MACH_LEMON              LEMON                   3158
+csc                    MACH_CSC                CSC                     3159
+gira_knxip_router      MACH_GIRA_KNXIP_ROUTER  GIRA_KNXIP_ROUTER       3160
+t20                    MACH_T20                T20                     3161
+hdmini                 MACH_HDMINI             HDMINI                  3162
+sciphone_g2            MACH_SCIPHONE_G2        SCIPHONE_G2             3163
+express                        MACH_EXPRESS            EXPRESS                 3164
+express_kt             MACH_EXPRESS_KT         EXPRESS_KT              3165
+maximasp               MACH_MAXIMASP           MAXIMASP                3166
+nitrogen_imx51         MACH_NITROGEN_IMX51     NITROGEN_IMX51          3167
+nitrogen_imx53         MACH_NITROGEN_IMX53     NITROGEN_IMX53          3168
+sunfire                        MACH_SUNFIRE            SUNFIRE                 3169
+arowana                        MACH_AROWANA            AROWANA                 3170
+tegra_daytona          MACH_TEGRA_DAYTONA      TEGRA_DAYTONA           3171
+tegra_swordfish                MACH_TEGRA_SWORDFISH    TEGRA_SWORDFISH         3172
+edison                 MACH_EDISON             EDISON                  3173
+svp8500v1              MACH_SVP8500V1          SVP8500V1               3174
+svp8500v2              MACH_SVP8500V2          SVP8500V2               3175
+svp5500                        MACH_SVP5500            SVP5500                 3176
+b5500                  MACH_B5500              B5500                   3177
+s5500                  MACH_S5500              S5500                   3178
+icon                   MACH_ICON               ICON                    3179
+elephant               MACH_ELEPHANT           ELEPHANT                3180
+msm8x60_fusion         MACH_MSM8X60_FUSION     MSM8X60_FUSION          3181
+shooter                        MACH_SHOOTER            SHOOTER                 3182
+spade_lte              MACH_SPADE_LTE          SPADE_LTE               3183
+philhwani              MACH_PHILHWANI          PHILHWANI               3184
+gsncomm                        MACH_GSNCOMM            GSNCOMM                 3185
+strasbourg_a2          MACH_STRASBOURG_A2      STRASBOURG_A2           3186
+mmm                    MACH_MMM                MMM                     3187
+davinci_dm365_bv       MACH_DAVINCI_DM365_BV   DAVINCI_DM365_BV        3188
+ag5evm                 MACH_AG5EVM             AG5EVM                  3189
+sc575plc               MACH_SC575PLC           SC575PLC                3190
+sc575hmi               MACH_SC575IPC           SC575IPC                3191
+omap3_tdm3730          MACH_OMAP3_TDM3730      OMAP3_TDM3730           3192
+g7                     MACH_G7                 G7                      3193
+top9000_eval           MACH_TOP9000_EVAL       TOP9000_EVAL            3194
+top9000_su             MACH_TOP9000_SU         TOP9000_SU              3195
+utm300                 MACH_UTM300             UTM300                  3196
+tsunagi                        MACH_TSUNAGI            TSUNAGI                 3197
+ts75xx                 MACH_TS75XX             TS75XX                  3198
+msm8x60_fusn_ffa       MACH_MSM8X60_FUSN_FFA   MSM8X60_FUSN_FFA        3199
+ts47xx                 MACH_TS47XX             TS47XX                  3200
+da850_k5               MACH_DA850_K5           DA850_K5                3201
+ax502                  MACH_AX502              AX502                   3202
+igep0032               MACH_IGEP0032           IGEP0032                3203
+antero                 MACH_ANTERO             ANTERO                  3204
+synergy                        MACH_SYNERGY            SYNERGY                 3205
+ics_if_voip            MACH_ICS_IF_VOIP        ICS_IF_VOIP             3206
+wlf_cragg_6410         MACH_WLF_CRAGG_6410     WLF_CRAGG_6410          3207
+punica                 MACH_PUNICA             PUNICA                  3208
+sbc_nt250              MACH_SBC_NT250          SBC_NT250               3209
+mx27_wmultra           MACH_MX27_WMULTRA       MX27_WMULTRA            3210
+mackerel               MACH_MACKEREL           MACKEREL                3211
+fa9x27                 MACH_FA9X27             FA9X27                  3213
+ns2816tb               MACH_NS2816TB           NS2816TB                3214
+ns2816_ntpad           MACH_NS2816_NTPAD       NS2816_NTPAD            3215
+ns2816_ntnb            MACH_NS2816_NTNB        NS2816_NTNB             3216
+kaen                   MACH_KAEN               KAEN                    3217
+nv1000                 MACH_NV1000             NV1000                  3218
+nuc950ts               MACH_NUC950TS           NUC950TS                3219
+nokia_rm680            MACH_NOKIA_RM680        NOKIA_RM680             3220
+ast2200                        MACH_AST2200            AST2200                 3221
+lead                   MACH_LEAD               LEAD                    3222
+unino1                 MACH_UNINO1             UNINO1                  3223
+greeco                 MACH_GREECO             GREECO                  3224
+verdi                  MACH_VERDI              VERDI                   3225
+dm6446_adbox           MACH_DM6446_ADBOX       DM6446_ADBOX            3226
+quad_salsa             MACH_QUAD_SALSA         QUAD_SALSA              3227
+abb_gma_1_1            MACH_ABB_GMA_1_1        ABB_GMA_1_1             3228
+svcid                  MACH_SVCID              SVCID                   3229
+msm8960_sim            MACH_MSM8960_SIM        MSM8960_SIM             3230
+msm8960_rumi3          MACH_MSM8960_RUMI3      MSM8960_RUMI3           3231
+icon_g                 MACH_ICON_G             ICON_G                  3232
+mb3                    MACH_MB3                MB3                     3233
+gsia18s                        MACH_GSIA18S            GSIA18S                 3234
+pivicc                 MACH_PIVICC             PIVICC                  3235
+pcm048                 MACH_PCM048             PCM048                  3236
+dds                    MACH_DDS                DDS                     3237
+chalten_xa1            MACH_CHALTEN_XA1        CHALTEN_XA1             3238
index d66cead97d28b3c5d63d9c22d4fdcb77b7d7bd8e..9897dcfc16d67a0e104552814adaad8ec1230e32 100644 (file)
@@ -206,6 +206,7 @@ ENTRY(vfp_save_state)
        mov     pc, lr
 ENDPROC(vfp_save_state)
 
+       .align
 last_VFP_context_address:
        .word   last_VFP_context
 
index 67a2fa2caa494ff06e2550aa8cea7cf61d69f39e..0a9b5b8b2a1935103ecf9d81a2367d0a0633f1e4 100644 (file)
@@ -19,6 +19,8 @@ config MIPS
        select GENERIC_ATOMIC64 if !64BIT
        select HAVE_DMA_ATTRS
        select HAVE_DMA_API_DEBUG
+       select HAVE_GENERIC_HARDIRQS
+       select GENERIC_IRQ_PROBE
 
 menu "Machine selection"
 
@@ -1664,6 +1666,28 @@ config PAGE_SIZE_64KB
 
 endchoice
 
+config FORCE_MAX_ZONEORDER
+       int "Maximum zone order"
+       range 13 64 if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_32KB
+       default "13" if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_32KB
+       range 12 64 if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_16KB
+       default "12" if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_16KB
+       range 11 64
+       default "11"
+       help
+         The kernel memory allocator divides physically contiguous memory
+         blocks into "zones", where each zone is a power of two number of
+         pages.  This option selects the largest power of two that the kernel
+         keeps in the memory allocator.  If you need to allocate very large
+         blocks of physically contiguous memory, then you may need to
+         increase this value.
+
+         This config option is actually maximum order plus one. For example,
+         a value of 11 means that the largest free memory block is 2^10 pages.
+
+         The page size is not necessarily 4KB.  Keep this in mind
+         when choosing a value for this option.
+
 config BOARD_SCACHE
        bool
 
@@ -1921,20 +1945,6 @@ config CPU_R4000_WORKAROUNDS
 config CPU_R4400_WORKAROUNDS
        bool
 
-#
-# Use the generic interrupt handling code in kernel/irq/:
-#
-config GENERIC_HARDIRQS
-       bool
-       default y
-
-config GENERIC_IRQ_PROBE
-       bool
-       default y
-
-config IRQ_PER_CPU
-       bool
-
 #
 # - Highmem only makes sense for the 32-bit kernel.
 # - The current highmem code will only work properly on physically indexed
index 3691630931d6100ae901d8adbddcc6ccb6cf960e..9e7814db3d03411d08bfe93868f84d646dd93d93 100644 (file)
@@ -27,6 +27,7 @@
 static void alchemy_8250_pm(struct uart_port *port, unsigned int state,
                            unsigned int old_state)
 {
+#ifdef CONFIG_SERIAL_8250
        switch (state) {
        case 0:
                if ((__raw_readl(port->membase + UART_MOD_CNTRL) & 3) != 3) {
@@ -49,6 +50,7 @@ static void alchemy_8250_pm(struct uart_port *port, unsigned int state,
                serial8250_do_pm(port, state, old_state);
                break;
        }
+#endif
 }
 
 #define PORT(_base, _irq)                                      \
index b30df5c97ad35e46e534b047c144975c01db6b76..baeb21385058b8d5efe5e046620e66746b754d73 100644 (file)
@@ -54,10 +54,9 @@ void __init prom_init(void)
 
        prom_init_cmdline();
        memsize_str = prom_getenv("memsize");
-       if (!memsize_str)
+       if (!memsize_str || strict_strtoul(memsize_str, 0, &memsize))
                memsize = ALCHEMY_BOARD_DEFAULT_MEMSIZE;
-       else
-               strict_strtoul(memsize_str, 0, &memsize);
+
        add_memory_region(0, memsize, BOOT_MEM_RAM);
 }
 
index fc0e7154e8d69835c56eb45891a9e98beca0e82f..2ca4ada1c291cf7cb13f0ac047d6b879e9e1b400 100644 (file)
@@ -239,12 +239,12 @@ static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock,
        calculate(base_clock, frequency, &prediv, &postdiv, &mul);
 
        writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl);
-       msleep(1);
+       mdelay(1);
        writel(4, &clock->pll);
        while (readl(&clock->pll) & PLL_STATUS)
                ;
        writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll);
-       msleep(75);
+       mdelay(75);
 }
 
 static void __init tnetd7300_init_clocks(void)
@@ -456,7 +456,7 @@ void clk_put(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_put);
 
-int __init ar7_init_clocks(void)
+void __init ar7_init_clocks(void)
 {
        switch (ar7_chip_id()) {
        case AR7_CHIP_7100:
@@ -472,7 +472,4 @@ int __init ar7_init_clocks(void)
        }
        /* adjust vbus clock rate */
        vbus_clk.rate = bus_clk.rate / 2;
-
-       return 0;
 }
-arch_initcall(ar7_init_clocks);
index 5fb8a01340855f402340914784c65924faaa163e..22c93213b233db0090a2c8175cee864f2cf62619 100644 (file)
@@ -30,6 +30,9 @@ void __init plat_time_init(void)
 {
        struct clk *cpu_clk;
 
+       /* Initialize ar7 clocks so the CPU clock frequency is correct */
+       ar7_init_clocks();
+
        cpu_clk = clk_get(NULL, "cpu");
        if (IS_ERR(cpu_clk)) {
                printk(KERN_ERR "unable to get cpu clock\n");
index b1aee33efd11454e7f47c7d8beb7d0d50ed9ca2a..c95f90bf734ca9c1765b14728f391a14af62917b 100644 (file)
@@ -32,7 +32,6 @@
 #include <asm/reboot.h>
 #include <asm/time.h>
 #include <bcm47xx.h>
-#include <asm/fw/cfe/cfe_api.h>
 #include <asm/mach-bcm47xx/nvram.h>
 
 struct ssb_bus ssb_bcm47xx;
@@ -57,68 +56,112 @@ static void bcm47xx_machine_halt(void)
                cpu_relax();
 }
 
-static void str2eaddr(char *str, char *dest)
-{
-       int i = 0;
+#define READ_FROM_NVRAM(_outvar, name, buf) \
+       if (nvram_getenv(name, buf, sizeof(buf)) >= 0)\
+               sprom->_outvar = simple_strtoul(buf, NULL, 0);
 
-       if (str == NULL) {
-               memset(dest, 0, 6);
-               return;
+static void bcm47xx_fill_sprom(struct ssb_sprom *sprom)
+{
+       char buf[100];
+       u32 boardflags;
+
+       memset(sprom, 0, sizeof(struct ssb_sprom));
+
+       sprom->revision = 1; /* Fallback: Old hardware does not define this. */
+       READ_FROM_NVRAM(revision, "sromrev", buf);
+       if (nvram_getenv("il0macaddr", buf, sizeof(buf)) >= 0)
+               nvram_parse_macaddr(buf, sprom->il0mac);
+       if (nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
+               nvram_parse_macaddr(buf, sprom->et0mac);
+       if (nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
+               nvram_parse_macaddr(buf, sprom->et1mac);
+       READ_FROM_NVRAM(et0phyaddr, "et0phyaddr", buf);
+       READ_FROM_NVRAM(et1phyaddr, "et1phyaddr", buf);
+       READ_FROM_NVRAM(et0mdcport, "et0mdcport", buf);
+       READ_FROM_NVRAM(et1mdcport, "et1mdcport", buf);
+       READ_FROM_NVRAM(board_rev, "boardrev", buf);
+       READ_FROM_NVRAM(country_code, "ccode", buf);
+       READ_FROM_NVRAM(ant_available_a, "aa5g", buf);
+       READ_FROM_NVRAM(ant_available_bg, "aa2g", buf);
+       READ_FROM_NVRAM(pa0b0, "pa0b0", buf);
+       READ_FROM_NVRAM(pa0b1, "pa0b1", buf);
+       READ_FROM_NVRAM(pa0b2, "pa0b2", buf);
+       READ_FROM_NVRAM(pa1b0, "pa1b0", buf);
+       READ_FROM_NVRAM(pa1b1, "pa1b1", buf);
+       READ_FROM_NVRAM(pa1b2, "pa1b2", buf);
+       READ_FROM_NVRAM(pa1lob0, "pa1lob0", buf);
+       READ_FROM_NVRAM(pa1lob2, "pa1lob1", buf);
+       READ_FROM_NVRAM(pa1lob1, "pa1lob2", buf);
+       READ_FROM_NVRAM(pa1hib0, "pa1hib0", buf);
+       READ_FROM_NVRAM(pa1hib2, "pa1hib1", buf);
+       READ_FROM_NVRAM(pa1hib1, "pa1hib2", buf);
+       READ_FROM_NVRAM(gpio0, "wl0gpio0", buf);
+       READ_FROM_NVRAM(gpio1, "wl0gpio1", buf);
+       READ_FROM_NVRAM(gpio2, "wl0gpio2", buf);
+       READ_FROM_NVRAM(gpio3, "wl0gpio3", buf);
+       READ_FROM_NVRAM(maxpwr_bg, "pa0maxpwr", buf);
+       READ_FROM_NVRAM(maxpwr_al, "pa1lomaxpwr", buf);
+       READ_FROM_NVRAM(maxpwr_a, "pa1maxpwr", buf);
+       READ_FROM_NVRAM(maxpwr_ah, "pa1himaxpwr", buf);
+       READ_FROM_NVRAM(itssi_a, "pa1itssit", buf);
+       READ_FROM_NVRAM(itssi_bg, "pa0itssit", buf);
+       READ_FROM_NVRAM(tri2g, "tri2g", buf);
+       READ_FROM_NVRAM(tri5gl, "tri5gl", buf);
+       READ_FROM_NVRAM(tri5g, "tri5g", buf);
+       READ_FROM_NVRAM(tri5gh, "tri5gh", buf);
+       READ_FROM_NVRAM(rxpo2g, "rxpo2g", buf);
+       READ_FROM_NVRAM(rxpo5g, "rxpo5g", buf);
+       READ_FROM_NVRAM(rssisav2g, "rssisav2g", buf);
+       READ_FROM_NVRAM(rssismc2g, "rssismc2g", buf);
+       READ_FROM_NVRAM(rssismf2g, "rssismf2g", buf);
+       READ_FROM_NVRAM(bxa2g, "bxa2g", buf);
+       READ_FROM_NVRAM(rssisav5g, "rssisav5g", buf);
+       READ_FROM_NVRAM(rssismc5g, "rssismc5g", buf);
+       READ_FROM_NVRAM(rssismf5g, "rssismf5g", buf);
+       READ_FROM_NVRAM(bxa5g, "bxa5g", buf);
+       READ_FROM_NVRAM(cck2gpo, "cck2gpo", buf);
+       READ_FROM_NVRAM(ofdm2gpo, "ofdm2gpo", buf);
+       READ_FROM_NVRAM(ofdm5glpo, "ofdm5glpo", buf);
+       READ_FROM_NVRAM(ofdm5gpo, "ofdm5gpo", buf);
+       READ_FROM_NVRAM(ofdm5ghpo, "ofdm5ghpo", buf);
+
+       if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0) {
+               boardflags = simple_strtoul(buf, NULL, 0);
+               if (boardflags) {
+                       sprom->boardflags_lo = (boardflags & 0x0000FFFFU);
+                       sprom->boardflags_hi = (boardflags & 0xFFFF0000U) >> 16;
+               }
        }
-
-       for (;;) {
-               dest[i++] = (char) simple_strtoul(str, NULL, 16);
-               str += 2;
-               if (!*str++ || i == 6)
-                       break;
+       if (nvram_getenv("boardflags2", buf, sizeof(buf)) >= 0) {
+               boardflags = simple_strtoul(buf, NULL, 0);
+               if (boardflags) {
+                       sprom->boardflags2_lo = (boardflags & 0x0000FFFFU);
+                       sprom->boardflags2_hi = (boardflags & 0xFFFF0000U) >> 16;
+               }
        }
 }
 
 static int bcm47xx_get_invariants(struct ssb_bus *bus,
                                   struct ssb_init_invariants *iv)
 {
-       char buf[100];
+       char buf[20];
 
        /* Fill boardinfo structure */
        memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
 
-       if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0)
-               iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
-       if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
+       if (nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0)
+               iv->boardinfo.vendor = (u16)simple_strtoul(buf, NULL, 0);
+       else
+               iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
+       if (nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
                iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
-       if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
+       if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
                iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
 
-       /* Fill sprom structure */
-       memset(&(iv->sprom), 0, sizeof(struct ssb_sprom));
-       iv->sprom.revision = 3;
-
-       if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
-               str2eaddr(buf, iv->sprom.et0mac);
+       bcm47xx_fill_sprom(&iv->sprom);
 
-       if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
-               str2eaddr(buf, iv->sprom.et1mac);
-
-       if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
-               iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 0);
-
-       if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
-               iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 0);
-
-       if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
-               iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10);
-
-       if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
-               iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10);
+       if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
+               iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
 
        return 0;
 }
@@ -126,12 +169,28 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus,
 void __init plat_mem_setup(void)
 {
        int err;
+       char buf[100];
+       struct ssb_mipscore *mcore;
 
        err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
                                      bcm47xx_get_invariants);
        if (err)
                panic("Failed to initialize SSB bus (err %d)\n", err);
 
+       mcore = &ssb_bcm47xx.mipscore;
+       if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) {
+               if (strstr(buf, "console=ttyS1")) {
+                       struct ssb_serial_port port;
+
+                       printk(KERN_DEBUG "Swapping serial ports!\n");
+                       /* swap serial ports */
+                       memcpy(&port, &mcore->serial_ports[0], sizeof(port));
+                       memcpy(&mcore->serial_ports[0], &mcore->serial_ports[1],
+                              sizeof(port));
+                       memcpy(&mcore->serial_ports[1], &port, sizeof(port));
+               }
+       }
+
        _machine_restart = bcm47xx_machine_restart;
        _machine_halt = bcm47xx_machine_halt;
        pm_power_off = bcm47xx_machine_halt;
index 06d59dcbe24310a92669983231a51e3aad34d324..86877539c6e83679f248d7245324693a690105e6 100644 (file)
  * These are the PRID's for when 23:16 == PRID_COMP_BROADCOM
  */
 
-#define PRID_IMP_BMIPS4KC      0x4000
-#define PRID_IMP_BMIPS32       0x8000
+#define PRID_IMP_BMIPS32_REV4  0x4000
+#define PRID_IMP_BMIPS32_REV8  0x8000
 #define PRID_IMP_BMIPS3300     0x9000
 #define PRID_IMP_BMIPS3300_ALT 0x9100
 #define PRID_IMP_BMIPS3300_BUG 0x0000
index fd1d39eb74319b60473daf46cb5e4ecf1bcacb2e..455c0ac7d4ea84632cc41c40ee48e7dd9e82ce86 100644 (file)
@@ -249,7 +249,8 @@ extern struct mips_abi mips_abi_n32;
 
 #define SET_PERSONALITY(ex)                                            \
 do {                                                                   \
-       set_personality(PER_LINUX);                                     \
+       if (personality(current->personality) != PER_LINUX)             \
+               set_personality(PER_LINUX);                             \
                                                                        \
        current->thread.abi = &mips_abi;                                \
 } while (0)
@@ -296,6 +297,8 @@ do {                                                                        \
 
 #define SET_PERSONALITY(ex)                                            \
 do {                                                                   \
+       unsigned int p;                                                 \
+                                                                       \
        clear_thread_flag(TIF_32BIT_REGS);                              \
        clear_thread_flag(TIF_32BIT_ADDR);                              \
                                                                        \
@@ -304,7 +307,8 @@ do {                                                                        \
        else                                                            \
                current->thread.abi = &mips_abi;                        \
                                                                        \
-       if (current->personality != PER_LINUX32)                        \
+       p = personality(current->personality);                          \
+       if (p != PER_LINUX32 && p != PER_LINUX)                         \
                set_personality(PER_LINUX);                             \
 } while (0)
 
index c98bf514ec7de9efe6596721cfa472d878da3f16..5b017f23e243d71b195cfea786c70ef389da7810 100644 (file)
@@ -329,10 +329,14 @@ static inline void pfx##write##bwlq(type val,                             \
                        "dsrl32 %L0, %L0, 0"                    "\n\t"  \
                        "dsll32 %M0, %M0, 0"                    "\n\t"  \
                        "or     %L0, %L0, %M0"                  "\n\t"  \
+                       ".set   push"                           "\n\t"  \
+                       ".set   noreorder"                      "\n\t"  \
+                       ".set   nomacro"                        "\n\t"  \
                        "sd     %L0, %2"                        "\n\t"  \
+                       ".set   pop"                            "\n\t"  \
                        ".set   mips0"                          "\n"    \
                        : "=r" (__tmp)                                  \
-                       : "0" (__val), "m" (*__mem));                   \
+                       : "0" (__val), "R" (*__mem));                   \
                if (irq)                                                \
                        local_irq_restore(__flags);                     \
        } else                                                          \
@@ -355,12 +359,16 @@ static inline type pfx##read##bwlq(const volatile void __iomem *mem)      \
                        local_irq_save(__flags);                        \
                __asm__ __volatile__(                                   \
                        ".set   mips3"          "\t\t# __readq" "\n\t"  \
+                       ".set   push"                           "\n\t"  \
+                       ".set   noreorder"                      "\n\t"  \
+                       ".set   nomacro"                        "\n\t"  \
                        "ld     %L0, %1"                        "\n\t"  \
+                       ".set   pop"                            "\n\t"  \
                        "dsra32 %M0, %L0, 0"                    "\n\t"  \
                        "sll    %L0, %L0, 0"                    "\n\t"  \
                        ".set   mips0"                          "\n"    \
                        : "=r" (__val)                                  \
-                       : "m" (*__mem));                                \
+                       : "R" (*__mem));                                \
                if (irq)                                                \
                        local_irq_restore(__flags);                     \
        } else {                                                        \
index 7919d76186bf1b78dca75c62e1fc41f731fc6ebb..07d3fadb24437e289bae5c8da747b2fdd647e8a5 100644 (file)
@@ -201,7 +201,6 @@ static inline void ar7_device_off(u32 bit)
 }
 
 int __init ar7_gpio_init(void);
-
-int __init ar7_gpio_init(void);
+void __init ar7_init_clocks(void);
 
 #endif /* __AR7_H__ */
index c58ebd8bc1551dd92e14111acc1ac92c4b17d1b7..9759588ba3cff0c81da6cd454148a6787e4babcf 100644 (file)
@@ -12,6 +12,7 @@
 #define __NVRAM_H
 
 #include <linux/types.h>
+#include <linux/kernel.h>
 
 struct nvram_header {
        u32 magic;
@@ -36,4 +37,10 @@ struct nvram_header {
 
 extern int nvram_getenv(char *name, char *val, size_t val_len);
 
+static inline void nvram_parse_macaddr(char *buf, u8 *macaddr)
+{
+       sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0], &macaddr[1],
+              &macaddr[2], &macaddr[3], &macaddr[4], &macaddr[5]);
+}
+
 #endif
index 5742bb4d78f4db6aefa966b443dee7e095a2cfc5..5c0a3575877cce27c171d2d9a676dd8cf8073a7a 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 2009 Qi Hardware inc.,
  * Author: Xiangfu Liu <xiangfu@qi-hardware.com>
- * Copyright 2010, Lars-Petrer Clausen <lars@metafoo.de>
+ * Copyright 2010, Lars-Peter Clausen <lars@metafoo.de>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 or later
@@ -235,7 +235,7 @@ static const unsigned int qi_lb60_keypad_rows[] = {
        QI_LB60_GPIO_KEYIN(3),
        QI_LB60_GPIO_KEYIN(4),
        QI_LB60_GPIO_KEYIN(5),
-       QI_LB60_GPIO_KEYIN(7),
+       QI_LB60_GPIO_KEYIN(6),
        QI_LB60_GPIO_KEYIN8,
 };
 
index 95bc2b5b14f1b2c56cd141f2c8a2b8ea6370dcde..1cc9e544d16bd16609aaef30bd5779ad26f5dc14 100644 (file)
@@ -208,7 +208,7 @@ struct platform_device jz4740_i2s_device = {
 
 /* PCM */
 struct platform_device jz4740_pcm_device = {
-       .name           = "jz4740-pcm",
+       .name           = "jz4740-pcm-audio",
        .id             = -1,
 };
 
index cfeac15eb2e4d5716530fd07c5b6db3a8d77cadb..4a70407f55bb7df9d68bc46256b8c007c08c6e59 100644 (file)
@@ -23,7 +23,7 @@
 #include <asm/bootinfo.h>
 #include <asm/mach-jz4740/base.h>
 
-void jz4740_init_cmdline(int argc, char *argv[])
+static __init void jz4740_init_cmdline(int argc, char *argv[])
 {
        unsigned int count = COMMAND_LINE_SIZE - 1;
        int i;
index 2f4d7a99bcc2fcc91b3838599b0b0c3d4fb1c432..98c5a9737c14d2c200a161640122f9a8af053e88 100644 (file)
@@ -32,7 +32,7 @@ static int mips_next_event(unsigned long delta,
        cnt = read_c0_count();
        cnt += delta;
        write_c0_compare(cnt);
-       res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0;
+       res = ((int)(read_c0_count() - cnt) >= 0) ? -ETIME : 0;
        return res;
 }
 
index 71620e19827ad681a7834f0e400104cec4968ef2..68dae7b6b5db62a0a48a17e6fe339a2d56bd8bd8 100644 (file)
@@ -905,7 +905,8 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
 {
        decode_configs(c);
        switch (c->processor_id & 0xff00) {
-       case PRID_IMP_BMIPS32:
+       case PRID_IMP_BMIPS32_REV4:
+       case PRID_IMP_BMIPS32_REV8:
                c->cputype = CPU_BMIPS32;
                __cpu_name[cpu] = "Broadcom BMIPS32";
                break;
@@ -933,10 +934,6 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
                __cpu_name[cpu] = "Broadcom BMIPS5000";
                c->options |= MIPS_CPU_ULRI;
                break;
-       case PRID_IMP_BMIPS4KC:
-               c->cputype = CPU_4KC;
-               __cpu_name[cpu] = "MIPS 4Kc";
-               break;
        }
 }
 
index 6343b4a5b8350cb3a93edea5d75f3154cde48343..876a75cc376f7a8602d231c1c11440be8c88d7ae 100644 (file)
@@ -251,14 +251,15 @@ SYSCALL_DEFINE5(n32_msgrcv, int, msqid, u32, msgp, size_t, msgsz,
 
 SYSCALL_DEFINE1(32_personality, unsigned long, personality)
 {
+       unsigned int p = personality & 0xffffffff;
        int ret;
-       personality &= 0xffffffff;
+
        if (personality(current->personality) == PER_LINUX32 &&
-           personality == PER_LINUX)
-               personality = PER_LINUX32;
-       ret = sys_personality(personality);
-       if (ret == PER_LINUX32)
-               ret = PER_LINUX;
+           personality(p) == PER_LINUX)
+               p = (p & ~PER_MASK) | PER_LINUX32;
+       ret = sys_personality(p);
+       if (ret != -1 && personality(ret) == PER_LINUX32)
+               ret = (ret & ~PER_MASK) | PER_LINUX;
        return ret;
 }
 
index 99960940d4a410bba1e9842a7049161e74d04d25..ae167df73dddf2df41a2158050c164cb4fb346d4 100644 (file)
@@ -142,7 +142,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
        childregs->regs[7] = 0; /* Clear error flag */
 
        childregs->regs[2] = 0; /* Child gets zero as return value */
-       regs->regs[2] = p->pid;
 
        if (childregs->cp0_status & ST0_CU0) {
                childregs->regs[28] = (unsigned long) ti;
index e000b278f0243cfdfa1986be89b728c5b371a480..9dbe58368953809f721e845a004f98cb57809dba 100644 (file)
@@ -100,7 +100,7 @@ void __init device_tree_init(void)
                return;
 
        base = virt_to_phys((void *)initial_boot_params);
-       size = initial_boot_params->totalsize;
+       size = be32_to_cpu(initial_boot_params->totalsize);
 
        /* Before we do anything, lets reserve the dt blob */
        reserve_mem_mach(base, size);
index 43e7cdc5ded23a42fa1a8f24376ddf60eb96ccac..c0e81418ba21281ea4f3b5cedff5e564f947c1a1 100644 (file)
@@ -153,7 +153,7 @@ static void __cpuinit vsmp_init_secondary(void)
 {
        extern int gic_present;
 
-       /* This is Malta specific: IPI,performance and timer inetrrupts */
+       /* This is Malta specific: IPI,performance and timer interrupts */
        if (gic_present)
                change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 |
                                         STATUSF_IP6 | STATUSF_IP7);
index 8e9fbe75894e5f5199618264fcddde6410d42dc7..e97104302541fd4111ae9ceca477e04cf2b5add7 100644 (file)
@@ -83,7 +83,8 @@ extern asmlinkage void handle_mcheck(void);
 extern asmlinkage void handle_reserved(void);
 
 extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
-       struct mips_fpu_struct *ctx, int has_fpu);
+                                   struct mips_fpu_struct *ctx, int has_fpu,
+                                   void *__user *fault_addr);
 
 void (*board_be_init)(void);
 int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
@@ -661,12 +662,36 @@ asmlinkage void do_ov(struct pt_regs *regs)
        force_sig_info(SIGFPE, &info, current);
 }
 
+static int process_fpemu_return(int sig, void __user *fault_addr)
+{
+       if (sig == SIGSEGV || sig == SIGBUS) {
+               struct siginfo si = {0};
+               si.si_addr = fault_addr;
+               si.si_signo = sig;
+               if (sig == SIGSEGV) {
+                       if (find_vma(current->mm, (unsigned long)fault_addr))
+                               si.si_code = SEGV_ACCERR;
+                       else
+                               si.si_code = SEGV_MAPERR;
+               } else {
+                       si.si_code = BUS_ADRERR;
+               }
+               force_sig_info(sig, &si, current);
+               return 1;
+       } else if (sig) {
+               force_sig(sig, current);
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
 /*
  * XXX Delayed fp exceptions when doing a lazy ctx switch XXX
  */
 asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
 {
-       siginfo_t info;
+       siginfo_t info = {0};
 
        if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), SIGFPE)
            == NOTIFY_STOP)
@@ -675,6 +700,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
 
        if (fcr31 & FPU_CSR_UNI_X) {
                int sig;
+               void __user *fault_addr = NULL;
 
                /*
                 * Unimplemented operation exception.  If we've got the full
@@ -690,7 +716,8 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
                lose_fpu(1);
 
                /* Run the emulator */
-               sig = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1);
+               sig = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1,
+                                              &fault_addr);
 
                /*
                 * We can't allow the emulated instruction to leave any of
@@ -702,8 +729,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
                own_fpu(1);     /* Using the FPU again.  */
 
                /* If something went wrong, signal */
-               if (sig)
-                       force_sig(sig, current);
+               process_fpemu_return(sig, fault_addr);
 
                return;
        } else if (fcr31 & FPU_CSR_INV_X)
@@ -996,11 +1022,11 @@ asmlinkage void do_cpu(struct pt_regs *regs)
 
                if (!raw_cpu_has_fpu) {
                        int sig;
+                       void __user *fault_addr = NULL;
                        sig = fpu_emulator_cop1Handler(regs,
-                                               &current->thread.fpu, 0);
-                       if (sig)
-                               force_sig(sig, current);
-                       else
+                                                      &current->thread.fpu,
+                                                      0, &fault_addr);
+                       if (!process_fpemu_return(sig, fault_addr))
                                mt_ase_fp_affinity();
                }
 
index 3eb3cde2f66160c0b4f5aeee889dc9adbfedf823..6a1fdfef8fded5763a457ec026467b356717fc78 100644 (file)
@@ -1092,6 +1092,10 @@ static int vpe_open(struct inode *inode, struct file *filp)
 
        /* this of-course trashes what was there before... */
        v->pbuffer = vmalloc(P_SIZE);
+       if (!v->pbuffer) {
+               pr_warning("VPE loader: unable to allocate memory\n");
+               return -ENOMEM;
+       }
        v->plen = P_SIZE;
        v->load_addr = NULL;
        v->len = 0;
@@ -1149,10 +1153,9 @@ static int vpe_release(struct inode *inode, struct file *filp)
        if (ret < 0)
                v->shared_ptr = NULL;
 
-       // cleanup any temp buffers
-       if (v->pbuffer)
-               vfree(v->pbuffer);
+       vfree(v->pbuffer);
        v->plen = 0;
+
        return ret;
 }
 
@@ -1169,11 +1172,6 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer,
        if (v == NULL)
                return -ENODEV;
 
-       if (v->pbuffer == NULL) {
-               printk(KERN_ERR "VPE loader: no buffer for program\n");
-               return -ENOMEM;
-       }
-
        if ((count + v->len) > v->plen) {
                printk(KERN_WARNING
                       "VPE loader: elf size too big. Perhaps strip uneeded symbols\n");
index 77dc3b20110ab9d583e09a9cac94e865bc2deab1..606c8a9efe3bb146930aca3b7c438f0095cbe066 100644 (file)
@@ -161,16 +161,16 @@ FEXPORT(__bzero)
 
 .Lfwd_fixup:
        PTR_L           t0, TI_TASK($28)
-       LONG_L          t0, THREAD_BUADDR(t0)
        andi            a2, 0x3f
+       LONG_L          t0, THREAD_BUADDR(t0)
        LONG_ADDU       a2, t1
        jr              ra
         LONG_SUBU      a2, t0
 
 .Lpartial_fixup:
        PTR_L           t0, TI_TASK($28)
-       LONG_L          t0, THREAD_BUADDR(t0)
        andi            a2, LONGMASK
+       LONG_L          t0, THREAD_BUADDR(t0)
        LONG_ADDU       a2, t1
        jr              ra
         LONG_SUBU      a2, t0
index ae4cff97a56c5073d75925a7c89a94ee5a410513..11b193f848f88b7aa1c5ab5a842c2cf4e80ed7d7 100644 (file)
@@ -29,9 +29,9 @@ unsigned long memsize, highmemsize;
 
 #define parse_even_earlier(res, option, p)                             \
 do {                                                                   \
+       int ret;                                                        \
        if (strncmp(option, (char *)p, strlen(option)) == 0)            \
-                       strict_strtol((char *)p + strlen(option"="),    \
-                                       10, &res);                      \
+               ret = strict_strtol((char *)p + strlen(option"="), 10, &res); \
 } while (0)
 
 void __init prom_init_env(void)
index b2ad1b0910ffb86d009dac8769310f30af3c3fcc..d32cb050311053a8e873ea470617b0ec17f13e26 100644 (file)
@@ -64,7 +64,7 @@ static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *,
 
 #if __mips >= 4 && __mips != 32
 static int fpux_emu(struct pt_regs *,
-       struct mips_fpu_struct *, mips_instruction);
+       struct mips_fpu_struct *, mips_instruction, void *__user *);
 #endif
 
 /* Further private data for which no space exists in mips_fpu_struct */
@@ -208,16 +208,23 @@ static inline int cop1_64bit(struct pt_regs *xcp)
  * Two instructions if the instruction is in a branch delay slot.
  */
 
-static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
+static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
+                      void *__user *fault_addr)
 {
        mips_instruction ir;
        unsigned long emulpc, contpc;
        unsigned int cond;
 
-       if (get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) {
+       if (!access_ok(VERIFY_READ, xcp->cp0_epc, sizeof(mips_instruction))) {
                MIPS_FPU_EMU_INC_STATS(errors);
+               *fault_addr = (mips_instruction __user *)xcp->cp0_epc;
                return SIGBUS;
        }
+       if (__get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) {
+               MIPS_FPU_EMU_INC_STATS(errors);
+               *fault_addr = (mips_instruction __user *)xcp->cp0_epc;
+               return SIGSEGV;
+       }
 
        /* XXX NEC Vr54xx bug workaround */
        if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir))
@@ -245,10 +252,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
 #endif
                        return SIGILL;
                }
-               if (get_user(ir, (mips_instruction __user *) emulpc)) {
+               if (!access_ok(VERIFY_READ, emulpc, sizeof(mips_instruction))) {
                        MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = (mips_instruction __user *)emulpc;
                        return SIGBUS;
                }
+               if (__get_user(ir, (mips_instruction __user *) emulpc)) {
+                       MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = (mips_instruction __user *)emulpc;
+                       return SIGSEGV;
+               }
                /* __compute_return_epc() will have updated cp0_epc */
                contpc = xcp->cp0_epc;
                /* In order not to confuse ptrace() et al, tweak context */
@@ -269,10 +282,17 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
                u64 val;
 
                MIPS_FPU_EMU_INC_STATS(loads);
-               if (get_user(val, va)) {
+
+               if (!access_ok(VERIFY_READ, va, sizeof(u64))) {
                        MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
                        return SIGBUS;
                }
+               if (__get_user(val, va)) {
+                       MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
+                       return SIGSEGV;
+               }
                DITOREG(val, MIPSInst_RT(ir));
                break;
        }
@@ -284,10 +304,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
 
                MIPS_FPU_EMU_INC_STATS(stores);
                DIFROMREG(val, MIPSInst_RT(ir));
-               if (put_user(val, va)) {
+               if (!access_ok(VERIFY_WRITE, va, sizeof(u64))) {
                        MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
                        return SIGBUS;
                }
+               if (__put_user(val, va)) {
+                       MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
+                       return SIGSEGV;
+               }
                break;
        }
 
@@ -297,10 +323,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
                u32 val;
 
                MIPS_FPU_EMU_INC_STATS(loads);
-               if (get_user(val, va)) {
+               if (!access_ok(VERIFY_READ, va, sizeof(u32))) {
                        MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
                        return SIGBUS;
                }
+               if (__get_user(val, va)) {
+                       MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
+                       return SIGSEGV;
+               }
                SITOREG(val, MIPSInst_RT(ir));
                break;
        }
@@ -312,10 +344,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
 
                MIPS_FPU_EMU_INC_STATS(stores);
                SIFROMREG(val, MIPSInst_RT(ir));
-               if (put_user(val, va)) {
+               if (!access_ok(VERIFY_WRITE, va, sizeof(u32))) {
                        MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
                        return SIGBUS;
                }
+               if (__put_user(val, va)) {
+                       MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
+                       return SIGSEGV;
+               }
                break;
        }
 
@@ -440,11 +478,18 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
                                contpc = (xcp->cp0_epc +
                                        (MIPSInst_SIMM(ir) << 2));
 
-                               if (get_user(ir,
-                                   (mips_instruction __user *) xcp->cp0_epc)) {
+                               if (!access_ok(VERIFY_READ, xcp->cp0_epc,
+                                              sizeof(mips_instruction))) {
                                        MIPS_FPU_EMU_INC_STATS(errors);
+                                       *fault_addr = (mips_instruction __user *)xcp->cp0_epc;
                                        return SIGBUS;
                                }
+                               if (__get_user(ir,
+                                   (mips_instruction __user *) xcp->cp0_epc)) {
+                                       MIPS_FPU_EMU_INC_STATS(errors);
+                                       *fault_addr = (mips_instruction __user *)xcp->cp0_epc;
+                                       return SIGSEGV;
+                               }
 
                                switch (MIPSInst_OPCODE(ir)) {
                                case lwc1_op:
@@ -506,9 +551,8 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
 
 #if __mips >= 4 && __mips != 32
        case cop1x_op:{
-               int sig;
-
-               if ((sig = fpux_emu(xcp, ctx, ir)))
+               int sig = fpux_emu(xcp, ctx, ir, fault_addr);
+               if (sig)
                        return sig;
                break;
        }
@@ -604,7 +648,7 @@ DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg);
 DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg);
 
 static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
-       mips_instruction ir)
+       mips_instruction ir, void *__user *fault_addr)
 {
        unsigned rcsr = 0;      /* resulting csr */
 
@@ -624,10 +668,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                                xcp->regs[MIPSInst_FT(ir)]);
 
                        MIPS_FPU_EMU_INC_STATS(loads);
-                       if (get_user(val, va)) {
+                       if (!access_ok(VERIFY_READ, va, sizeof(u32))) {
                                MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
                                return SIGBUS;
                        }
+                       if (__get_user(val, va)) {
+                               MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
+                               return SIGSEGV;
+                       }
                        SITOREG(val, MIPSInst_FD(ir));
                        break;
 
@@ -638,10 +688,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                        MIPS_FPU_EMU_INC_STATS(stores);
 
                        SIFROMREG(val, MIPSInst_FS(ir));
-                       if (put_user(val, va)) {
+                       if (!access_ok(VERIFY_WRITE, va, sizeof(u32))) {
                                MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
                                return SIGBUS;
                        }
+                       if (put_user(val, va)) {
+                               MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
+                               return SIGSEGV;
+                       }
                        break;
 
                case madd_s_op:
@@ -701,10 +757,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                                xcp->regs[MIPSInst_FT(ir)]);
 
                        MIPS_FPU_EMU_INC_STATS(loads);
-                       if (get_user(val, va)) {
+                       if (!access_ok(VERIFY_READ, va, sizeof(u64))) {
                                MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
                                return SIGBUS;
                        }
+                       if (__get_user(val, va)) {
+                               MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
+                               return SIGSEGV;
+                       }
                        DITOREG(val, MIPSInst_FD(ir));
                        break;
 
@@ -714,10 +776,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 
                        MIPS_FPU_EMU_INC_STATS(stores);
                        DIFROMREG(val, MIPSInst_FS(ir));
-                       if (put_user(val, va)) {
+                       if (!access_ok(VERIFY_WRITE, va, sizeof(u64))) {
                                MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
                                return SIGBUS;
                        }
+                       if (__put_user(val, va)) {
+                               MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
+                               return SIGSEGV;
+                       }
                        break;
 
                case madd_d_op:
@@ -1242,7 +1310,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 }
 
 int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
-       int has_fpu)
+       int has_fpu, void *__user *fault_addr)
 {
        unsigned long oldepc, prevepc;
        mips_instruction insn;
@@ -1252,10 +1320,16 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
        do {
                prevepc = xcp->cp0_epc;
 
-               if (get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) {
+               if (!access_ok(VERIFY_READ, xcp->cp0_epc, sizeof(mips_instruction))) {
                        MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = (mips_instruction __user *)xcp->cp0_epc;
                        return SIGBUS;
                }
+               if (__get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) {
+                       MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = (mips_instruction __user *)xcp->cp0_epc;
+                       return SIGSEGV;
+               }
                if (insn == 0)
                        xcp->cp0_epc += 4;      /* skip nops */
                else {
@@ -1267,7 +1341,7 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                         */
                        /* convert to ieee library modes */
                        ieee754_csr.rm = ieee_rm[ieee754_csr.rm];
-                       sig = cop1Emulate(xcp, ctx);
+                       sig = cop1Emulate(xcp, ctx, fault_addr);
                        /* revert to mips rounding mode */
                        ieee754_csr.rm = mips_rm[ieee754_csr.rm];
                }
index 4fc1a0fbe0074e154c64a89f8f40d90bd6e1bd91..21ea14efb83747c5275858c6b64a18b6ea040131 100644 (file)
@@ -288,7 +288,7 @@ int mips_dma_supported(struct device *dev, u64 mask)
        return plat_dma_supported(dev, mask);
 }
 
-void mips_dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
                         enum dma_data_direction direction)
 {
        BUG_ON(direction == DMA_NONE);
@@ -298,6 +298,8 @@ void mips_dma_cache_sync(struct device *dev, void *vaddr, size_t size,
                __dma_sync((unsigned long)vaddr, size, direction);
 }
 
+EXPORT_SYMBOL(dma_cache_sync);
+
 static struct dma_map_ops mips_default_dma_map_ops = {
        .alloc_coherent = mips_dma_alloc_coherent,
        .free_coherent = mips_dma_free_coherent,
index 505fecad4684f272b7a00d6dd8e3f3098875df4c..9cca8de0054507ca3869071d6bc72dab01e13170 100644 (file)
@@ -68,6 +68,9 @@ static struct bcache_ops mips_sc_ops = {
  */
 static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
 {
+       unsigned int config2 = read_c0_config2();
+       unsigned int tmp;
+
        /* Check the bypass bit (L2B) */
        switch (c->cputype) {
        case CPU_34K:
@@ -83,6 +86,7 @@ static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
                c->scache.linesz = 2 << tmp;
        else
                return 0;
+       return 1;
 }
 
 static inline int __init mips_sc_probe(void)
index b7f1d9c4a8a3c7d588b270d6bd6e1bad0590f6b2..434d7b1a8c6a7abf4c492a14b975111a21b1a4ab 100644 (file)
@@ -65,11 +65,15 @@ static unsigned char readb_outer_space(unsigned long long phys)
 
        __asm__ __volatile__ (
        "       .set    mips3           \n"
+       "       .set    push            \n"
+       "       .set    noreorder       \n"
+       "       .set    nomacro         \n"
        "       ld      %0, %1          \n"
+       "       .set    pop             \n"
        "       lbu     %0, (%0)        \n"
        "       .set    mips0           \n"
        : "=r" (res)
-       : "m" (vaddr));
+       : "R" (vaddr));
 
        write_c0_status(sr);
        ssnop_4();
@@ -89,11 +93,15 @@ static void writeb_outer_space(unsigned long long phys, unsigned char c)
 
        __asm__ __volatile__ (
        "       .set    mips3           \n"
+       "       .set    push            \n"
+       "       .set    noreorder       \n"
+       "       .set    nomacro         \n"
        "       ld      %0, %1          \n"
+       "       .set    pop             \n"
        "       sb      %2, (%0)        \n"
        "       .set    mips0           \n"
        : "=&r" (tmp)
-       : "m" (vaddr), "r" (c));
+       : "R" (vaddr), "r" (c));
 
        write_c0_status(sr);
        ssnop_4();
index c308989fc464c3c76a1bc258d38713543c4004c8..41707a245dea61c1cabd467f2bc3d2ec2ca28cd8 100644 (file)
@@ -82,7 +82,7 @@ int swarm_be_handler(struct pt_regs *regs, int is_fixup)
 enum swarm_rtc_type {
        RTC_NONE,
        RTC_XICOR,
-       RTC_M4LT81
+       RTC_M41T81,
 };
 
 enum swarm_rtc_type swarm_rtc_type;
@@ -96,7 +96,7 @@ void read_persistent_clock(struct timespec *ts)
                sec = xicor_get_time();
                break;
 
-       case RTC_M4LT81:
+       case RTC_M41T81:
                sec = m41t81_get_time();
                break;
 
@@ -115,7 +115,7 @@ int rtc_mips_set_time(unsigned long sec)
        case RTC_XICOR:
                return xicor_set_time(sec);
 
-       case RTC_M4LT81:
+       case RTC_M41T81:
                return m41t81_set_time(sec);
 
        case RTC_NONE:
@@ -141,7 +141,7 @@ void __init plat_mem_setup(void)
        if (xicor_probe())
                swarm_rtc_type = RTC_XICOR;
        if (m41t81_probe())
-               swarm_rtc_type = RTC_M4LT81;
+               swarm_rtc_type = RTC_M41T81;
 
 #ifdef CONFIG_VT
        screen_info = (struct screen_info) {
diff --git a/arch/mn10300/include/asm/syscall.h b/arch/mn10300/include/asm/syscall.h
new file mode 100644 (file)
index 0000000..b44b0bb
--- /dev/null
@@ -0,0 +1,117 @@
+/* Access to user system call parameters and results
+ *
+ * See asm-generic/syscall.h for function descriptions.
+ *
+ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_SYSCALL_H
+#define _ASM_SYSCALL_H
+
+#include <linux/sched.h>
+#include <linux/err.h>
+
+extern const unsigned long sys_call_table[];
+
+static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
+{
+       return regs->orig_d0;
+}
+
+static inline void syscall_rollback(struct task_struct *task,
+                                   struct pt_regs *regs)
+{
+       regs->d0 = regs->orig_d0;
+}
+
+static inline long syscall_get_error(struct task_struct *task,
+                                    struct pt_regs *regs)
+{
+       unsigned long error = regs->d0;
+       return IS_ERR_VALUE(error) ? error : 0;
+}
+
+static inline long syscall_get_return_value(struct task_struct *task,
+                                           struct pt_regs *regs)
+{
+       return regs->d0;
+}
+
+static inline void syscall_set_return_value(struct task_struct *task,
+                                           struct pt_regs *regs,
+                                           int error, long val)
+{
+       regs->d0 = (long) error ?: val;
+}
+
+static inline void syscall_get_arguments(struct task_struct *task,
+                                        struct pt_regs *regs,
+                                        unsigned int i, unsigned int n,
+                                        unsigned long *args)
+{
+       switch (i) {
+       case 0:
+               if (!n--) break;
+               *args++ = regs->a0;
+       case 1:
+               if (!n--) break;
+               *args++ = regs->d1;
+       case 2:
+               if (!n--) break;
+               *args++ = regs->a3;
+       case 3:
+               if (!n--) break;
+               *args++ = regs->a2;
+       case 4:
+               if (!n--) break;
+               *args++ = regs->d3;
+       case 5:
+               if (!n--) break;
+               *args++ = regs->d2;
+       case 6:
+               if (!n--) break;
+       default:
+               BUG();
+               break;
+       }
+}
+
+static inline void syscall_set_arguments(struct task_struct *task,
+                                        struct pt_regs *regs,
+                                        unsigned int i, unsigned int n,
+                                        const unsigned long *args)
+{
+       switch (i) {
+       case 0:
+               if (!n--) break;
+               regs->a0 = *args++;
+       case 1:
+               if (!n--) break;
+               regs->d1 = *args++;
+       case 2:
+               if (!n--) break;
+               regs->a3 = *args++;
+       case 3:
+               if (!n--) break;
+               regs->a2 = *args++;
+       case 4:
+               if (!n--) break;
+               regs->d3 = *args++;
+       case 5:
+               if (!n--) break;
+               regs->d2 = *args++;
+       case 6:
+               if (!n--) break;
+       default:
+               BUG();
+               break;
+       }
+}
+
+#endif /* _ASM_SYSCALL_H */
index 0d5d63c91dc3ee74457d183a11d59a149022d0c5..f28dc99c6f729a23ba20cd73dd1bb39d80917cda 100644 (file)
@@ -73,7 +73,8 @@ void gdbstub_io_init(void)
        GDBPORT_SERIAL_IER = UART_IER_RDI | UART_IER_RLSI;
 
        /* permit level 0 IRQs to take place */
-       local_change_intr_mask_level(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
+       arch_local_change_intr_mask_level(
+               NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
 }
 
 /*
index 97dfda23342c8d9fe8aef19d8c9d4dfaeb170a7d..abdeea153c89643184df8f7b1c13805a504b0b7a 100644 (file)
@@ -87,7 +87,8 @@ void __init gdbstub_io_init(void)
        tmp = *gdbstub_port->_control;
 
        /* permit level 0 IRQs only */
-       local_change_intr_mask_level(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
+       arch_local_change_intr_mask_level(
+               NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
 }
 
 /*
index a5fc3f05309b2fc26960a36fe68ef1339683c4fd..b169d99d9f20e8fd4b5da5ea353b70f02819844b 100644 (file)
@@ -1194,7 +1194,8 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
 
        asm volatile("mov mdr,%0" : "=d"(mdr));
        local_save_flags(epsw);
-       local_change_intr_mask_level(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
+       arch_local_change_intr_mask_level(
+               NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
 
        gdbstub_store_fpu();
 
index f860a340acc920e0565f4d341fa263b5c8ea49a5..75da468090b90342ef5ff2566389b6efa1b28487 100644 (file)
@@ -40,21 +40,17 @@ unsigned long long sched_clock(void)
                unsigned long long ll;
                unsigned l[2];
        } tsc64, result;
-       unsigned long tsc, tmp;
+       unsigned long tmp;
        unsigned product[3]; /* 96-bit intermediate value */
 
        /* cnt32_to_63() is not safe with preemption */
        preempt_disable();
 
-       /* read the TSC value
-        */
-       tsc = get_cycles();
-
-       /* expand to 64-bits.
+       /* expand the tsc to 64-bits.
         * - sched_clock() must be called once a minute or better or the
         *   following will go horribly wrong - see cnt32_to_63()
         */
-       tsc64.ll = cnt32_to_63(tsc) & 0x7fffffffffffffffULL;
+       tsc64.ll = cnt32_to_63(get_cycles()) & 0x7fffffffffffffffULL;
 
        preempt_enable();
 
index 5024f643b3b1a4c75a57a08756298c5b72e874a2..d7d94b845dc2c8bb08ece9d5e420f8cae5b7abe2 100644 (file)
@@ -75,9 +75,6 @@ static void cpu_unmask_irq(unsigned int irq)
        smp_send_all_nop();
 }
 
-void no_ack_irq(unsigned int irq) { }
-void no_end_irq(unsigned int irq) { }
-
 void cpu_ack_irq(unsigned int irq)
 {
        unsigned long mask = EIEM_MASK(irq);
@@ -241,7 +238,7 @@ int cpu_claim_irq(unsigned int irq, struct irq_chip *type, void *data)
 
        /* for iosapic interrupts */
        if (type) {
-               set_irq_chip_and_handler(irq, type, handle_level_irq);
+               set_irq_chip_and_handler(irq, type, handle_percpu_irq);
                set_irq_chip_data(irq, data);
                cpu_unmask_irq(irq);
        }
@@ -392,7 +389,7 @@ static void claim_cpu_irqs(void)
        int i;
        for (i = CPU_IRQ_BASE; i <= CPU_IRQ_MAX; i++) {
                set_irq_chip_and_handler(i, &cpu_interrupt_type,
-                       handle_level_irq);
+                                        handle_percpu_irq);
        }
 
        set_irq_handler(TIMER_IRQ, handle_percpu_irq);
index 35c827e94e311366af3bcaff6554688558d6dde5..609a331878e72e172fecc2e85c9695d2c36cad60 100644 (file)
@@ -98,7 +98,6 @@ void
 sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
 {
        struct rt_sigframe __user *frame;
-       struct siginfo si;
        sigset_t set;
        unsigned long usp = (regs->gr[30] & ~(0x01UL));
        unsigned long sigframe_size = PARISC_RT_SIGFRAME_SIZE;
@@ -178,13 +177,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
 
 give_sigsegv:
        DBG(1,"sys_rt_sigreturn: Sending SIGSEGV\n");
-       si.si_signo = SIGSEGV;
-       si.si_errno = 0;
-       si.si_code = SI_KERNEL;
-       si.si_pid = task_pid_vnr(current);
-       si.si_uid = current_uid();
-       si.si_addr = &frame->uc;
-       force_sig_info(SIGSEGV, &si, current);
+       force_sig(SIGSEGV, current);
        return;
 }
 
index b6447190e1a2acee2b6fddf9ef90bd5a3d0a1da9..e625e9e034ae19abe973282a3d83952493e8b709 100644 (file)
@@ -4,6 +4,10 @@ config PPC32
        bool
        default y if !PPC64
 
+config 32BIT
+       bool
+       default y if PPC32
+
 config 64BIT
        bool
        default y if PPC64
index 722f360a32a9e905b2edf6f3cdb90b9ef9e5d588..d271ab5426732ab07ec0bec73e52a195e493fe64 100644 (file)
@@ -33,9 +33,10 @@ __div64_32:
        cntlzw  r0,r5           # we are shifting the dividend right
        li      r10,-1          # to make it < 2^32, and shifting
        srw     r10,r10,r0      # the divisor right the same amount,
-       add     r9,r4,r10       # rounding up (so the estimate cannot
+       addc    r9,r4,r10       # rounding up (so the estimate cannot
        andc    r11,r6,r10      # ever be too large, only too small)
        andc    r9,r9,r10
+       addze   r9,r9
        or      r11,r5,r11
        rotlw   r9,r9,r0
        rotlw   r11,r11,r0
index 7a9db64f3f0438f8bf366b9cb2244f1ef3178004..42850ee00adabfa33f0bb5ccd69efe1388d8ec96 100644 (file)
@@ -337,7 +337,7 @@ char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
                /* FP registers 32 -> 63 */
 #if defined(CONFIG_FSL_BOOKE) && defined(CONFIG_SPE)
                if (current)
-                       memcpy(mem, current->thread.evr[regno-32],
+                       memcpy(mem, &current->thread.evr[regno-32],
                                        dbg_reg_def[regno].size);
 #else
                /* fp registers not used by kernel, leave zero */
@@ -362,7 +362,7 @@ int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
        if (regno >= 32 && regno < 64) {
                /* FP registers 32 -> 63 */
 #if defined(CONFIG_FSL_BOOKE) && defined(CONFIG_SPE)
-               memcpy(current->thread.evr[regno-32], mem,
+               memcpy(&current->thread.evr[regno-32], mem,
                                dbg_reg_def[regno].size);
 #else
                /* fp registers not used by kernel, leave zero */
index 2a178b0ebcdf8ea33ed67c8a4516b7ec0f1d9f26..ce6f61c6f871022baedac98bd751de6110ff42c1 100644 (file)
@@ -497,9 +497,8 @@ static void __init emergency_stack_init(void)
 }
 
 /*
- * Called into from start_kernel, after lock_kernel has been called.
- * Initializes bootmem, which is unsed to manage page allocation until
- * mem_init is called.
+ * Called into from start_kernel this initializes bootmem, which is used
+ * to manage page allocation until mem_init is called.
  */
 void __init setup_arch(char **cmdline_p)
 {
index 83f534d862db2cd3934fca431e9b4d67b4ac7d38..5e9584405c4560c13c5567ba6affa81b2391e6bd 100644 (file)
@@ -1123,7 +1123,7 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
        else
 #endif /* CONFIG_PPC_HAS_HASH_64K */
                rc = __hash_page_4K(ea, access, vsid, ptep, trap, local, ssize,
-                                   subpage_protection(pgdir, ea));
+                                   subpage_protection(mm, ea));
 
        /* Dump some info in case of hash insertion failure, they should
         * never happen so it is really useful to know if/when they do
index 2c7e801ab20b617cc3934e9ad355af8b8734a0ec..6a3997f98dfb90a2f3d01da4b53156c2098a38f8 100644 (file)
@@ -92,7 +92,7 @@ static void pte_free_rcu_callback(struct rcu_head *head)
 
 static void pte_free_submit(struct pte_freelist_batch *batch)
 {
-       call_rcu(&batch->rcu, pte_free_rcu_callback);
+       call_rcu_sched(&batch->rcu, pte_free_rcu_callback);
 }
 
 void pgtable_free_tlb(struct mmu_gather *tlb, void *table, unsigned shift)
index 8b04c54e596f2a5a1bf770cb44013808eaf27246..8526bd9d2aa33603be03dbf10bc3656c7a833448 100644 (file)
        cmpldi  cr0,r15,0                       /* Check for user region */
        std     r14,EX_TLB_ESR(r12)             /* write crazy -1 to frame */
        beq     normal_tlb_miss
+
+       li      r11,_PAGE_PRESENT|_PAGE_BAP_SX  /* Base perm */
+       oris    r11,r11,_PAGE_ACCESSED@h
        /* XXX replace the RMW cycles with immediate loads + writes */
-1:     mfspr   r10,SPRN_MAS1
+       mfspr   r10,SPRN_MAS1
        cmpldi  cr0,r15,8                       /* Check for vmalloc region */
        rlwinm  r10,r10,0,16,1                  /* Clear TID */
        mtspr   SPRN_MAS1,r10
index 36c0c449a89993659c60d1b4c4b772fb5aa5f94c..2a030d89bbc6e65a847a29f6c4bf012f2e6188b0 100644 (file)
@@ -585,6 +585,6 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base,
        ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000);
 
        /* Finally limit subsequent allocations */
-       memblock_set_current_limit(ppc64_memblock_base + ppc64_rma_size);
+       memblock_set_current_limit(first_memblock_base + ppc64_rma_size);
 }
 #endif /* CONFIG_PPC64 */
index c667f0f02c34cc44eb75138e8eae6b140a49c3e8..3139814f643985e1879ed876b651a7f1e2a370a7 100644 (file)
@@ -47,6 +47,12 @@ config LPARCFG
 config PPC_PSERIES_DEBUG
        depends on PPC_PSERIES && PPC_EARLY_DEBUG
        bool "Enable extra debug logging in platforms/pseries"
+        help
+         Say Y here if you want the pseries core to produce a bunch of
+         debug messages to the system log. Select this if you are having a
+         problem with the pseries core and want to see more of what is
+         going on. This does not enable debugging in lpar.c, which must
+         be manually done due to its verbosity.
        default y
 
 config PPC_SMLPAR
index 34b7dc12e731231e9c0110bbe7caeda20ec5c0c0..17a11c82e6f8d61676edc341783a81fc4da1cb4a 100644 (file)
@@ -21,8 +21,6 @@
  * Please address comments and feedback to Linas Vepstas <linas@austin.ibm.com>
  */
 
-#undef DEBUG
-
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/list.h>
index 4b7a062dee15373e93b0b44c66c5ad0fbd5ee086..5fcc92a12d3e1256b1c5d648b624f4791e3b0817 100644 (file)
@@ -25,8 +25,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#undef DEBUG
-
 #include <linux/pci.h>
 #include <asm/pci-bridge.h>
 #include <asm/ppc-pci.h>
index ac151399ef34153cb69da534bd52ff51fd2528fb..1995c1712fc83485193dab760623241576b0ef29 100644 (file)
@@ -95,7 +95,6 @@ EXPORT_SYMBOL_GPL(s390_handle_mcck);
 static int notrace s390_revalidate_registers(struct mci *mci)
 {
        int kill_task;
-       u64 tmpclock;
        u64 zero;
        void *fpt_save_area, *fpt_creg_save_area;
 
@@ -214,11 +213,10 @@ static int notrace s390_revalidate_registers(struct mci *mci)
                        : "0", "cc");
 #endif
        /* Revalidate clock comparator register */
-       asm volatile(
-               "       stck    0(%1)\n"
-               "       sckc    0(%1)"
-               : "=m" (tmpclock) : "a" (&(tmpclock)) : "cc", "memory");
-
+       if (S390_lowcore.clock_comparator == -1)
+               set_clock_comparator(S390_lowcore.mcck_clock);
+       else
+               set_clock_comparator(S390_lowcore.clock_comparator);
        /* Check if old PSW is valid */
        if (!mci->wp)
                /*
index 56c8687b29b3a48b9487921d2b0fdaea5767ec5b..7eff9b7347c00ff8a825624500f5713a04ccd79e 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/rcupdate.h>
 #include <linux/posix-timers.h>
+#include <linux/cpu.h>
 
 #include <asm/s390_ext.h>
 #include <asm/timer.h>
@@ -566,6 +567,23 @@ void init_cpu_vtimer(void)
        __ctl_set_bit(0,10);
 }
 
+static int __cpuinit s390_nohz_notify(struct notifier_block *self,
+                                     unsigned long action, void *hcpu)
+{
+       struct s390_idle_data *idle;
+       long cpu = (long) hcpu;
+
+       idle = &per_cpu(s390_idle, cpu);
+       switch (action) {
+       case CPU_DYING:
+       case CPU_DYING_FROZEN:
+               idle->nohz_delay = 0;
+       default:
+               break;
+       }
+       return NOTIFY_OK;
+}
+
 void __init vtime_init(void)
 {
        /* request the cpu timer external interrupt */
@@ -574,5 +592,6 @@ void __init vtime_init(void)
 
        /* Enable cpu timer interrupts on the boot cpu. */
        init_cpu_vtimer();
+       cpu_notifier(s390_nohz_notify, 0);
 }
 
index 752b362bf651d7e1bdf84a3f54601ddf863e8b12..7c37ec359ec29ad40fc2cf47642316ac3cbba8bc 100644 (file)
@@ -29,17 +29,21 @@ static void __udelay_disabled(unsigned long long usecs)
 {
        unsigned long mask, cr0, cr0_saved;
        u64 clock_saved;
+       u64 end;
 
+       mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT;
+       end = get_clock() + (usecs << 12);
        clock_saved = local_tick_disable();
-       set_clock_comparator(get_clock() + (usecs << 12));
        __ctl_store(cr0_saved, 0, 0);
        cr0 = (cr0_saved & 0xffff00e0) | 0x00000800;
        __ctl_load(cr0 , 0, 0);
-       mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT;
        lockdep_off();
-       trace_hardirqs_on();
-       __load_psw_mask(mask);
-       local_irq_disable();
+       do {
+               set_clock_comparator(end);
+               trace_hardirqs_on();
+               __load_psw_mask(mask);
+               local_irq_disable();
+       } while (get_clock() < end);
        lockdep_on();
        __ctl_load(cr0_saved, 0, 0);
        local_tick_enable(clock_saved);
index 7f217b3a50a806b7347f991b588397011aa3388e..2e9d78d21fd36f9648286b2eb46df84beb4c9816 100644 (file)
@@ -22,7 +22,8 @@ config SUPERH
        select HAVE_SPARSE_IRQ
        select RTC_LIB
        select GENERIC_ATOMIC64
-       select GENERIC_HARDIRQS_NO_DEPRECATED
+       # Support the deprecated APIs until MFD and GPIOLIB catch up.
+       select GENERIC_HARDIRQS_NO_DEPRECATED if !MFD_SUPPORT && !GPIOLIB
        help
          The SuperH is a RISC processor targeted for use in embedded systems
          and consumer electronics; it was also used in the Sega Dreamcast
index 2eaeb9e5958575f59f3dd1f8d40b54ae03f5de00..f48c492a68d3824158828e820175446eb7ecc44a 100644 (file)
@@ -720,32 +720,6 @@ static struct platform_device camera_devices[] = {
 };
 
 /* FSI */
-/*
- * FSI-B use external clock which came from da7210.
- * So, we should change parent of fsi
- */
-#define FCLKBCR                0xa415000c
-static void fsimck_init(struct clk *clk)
-{
-       u32 status = __raw_readl(clk->enable_reg);
-
-       /* use external clock */
-       status &= ~0x000000ff;
-       status |= 0x00000080;
-
-       __raw_writel(status, clk->enable_reg);
-}
-
-static struct clk_ops fsimck_clk_ops = {
-       .init = fsimck_init,
-};
-
-static struct clk fsimckb_clk = {
-       .ops            = &fsimck_clk_ops,
-       .enable_reg     = (void __iomem *)FCLKBCR,
-       .rate           = 0, /* unknown */
-};
-
 static struct sh_fsi_platform_info fsi_info = {
        .portb_flags = SH_FSI_BRS_INV |
                       SH_FSI_OUT_SLAVE_MODE |
@@ -1264,10 +1238,10 @@ static int __init arch_setup(void)
        /* change parent of FSI B */
        clk = clk_get(NULL, "fsib_clk");
        if (!IS_ERR(clk)) {
-               clk_register(&fsimckb_clk);
-               clk_set_parent(clk, &fsimckb_clk);
-               clk_set_rate(clk, 11000);
-               clk_set_rate(&fsimckb_clk, 11000);
+               /* 48kHz dummy clock was used to make sure 1/1 divide */
+               clk_set_rate(&sh7724_fsimckb_clk, 48000);
+               clk_set_parent(clk, &sh7724_fsimckb_clk);
+               clk_set_rate(clk, 48000);
                clk_put(clk);
        }
 
index c31d228fdfc6257d248c28f0fac88ba274dc52b1..527a0cd956b55e87cf785fbc885d1b39dcffac55 100644 (file)
@@ -283,31 +283,6 @@ static struct platform_device ceu1_device = {
 };
 
 /* FSI */
-/*
- * FSI-A use external clock which came from ak464x.
- * So, we should change parent of fsi
- */
-#define FCLKACR                0xa4150008
-static void fsimck_init(struct clk *clk)
-{
-       u32 status = __raw_readl(clk->enable_reg);
-
-       /* use external clock */
-       status &= ~0x000000ff;
-       status |= 0x00000080;
-       __raw_writel(status, clk->enable_reg);
-}
-
-static struct clk_ops fsimck_clk_ops = {
-       .init = fsimck_init,
-};
-
-static struct clk fsimcka_clk = {
-       .ops            = &fsimck_clk_ops,
-       .enable_reg     = (void __iomem *)FCLKACR,
-       .rate           = 0, /* unknown */
-};
-
 /* change J20, J21, J22 pin to 1-2 connection to use slave mode */
 static struct sh_fsi_platform_info fsi_info = {
        .porta_flags = SH_FSI_BRS_INV |
@@ -852,37 +827,29 @@ static int __init devices_setup(void)
        gpio_request(GPIO_FN_KEYOUT0,     NULL);
 
        /* enable FSI */
-       gpio_request(GPIO_FN_FSIMCKB,    NULL);
        gpio_request(GPIO_FN_FSIMCKA,    NULL);
+       gpio_request(GPIO_FN_FSIIASD,    NULL);
        gpio_request(GPIO_FN_FSIOASD,    NULL);
        gpio_request(GPIO_FN_FSIIABCK,   NULL);
        gpio_request(GPIO_FN_FSIIALRCK,  NULL);
        gpio_request(GPIO_FN_FSIOABCK,   NULL);
        gpio_request(GPIO_FN_FSIOALRCK,  NULL);
        gpio_request(GPIO_FN_CLKAUDIOAO, NULL);
-       gpio_request(GPIO_FN_FSIIBSD,    NULL);
-       gpio_request(GPIO_FN_FSIOBSD,    NULL);
-       gpio_request(GPIO_FN_FSIIBBCK,   NULL);
-       gpio_request(GPIO_FN_FSIIBLRCK,  NULL);
-       gpio_request(GPIO_FN_FSIOBBCK,   NULL);
-       gpio_request(GPIO_FN_FSIOBLRCK,  NULL);
-       gpio_request(GPIO_FN_CLKAUDIOBO, NULL);
-       gpio_request(GPIO_FN_FSIIASD,    NULL);
 
        /* set SPU2 clock to 83.4 MHz */
        clk = clk_get(NULL, "spu_clk");
-       if (clk) {
+       if (!IS_ERR(clk)) {
                clk_set_rate(clk, clk_round_rate(clk, 83333333));
                clk_put(clk);
        }
 
        /* change parent of FSI A */
        clk = clk_get(NULL, "fsia_clk");
-       if (clk) {
-               clk_register(&fsimcka_clk);
-               clk_set_parent(clk, &fsimcka_clk);
-               clk_set_rate(clk, 11000);
-               clk_set_rate(&fsimcka_clk, 11000);
+       if (!IS_ERR(clk)) {
+               /* 48kHz dummy clock was used to make sure 1/1 divide */
+               clk_set_rate(&sh7724_fsimcka_clk, 48000);
+               clk_set_parent(clk, &sh7724_fsimcka_clk);
+               clk_set_rate(clk, 48000);
                clk_put(clk);
        }
 
index 1f4e562c5e8cc1317bd97a448e5067465bad26a9..82e1eabeac989fff1b4c2fc43aa74bcd2b23d715 100644 (file)
@@ -96,7 +96,7 @@ void kmap_coherent_init(void);
 void *kmap_coherent(struct page *page, unsigned long addr);
 void kunmap_coherent(void *kvaddr);
 
-#define PG_dcache_dirty        PG_arch_1
+#define PG_dcache_clean        PG_arch_1
 
 void cpu_cache_init(void);
 
index 46d5179c9f4902fef3b797a8772e6a65652c7aeb..e3c73cdd8c909444fa64865e24bffc5b7ed8a0d9 100644 (file)
@@ -199,10 +199,13 @@ extern unsigned long get_wchan(struct task_struct *p);
 #define ARCH_HAS_PREFETCHW
 static inline void prefetch(void *x)
 {
-       __asm__ __volatile__ ("pref @%0\n\t" : : "r" (x) : "memory");
+       __builtin_prefetch(x, 0, 3);
 }
 
-#define prefetchw(x)   prefetch(x)
+static inline void prefetchw(void *x)
+{
+       __builtin_prefetch(x, 1, 3);
+}
 #endif
 
 #endif /* __KERNEL__ */
index 903cd618eb740606853662d23765a694044e586c..d6741fca89a4f2d42b763d9789c5b81dc574988e 100644 (file)
 #define __NR_sendmsg           355
 #define __NR_recvmsg           356
 #define __NR_recvmmsg          357
+#define __NR_accept4           358
 
-#define NR_syscalls 358
+#define NR_syscalls 359
 
 #ifdef __KERNEL__
 
index 4c27b68789b3fd02a89fea5c6ae42fb0a347e0d5..7eb435999426e1979a5127942a4686114626e724 100644 (file)
@@ -303,4 +303,7 @@ enum {
        SHDMA_SLAVE_SDHI1_RX,
 };
 
+extern struct clk sh7724_fsimcka_clk;
+extern struct clk sh7724_fsimckb_clk;
+
 #endif /* __ASM_SH7724_H__ */
index 4eabc68cd75325cb9952914879cb2b7235bac3a3..b601fa3978d1995f53ea466e6aed5145e6ef1f75 100644 (file)
@@ -110,7 +110,7 @@ static int shoc_clk_verify_rate(struct clk *clk, unsigned long rate)
        return 0;
 }
 
-static int shoc_clk_set_rate(struct clk *clk, unsigned long rate, int algo_id)
+static int shoc_clk_set_rate(struct clk *clk, unsigned long rate)
 {
        unsigned long frqcr3;
        unsigned int tmp;
index 0fe2e9329cb25f699acd433dd4f2d9b4b945f00b..271c0b325a9a4d7f5dde40a45152546b7aa6dce0 100644 (file)
@@ -111,12 +111,21 @@ static struct clk div3_clk = {
        .parent         = &pll_clk,
 };
 
+/* External input clock (pin name: FSIMCKA/FSIMCKB ) */
+struct clk sh7724_fsimcka_clk = {
+};
+
+struct clk sh7724_fsimckb_clk = {
+};
+
 static struct clk *main_clks[] = {
        &r_clk,
        &extal_clk,
        &fll_clk,
        &pll_clk,
        &div3_clk,
+       &sh7724_fsimcka_clk,
+       &sh7724_fsimckb_clk,
 };
 
 static void div4_kick(struct clk *clk)
@@ -154,16 +163,38 @@ struct clk div4_clks[DIV4_NR] = {
        [DIV4_M1] = DIV4(FRQCRB, 4, 0x2f7c, CLK_ENABLE_ON_INIT),
 };
 
-enum { DIV6_V, DIV6_FA, DIV6_FB, DIV6_I, DIV6_S, DIV6_NR };
+enum { DIV6_V, DIV6_I, DIV6_S, DIV6_NR };
 
 static struct clk div6_clks[DIV6_NR] = {
        [DIV6_V] = SH_CLK_DIV6(&div3_clk, VCLKCR, 0),
-       [DIV6_FA] = SH_CLK_DIV6(&div3_clk, FCLKACR, 0),
-       [DIV6_FB] = SH_CLK_DIV6(&div3_clk, FCLKBCR, 0),
        [DIV6_I] = SH_CLK_DIV6(&div3_clk, IRDACLKCR, 0),
        [DIV6_S] = SH_CLK_DIV6(&div3_clk, SPUCLKCR, CLK_ENABLE_ON_INIT),
 };
 
+enum { DIV6_FA, DIV6_FB, DIV6_REPARENT_NR };
+
+/* Indices are important - they are the actual src selecting values */
+static struct clk *fclkacr_parent[] = {
+       [0] = &div3_clk,
+       [1] = NULL,
+       [2] = &sh7724_fsimcka_clk,
+       [3] = NULL,
+};
+
+static struct clk *fclkbcr_parent[] = {
+       [0] = &div3_clk,
+       [1] = NULL,
+       [2] = &sh7724_fsimckb_clk,
+       [3] = NULL,
+};
+
+static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = {
+       [DIV6_FA] = SH_CLK_DIV6_EXT(&div3_clk, FCLKACR, 0,
+                                     fclkacr_parent, ARRAY_SIZE(fclkacr_parent), 6, 2),
+       [DIV6_FB] = SH_CLK_DIV6_EXT(&div3_clk, FCLKBCR, 0,
+                                     fclkbcr_parent, ARRAY_SIZE(fclkbcr_parent), 6, 2),
+};
+
 static struct clk mstp_clks[HWBLK_NR] = {
        SH_HWBLK_CLK(HWBLK_TLB, &div4_clks[DIV4_I], CLK_ENABLE_ON_INIT),
        SH_HWBLK_CLK(HWBLK_IC, &div4_clks[DIV4_I], CLK_ENABLE_ON_INIT),
@@ -240,8 +271,8 @@ static struct clk_lookup lookups[] = {
 
        /* DIV6 clocks */
        CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]),
-       CLKDEV_CON_ID("fsia_clk", &div6_clks[DIV6_FA]),
-       CLKDEV_CON_ID("fsib_clk", &div6_clks[DIV6_FB]),
+       CLKDEV_CON_ID("fsia_clk", &div6_reparent_clks[DIV6_FA]),
+       CLKDEV_CON_ID("fsib_clk", &div6_reparent_clks[DIV6_FB]),
        CLKDEV_CON_ID("irda_clk", &div6_clks[DIV6_I]),
        CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_S]),
 
@@ -375,6 +406,9 @@ int __init arch_clk_init(void)
        if (!ret)
                ret = sh_clk_div6_register(div6_clks, DIV6_NR);
 
+       if (!ret)
+               ret = sh_clk_div6_reparent_register(div6_reparent_clks, DIV6_REPARENT_NR);
+
        if (!ret)
                ret = sh_hwblk_clk_register(mstp_clks, HWBLK_NR);
 
index 81f58371613dc71c97e2cc576d91eae8266d6934..8c6a350df751a97779cfe7030054b416203f9d9a 100644 (file)
@@ -88,7 +88,7 @@ asmlinkage int sys_cacheflush(unsigned long addr, unsigned long len, int op)
        }
 
        if (op & CACHEFLUSH_I)
-               flush_cache_all();
+               flush_icache_range(addr, addr+len);
 
        up_read(&current->mm->mmap_sem);
        return 0;
index e872e81add8a96ed12709964768a699f8a50306d..6fc347ebe59dfe0a356fe4d2d4f31ea52fa69206 100644 (file)
@@ -375,3 +375,4 @@ ENTRY(sys_call_table)
        .long sys_sendmsg               /* 355 */
        .long sys_recvmsg
        .long sys_recvmmsg
+       .long sys_accept4
index 3b6eb34c43fa36aac0ba0bcccd2ed0168190304e..3e70f851cdc6c1b674af7dec81bb8f19e290d4ad 100644 (file)
@@ -8,9 +8,9 @@ __kernel_vsyscall:
         * fill out .eh_frame -- PFM. */
 .LEND_vsyscall:
        .size __kernel_vsyscall,.-.LSTART_vsyscall
-       .previous
 
        .section .eh_frame,"a",@progbits
+       .previous
 .LCIE:
        .ualong .LCIE_end - .LCIE_start
 .LCIE_start:
index 2cfae81914aaac53289df444123cfb9f5f99476d..92eb98633ab05655fcdc3c4073f071798302e632 100644 (file)
@@ -114,7 +114,7 @@ static void sh4_flush_dcache_page(void *arg)
        struct address_space *mapping = page_mapping(page);
 
        if (mapping && !mapping_mapped(mapping))
-               set_bit(PG_dcache_dirty, &page->flags);
+               clear_bit(PG_dcache_clean, &page->flags);
        else
 #endif
                flush_cache_one(CACHE_OC_ADDRESS_ARRAY |
@@ -239,7 +239,7 @@ static void sh4_flush_cache_page(void *args)
                 * another ASID than the current one.
                 */
                map_coherent = (current_cpu_data.dcache.n_aliases &&
-                       !test_bit(PG_dcache_dirty, &page->flags) &&
+                       test_bit(PG_dcache_clean, &page->flags) &&
                        page_mapped(page));
                if (map_coherent)
                        vaddr = kmap_coherent(page, address);
index f498da1cce7ac5a070e3c563f94d04a1b812f17f..7729cca727ebebb48dfd787d0dd9a601dc9d1be3 100644 (file)
@@ -139,7 +139,7 @@ static void sh7705_flush_dcache_page(void *arg)
        struct address_space *mapping = page_mapping(page);
 
        if (mapping && !mapping_mapped(mapping))
-               set_bit(PG_dcache_dirty, &page->flags);
+               clear_bit(PG_dcache_clean, &page->flags);
        else
                __flush_dcache_page(__pa(page_address(page)));
 }
index ba401d137bb9f5057b93f18afdd75da87209525e..88d3dc3d30d50aabcbdfcff04ac197cf19470bb7 100644 (file)
@@ -60,14 +60,14 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
                       unsigned long len)
 {
        if (boot_cpu_data.dcache.n_aliases && page_mapped(page) &&
-           !test_bit(PG_dcache_dirty, &page->flags)) {
+           test_bit(PG_dcache_clean, &page->flags)) {
                void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
                memcpy(vto, src, len);
                kunmap_coherent(vto);
        } else {
                memcpy(dst, src, len);
                if (boot_cpu_data.dcache.n_aliases)
-                       set_bit(PG_dcache_dirty, &page->flags);
+                       clear_bit(PG_dcache_clean, &page->flags);
        }
 
        if (vma->vm_flags & VM_EXEC)
@@ -79,14 +79,14 @@ void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
                         unsigned long len)
 {
        if (boot_cpu_data.dcache.n_aliases && page_mapped(page) &&
-           !test_bit(PG_dcache_dirty, &page->flags)) {
+           test_bit(PG_dcache_clean, &page->flags)) {
                void *vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
                memcpy(dst, vfrom, len);
                kunmap_coherent(vfrom);
        } else {
                memcpy(dst, src, len);
                if (boot_cpu_data.dcache.n_aliases)
-                       set_bit(PG_dcache_dirty, &page->flags);
+                       clear_bit(PG_dcache_clean, &page->flags);
        }
 }
 
@@ -98,7 +98,7 @@ void copy_user_highpage(struct page *to, struct page *from,
        vto = kmap_atomic(to, KM_USER1);
 
        if (boot_cpu_data.dcache.n_aliases && page_mapped(from) &&
-           !test_bit(PG_dcache_dirty, &from->flags)) {
+           test_bit(PG_dcache_clean, &from->flags)) {
                vfrom = kmap_coherent(from, vaddr);
                copy_page(vto, vfrom);
                kunmap_coherent(vfrom);
@@ -141,7 +141,7 @@ void __update_cache(struct vm_area_struct *vma,
 
        page = pfn_to_page(pfn);
        if (pfn_valid(pfn)) {
-               int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
+               int dirty = !test_and_set_bit(PG_dcache_clean, &page->flags);
                if (dirty)
                        __flush_purge_region(page_address(page), PAGE_SIZE);
        }
@@ -153,7 +153,7 @@ void __flush_anon_page(struct page *page, unsigned long vmaddr)
 
        if (pages_do_alias(addr, vmaddr)) {
                if (boot_cpu_data.dcache.n_aliases && page_mapped(page) &&
-                   !test_bit(PG_dcache_dirty, &page->flags)) {
+                   test_bit(PG_dcache_clean, &page->flags)) {
                        void *kaddr;
 
                        kaddr = kmap_coherent(page, vmaddr);
index 15d74ea4209497b8d938840a7fbf6b7cfce19666..ec29e14ec5a85643b600952b3140f013ada5d258 100644 (file)
@@ -34,7 +34,7 @@ void *kmap_coherent(struct page *page, unsigned long addr)
        enum fixed_addresses idx;
        unsigned long vaddr;
 
-       BUG_ON(test_bit(PG_dcache_dirty, &page->flags));
+       BUG_ON(!test_bit(PG_dcache_clean, &page->flags));
 
        pagefault_disable();
 
index 81cd43432dc0ea5027eb0757ae2e27e2b13c5358..47eaafad15ceb63c8de66a8ef573d8fed32a714d 100644 (file)
@@ -39,7 +39,7 @@ struct linux_dev_v2_funcs {
        int (*v2_dev_open)(char *devpath);
        void (*v2_dev_close)(int d);
        int (*v2_dev_read)(int d, char *buf, int nbytes);
-       int (*v2_dev_write)(int d, char *buf, int nbytes);
+       int (*v2_dev_write)(int d, const char *buf, int nbytes);
        int (*v2_dev_seek)(int d, int hi, int lo);
 
        /* Never issued (multistage load support) */
index 51296a6f5005389877ca17c234f670fa71a3f8c0..9e5c64084b865781ca6782ced49b670ae35a5490 100644 (file)
@@ -60,25 +60,6 @@ extern char *prom_getbootargs(void);
 extern char *prom_mapio(char *virt_hint, int io_space, unsigned int phys_addr, unsigned int num_bytes);
 extern void prom_unmapio(char *virt_addr, unsigned int num_bytes);
 
-/* Device operations. */
-
-/* Open the device described by the passed string.  Note, that the format
- * of the string is different on V0 vs. V2->higher proms.  The caller must
- * know what he/she is doing!  Returns the device descriptor, an int.
- */
-extern int prom_devopen(char *device_string);
-
-/* Close a previously opened device described by the passed integer
- * descriptor.
- */
-extern int prom_devclose(int device_handle);
-
-/* Do a seek operation on the device described by the passed integer
- * descriptor.
- */
-extern void prom_seek(int device_handle, unsigned int seek_hival,
-                     unsigned int seek_lowval);
-
 /* Miscellaneous routines, don't really fit in any category per se. */
 
 /* Reboot the machine with the command line passed. */
@@ -121,19 +102,8 @@ extern int prom_getrev(void);
 /* Get the prom firmware revision. */
 extern int prom_getprev(void);
 
-/* Character operations to/from the console.... */
-
-/* Non-blocking get character from console. */
-extern int prom_nbgetchar(void);
-
-/* Non-blocking put character to console. */
-extern int prom_nbputchar(char character);
-
-/* Blocking get character from console. */
-extern char prom_getchar(void);
-
-/* Blocking put character to console. */
-extern void prom_putchar(char character);
+/* Write a buffer of characters to the console. */
+extern void prom_console_write_buf(const char *buf, int len);
 
 /* Prom's internal routines, don't use in kernel/boot code. */
 extern void prom_printf(const char *fmt, ...);
@@ -238,7 +208,6 @@ extern int prom_node_has_property(phandle node, char *property);
 extern int prom_setprop(phandle node, const char *prop_name, char *prop_value,
                        int value_size);
 
-extern phandle prom_pathtoinode(char *path);
 extern phandle prom_inst2pkg(int);
 
 /* Dorking with Bus ranges... */
index c9cc078e3e31531522fe5d531abcb0b72a1980b2..8cd0df34e82b86ada58f1399a8dab12a260adacb 100644 (file)
@@ -67,27 +67,6 @@ extern void prom_init(void *cif_handler, void *cif_stack);
 /* Boot argument acquisition, returns the boot command line string. */
 extern char *prom_getbootargs(void);
 
-/* Device utilities. */
-
-/* Device operations. */
-
-/* Open the device described by the passed string.  Note, that the format
- * of the string is different on V0 vs. V2->higher proms.  The caller must
- * know what he/she is doing!  Returns the device descriptor, an int.
- */
-extern int prom_devopen(const char *device_string);
-
-/* Close a previously opened device described by the passed integer
- * descriptor.
- */
-extern int prom_devclose(int device_handle);
-
-/* Do a seek operation on the device described by the passed integer
- * descriptor.
- */
-extern void prom_seek(int device_handle, unsigned int seek_hival,
-                     unsigned int seek_lowval);
-
 /* Miscellaneous routines, don't really fit in any category per se. */
 
 /* Reboot the machine with the command line passed. */
@@ -109,33 +88,14 @@ extern void prom_halt(void) __attribute__ ((noreturn));
 /* Halt and power-off the machine. */
 extern void prom_halt_power_off(void) __attribute__ ((noreturn));
 
-/* Set the PROM 'sync' callback function to the passed function pointer.
- * When the user gives the 'sync' command at the prom prompt while the
- * kernel is still active, the prom will call this routine.
- *
- */
-typedef int (*callback_func_t)(long *cmd);
-extern void prom_setcallback(callback_func_t func_ptr);
-
 /* Acquire the IDPROM of the root node in the prom device tree.  This
  * gets passed a buffer where you would like it stuffed.  The return value
  * is the format type of this idprom or 0xff on error.
  */
 extern unsigned char prom_get_idprom(char *idp_buffer, int idpbuf_size);
 
-/* Character operations to/from the console.... */
-
-/* Non-blocking get character from console. */
-extern int prom_nbgetchar(void);
-
-/* Non-blocking put character to console. */
-extern int prom_nbputchar(char character);
-
-/* Blocking get character from console. */
-extern char prom_getchar(void);
-
-/* Blocking put character to console. */
-extern void prom_putchar(char character);
+/* Write a buffer of characters to the console. */
+extern void prom_console_write_buf(const char *buf, int len);
 
 /* Prom's internal routines, don't use in kernel/boot code. */
 extern void prom_printf(const char *fmt, ...);
@@ -279,9 +239,7 @@ extern phandle prom_finddevice(const char *name);
 extern int prom_setprop(phandle node, const char *prop_name, char *prop_value,
                        int value_size);
 
-extern phandle prom_pathtoinode(const char *path);
 extern phandle prom_inst2pkg(int);
-extern int prom_service_exists(const char *service_name);
 extern void prom_sun4v_guest_soft_state(void);
 
 extern int prom_ihandle2path(int handle, char *buffer, int bufsize);
index 2d51527d810fc811531dae33c4bafc281b47d924..f01c42661ee51283183e6b6588297d20a78ec392 100644 (file)
@@ -114,7 +114,7 @@ void __init leon_init_timers(irq_handler_t counter_fn)
        if (leon3_gptimer_regs && leon3_irqctrl_regs) {
                LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].val, 0);
                LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].rld,
-                                     (((1000000 / 100) - 1)));
+                                     (((1000000 / HZ) - 1)));
                LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, 0);
 
 #ifdef CONFIG_SMP
@@ -128,7 +128,7 @@ void __init leon_init_timers(irq_handler_t counter_fn)
                }
 
                LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].val, 0);
-               LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].rld, (((1000000/100) - 1)));
+               LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].rld, (((1000000/HZ) - 1)));
                LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0);
 # endif
 
index 1b8c073adb44fe341b883f87865b28531d61b95f..816c0fa12dc0f546b94b58a728a24197adb48d22 100644 (file)
@@ -6,7 +6,6 @@ ccflags := -Werror
 
 lib-y                 := bootstr_$(BITS).o
 lib-$(CONFIG_SPARC32) += devmap.o
-lib-y                 += devops_$(BITS).o
 lib-y                 += init_$(BITS).o
 lib-$(CONFIG_SPARC32) += memory.o
 lib-y                 += misc_$(BITS).o
index 5340264b78f57c79dcd4f031d8348d31e9df1100..48863108a44ce6af379436c7f32ba2063e39a3f2 100644 (file)
 
 extern void restore_current(void);
 
-/* Non blocking get character from console input device, returns -1
- * if no input was taken.  This can be used for polling.
- */
-int
-prom_nbgetchar(void)
-{
-       static char inc;
-       int i = -1;
-       unsigned long flags;
-
-       spin_lock_irqsave(&prom_lock, flags);
-       switch(prom_vers) {
-       case PROM_V0:
-               i = (*(romvec->pv_nbgetchar))();
-               break;
-       case PROM_V2:
-       case PROM_V3:
-               if( (*(romvec->pv_v2devops).v2_dev_read)(*romvec->pv_v2bootargs.fd_stdin , &inc, 0x1) == 1) {
-                       i = inc;
-               } else {
-                       i = -1;
-               }
-               break;
-       default:
-               i = -1;
-               break;
-       };
-       restore_current();
-       spin_unlock_irqrestore(&prom_lock, flags);
-       return i; /* Ugh, we could spin forever on unsupported proms ;( */
-}
-
 /* Non blocking put character to console device, returns -1 if
  * unsuccessful.
  */
-int
-prom_nbputchar(char c)
+static int prom_nbputchar(const char *buf)
 {
-       static char outc;
        unsigned long flags;
        int i = -1;
 
        spin_lock_irqsave(&prom_lock, flags);
        switch(prom_vers) {
        case PROM_V0:
-               i = (*(romvec->pv_nbputchar))(c);
+               i = (*(romvec->pv_nbputchar))(*buf);
                break;
        case PROM_V2:
        case PROM_V3:
-               outc = c;
-               if( (*(romvec->pv_v2devops).v2_dev_write)(*romvec->pv_v2bootargs.fd_stdout, &outc, 0x1) == 1)
+               if ((*(romvec->pv_v2devops).v2_dev_write)(*romvec->pv_v2bootargs.fd_stdout,
+                                                         buf, 0x1) == 1)
                        i = 0;
-               else
-                       i = -1;
                break;
        default:
-               i = -1;
                break;
        };
        restore_current();
@@ -80,18 +43,14 @@ prom_nbputchar(char c)
        return i; /* Ugh, we could spin forever on unsupported proms ;( */
 }
 
-/* Blocking version of get character routine above. */
-char
-prom_getchar(void)
+void prom_console_write_buf(const char *buf, int len)
 {
-       int character;
-       while((character = prom_nbgetchar()) == -1) ;
-       return (char) character;
+       while (len) {
+               int n = prom_nbputchar(buf);
+               if (n)
+                       continue;
+               len--;
+               buf++;
+       }
 }
 
-/* Blocking version of put character routine above. */
-void
-prom_putchar(char c)
-{
-       while(prom_nbputchar(c) == -1) ;
-}
index 10322dc2f557a22d5befcc17dd4a27d8b6604f89..ed39e75828bd1eb6057f192d052ab88f5b943ddd 100644 (file)
 
 extern int prom_stdin, prom_stdout;
 
-/* Non blocking get character from console input device, returns -1
- * if no input was taken.  This can be used for polling.
- */
-inline int
-prom_nbgetchar(void)
-{
-       unsigned long args[7];
-       char inc;
-
-       args[0] = (unsigned long) "read";
-       args[1] = 3;
-       args[2] = 1;
-       args[3] = (unsigned int) prom_stdin;
-       args[4] = (unsigned long) &inc;
-       args[5] = 1;
-       args[6] = (unsigned long) -1;
-
-       p1275_cmd_direct(args);
-
-       if (args[6] == 1)
-               return inc;
-       return -1;
-}
-
-/* Non blocking put character to console device, returns -1 if
- * unsuccessful.
- */
-inline int
-prom_nbputchar(char c)
+static int __prom_console_write_buf(const char *buf, int len)
 {
        unsigned long args[7];
-       char outc;
-       
-       outc = c;
+       int ret;
 
        args[0] = (unsigned long) "write";
        args[1] = 3;
        args[2] = 1;
        args[3] = (unsigned int) prom_stdout;
-       args[4] = (unsigned long) &outc;
-       args[5] = 1;
+       args[4] = (unsigned long) buf;
+       args[5] = (unsigned int) len;
        args[6] = (unsigned long) -1;
 
        p1275_cmd_direct(args);
 
-       if (args[6] == 1)
-               return 0;
-       else
+       ret = (int) args[6];
+       if (ret < 0)
                return -1;
+       return ret;
 }
 
-/* Blocking version of get character routine above. */
-char
-prom_getchar(void)
-{
-       int character;
-       while((character = prom_nbgetchar()) == -1) ;
-       return (char) character;
-}
-
-/* Blocking version of put character routine above. */
-void
-prom_putchar(char c)
+void prom_console_write_buf(const char *buf, int len)
 {
-       prom_nbputchar(c);
-}
-
-void
-prom_puts(const char *s, int len)
-{
-       unsigned long args[7];
-
-       args[0] = (unsigned long) "write";
-       args[1] = 3;
-       args[2] = 1;
-       args[3] = (unsigned int) prom_stdout;
-       args[4] = (unsigned long) s;
-       args[5] = len;
-       args[6] = (unsigned long) -1;
-
-       p1275_cmd_direct(args);
+       while (len) {
+               int n = __prom_console_write_buf(buf, len);
+               if (n < 0)
+                       continue;
+               len -= n;
+               buf += len;
+       }
 }
diff --git a/arch/sparc/prom/devops_32.c b/arch/sparc/prom/devops_32.c
deleted file mode 100644 (file)
index 9c5d468..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * devops.c:  Device operations using the PROM.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-
-extern void restore_current(void);
-
-/* Open the device described by the string 'dstr'.  Returns the handle
- * to that device used for subsequent operations on that device.
- * Returns -1 on failure.
- */
-int
-prom_devopen(char *dstr)
-{
-       int handle;
-       unsigned long flags;
-       spin_lock_irqsave(&prom_lock, flags);
-       switch(prom_vers) {
-       case PROM_V0:
-               handle = (*(romvec->pv_v0devops.v0_devopen))(dstr);
-               if(handle == 0) handle = -1;
-               break;
-       case PROM_V2:
-       case PROM_V3:
-               handle = (*(romvec->pv_v2devops.v2_dev_open))(dstr);
-               break;
-       default:
-               handle = -1;
-               break;
-       };
-       restore_current();
-       spin_unlock_irqrestore(&prom_lock, flags);
-
-       return handle;
-}
-
-/* Close the device described by device handle 'dhandle'. */
-int
-prom_devclose(int dhandle)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&prom_lock, flags);
-       switch(prom_vers) {
-       case PROM_V0:
-               (*(romvec->pv_v0devops.v0_devclose))(dhandle);
-               break;
-       case PROM_V2:
-       case PROM_V3:
-               (*(romvec->pv_v2devops.v2_dev_close))(dhandle);
-               break;
-       default:
-               break;
-       };
-       restore_current();
-       spin_unlock_irqrestore(&prom_lock, flags);
-       return 0;
-}
-
-/* Seek to specified location described by 'seekhi' and 'seeklo'
- * for device 'dhandle'.
- */
-void
-prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&prom_lock, flags);
-       switch(prom_vers) {
-       case PROM_V0:
-               (*(romvec->pv_v0devops.v0_seekdev))(dhandle, seekhi, seeklo);
-               break;
-       case PROM_V2:
-       case PROM_V3:
-               (*(romvec->pv_v2devops.v2_dev_seek))(dhandle, seekhi, seeklo);
-               break;
-       default:
-               break;
-       };
-       restore_current();
-       spin_unlock_irqrestore(&prom_lock, flags);
-}
diff --git a/arch/sparc/prom/devops_64.c b/arch/sparc/prom/devops_64.c
deleted file mode 100644 (file)
index a017119..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * devops.c:  Device operations using the PROM.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- */
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-
-/* Open the device described by the string 'dstr'.  Returns the handle
- * to that device used for subsequent operations on that device.
- * Returns 0 on failure.
- */
-int
-prom_devopen(const char *dstr)
-{
-       unsigned long args[5];
-
-       args[0] = (unsigned long) "open";
-       args[1] = 1;
-       args[2] = 1;
-       args[3] = (unsigned long) dstr;
-       args[4] = (unsigned long) -1;
-
-       p1275_cmd_direct(args);
-
-       return (int) args[4];
-}
-
-/* Close the device described by device handle 'dhandle'. */
-int
-prom_devclose(int dhandle)
-{
-       unsigned long args[4];
-
-       args[0] = (unsigned long) "close";
-       args[1] = 1;
-       args[2] = 0;
-       args[3] = (unsigned int) dhandle;
-
-       p1275_cmd_direct(args);
-
-       return 0;
-}
-
-/* Seek to specified location described by 'seekhi' and 'seeklo'
- * for device 'dhandle'.
- */
-void
-prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo)
-{
-       unsigned long args[7];
-
-       args[0] = (unsigned long) "seek";
-       args[1] = 3;
-       args[2] = 1;
-       args[3] = (unsigned int) dhandle;
-       args[4] = seekhi;
-       args[5] = seeklo;
-       args[6] = (unsigned long) -1;
-
-       p1275_cmd_direct(args);
-}
index d24bc44e361ee20b654960cc7784176670705da6..e4f31d4d3715cc5c27752633ba58e052e853a956 100644 (file)
@@ -18,7 +18,7 @@
 #include <asm/system.h>
 #include <asm/ldc.h>
 
-int prom_service_exists(const char *service_name)
+static int prom_service_exists(const char *service_name)
 {
        unsigned long args[5];
 
@@ -150,20 +150,6 @@ void prom_halt_power_off(void)
        prom_halt();
 }
 
-/* Set prom sync handler to call function 'funcp'. */
-void prom_setcallback(callback_func_t funcp)
-{
-       unsigned long args[5];
-       if (!funcp)
-               return;
-       args[0] = (unsigned long) "set-callback";
-       args[1] = 1;
-       args[2] = 1;
-       args[3] = (unsigned long) funcp;
-       args[4] = (unsigned long) -1;
-       p1275_cmd_direct(args);
-}
-
 /* Get the idprom and stuff it into buffer 'idbuf'.  Returns the
  * format type.  'num_bytes' is the number of bytes that your idbuf
  * has space for.  Returns 0xff on error.
index ca869266b9f3d0106e60d7b8c28f5cdcf614826b..d9682f06b3b056c7862ec7cda4214a95ab213a03 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/compiler.h>
+#include <linux/spinlock.h>
 
 #include <asm/openprom.h>
 #include <asm/oplib.h>
 
+#define CONSOLE_WRITE_BUF_SIZE 1024
+
 static char ppbuf[1024];
+static char console_write_buf[CONSOLE_WRITE_BUF_SIZE];
+static DEFINE_RAW_SPINLOCK(console_write_lock);
 
 void notrace prom_write(const char *buf, unsigned int n)
 {
-       char ch;
+       unsigned int dest_len;
+       unsigned long flags;
+       char *dest;
+
+       dest = console_write_buf;
+       raw_spin_lock_irqsave(&console_write_lock, flags);
 
-       while (n != 0) {
-               --n;
-               if ((ch = *buf++) == '\n')
-                       prom_putchar('\r');
-               prom_putchar(ch);
+       dest_len = 0;
+       while (n-- != 0) {
+               char ch = *buf++;
+               if (ch == '\n') {
+                       *dest++ = '\r';
+                       dest_len++;
+               }
+               *dest++ = ch;
+               dest_len++;
+               if (dest_len >= CONSOLE_WRITE_BUF_SIZE - 1) {
+                       prom_console_write_buf(console_write_buf, dest_len);
+                       dest = console_write_buf;
+                       dest_len = 0;
+               }
        }
+       if (dest_len)
+               prom_console_write_buf(console_write_buf, dest_len);
+
+       raw_spin_unlock_irqrestore(&console_write_lock, flags);
 }
 
 void notrace prom_printf(const char *fmt, ...)
index 63e08e149774fc6a0a30fcd9228abb83f434aae7..535e2e69ac1d8287470356218511c25af6be7a8c 100644 (file)
@@ -342,19 +342,3 @@ phandle prom_inst2pkg(int inst)
        if (node == -1) return 0;
        return node;
 }
-
-/* Return 'node' assigned to a particular prom 'path'
- * FIXME: Should work for v0 as well
- */
-phandle prom_pathtoinode(char *path)
-{
-       phandle node;
-       int inst;
-       
-       inst = prom_devopen (path);
-       if (inst == -1) return 0;
-       node = prom_inst2pkg (inst);
-       prom_devclose (inst);
-       if (node == -1) return 0;
-       return node;
-}
index 691be68932f84cf7d804b2a7ce6720fceeedc447..d93660048376c9d9bf4478720a6825e9e7b117ed 100644 (file)
@@ -374,24 +374,6 @@ inline phandle prom_inst2pkg(int inst)
        return node;
 }
 
-/* Return 'node' assigned to a particular prom 'path'
- * FIXME: Should work for v0 as well
- */
-phandle prom_pathtoinode(const char *path)
-{
-       phandle node;
-       int inst;
-
-       inst = prom_devopen (path);
-       if (inst == 0)
-               return 0;
-       node = prom_inst2pkg(inst);
-       prom_devclose(inst);
-       if (node == -1)
-               return 0;
-       return node;
-}
-
 int prom_ihandle2path(int handle, char *buffer, int bufsize)
 {
        unsigned long args[7];
index 07ec8a865c1d3fc122232e5aa2273814640a9e5a..e11b5fcb70ebe07d0bf7fd677a9c61943728d169 100644 (file)
@@ -329,6 +329,18 @@ endmenu  # Tilera-specific configuration
 
 menu "Bus options"
 
+config PCI
+       bool "PCI support"
+       default y
+       select PCI_DOMAINS
+       ---help---
+         Enable PCI root complex support, so PCIe endpoint devices can
+         be attached to the Tile chip.  Many, but not all, PCI devices
+         are supported under Tilera's root complex driver.
+
+config PCI_DOMAINS
+       bool
+
 config NO_IOMEM
        def_bool !PCI
 
index c5741da4eeac8dd47e45397b74be71f8890ed8ca..14a3f8556ace46362a96c80851c4e656d5d7dcee 100644 (file)
@@ -137,4 +137,56 @@ static inline void finv_buffer(void *buffer, size_t size)
        mb_incoherent();
 }
 
+/*
+ * Flush & invalidate a VA range that is homed remotely on a single core,
+ * waiting until the memory controller holds the flushed values.
+ */
+static inline void finv_buffer_remote(void *buffer, size_t size)
+{
+       char *p;
+       int i;
+
+       /*
+        * Flush and invalidate the buffer out of the local L1/L2
+        * and request the home cache to flush and invalidate as well.
+        */
+       __finv_buffer(buffer, size);
+
+       /*
+        * Wait for the home cache to acknowledge that it has processed
+        * all the flush-and-invalidate requests.  This does not mean
+        * that the flushed data has reached the memory controller yet,
+        * but it does mean the home cache is processing the flushes.
+        */
+       __insn_mf();
+
+       /*
+        * Issue a load to the last cache line, which can't complete
+        * until all the previously-issued flushes to the same memory
+        * controller have also completed.  If we weren't striping
+        * memory, that one load would be sufficient, but since we may
+        * be, we also need to back up to the last load issued to
+        * another memory controller, which would be the point where
+        * we crossed an 8KB boundary (the granularity of striping
+        * across memory controllers).  Keep backing up and doing this
+        * until we are before the beginning of the buffer, or have
+        * hit all the controllers.
+        */
+       for (i = 0, p = (char *)buffer + size - 1;
+            i < (1 << CHIP_LOG_NUM_MSHIMS()) && p >= (char *)buffer;
+            ++i) {
+               const unsigned long STRIPE_WIDTH = 8192;
+
+               /* Force a load instruction to issue. */
+               *(volatile char *)p;
+
+               /* Jump to end of previous stripe. */
+               p -= STRIPE_WIDTH;
+               p = (char *)((unsigned long)p | (STRIPE_WIDTH - 1));
+       }
+
+       /* Wait for the loads (and thus flushes) to have completed. */
+       __insn_mf();
+}
+
 #endif /* _ASM_TILE_CACHEFLUSH_H */
index ee43328713abf2ace9f76e885e9e26ce7b615b3a..d3cbb9b14cbe4b7950575c46b6f8b34312f42a78 100644 (file)
@@ -55,9 +55,6 @@ extern void iounmap(volatile void __iomem *addr);
 #define ioremap_writethrough(physaddr, size)   ioremap(physaddr, size)
 #define ioremap_fullcache(physaddr, size)      ioremap(physaddr, size)
 
-void __iomem *ioport_map(unsigned long port, unsigned int len);
-extern inline void ioport_unmap(void __iomem *addr) {}
-
 #define mmiowb()
 
 /* Conversion between virtual and physical mappings.  */
@@ -189,12 +186,22 @@ static inline void memcpy_toio(volatile void __iomem *dst, const void *src,
  * we never run, uses them unconditionally.
  */
 
-static inline int ioport_panic(void)
+static inline long ioport_panic(void)
 {
        panic("inb/outb and friends do not exist on tile");
        return 0;
 }
 
+static inline void __iomem *ioport_map(unsigned long port, unsigned int len)
+{
+       return (void __iomem *) ioport_panic();
+}
+
+static inline void ioport_unmap(void __iomem *addr)
+{
+       ioport_panic();
+}
+
 static inline u8 inb(unsigned long addr)
 {
        return ioport_panic();
diff --git a/arch/tile/include/asm/pci-bridge.h b/arch/tile/include/asm/pci-bridge.h
deleted file mode 100644 (file)
index e853b0e..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2010 Tilera Corporation. All Rights Reserved.
- *
- *   This program is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU General Public License
- *   as published by the Free Software Foundation, version 2.
- *
- *   This program is 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, GOOD TITLE or
- *   NON INFRINGEMENT.  See the GNU General Public License for
- *   more details.
- */
-
-#ifndef _ASM_TILE_PCI_BRIDGE_H
-#define _ASM_TILE_PCI_BRIDGE_H
-
-#include <linux/ioport.h>
-#include <linux/pci.h>
-
-struct device_node;
-struct pci_controller;
-
-/*
- * pci_io_base returns the memory address at which you can access
- * the I/O space for PCI bus number `bus' (or NULL on error).
- */
-extern void __iomem *pci_bus_io_base(unsigned int bus);
-extern unsigned long pci_bus_io_base_phys(unsigned int bus);
-extern unsigned long pci_bus_mem_base_phys(unsigned int bus);
-
-/* Allocate a new PCI host bridge structure */
-extern struct pci_controller *pcibios_alloc_controller(void);
-
-/* Helper function for setting up resources */
-extern void pci_init_resource(struct resource *res, unsigned long start,
-                             unsigned long end, int flags, char *name);
-
-/* Get the PCI host controller for a bus */
-extern struct pci_controller *pci_bus_to_hose(int bus);
-
-/*
- * Structure of a PCI controller (host bridge)
- */
-struct pci_controller {
-       int index;              /* PCI domain number */
-       struct pci_bus *root_bus;
-
-       int first_busno;
-       int last_busno;
-
-       int hv_cfg_fd[2];       /* config{0,1} fds for this PCIe controller */
-       int hv_mem_fd;          /* fd to Hypervisor for MMIO operations */
-
-       struct pci_ops *ops;
-
-       int irq_base;           /* Base IRQ from the Hypervisor */
-       int plx_gen1;           /* flag for PLX Gen 1 configuration */
-
-       /* Address ranges that are routed to this controller/bridge. */
-       struct resource mem_resources[3];
-};
-
-static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
-{
-       return bus->sysdata;
-}
-
-extern void setup_indirect_pci_nomap(struct pci_controller *hose,
-                              void __iomem *cfg_addr, void __iomem *cfg_data);
-extern void setup_indirect_pci(struct pci_controller *hose,
-                              u32 cfg_addr, u32 cfg_data);
-extern void setup_grackle(struct pci_controller *hose);
-
-extern unsigned char common_swizzle(struct pci_dev *, unsigned char *);
-
-/*
- *   The following code swizzles for exactly one bridge.  The routine
- *   common_swizzle below handles multiple bridges.  But there are a
- *   some boards that don't follow the PCI spec's suggestion so we
- *   break this piece out separately.
- */
-static inline unsigned char bridge_swizzle(unsigned char pin,
-               unsigned char idsel)
-{
-       return (((pin-1) + idsel) % 4) + 1;
-}
-
-/*
- * The following macro is used to lookup irqs in a standard table
- * format for those PPC systems that do not already have PCI
- * interrupts properly routed.
- */
-/* FIXME - double check this */
-#define PCI_IRQ_TABLE_LOOKUP ({ \
-       long _ctl_ = -1; \
-       if (idsel >= min_idsel && idsel <= max_idsel && pin <= irqs_per_slot) \
-               _ctl_ = pci_irq_table[idsel - min_idsel][pin-1]; \
-       _ctl_; \
-})
-
-/*
- * Scan the buses below a given PCI host bridge and assign suitable
- * resources to all devices found.
- */
-extern int pciauto_bus_scan(struct pci_controller *, int);
-
-#ifdef CONFIG_PCI
-extern unsigned long pci_address_to_pio(phys_addr_t address);
-#else
-static inline unsigned long pci_address_to_pio(phys_addr_t address)
-{
-       return (unsigned long)-1;
-}
-#endif
-
-#endif /* _ASM_TILE_PCI_BRIDGE_H */
index b0c15da2d5d58e91dedb4fd21978a7506683c65c..c3fc458a0d323485557c1b6a97db662534fd9c3f 100644 (file)
 #ifndef _ASM_TILE_PCI_H
 #define _ASM_TILE_PCI_H
 
-#include <asm/pci-bridge.h>
+#include <linux/pci.h>
+
+/*
+ * Structure of a PCI controller (host bridge)
+ */
+struct pci_controller {
+       int index;              /* PCI domain number */
+       struct pci_bus *root_bus;
+
+       int first_busno;
+       int last_busno;
+
+       int hv_cfg_fd[2];       /* config{0,1} fds for this PCIe controller */
+       int hv_mem_fd;          /* fd to Hypervisor for MMIO operations */
+
+       struct pci_ops *ops;
+
+       int irq_base;           /* Base IRQ from the Hypervisor */
+       int plx_gen1;           /* flag for PLX Gen 1 configuration */
+
+       /* Address ranges that are routed to this controller/bridge. */
+       struct resource mem_resources[3];
+};
 
 /*
  * The hypervisor maps the entirety of CPA-space as bus addresses, so
  */
 #define PCI_DMA_BUS_IS_PHYS     1
 
-struct pci_controller *pci_bus_to_hose(int bus);
-unsigned char __init common_swizzle(struct pci_dev *dev, unsigned char *pinp);
 int __init tile_pci_init(void);
-void pci_iounmap(struct pci_dev *dev, void __iomem *addr);
-void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
-void __devinit pcibios_fixup_bus(struct pci_bus *bus);
 
-int __devinit _tile_cfg_read(struct pci_controller *hose,
-                                   int bus,
-                                   int slot,
-                                   int function,
-                                   int offset,
-                                   int size,
-                                   u32 *val);
-int __devinit _tile_cfg_write(struct pci_controller *hose,
-                                    int bus,
-                                    int slot,
-                                    int function,
-                                    int offset,
-                                    int size,
-                                    u32 val);
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
+static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) {}
 
-/*
- * These are used to to config reads and writes in the early stages of
- * setup before the driver infrastructure has been set up enough to be
- * able to do config reads and writes.
- */
-#define early_cfg_read(where, size, value) \
-       _tile_cfg_read(controller, \
-                      current_bus, \
-                      pci_slot, \
-                      pci_fn, \
-                      where, \
-                      size, \
-                      value)
-
-#define early_cfg_write(where, size, value) \
-       _tile_cfg_write(controller, \
-                      current_bus, \
-                      pci_slot, \
-                      pci_fn, \
-                      where, \
-                      size, \
-                      value)
-
-
-
-#define PCICFG_BYTE    1
-#define PCICFG_WORD    2
-#define PCICFG_DWORD   4
+void __devinit pcibios_fixup_bus(struct pci_bus *bus);
 
 #define        TILE_NUM_PCIE   2
 
@@ -88,33 +66,33 @@ static inline int pci_proc_domain(struct pci_bus *bus)
 }
 
 /*
- * I/O space is currently not supported.
+ * pcibios_assign_all_busses() tells whether or not the bus numbers
+ * should be reassigned, in case the BIOS didn't do it correctly, or
+ * in case we don't have a BIOS and we want to let Linux do it.
  */
+static inline int pcibios_assign_all_busses(void)
+{
+       return 1;
+}
 
-#define TILE_PCIE_LOWER_IO             0x0
-#define TILE_PCIE_UPPER_IO             0x10000
-#define TILE_PCIE_PCIE_IO_SIZE         0x0000FFFF
-
-#define _PAGE_NO_CACHE         0
-#define _PAGE_GUARDED          0
-
-
-#define pcibios_assign_all_busses()    pci_assign_all_buses
-extern int pci_assign_all_buses;
-
+/*
+ * No special bus mastering setup handling.
+ */
 static inline void pcibios_set_master(struct pci_dev *dev)
 {
-       /* No special bus mastering setup handling */
 }
 
 #define PCIBIOS_MIN_MEM                0
-#define PCIBIOS_MIN_IO         TILE_PCIE_LOWER_IO
+#define PCIBIOS_MIN_IO         0
 
 /*
  * This flag tells if the platform is TILEmpower that needs
  * special configuration for the PLX switch chip.
  */
-extern int blade_pci;
+extern int tile_plx_gen1;
+
+/* Use any cpu for PCI. */
+#define cpumask_of_pcibus(bus) cpu_online_mask
 
 /* implement the pci_ DMA API in terms of the generic device dma_ one */
 #include <asm-generic/pci-dma-compat.h>
@@ -122,7 +100,4 @@ extern int blade_pci;
 /* generic pci stuff */
 #include <asm-generic/pci.h>
 
-/* Use any cpu for PCI. */
-#define cpumask_of_pcibus(bus) cpu_online_mask
-
 #endif /* _ASM_TILE_PCI_H */
index 1747ff3946b2ef50dea6e9591730238f3c720d08..a9e7c8760334b8430b2a8c30c5a6954d4ab4cbcd 100644 (file)
@@ -292,8 +292,18 @@ extern int kstack_hash;
 /* Are we using huge pages in the TLB for kernel data? */
 extern int kdata_huge;
 
+/* Support standard Linux prefetching. */
+#define ARCH_HAS_PREFETCH
+#define prefetch(x) __builtin_prefetch(x)
 #define PREFETCH_STRIDE CHIP_L2_LINE_SIZE()
 
+/* Bring a value into the L1D, faulting the TLB if necessary. */
+#ifdef __tilegx__
+#define prefetch_L1(x) __insn_prefetch_l1_fault((void *)(x))
+#else
+#define prefetch_L1(x) __insn_prefetch_L1((void *)(x))
+#endif
+
 #else /* __ASSEMBLY__ */
 
 /* Do some slow action (e.g. read a slow SPR). */
index c1ee1d61d44ca8a07c504b9af425df3a9c7185c7..81d92a45cd4b613e2c18add9afe153e43a5d703e 100644 (file)
@@ -25,7 +25,7 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 struct pt_regs;
-int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *);
+int restore_sigcontext(struct pt_regs *, struct sigcontext __user *);
 int setup_sigcontext(struct sigcontext __user *, struct pt_regs *);
 void do_signal(struct pt_regs *regs);
 #endif
diff --git a/arch/tile/include/hv/drv_xgbe_impl.h b/arch/tile/include/hv/drv_xgbe_impl.h
new file mode 100644 (file)
index 0000000..3a73b2b
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2010 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is 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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/**
+ * @file drivers/xgbe/impl.h
+ * Implementation details for the NetIO library.
+ */
+
+#ifndef __DRV_XGBE_IMPL_H__
+#define __DRV_XGBE_IMPL_H__
+
+#include <hv/netio_errors.h>
+#include <hv/netio_intf.h>
+#include <hv/drv_xgbe_intf.h>
+
+
+/** How many groups we have (log2). */
+#define LOG2_NUM_GROUPS (12)
+/** How many groups we have. */
+#define NUM_GROUPS (1 << LOG2_NUM_GROUPS)
+
+/** Number of output requests we'll buffer per tile. */
+#define EPP_REQS_PER_TILE (32)
+
+/** Words used in an eDMA command without checksum acceleration. */
+#define EDMA_WDS_NO_CSUM      8
+/** Words used in an eDMA command with checksum acceleration. */
+#define EDMA_WDS_CSUM        10
+/** Total available words in the eDMA command FIFO. */
+#define EDMA_WDS_TOTAL      128
+
+
+/*
+ * FIXME: These definitions are internal and should have underscores!
+ * NOTE: The actual numeric values here are intentional and allow us to
+ * optimize the concept "if small ... else if large ... else ...", by
+ * checking for the low bit being set, and then for non-zero.
+ * These are used as array indices, so they must have the values (0, 1, 2)
+ * in some order.
+ */
+#define SIZE_SMALL (1)       /**< Small packet queue. */
+#define SIZE_LARGE (2)       /**< Large packet queue. */
+#define SIZE_JUMBO (0)       /**< Jumbo packet queue. */
+
+/** The number of "SIZE_xxx" values. */
+#define NETIO_NUM_SIZES 3
+
+
+/*
+ * Default numbers of packets for IPP drivers.  These values are chosen
+ * such that CIPP1 will not overflow its L2 cache.
+ */
+
+/** The default number of small packets. */
+#define NETIO_DEFAULT_SMALL_PACKETS 2750
+/** The default number of large packets. */
+#define NETIO_DEFAULT_LARGE_PACKETS 2500
+/** The default number of jumbo packets. */
+#define NETIO_DEFAULT_JUMBO_PACKETS 250
+
+
+/** Log2 of the size of a memory arena. */
+#define NETIO_ARENA_SHIFT      24      /* 16 MB */
+/** Size of a memory arena. */
+#define NETIO_ARENA_SIZE       (1 << NETIO_ARENA_SHIFT)
+
+
+/** A queue of packets.
+ *
+ * This structure partially defines a queue of packets waiting to be
+ * processed.  The queue as a whole is written to by an interrupt handler and
+ * read by non-interrupt code; this data structure is what's touched by the
+ * interrupt handler.  The other part of the queue state, the read offset, is
+ * kept in user space, not in hypervisor space, so it is in a separate data
+ * structure.
+ *
+ * The read offset (__packet_receive_read in the user part of the queue
+ * structure) points to the next packet to be read. When the read offset is
+ * equal to the write offset, the queue is empty; therefore the queue must
+ * contain one more slot than the required maximum queue size.
+ *
+ * Here's an example of all 3 state variables and what they mean.  All
+ * pointers move left to right.
+ *
+ * @code
+ *   I   I   V   V   V   V   I   I   I   I
+ *   0   1   2   3   4   5   6   7   8   9  10
+ *           ^       ^       ^               ^
+ *           |               |               |
+ *           |               |               __last_packet_plus_one
+ *           |               __buffer_write
+ *           __packet_receive_read
+ * @endcode
+ *
+ * This queue has 10 slots, and thus can hold 9 packets (_last_packet_plus_one
+ * = 10).  The read pointer is at 2, and the write pointer is at 6; thus,
+ * there are valid, unread packets in slots 2, 3, 4, and 5.  The remaining
+ * slots are invalid (do not contain a packet).
+ */
+typedef struct {
+  /** Byte offset of the next notify packet to be written: zero for the first
+   *  packet on the queue, sizeof (netio_pkt_t) for the second packet on the
+   *  queue, etc. */
+  volatile uint32_t __packet_write;
+
+  /** Offset of the packet after the last valid packet (i.e., when any
+   *  pointer is incremented to this value, it wraps back to zero). */
+  uint32_t __last_packet_plus_one;
+}
+__netio_packet_queue_t;
+
+
+/** A queue of buffers.
+ *
+ * This structure partially defines a queue of empty buffers which have been
+ * obtained via requests to the IPP.  (The elements of the queue are packet
+ * handles, which are transformed into a full netio_pkt_t when the buffer is
+ * retrieved.)  The queue as a whole is written to by an interrupt handler and
+ * read by non-interrupt code; this data structure is what's touched by the
+ * interrupt handler.  The other parts of the queue state, the read offset and
+ * requested write offset, are kept in user space, not in hypervisor space, so
+ * they are in a separate data structure.
+ *
+ * The read offset (__buffer_read in the user part of the queue structure)
+ * points to the next buffer to be read. When the read offset is equal to the
+ * write offset, the queue is empty; therefore the queue must contain one more
+ * slot than the required maximum queue size.
+ *
+ * The requested write offset (__buffer_requested_write in the user part of
+ * the queue structure) points to the slot which will hold the next buffer we
+ * request from the IPP, once we get around to sending such a request.  When
+ * the requested write offset is equal to the write offset, no requests for
+ * new buffers are outstanding; when the requested write offset is one greater
+ * than the read offset, no more requests may be sent.
+ *
+ * Note that, unlike the packet_queue, the buffer_queue places incoming
+ * buffers at decreasing addresses.  This makes the check for "is it time to
+ * wrap the buffer pointer" cheaper in the assembly code which receives new
+ * buffers, and means that the value which defines the queue size,
+ * __last_buffer, is different than in the packet queue.  Also, the offset
+ * used in the packet_queue is already scaled by the size of a packet; here we
+ * use unscaled slot indices for the offsets.  (These differences are
+ * historical, and in the future it's possible that the packet_queue will look
+ * more like this queue.)
+ *
+ * @code
+ * Here's an example of all 4 state variables and what they mean.  Remember:
+ * all pointers move right to left.
+ *
+ *   V   V   V   I   I   R   R   V   V   V
+ *   0   1   2   3   4   5   6   7   8   9
+ *           ^       ^       ^           ^
+ *           |       |       |           |
+ *           |       |       |           __last_buffer
+ *           |       |       __buffer_write
+ *           |       __buffer_requested_write
+ *           __buffer_read
+ * @endcode
+ *
+ * This queue has 10 slots, and thus can hold 9 buffers (_last_buffer = 9).
+ * The read pointer is at 2, and the write pointer is at 6; thus, there are
+ * valid, unread buffers in slots 2, 1, 0, 9, 8, and 7.  The requested write
+ * pointer is at 4; thus, requests have been made to the IPP for buffers which
+ * will be placed in slots 6 and 5 when they arrive.  Finally, the remaining
+ * slots are invalid (do not contain a buffer).
+ */
+typedef struct
+{
+  /** Ordinal number of the next buffer to be written: 0 for the first slot in
+   *  the queue, 1 for the second slot in the queue, etc. */
+  volatile uint32_t __buffer_write;
+
+  /** Ordinal number of the last buffer (i.e., when any pointer is decremented
+   *  below zero, it is reloaded with this value). */
+  uint32_t __last_buffer;
+}
+__netio_buffer_queue_t;
+
+
+/**
+ * An object for providing Ethernet packets to a process.
+ */
+typedef struct __netio_queue_impl_t
+{
+  /** The queue of packets waiting to be received. */
+  __netio_packet_queue_t __packet_receive_queue;
+  /** The intr bit mask that IDs this device. */
+  unsigned int __intr_id;
+  /** Offset to queues of empty buffers, one per size. */
+  uint32_t __buffer_queue[NETIO_NUM_SIZES];
+  /** The address of the first EPP tile, or -1 if no EPP. */
+  /* ISSUE: Actually this is always "0" or "~0". */
+  uint32_t __epp_location;
+  /** The queue ID that this queue represents. */
+  unsigned int __queue_id;
+  /** Number of acknowledgements received. */
+  volatile uint32_t __acks_received;
+  /** Last completion number received for packet_sendv. */
+  volatile uint32_t __last_completion_rcv;
+  /** Number of packets allowed to be outstanding. */
+  uint32_t __max_outstanding;
+  /** First VA available for packets. */
+  void* __va_0;
+  /** First VA in second range available for packets. */
+  void* __va_1;
+  /** Padding to align the "__packets" field to the size of a netio_pkt_t. */
+  uint32_t __padding[3];
+  /** The packets themselves. */
+  netio_pkt_t __packets[0];
+}
+netio_queue_impl_t;
+
+
+/**
+ * An object for managing the user end of a NetIO queue.
+ */
+typedef struct __netio_queue_user_impl_t
+{
+  /** The next incoming packet to be read. */
+  uint32_t __packet_receive_read;
+  /** The next empty buffers to be read, one index per size. */
+  uint8_t __buffer_read[NETIO_NUM_SIZES];
+  /** Where the empty buffer we next request from the IPP will go, one index
+   * per size. */
+  uint8_t __buffer_requested_write[NETIO_NUM_SIZES];
+  /** PCIe interface flag. */
+  uint8_t __pcie;
+  /** Number of packets left to be received before we send a credit update. */
+  uint32_t __receive_credit_remaining;
+  /** Value placed in __receive_credit_remaining when it reaches zero. */
+  uint32_t __receive_credit_interval;
+  /** First fast I/O routine index. */
+  uint32_t __fastio_index;
+  /** Number of acknowledgements expected. */
+  uint32_t __acks_outstanding;
+  /** Last completion number requested. */
+  uint32_t __last_completion_req;
+  /** File descriptor for driver. */
+  int __fd;
+}
+netio_queue_user_impl_t;
+
+
+#define NETIO_GROUP_CHUNK_SIZE   64   /**< Max # groups in one IPP request */
+#define NETIO_BUCKET_CHUNK_SIZE  64   /**< Max # buckets in one IPP request */
+
+
+/** Internal structure used to convey packet send information to the
+ * hypervisor.  FIXME: Actually, it's not used for that anymore, but
+ * netio_packet_send() still uses it internally.
+ */
+typedef struct
+{
+  uint16_t flags;              /**< Packet flags (__NETIO_SEND_FLG_xxx) */
+  uint16_t transfer_size;      /**< Size of packet */
+  uint32_t va;                 /**< VA of start of packet */
+  __netio_pkt_handle_t handle; /**< Packet handle */
+  uint32_t csum0;              /**< First checksum word */
+  uint32_t csum1;              /**< Second checksum word */
+}
+__netio_send_cmd_t;
+
+
+/** Flags used in two contexts:
+ *  - As the "flags" member in the __netio_send_cmd_t, above; used only
+ *    for netio_pkt_send_{prepare,commit}.
+ *  - As part of the flags passed to the various send packet fast I/O calls.
+ */
+
+/** Need acknowledgement on this packet.  Note that some code in the
+ *  normal send_pkt fast I/O handler assumes that this is equal to 1. */
+#define __NETIO_SEND_FLG_ACK    0x1
+
+/** Do checksum on this packet.  (Only used with the __netio_send_cmd_t;
+ *  normal packet sends use a special fast I/O index to denote checksumming,
+ *  and multi-segment sends test the checksum descriptor.) */
+#define __NETIO_SEND_FLG_CSUM   0x2
+
+/** Get a completion on this packet.  Only used with multi-segment sends.  */
+#define __NETIO_SEND_FLG_COMPLETION 0x4
+
+/** Position of the number-of-extra-segments value in the flags word.
+    Only used with multi-segment sends. */
+#define __NETIO_SEND_FLG_XSEG_SHIFT 3
+
+/** Width of the number-of-extra-segments value in the flags word. */
+#define __NETIO_SEND_FLG_XSEG_WIDTH 2
+
+#endif /* __DRV_XGBE_IMPL_H__ */
diff --git a/arch/tile/include/hv/drv_xgbe_intf.h b/arch/tile/include/hv/drv_xgbe_intf.h
new file mode 100644 (file)
index 0000000..146e47d
--- /dev/null
@@ -0,0 +1,615 @@
+/*
+ * Copyright 2010 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is 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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/**
+ * @file drv_xgbe_intf.h
+ * Interface to the hypervisor XGBE driver.
+ */
+
+#ifndef __DRV_XGBE_INTF_H__
+#define __DRV_XGBE_INTF_H__
+
+/**
+ * An object for forwarding VAs and PAs to the hypervisor.
+ * @ingroup types
+ *
+ * This allows the supervisor to specify a number of areas of memory to
+ * store packet buffers.
+ */
+typedef struct
+{
+  /** The physical address of the memory. */
+  HV_PhysAddr pa;
+  /** Page table entry for the memory.  This is only used to derive the
+   *  memory's caching mode; the PA bits are ignored. */
+  HV_PTE pte;
+  /** The virtual address of the memory. */
+  HV_VirtAddr va;
+  /** Size (in bytes) of the memory area. */
+  int size;
+
+}
+netio_ipp_address_t;
+
+/** The various pread/pwrite offsets into the hypervisor-level driver.
+ * @ingroup types
+ */
+typedef enum
+{
+  /** Inform the Linux driver of the address of the NetIO arena memory.
+   *  This offset is actually only used to convey information from netio
+   *  to the Linux driver; it never makes it from there to the hypervisor.
+   *  Write-only; takes a uint32_t specifying the VA address. */
+  NETIO_FIXED_ADDR               = 0x5000000000000000ULL,
+
+  /** Inform the Linux driver of the size of the NetIO arena memory.
+   *  This offset is actually only used to convey information from netio
+   *  to the Linux driver; it never makes it from there to the hypervisor.
+   *  Write-only; takes a uint32_t specifying the VA size. */
+  NETIO_FIXED_SIZE               = 0x5100000000000000ULL,
+
+  /** Register current tile with IPP.  Write then read: write, takes a
+   *  netio_input_config_t, read returns a pointer to a netio_queue_impl_t. */
+  NETIO_IPP_INPUT_REGISTER_OFF   = 0x6000000000000000ULL,
+
+  /** Unregister current tile from IPP.  Write-only, takes a dummy argument. */
+  NETIO_IPP_INPUT_UNREGISTER_OFF = 0x6100000000000000ULL,
+
+  /** Start packets flowing.  Write-only, takes a dummy argument. */
+  NETIO_IPP_INPUT_INIT_OFF       = 0x6200000000000000ULL,
+
+  /** Stop packets flowing.  Write-only, takes a dummy argument. */
+  NETIO_IPP_INPUT_UNINIT_OFF     = 0x6300000000000000ULL,
+
+  /** Configure group (typically we group on VLAN).  Write-only: takes an
+   *  array of netio_group_t's, low 24 bits of the offset is the base group
+   *  number times the size of a netio_group_t. */
+  NETIO_IPP_INPUT_GROUP_CFG_OFF  = 0x6400000000000000ULL,
+
+  /** Configure bucket.  Write-only: takes an array of netio_bucket_t's, low
+   *  24 bits of the offset is the base bucket number times the size of a
+   *  netio_bucket_t. */
+  NETIO_IPP_INPUT_BUCKET_CFG_OFF = 0x6500000000000000ULL,
+
+  /** Get/set a parameter.  Read or write: read or write data is the parameter
+   *  value, low 32 bits of the offset is a __netio_getset_offset_t. */
+  NETIO_IPP_PARAM_OFF            = 0x6600000000000000ULL,
+
+  /** Get fast I/O index.  Read-only; returns a 4-byte base index value. */
+  NETIO_IPP_GET_FASTIO_OFF       = 0x6700000000000000ULL,
+
+  /** Configure hijack IP address.  Packets with this IPv4 dest address
+   *  go to bucket NETIO_NUM_BUCKETS - 1.  Write-only: takes an IP address
+   *  in some standard form.  FIXME: Define the form! */
+  NETIO_IPP_INPUT_HIJACK_CFG_OFF  = 0x6800000000000000ULL,
+
+  /**
+   * Offsets beyond this point are reserved for the supervisor (although that
+   * enforcement must be done by the supervisor driver itself).
+   */
+  NETIO_IPP_USER_MAX_OFF         = 0x6FFFFFFFFFFFFFFFULL,
+
+  /** Register I/O memory.  Write-only, takes a netio_ipp_address_t. */
+  NETIO_IPP_IOMEM_REGISTER_OFF   = 0x7000000000000000ULL,
+
+  /** Unregister I/O memory.  Write-only, takes a netio_ipp_address_t. */
+  NETIO_IPP_IOMEM_UNREGISTER_OFF = 0x7100000000000000ULL,
+
+  /* Offsets greater than 0x7FFFFFFF can't be used directly from Linux
+   * userspace code due to limitations in the pread/pwrite syscalls. */
+
+  /** Drain LIPP buffers. */
+  NETIO_IPP_DRAIN_OFF              = 0xFA00000000000000ULL,
+
+  /** Supply a netio_ipp_address_t to be used as shared memory for the
+   *  LEPP command queue. */
+  NETIO_EPP_SHM_OFF              = 0xFB00000000000000ULL,
+
+  /* 0xFC... is currently unused. */
+
+  /** Stop IPP/EPP tiles.  Write-only, takes a dummy argument.  */
+  NETIO_IPP_STOP_SHIM_OFF        = 0xFD00000000000000ULL,
+
+  /** Start IPP/EPP tiles.  Write-only, takes a dummy argument.  */
+  NETIO_IPP_START_SHIM_OFF       = 0xFE00000000000000ULL,
+
+  /** Supply packet arena.  Write-only, takes an array of
+    * netio_ipp_address_t values. */
+  NETIO_IPP_ADDRESS_OFF          = 0xFF00000000000000ULL,
+} netio_hv_offset_t;
+
+/** Extract the base offset from an offset */
+#define NETIO_BASE_OFFSET(off)    ((off) & 0xFF00000000000000ULL)
+/** Extract the local offset from an offset */
+#define NETIO_LOCAL_OFFSET(off)   ((off) & 0x00FFFFFFFFFFFFFFULL)
+
+
+/**
+ * Get/set offset.
+ */
+typedef union
+{
+  struct
+  {
+    uint64_t addr:48;        /**< Class-specific address */
+    unsigned int class:8;    /**< Class (e.g., NETIO_PARAM) */
+    unsigned int opcode:8;   /**< High 8 bits of NETIO_IPP_PARAM_OFF */
+  }
+  bits;                      /**< Bitfields */
+  uint64_t word;             /**< Aggregated value to use as the offset */
+}
+__netio_getset_offset_t;
+
+/**
+ * Fast I/O index offsets (must be contiguous).
+ */
+typedef enum
+{
+  NETIO_FASTIO_ALLOCATE         = 0, /**< Get empty packet buffer */
+  NETIO_FASTIO_FREE_BUFFER      = 1, /**< Give buffer back to IPP */
+  NETIO_FASTIO_RETURN_CREDITS   = 2, /**< Give credits to IPP */
+  NETIO_FASTIO_SEND_PKT_NOCK    = 3, /**< Send a packet, no checksum */
+  NETIO_FASTIO_SEND_PKT_CK      = 4, /**< Send a packet, with checksum */
+  NETIO_FASTIO_SEND_PKT_VEC     = 5, /**< Send a vector of packets */
+  NETIO_FASTIO_SENDV_PKT        = 6, /**< Sendv one packet */
+  NETIO_FASTIO_NUM_INDEX        = 7, /**< Total number of fast I/O indices */
+} netio_fastio_index_t;
+
+/** 3-word return type for Fast I/O call. */
+typedef struct
+{
+  int err;            /**< Error code. */
+  uint32_t val0;      /**< Value.  Meaning depends upon the specific call. */
+  uint32_t val1;      /**< Value.  Meaning depends upon the specific call. */
+} netio_fastio_rv3_t;
+
+/** 0-argument fast I/O call */
+int __netio_fastio0(uint32_t fastio_index);
+/** 1-argument fast I/O call */
+int __netio_fastio1(uint32_t fastio_index, uint32_t arg0);
+/** 3-argument fast I/O call, 2-word return value */
+netio_fastio_rv3_t __netio_fastio3_rv3(uint32_t fastio_index, uint32_t arg0,
+                                       uint32_t arg1, uint32_t arg2);
+/** 4-argument fast I/O call */
+int __netio_fastio4(uint32_t fastio_index, uint32_t arg0, uint32_t arg1,
+                    uint32_t arg2, uint32_t arg3);
+/** 6-argument fast I/O call */
+int __netio_fastio6(uint32_t fastio_index, uint32_t arg0, uint32_t arg1,
+                    uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5);
+/** 9-argument fast I/O call */
+int __netio_fastio9(uint32_t fastio_index, uint32_t arg0, uint32_t arg1,
+                    uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5,
+                    uint32_t arg6, uint32_t arg7, uint32_t arg8);
+
+/** Allocate an empty packet.
+ * @param fastio_index Fast I/O index.
+ * @param size Size of the packet to allocate.
+ */
+#define __netio_fastio_allocate(fastio_index, size) \
+  __netio_fastio1((fastio_index) + NETIO_FASTIO_ALLOCATE, size)
+
+/** Free a buffer.
+ * @param fastio_index Fast I/O index.
+ * @param handle Handle for the packet to free.
+ */
+#define __netio_fastio_free_buffer(fastio_index, handle) \
+  __netio_fastio1((fastio_index) + NETIO_FASTIO_FREE_BUFFER, handle)
+
+/** Increment our receive credits.
+ * @param fastio_index Fast I/O index.
+ * @param credits Number of credits to add.
+ */
+#define __netio_fastio_return_credits(fastio_index, credits) \
+  __netio_fastio1((fastio_index) + NETIO_FASTIO_RETURN_CREDITS, credits)
+
+/** Send packet, no checksum.
+ * @param fastio_index Fast I/O index.
+ * @param ackflag Nonzero if we want an ack.
+ * @param size Size of the packet.
+ * @param va Virtual address of start of packet.
+ * @param handle Packet handle.
+ */
+#define __netio_fastio_send_pkt_nock(fastio_index, ackflag, size, va, handle) \
+  __netio_fastio4((fastio_index) + NETIO_FASTIO_SEND_PKT_NOCK, ackflag, \
+                  size, va, handle)
+
+/** Send packet, calculate checksum.
+ * @param fastio_index Fast I/O index.
+ * @param ackflag Nonzero if we want an ack.
+ * @param size Size of the packet.
+ * @param va Virtual address of start of packet.
+ * @param handle Packet handle.
+ * @param csum0 Shim checksum header.
+ * @param csum1 Checksum seed.
+ */
+#define __netio_fastio_send_pkt_ck(fastio_index, ackflag, size, va, handle, \
+                                   csum0, csum1) \
+  __netio_fastio6((fastio_index) + NETIO_FASTIO_SEND_PKT_CK, ackflag, \
+                  size, va, handle, csum0, csum1)
+
+
+/** Format for the "csum0" argument to the __netio_fastio_send routines
+ * and LEPP.  Note that this is currently exactly identical to the
+ * ShimProtocolOffloadHeader.
+ */
+typedef union
+{
+  struct
+  {
+    unsigned int start_byte:7;       /**< The first byte to be checksummed */
+    unsigned int count:14;           /**< Number of bytes to be checksummed. */
+    unsigned int destination_byte:7; /**< The byte to write the checksum to. */
+    unsigned int reserved:4;         /**< Reserved. */
+  } bits;                            /**< Decomposed method of access. */
+  unsigned int word;                 /**< To send out the IDN. */
+} __netio_checksum_header_t;
+
+
+/** Sendv packet with 1 or 2 segments.
+ * @param fastio_index Fast I/O index.
+ * @param flags Ack/csum/notify flags in low 3 bits; number of segments minus
+ *        1 in next 2 bits; expected checksum in high 16 bits.
+ * @param confno Confirmation number to request, if notify flag set.
+ * @param csum0 Checksum descriptor; if zero, no checksum.
+ * @param va_F Virtual address of first segment.
+ * @param va_L Virtual address of last segment, if 2 segments.
+ * @param len_F_L Length of first segment in low 16 bits; length of last
+ *        segment, if 2 segments, in high 16 bits.
+ */
+#define __netio_fastio_sendv_pkt_1_2(fastio_index, flags, confno, csum0, \
+                                     va_F, va_L, len_F_L) \
+  __netio_fastio6((fastio_index) + NETIO_FASTIO_SENDV_PKT, flags, confno, \
+                  csum0, va_F, va_L, len_F_L)
+
+/** Send packet on PCIe interface.
+ * @param fastio_index Fast I/O index.
+ * @param flags Ack/csum/notify flags in low 3 bits.
+ * @param confno Confirmation number to request, if notify flag set.
+ * @param csum0 Checksum descriptor; Hard wired 0, not needed for PCIe.
+ * @param va_F Virtual address of the packet buffer.
+ * @param va_L Virtual address of last segment, if 2 segments. Hard wired 0.
+ * @param len_F_L Length of the packet buffer in low 16 bits.
+ */
+#define __netio_fastio_send_pcie_pkt(fastio_index, flags, confno, csum0, \
+                                     va_F, va_L, len_F_L) \
+  __netio_fastio6((fastio_index) + PCIE_FASTIO_SENDV_PKT, flags, confno, \
+                  csum0, va_F, va_L, len_F_L)
+
+/** Sendv packet with 3 or 4 segments.
+ * @param fastio_index Fast I/O index.
+ * @param flags Ack/csum/notify flags in low 3 bits; number of segments minus
+ *        1 in next 2 bits; expected checksum in high 16 bits.
+ * @param confno Confirmation number to request, if notify flag set.
+ * @param csum0 Checksum descriptor; if zero, no checksum.
+ * @param va_F Virtual address of first segment.
+ * @param va_L Virtual address of last segment (third segment if 3 segments,
+ *        fourth segment if 4 segments).
+ * @param len_F_L Length of first segment in low 16 bits; length of last
+ *        segment in high 16 bits.
+ * @param va_M0 Virtual address of "middle 0" segment; this segment is sent
+ *        second when there are three segments, and third if there are four.
+ * @param va_M1 Virtual address of "middle 1" segment; this segment is sent
+ *        second when there are four segments.
+ * @param len_M0_M1 Length of middle 0 segment in low 16 bits; length of middle
+ *        1 segment, if 4 segments, in high 16 bits.
+ */
+#define __netio_fastio_sendv_pkt_3_4(fastio_index, flags, confno, csum0, va_F, \
+                                     va_L, len_F_L, va_M0, va_M1, len_M0_M1) \
+  __netio_fastio9((fastio_index) + NETIO_FASTIO_SENDV_PKT, flags, confno, \
+                  csum0, va_F, va_L, len_F_L, va_M0, va_M1, len_M0_M1)
+
+/** Send vector of packets.
+ * @param fastio_index Fast I/O index.
+ * @param seqno Number of packets transmitted so far on this interface;
+ *        used to decide which packets should be acknowledged.
+ * @param nentries Number of entries in vector.
+ * @param va Virtual address of start of vector entry array.
+ * @return 3-word netio_fastio_rv3_t structure.  The structure's err member
+ *         is an error code, or zero if no error.  The val0 member is the
+ *         updated value of seqno; it has been incremented by 1 for each
+ *         packet sent.  That increment may be less than nentries if an
+ *         error occured, or if some of the entries in the vector contain
+ *         handles equal to NETIO_PKT_HANDLE_NONE.  The val1 member is the
+ *         updated value of nentries; it has been decremented by 1 for each
+ *         vector entry processed.  Again, that decrement may be less than
+ *         nentries (leaving the returned value positive) if an error
+ *         occurred.
+ */
+#define __netio_fastio_send_pkt_vec(fastio_index, seqno, nentries, va) \
+  __netio_fastio3_rv3((fastio_index) + NETIO_FASTIO_SEND_PKT_VEC, seqno, \
+                      nentries, va)
+
+
+/** An egress DMA command for LEPP. */
+typedef struct
+{
+  /** Is this a TSO transfer?
+   *
+   * NOTE: This field is always 0, to distinguish it from
+   * lepp_tso_cmd_t.  It must come first!
+   */
+  uint8_t tso               : 1;
+
+  /** Unused padding bits. */
+  uint8_t _unused           : 3;
+
+  /** Should this packet be sent directly from caches instead of DRAM,
+   * using hash-for-home to locate the packet data?
+   */
+  uint8_t hash_for_home     : 1;
+
+  /** Should we compute a checksum? */
+  uint8_t compute_checksum  : 1;
+
+  /** Is this the final buffer for this packet?
+   *
+   * A single packet can be split over several input buffers (a "gather"
+   * operation).  This flag indicates that this is the last buffer
+   * in a packet.
+   */
+  uint8_t end_of_packet     : 1;
+
+  /** Should LEPP advance 'comp_busy' when this DMA is fully finished? */
+  uint8_t send_completion   : 1;
+
+  /** High bits of Client Physical Address of the start of the buffer
+   *  to be egressed.
+   *
+   *  NOTE: Only 6 bits are actually needed here, as CPAs are
+   *  currently 38 bits.  So two bits could be scavenged from this.
+   */
+  uint8_t cpa_hi;
+
+  /** The number of bytes to be egressed. */
+  uint16_t length;
+
+  /** Low 32 bits of Client Physical Address of the start of the buffer
+   *  to be egressed.
+   */
+  uint32_t cpa_lo;
+
+  /** Checksum information (only used if 'compute_checksum'). */
+  __netio_checksum_header_t checksum_data;
+
+} lepp_cmd_t;
+
+
+/** A chunk of physical memory for a TSO egress. */
+typedef struct
+{
+  /** The low bits of the CPA. */
+  uint32_t cpa_lo;
+  /** The high bits of the CPA. */
+  uint16_t cpa_hi              : 15;
+  /** Should this packet be sent directly from caches instead of DRAM,
+   *  using hash-for-home to locate the packet data?
+   */
+  uint16_t hash_for_home       : 1;
+  /** The length in bytes. */
+  uint16_t length;
+} lepp_frag_t;
+
+
+/** An LEPP command that handles TSO. */
+typedef struct
+{
+  /** Is this a TSO transfer?
+   *
+   *  NOTE: This field is always 1, to distinguish it from
+   *  lepp_cmd_t.  It must come first!
+   */
+  uint8_t tso             : 1;
+
+  /** Unused padding bits. */
+  uint8_t _unused         : 7;
+
+  /** Size of the header[] array in bytes.  It must be in the range
+   *  [40, 127], which are the smallest header for a TCP packet over
+   *  Ethernet and the maximum possible prepend size supported by
+   *  hardware, respectively.  Note that the array storage must be
+   *  padded out to a multiple of four bytes so that the following
+   *  LEPP command is aligned properly.
+   */
+  uint8_t header_size;
+
+  /** Byte offset of the IP header in header[]. */
+  uint8_t ip_offset;
+
+  /** Byte offset of the TCP header in header[]. */
+  uint8_t tcp_offset;
+
+  /** The number of bytes to use for the payload of each packet,
+   *  except of course the last one, which may not have enough bytes.
+   *  This means that each Ethernet packet except the last will have a
+   *  size of header_size + payload_size.
+   */
+  uint16_t payload_size;
+
+  /** The length of the 'frags' array that follows this struct. */
+  uint16_t num_frags;
+
+  /** The actual frags. */
+  lepp_frag_t frags[0 /* Variable-sized; num_frags entries. */];
+
+  /*
+   * The packet header template logically follows frags[],
+   * but you can't declare that in C.
+   *
+   * uint32_t header[header_size_in_words_rounded_up];
+   */
+
+} lepp_tso_cmd_t;
+
+
+/** An LEPP completion ring entry. */
+typedef void* lepp_comp_t;
+
+
+/** Maximum number of frags for one TSO command.  This is adapted from
+ *  linux's "MAX_SKB_FRAGS", and presumably over-estimates by one, for
+ *  our page size of exactly 65536.  We add one for a "body" fragment.
+ */
+#define LEPP_MAX_FRAGS (65536 / HV_PAGE_SIZE_SMALL + 2 + 1)
+
+/** Total number of bytes needed for an lepp_tso_cmd_t. */
+#define LEPP_TSO_CMD_SIZE(num_frags, header_size) \
+  (sizeof(lepp_tso_cmd_t) + \
+   (num_frags) * sizeof(lepp_frag_t) + \
+   (((header_size) + 3) & -4))
+
+/** The size of the lepp "cmd" queue. */
+#define LEPP_CMD_QUEUE_BYTES \
+ (((CHIP_L2_CACHE_SIZE() - 2 * CHIP_L2_LINE_SIZE()) / \
+  (sizeof(lepp_cmd_t) + sizeof(lepp_comp_t))) * sizeof(lepp_cmd_t))
+
+/** The largest possible command that can go in lepp_queue_t::cmds[]. */
+#define LEPP_MAX_CMD_SIZE LEPP_TSO_CMD_SIZE(LEPP_MAX_FRAGS, 128)
+
+/** The largest possible value of lepp_queue_t::cmd_{head, tail} (inclusive).
+ */
+#define LEPP_CMD_LIMIT \
+  (LEPP_CMD_QUEUE_BYTES - LEPP_MAX_CMD_SIZE)
+
+/** The maximum number of completions in an LEPP queue. */
+#define LEPP_COMP_QUEUE_SIZE \
+  ((LEPP_CMD_LIMIT + sizeof(lepp_cmd_t) - 1) / sizeof(lepp_cmd_t))
+
+/** Increment an index modulo the queue size. */
+#define LEPP_QINC(var) \
+  (var = __insn_mnz(var - (LEPP_COMP_QUEUE_SIZE - 1), var + 1))
+
+/** A queue used to convey egress commands from the client to LEPP. */
+typedef struct
+{
+  /** Index of first completion not yet processed by user code.
+   *  If this is equal to comp_busy, there are no such completions.
+   *
+   *  NOTE: This is only read/written by the user.
+   */
+  unsigned int comp_head;
+
+  /** Index of first completion record not yet completed.
+   *  If this is equal to comp_tail, there are no such completions.
+   *  This index gets advanced (modulo LEPP_QUEUE_SIZE) whenever
+   *  a command with the 'completion' bit set is finished.
+   *
+   *  NOTE: This is only written by LEPP, only read by the user.
+   */
+  volatile unsigned int comp_busy;
+
+  /** Index of the first empty slot in the completion ring.
+   *  Entries from this up to but not including comp_head (in ring order)
+   *  can be filled in with completion data.
+   *
+   *  NOTE: This is only read/written by the user.
+   */
+  unsigned int comp_tail;
+
+  /** Byte index of first command enqueued for LEPP but not yet processed.
+   *
+   *  This is always divisible by sizeof(void*) and always <= LEPP_CMD_LIMIT.
+   *
+   *  NOTE: LEPP advances this counter as soon as it no longer needs
+   *  the cmds[] storage for this entry, but the transfer is not actually
+   *  complete (i.e. the buffer pointed to by the command is no longer
+   *  needed) until comp_busy advances.
+   *
+   *  If this is equal to cmd_tail, the ring is empty.
+   *
+   *  NOTE: This is only written by LEPP, only read by the user.
+   */
+  volatile unsigned int cmd_head;
+
+  /** Byte index of first empty slot in the command ring.  This field can
+   *  be incremented up to but not equal to cmd_head (because that would
+   *  mean the ring is empty).
+   *
+   *  This is always divisible by sizeof(void*) and always <= LEPP_CMD_LIMIT.
+   *
+   *  NOTE: This is read/written by the user, only read by LEPP.
+   */
+  volatile unsigned int cmd_tail;
+
+  /** A ring of variable-sized egress DMA commands.
+   *
+   *  NOTE: Only written by the user, only read by LEPP.
+   */
+  char cmds[LEPP_CMD_QUEUE_BYTES]
+    __attribute__((aligned(CHIP_L2_LINE_SIZE())));
+
+  /** A ring of user completion data.
+   *  NOTE: Only read/written by the user.
+   */
+  lepp_comp_t comps[LEPP_COMP_QUEUE_SIZE]
+    __attribute__((aligned(CHIP_L2_LINE_SIZE())));
+} lepp_queue_t;
+
+
+/** An internal helper function for determining the number of entries
+ *  available in a ring buffer, given that there is one sentinel.
+ */
+static inline unsigned int
+_lepp_num_free_slots(unsigned int head, unsigned int tail)
+{
+  /*
+   * One entry is reserved for use as a sentinel, to distinguish
+   * "empty" from "full".  So we compute
+   * (head - tail - 1) % LEPP_QUEUE_SIZE, but without using a slow % operation.
+   */
+  return (head - tail - 1) + ((head <= tail) ? LEPP_COMP_QUEUE_SIZE : 0);
+}
+
+
+/** Returns how many new comp entries can be enqueued. */
+static inline unsigned int
+lepp_num_free_comp_slots(const lepp_queue_t* q)
+{
+  return _lepp_num_free_slots(q->comp_head, q->comp_tail);
+}
+
+static inline int
+lepp_qsub(int v1, int v2)
+{
+  int delta = v1 - v2;
+  return delta + ((delta >> 31) & LEPP_COMP_QUEUE_SIZE);
+}
+
+
+/** FIXME: Check this from linux, via a new "pwrite()" call. */
+#define LIPP_VERSION 1
+
+
+/** We use exactly two bytes of alignment padding. */
+#define LIPP_PACKET_PADDING 2
+
+/** The minimum size of a "small" buffer (including the padding). */
+#define LIPP_SMALL_PACKET_SIZE 128
+
+/*
+ * NOTE: The following two values should total to less than around
+ * 13582, to keep the total size used for "lipp_state_t" below 64K.
+ */
+
+/** The maximum number of "small" buffers.
+ *  This is enough for 53 network cpus with 128 credits.  Note that
+ *  if these are exhausted, we will fall back to using large buffers.
+ */
+#define LIPP_SMALL_BUFFERS 6785
+
+/** The maximum number of "large" buffers.
+ *  This is enough for 53 network cpus with 128 credits.
+ */
+#define LIPP_LARGE_BUFFERS 6785
+
+#endif /* __DRV_XGBE_INTF_H__ */
diff --git a/arch/tile/include/hv/netio_errors.h b/arch/tile/include/hv/netio_errors.h
new file mode 100644 (file)
index 0000000..e1591bf
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2010 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is 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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/**
+ * Error codes returned from NetIO routines.
+ */
+
+#ifndef __NETIO_ERRORS_H__
+#define __NETIO_ERRORS_H__
+
+/**
+ * @addtogroup error
+ *
+ * @brief The error codes returned by NetIO functions.
+ *
+ * NetIO functions return 0 (defined as ::NETIO_NO_ERROR) on success, and
+ * a negative value if an error occurs.
+ *
+ * In cases where a NetIO function failed due to a error reported by
+ * system libraries, the error code will be the negation of the
+ * system errno at the time of failure.  The @ref netio_strerror()
+ * function will deliver error strings for both NetIO and system error
+ * codes.
+ *
+ * @{
+ */
+
+/** The set of all NetIO errors. */
+typedef enum
+{
+  /** Operation successfully completed. */
+  NETIO_NO_ERROR        = 0,
+
+  /** A packet was successfully retrieved from an input queue. */
+  NETIO_PKT             = 0,
+
+  /** Largest NetIO error number. */
+  NETIO_ERR_MAX         = -701,
+
+  /** The tile is not registered with the IPP. */
+  NETIO_NOT_REGISTERED  = -701,
+
+  /** No packet was available to retrieve from the input queue. */
+  NETIO_NOPKT           = -702,
+
+  /** The requested function is not implemented. */
+  NETIO_NOT_IMPLEMENTED = -703,
+
+  /** On a registration operation, the target queue already has the maximum
+   *  number of tiles registered for it, and no more may be added.  On a
+   *  packet send operation, the output queue is full and nothing more can
+   *  be queued until some of the queued packets are actually transmitted. */
+  NETIO_QUEUE_FULL      = -704,
+
+  /** The calling process or thread is not bound to exactly one CPU. */
+  NETIO_BAD_AFFINITY    = -705,
+
+  /** Cannot allocate memory on requested controllers. */
+  NETIO_CANNOT_HOME     = -706,
+
+  /** On a registration operation, the IPP specified is not configured
+   *  to support the options requested; for instance, the application
+   *  wants a specific type of tagged headers which the configured IPP
+   *  doesn't support.  Or, the supplied configuration information is
+   *  not self-consistent, or is out of range; for instance, specifying
+   *  both NETIO_RECV and NETIO_NO_RECV, or asking for more than
+   *  NETIO_MAX_SEND_BUFFERS to be preallocated.  On a VLAN or bucket
+   *  configure operation, the number of items, or the base item, was
+   *  out of range.
+   */
+  NETIO_BAD_CONFIG      = -707,
+
+  /** Too many tiles have registered to transmit packets. */
+  NETIO_TOOMANY_XMIT    = -708,
+
+  /** Packet transmission was attempted on a queue which was registered
+      with transmit disabled. */
+  NETIO_UNREG_XMIT      = -709,
+
+  /** This tile is already registered with the IPP. */
+  NETIO_ALREADY_REGISTERED = -710,
+
+  /** The Ethernet link is down. The application should try again later. */
+  NETIO_LINK_DOWN       = -711,
+
+  /** An invalid memory buffer has been specified.  This may be an unmapped
+   * virtual address, or one which does not meet alignment requirements.
+   * For netio_input_register(), this error may be returned when multiple
+   * processes specify different memory regions to be used for NetIO
+   * buffers.  That can happen if these processes specify explicit memory
+   * regions with the ::NETIO_FIXED_BUFFER_VA flag, or if tmc_cmem_init()
+   * has not been called by a common ancestor of the processes.
+   */
+  NETIO_FAULT           = -712,
+
+  /** Cannot combine user-managed shared memory and cache coherence. */
+  NETIO_BAD_CACHE_CONFIG = -713,
+
+  /** Smallest NetIO error number. */
+  NETIO_ERR_MIN         = -713,
+
+#ifndef __DOXYGEN__
+  /** Used internally to mean that no response is needed; never returned to
+   *  an application. */
+  NETIO_NO_RESPONSE     = 1
+#endif
+} netio_error_t;
+
+/** @} */
+
+#endif /* __NETIO_ERRORS_H__ */
diff --git a/arch/tile/include/hv/netio_intf.h b/arch/tile/include/hv/netio_intf.h
new file mode 100644 (file)
index 0000000..8d20972
--- /dev/null
@@ -0,0 +1,2975 @@
+/*
+ * Copyright 2010 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is 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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/**
+ * NetIO interface structures and macros.
+ */
+
+#ifndef __NETIO_INTF_H__
+#define __NETIO_INTF_H__
+
+#include <hv/netio_errors.h>
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <stdint.h>
+#endif
+
+#if !defined(__HV__) && !defined(__BOGUX__) && !defined(__KERNEL__)
+#include <assert.h>
+#define netio_assert assert  /**< Enable assertions from macros */
+#else
+#define netio_assert(...) ((void)(0))  /**< Disable assertions from macros */
+#endif
+
+/*
+ * If none of these symbols are defined, we're building libnetio in an
+ * environment where we have pthreads, so we'll enable locking.
+ */
+#if !defined(__HV__) && !defined(__BOGUX__) && !defined(__KERNEL__) && \
+    !defined(__NEWLIB__)
+#define _NETIO_PTHREAD       /**< Include a mutex in netio_queue_t below */
+
+/*
+ * If NETIO_UNLOCKED is defined, we don't do use per-cpu locks on
+ * per-packet NetIO operations.  We still do pthread locking on things
+ * like netio_input_register, though.  This is used for building
+ * libnetio_unlocked.
+ */
+#ifndef NETIO_UNLOCKED
+
+/* Avoid PLT overhead by using our own inlined per-cpu lock. */
+#include <sched.h>
+typedef int _netio_percpu_mutex_t;
+
+static __inline int
+_netio_percpu_mutex_init(_netio_percpu_mutex_t* lock)
+{
+  *lock = 0;
+  return 0;
+}
+
+static __inline int
+_netio_percpu_mutex_lock(_netio_percpu_mutex_t* lock)
+{
+  while (__builtin_expect(__insn_tns(lock), 0))
+    sched_yield();
+  return 0;
+}
+
+static __inline int
+_netio_percpu_mutex_unlock(_netio_percpu_mutex_t* lock)
+{
+  *lock = 0;
+  return 0;
+}
+
+#else /* NETIO_UNLOCKED */
+
+/* Don't do any locking for per-packet NetIO operations. */
+typedef int _netio_percpu_mutex_t;
+#define _netio_percpu_mutex_init(L)
+#define _netio_percpu_mutex_lock(L)
+#define _netio_percpu_mutex_unlock(L)
+
+#endif /* NETIO_UNLOCKED */
+#endif /* !__HV__, !__BOGUX, !__KERNEL__, !__NEWLIB__ */
+
+/** How many tiles can register for a given queue.
+ *  @ingroup setup */
+#define NETIO_MAX_TILES_PER_QUEUE  64
+
+
+/** Largest permissible queue identifier.
+ *  @ingroup setup  */
+#define NETIO_MAX_QUEUE_ID        255
+
+
+#ifndef __DOXYGEN__
+
+/* Metadata packet checksum/ethertype flags. */
+
+/** The L4 checksum has not been calculated. */
+#define _NETIO_PKT_NO_L4_CSUM_SHIFT           0
+#define _NETIO_PKT_NO_L4_CSUM_RMASK           1
+#define _NETIO_PKT_NO_L4_CSUM_MASK \
+         (_NETIO_PKT_NO_L4_CSUM_RMASK << _NETIO_PKT_NO_L4_CSUM_SHIFT)
+
+/** The L3 checksum has not been calculated. */
+#define _NETIO_PKT_NO_L3_CSUM_SHIFT           1
+#define _NETIO_PKT_NO_L3_CSUM_RMASK           1
+#define _NETIO_PKT_NO_L3_CSUM_MASK \
+         (_NETIO_PKT_NO_L3_CSUM_RMASK << _NETIO_PKT_NO_L3_CSUM_SHIFT)
+
+/** The L3 checksum is incorrect (or perhaps has not been calculated). */
+#define _NETIO_PKT_BAD_L3_CSUM_SHIFT          2
+#define _NETIO_PKT_BAD_L3_CSUM_RMASK          1
+#define _NETIO_PKT_BAD_L3_CSUM_MASK \
+         (_NETIO_PKT_BAD_L3_CSUM_RMASK << _NETIO_PKT_BAD_L3_CSUM_SHIFT)
+
+/** The Ethernet packet type is unrecognized. */
+#define _NETIO_PKT_TYPE_UNRECOGNIZED_SHIFT    3
+#define _NETIO_PKT_TYPE_UNRECOGNIZED_RMASK    1
+#define _NETIO_PKT_TYPE_UNRECOGNIZED_MASK \
+         (_NETIO_PKT_TYPE_UNRECOGNIZED_RMASK << \
+          _NETIO_PKT_TYPE_UNRECOGNIZED_SHIFT)
+
+/* Metadata packet type flags. */
+
+/** Where the packet type bits are; this field is the index into
+ *  _netio_pkt_info. */
+#define _NETIO_PKT_TYPE_SHIFT        4
+#define _NETIO_PKT_TYPE_RMASK        0x3F
+
+/** How many VLAN tags the packet has, and, if we have two, which one we
+ *  actually grouped on.  A VLAN within a proprietary (Marvell or Broadcom)
+ *  tag is counted here. */
+#define _NETIO_PKT_VLAN_SHIFT        4
+#define _NETIO_PKT_VLAN_RMASK        0x3
+#define _NETIO_PKT_VLAN_MASK \
+         (_NETIO_PKT_VLAN_RMASK << _NETIO_PKT_VLAN_SHIFT)
+#define _NETIO_PKT_VLAN_NONE         0   /* No VLAN tag. */
+#define _NETIO_PKT_VLAN_ONE          1   /* One VLAN tag. */
+#define _NETIO_PKT_VLAN_TWO_OUTER    2   /* Two VLAN tags, outer one used. */
+#define _NETIO_PKT_VLAN_TWO_INNER    3   /* Two VLAN tags, inner one used. */
+
+/** Which proprietary tags the packet has. */
+#define _NETIO_PKT_TAG_SHIFT         6
+#define _NETIO_PKT_TAG_RMASK         0x3
+#define _NETIO_PKT_TAG_MASK \
+          (_NETIO_PKT_TAG_RMASK << _NETIO_PKT_TAG_SHIFT)
+#define _NETIO_PKT_TAG_NONE          0   /* No proprietary tags. */
+#define _NETIO_PKT_TAG_MRVL          1   /* Marvell HyperG.Stack tags. */
+#define _NETIO_PKT_TAG_MRVL_EXT      2   /* HyperG.Stack extended tags. */
+#define _NETIO_PKT_TAG_BRCM          3   /* Broadcom HiGig tags. */
+
+/** Whether a packet has an LLC + SNAP header. */
+#define _NETIO_PKT_SNAP_SHIFT        8
+#define _NETIO_PKT_SNAP_RMASK        0x1
+#define _NETIO_PKT_SNAP_MASK \
+          (_NETIO_PKT_SNAP_RMASK << _NETIO_PKT_SNAP_SHIFT)
+
+/* NOTE: Bits 9 and 10 are unused. */
+
+/** Length of any custom data before the L2 header, in words. */
+#define _NETIO_PKT_CUSTOM_LEN_SHIFT  11
+#define _NETIO_PKT_CUSTOM_LEN_RMASK  0x1F
+#define _NETIO_PKT_CUSTOM_LEN_MASK \
+          (_NETIO_PKT_CUSTOM_LEN_RMASK << _NETIO_PKT_CUSTOM_LEN_SHIFT)
+
+/** The L4 checksum is incorrect (or perhaps has not been calculated). */
+#define _NETIO_PKT_BAD_L4_CSUM_SHIFT 16
+#define _NETIO_PKT_BAD_L4_CSUM_RMASK 0x1
+#define _NETIO_PKT_BAD_L4_CSUM_MASK \
+          (_NETIO_PKT_BAD_L4_CSUM_RMASK << _NETIO_PKT_BAD_L4_CSUM_SHIFT)
+
+/** Length of the L2 header, in words. */
+#define _NETIO_PKT_L2_LEN_SHIFT  17
+#define _NETIO_PKT_L2_LEN_RMASK  0x1F
+#define _NETIO_PKT_L2_LEN_MASK \
+          (_NETIO_PKT_L2_LEN_RMASK << _NETIO_PKT_L2_LEN_SHIFT)
+
+
+/* Flags in minimal packet metadata. */
+
+/** We need an eDMA checksum on this packet. */
+#define _NETIO_PKT_NEED_EDMA_CSUM_SHIFT            0
+#define _NETIO_PKT_NEED_EDMA_CSUM_RMASK            1
+#define _NETIO_PKT_NEED_EDMA_CSUM_MASK \
+         (_NETIO_PKT_NEED_EDMA_CSUM_RMASK << _NETIO_PKT_NEED_EDMA_CSUM_SHIFT)
+
+/* Data within the packet information table. */
+
+/* Note that, for efficiency, code which uses these fields assumes that none
+ * of the shift values below are zero.  See uses below for an explanation. */
+
+/** Offset within the L2 header of the innermost ethertype (in halfwords). */
+#define _NETIO_PKT_INFO_ETYPE_SHIFT       6
+#define _NETIO_PKT_INFO_ETYPE_RMASK    0x1F
+
+/** Offset within the L2 header of the VLAN tag (in halfwords). */
+#define _NETIO_PKT_INFO_VLAN_SHIFT       11
+#define _NETIO_PKT_INFO_VLAN_RMASK     0x1F
+
+#endif
+
+
+/** The size of a memory buffer representing a small packet.
+ *  @ingroup egress */
+#define SMALL_PACKET_SIZE 256
+
+/** The size of a memory buffer representing a large packet.
+ *  @ingroup egress */
+#define LARGE_PACKET_SIZE 2048
+
+/** The size of a memory buffer representing a jumbo packet.
+ *  @ingroup egress */
+#define JUMBO_PACKET_SIZE (12 * 1024)
+
+
+/* Common ethertypes.
+ * @ingroup ingress */
+/** @{ */
+/** The ethertype of IPv4. */
+#define ETHERTYPE_IPv4 (0x0800)
+/** The ethertype of ARP. */
+#define ETHERTYPE_ARP (0x0806)
+/** The ethertype of VLANs. */
+#define ETHERTYPE_VLAN (0x8100)
+/** The ethertype of a Q-in-Q header. */
+#define ETHERTYPE_Q_IN_Q (0x9100)
+/** The ethertype of IPv6. */
+#define ETHERTYPE_IPv6 (0x86DD)
+/** The ethertype of MPLS. */
+#define ETHERTYPE_MPLS (0x8847)
+/** @} */
+
+
+/** The possible return values of NETIO_PKT_STATUS.
+ * @ingroup ingress
+ */
+typedef enum
+{
+  /** No problems were detected with this packet. */
+  NETIO_PKT_STATUS_OK,
+  /** The packet is undersized; this is expected behavior if the packet's
+    * ethertype is unrecognized, but otherwise the packet is likely corrupt. */
+  NETIO_PKT_STATUS_UNDERSIZE,
+  /** The packet is oversized and some trailing bytes have been discarded.
+      This is expected behavior for short packets, since it's impossible to
+      precisely determine the amount of padding which may have been added to
+      them to make them meet the minimum Ethernet packet size. */
+  NETIO_PKT_STATUS_OVERSIZE,
+  /** The packet was judged to be corrupt by hardware (for instance, it had
+      a bad CRC, or part of it was discarded due to lack of buffer space in
+      the I/O shim) and should be discarded. */
+  NETIO_PKT_STATUS_BAD
+} netio_pkt_status_t;
+
+
+/** Log2 of how many buckets we have. */
+#define NETIO_LOG2_NUM_BUCKETS (10)
+
+/** How many buckets we have.
+ * @ingroup ingress */
+#define NETIO_NUM_BUCKETS (1 << NETIO_LOG2_NUM_BUCKETS)
+
+
+/**
+ * @brief A group-to-bucket identifier.
+ *
+ * @ingroup setup
+ *
+ * This tells us what to do with a given group.
+ */
+typedef union {
+  /** The header broken down into bits. */
+  struct {
+    /** Whether we should balance on L4, if available */
+    unsigned int __balance_on_l4:1;
+    /** Whether we should balance on L3, if available */
+    unsigned int __balance_on_l3:1;
+    /** Whether we should balance on L2, if available */
+    unsigned int __balance_on_l2:1;
+    /** Reserved for future use */
+    unsigned int __reserved:1;
+    /** The base bucket to use to send traffic */
+    unsigned int __bucket_base:NETIO_LOG2_NUM_BUCKETS;
+    /** The mask to apply to the balancing value. This must be one less
+     * than a power of two, e.g. 0x3 or 0xFF.
+     */
+    unsigned int __bucket_mask:NETIO_LOG2_NUM_BUCKETS;
+    /** Pad to 32 bits */
+    unsigned int __padding:(32 - 4 - 2 * NETIO_LOG2_NUM_BUCKETS);
+  } bits;
+  /** To send out the IDN. */
+  unsigned int word;
+}
+netio_group_t;
+
+
+/**
+ * @brief A VLAN-to-bucket identifier.
+ *
+ * @ingroup setup
+ *
+ * This tells us what to do with a given VLAN.
+ */
+typedef netio_group_t netio_vlan_t;
+
+
+/**
+ * A bucket-to-queue mapping.
+ * @ingroup setup
+ */
+typedef unsigned char netio_bucket_t;
+
+
+/**
+ * A packet size can always fit in a netio_size_t.
+ * @ingroup setup
+ */
+typedef unsigned int netio_size_t;
+
+
+/**
+ * @brief Ethernet standard (ingress) packet metadata.
+ *
+ * @ingroup ingress
+ *
+ * This is additional data associated with each packet.
+ * This structure is opaque and accessed through the @ref ingress.
+ *
+ * Also, the buffer population operation currently assumes that standard
+ * metadata is at least as large as minimal metadata, and will need to be
+ * modified if that is no longer the case.
+ */
+typedef struct
+{
+#ifdef __DOXYGEN__
+  /** This structure is opaque. */
+  unsigned char opaque[24];
+#else
+  /** The overall ordinal of the packet */
+  unsigned int __packet_ordinal;
+  /** The ordinal of the packet within the group */
+  unsigned int __group_ordinal;
+  /** The best flow hash IPP could compute. */
+  unsigned int __flow_hash;
+  /** Flags pertaining to checksum calculation, packet type, etc. */
+  unsigned int __flags;
+  /** The first word of "user data". */
+  unsigned int __user_data_0;
+  /** The second word of "user data". */
+  unsigned int __user_data_1;
+#endif
+}
+netio_pkt_metadata_t;
+
+
+/** To ensure that the L3 header is aligned mod 4, the L2 header should be
+ * aligned mod 4 plus 2, since every supported L2 header is 4n + 2 bytes
+ * long.  The standard way to do this is to simply add 2 bytes of padding
+ * before the L2 header.
+ */
+#define NETIO_PACKET_PADDING 2
+
+
+
+/**
+ * @brief Ethernet minimal (egress) packet metadata.
+ *
+ * @ingroup egress
+ *
+ * This structure represents information about packets which have
+ * been processed by @ref netio_populate_buffer() or
+ * @ref netio_populate_prepend_buffer().  This structure is opaque
+ * and accessed through the @ref egress.
+ *
+ * @internal This structure is actually copied into the memory used by
+ * standard metadata, which is assumed to be large enough.
+ */
+typedef struct
+{
+#ifdef __DOXYGEN__
+  /** This structure is opaque. */
+  unsigned char opaque[14];
+#else
+  /** The offset of the L2 header from the start of the packet data. */
+  unsigned short l2_offset;
+  /** The offset of the L3 header from the start of the packet data. */
+  unsigned short l3_offset;
+  /** Where to write the checksum. */
+  unsigned char csum_location;
+  /** Where to start checksumming from. */
+  unsigned char csum_start;
+  /** Flags pertaining to checksum calculation etc. */
+  unsigned short flags;
+  /** The L2 length of the packet. */
+  unsigned short l2_length;
+  /** The checksum with which to seed the checksum generator. */
+  unsigned short csum_seed;
+  /** How much to checksum. */
+  unsigned short csum_length;
+#endif
+}
+netio_pkt_minimal_metadata_t;
+
+
+#ifndef __DOXYGEN__
+
+/**
+ * @brief An I/O notification header.
+ *
+ * This is the first word of data received from an I/O shim in a notification
+ * packet. It contains framing and status information.
+ */
+typedef union
+{
+  unsigned int word; /**< The whole word. */
+  /** The various fields. */
+  struct
+  {
+    unsigned int __channel:7;    /**< Resource channel. */
+    unsigned int __type:4;       /**< Type. */
+    unsigned int __ack:1;        /**< Whether an acknowledgement is needed. */
+    unsigned int __reserved:1;   /**< Reserved. */
+    unsigned int __protocol:1;   /**< A protocol-specific word is added. */
+    unsigned int __status:2;     /**< Status of the transfer. */
+    unsigned int __framing:2;    /**< Framing of the transfer. */
+    unsigned int __transfer_size:14; /**< Transfer size in bytes (total). */
+  } bits;
+}
+__netio_pkt_notif_t;
+
+
+/**
+ * Returns the base address of the packet.
+ */
+#define _NETIO_PKT_HANDLE_BASE(p) \
+  ((unsigned char*)((p).word & 0xFFFFFFC0))
+
+/**
+ * Returns the base address of the packet.
+ */
+#define _NETIO_PKT_BASE(p) \
+  _NETIO_PKT_HANDLE_BASE(p->__packet)
+
+/**
+ * @brief An I/O notification packet (second word)
+ *
+ * This is the second word of data received from an I/O shim in a notification
+ * packet.  This is the virtual address of the packet buffer, plus some flag
+ * bits.  (The virtual address of the packet is always 256-byte aligned so we
+ * have room for 8 bits' worth of flags in the low 8 bits.)
+ *
+ * @internal
+ * NOTE: The low two bits must contain "__queue", so the "packet size"
+ * (SIZE_SMALL, SIZE_LARGE, or SIZE_JUMBO) can be determined quickly.
+ *
+ * If __addr or __offset are moved, _NETIO_PKT_BASE
+ * (defined right below this) must be changed.
+ */
+typedef union
+{
+  unsigned int word; /**< The whole word. */
+  /** The various fields. */
+  struct
+  {
+    /** Which queue the packet will be returned to once it is sent back to
+        the IPP.  This is one of the SIZE_xxx values. */
+    unsigned int __queue:2;
+
+    /** The IPP handle of the sending IPP. */
+    unsigned int __ipp_handle:2;
+
+    /** Reserved for future use. */
+    unsigned int __reserved:1;
+
+    /** If 1, this packet has minimal (egress) metadata; otherwise, it
+        has standard (ingress) metadata. */
+    unsigned int __minimal:1;
+
+    /** Offset of the metadata within the packet.  This value is multiplied
+     *  by 64 and added to the base packet address to get the metadata
+     *  address.  Note that this field is aligned within the word such that
+     *  you can easily extract the metadata address with a 26-bit mask. */
+    unsigned int __offset:2;
+
+    /** The top 24 bits of the packet's virtual address. */
+    unsigned int __addr:24;
+  } bits;
+}
+__netio_pkt_handle_t;
+
+#endif /* !__DOXYGEN__ */
+
+
+/**
+ * @brief A handle for an I/O packet's storage.
+ * @ingroup ingress
+ *
+ * netio_pkt_handle_t encodes the concept of a ::netio_pkt_t with its
+ * packet metadata removed.  It is a much smaller type that exists to
+ * facilitate applications where the full ::netio_pkt_t type is too
+ * large, such as those that cache enormous numbers of packets or wish
+ * to transmit packet descriptors over the UDN.
+ *
+ * Because there is no metadata, most ::netio_pkt_t operations cannot be
+ * performed on a netio_pkt_handle_t.  It supports only
+ * netio_free_handle() (to free the buffer) and
+ * NETIO_PKT_CUSTOM_DATA_H() (to access a pointer to its contents).
+ * The application must acquire any additional metadata it wants from the
+ * original ::netio_pkt_t and record it separately.
+ *
+ * A netio_pkt_handle_t can be extracted from a ::netio_pkt_t by calling
+ * NETIO_PKT_HANDLE().  An invalid handle (analogous to NULL) can be
+ * created by assigning the value ::NETIO_PKT_HANDLE_NONE. A handle can
+ * be tested for validity with NETIO_PKT_HANDLE_IS_VALID().
+ */
+typedef struct
+{
+  unsigned int word; /**< Opaque bits. */
+} netio_pkt_handle_t;
+
+/**
+ * @brief A packet descriptor.
+ *
+ * @ingroup ingress
+ * @ingroup egress
+ *
+ * This data structure represents a packet.  The structure is manipulated
+ * through the @ref ingress and the @ref egress.
+ *
+ * While the contents of a netio_pkt_t are opaque, the structure itself is
+ * portable.  This means that it may be shared between all tiles which have
+ * done a netio_input_register() call for the interface on which the pkt_t
+ * was initially received (via netio_get_packet()) or retrieved (via
+ * netio_get_buffer()).  The contents of a netio_pkt_t can be transmitted to
+ * another tile via shared memory, or via a UDN message, or by other means.
+ * The destination tile may then use the pkt_t as if it had originally been
+ * received locally; it may read or write the packet's data, read its
+ * metadata, free the packet, send the packet, transfer the netio_pkt_t to
+ * yet another tile, and so forth.
+ *
+ * Once a netio_pkt_t has been transferred to a second tile, the first tile
+ * should not reference the original copy; in particular, if more than one
+ * tile frees or sends the same netio_pkt_t, the IPP's packet free lists will
+ * become corrupted.  Note also that each tile which reads or modifies
+ * packet data must obey the memory coherency rules outlined in @ref input.
+ */
+typedef struct
+{
+#ifdef __DOXYGEN__
+  /** This structure is opaque. */
+  unsigned char opaque[32];
+#else
+  /** For an ingress packet (one with standard metadata), this is the
+   *  notification header we got from the I/O shim.  For an egress packet
+   *  (one with minimal metadata), this word is zero if the packet has not
+   *  been populated, and nonzero if it has. */
+  __netio_pkt_notif_t __notif_header;
+
+  /** Virtual address of the packet buffer, plus state flags. */
+  __netio_pkt_handle_t __packet;
+
+  /** Metadata associated with the packet. */
+  netio_pkt_metadata_t __metadata;
+#endif
+}
+netio_pkt_t;
+
+
+#ifndef __DOXYGEN__
+
+#define __NETIO_PKT_NOTIF_HEADER(pkt) ((pkt)->__notif_header)
+#define __NETIO_PKT_IPP_HANDLE(pkt) ((pkt)->__packet.bits.__ipp_handle)
+#define __NETIO_PKT_QUEUE(pkt) ((pkt)->__packet.bits.__queue)
+#define __NETIO_PKT_NOTIF_HEADER_M(mda, pkt) ((pkt)->__notif_header)
+#define __NETIO_PKT_IPP_HANDLE_M(mda, pkt) ((pkt)->__packet.bits.__ipp_handle)
+#define __NETIO_PKT_MINIMAL(pkt) ((pkt)->__packet.bits.__minimal)
+#define __NETIO_PKT_QUEUE_M(mda, pkt) ((pkt)->__packet.bits.__queue)
+#define __NETIO_PKT_FLAGS_M(mda, pkt) ((mda)->__flags)
+
+/* Packet information table, used by the attribute access functions below. */
+extern const uint16_t _netio_pkt_info[];
+
+#endif /* __DOXYGEN__ */
+
+
+#ifndef __DOXYGEN__
+/* These macros are deprecated and will disappear in a future MDE release. */
+#define NETIO_PKT_GOOD_CHECKSUM(pkt) \
+  NETIO_PKT_L4_CSUM_CORRECT(pkt)
+#define NETIO_PKT_GOOD_CHECKSUM_M(mda, pkt) \
+  NETIO_PKT_L4_CSUM_CORRECT_M(mda, pkt)
+#endif /* __DOXYGEN__ */
+
+
+/* Packet attribute access functions. */
+
+/** Return a pointer to the metadata for a packet.
+ * @ingroup ingress
+ *
+ * Calling this function once and passing the result to other retrieval
+ * functions with a "_M" suffix usually improves performance.  This
+ * function must be called on an 'ingress' packet (i.e. one retrieved
+ * by @ref netio_get_packet(), on which @ref netio_populate_buffer() or
+ * @ref netio_populate_prepend_buffer have not been called). Use of this
+ * function on an 'egress' packet will cause an assertion failure.
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return A pointer to the packet's standard metadata.
+ */
+static __inline netio_pkt_metadata_t*
+NETIO_PKT_METADATA(netio_pkt_t* pkt)
+{
+  netio_assert(!pkt->__packet.bits.__minimal);
+  return &pkt->__metadata;
+}
+
+
+/** Return a pointer to the minimal metadata for a packet.
+ * @ingroup egress
+ *
+ * Calling this function once and passing the result to other retrieval
+ * functions with a "_MM" suffix usually improves performance.  This
+ * function must be called on an 'egress' packet (i.e. one on which
+ * @ref netio_populate_buffer() or @ref netio_populate_prepend_buffer()
+ * have been called, or one retrieved by @ref netio_get_buffer()). Use of
+ * this function on an 'ingress' packet will cause an assertion failure.
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return A pointer to the packet's standard metadata.
+ */
+static __inline netio_pkt_minimal_metadata_t*
+NETIO_PKT_MINIMAL_METADATA(netio_pkt_t* pkt)
+{
+  netio_assert(pkt->__packet.bits.__minimal);
+  return (netio_pkt_minimal_metadata_t*) &pkt->__metadata;
+}
+
+
+/** Determine whether a packet has 'minimal' metadata.
+ * @ingroup pktfuncs
+ *
+ * This function will return nonzero if the packet is an 'egress'
+ * packet (i.e. one on which @ref netio_populate_buffer() or
+ * @ref netio_populate_prepend_buffer() have been called, or one
+ * retrieved by @ref netio_get_buffer()), and zero if the packet
+ * is an 'ingress' packet (i.e. one retrieved by @ref netio_get_packet(),
+ * which has not been converted into an 'egress' packet).
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return Nonzero if the packet has minimal metadata.
+ */
+static __inline unsigned int
+NETIO_PKT_IS_MINIMAL(netio_pkt_t* pkt)
+{
+  return pkt->__packet.bits.__minimal;
+}
+
+
+/** Return a handle for a packet's storage.
+ * @ingroup pktfuncs
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return A handle for the packet's storage.
+ */
+static __inline netio_pkt_handle_t
+NETIO_PKT_HANDLE(netio_pkt_t* pkt)
+{
+  netio_pkt_handle_t h;
+  h.word = pkt->__packet.word;
+  return h;
+}
+
+
+/** A special reserved value indicating the absence of a packet handle.
+ *
+ * @ingroup pktfuncs
+ */
+#define NETIO_PKT_HANDLE_NONE ((netio_pkt_handle_t) { 0 })
+
+
+/** Test whether a packet handle is valid.
+ *
+ * Applications may wish to use the reserved value NETIO_PKT_HANDLE_NONE
+ * to indicate no packet at all.  This function tests to see if a packet
+ * handle is a real handle, not this special reserved value.
+ *
+ * @ingroup pktfuncs
+ *
+ * @param[in] handle Handle on which to operate.
+ * @return One if the packet handle is valid, else zero.
+ */
+static __inline unsigned int
+NETIO_PKT_HANDLE_IS_VALID(netio_pkt_handle_t handle)
+{
+  return handle.word != 0;
+}
+
+
+
+/** Return a pointer to the start of the packet's custom header.
+ *  A custom header may or may not be present, depending upon the IPP; its
+ *  contents and alignment are also IPP-dependent.  Currently, none of the
+ *  standard IPPs supplied by Tilera produce a custom header.  If present,
+ *  the custom header precedes the L2 header in the packet buffer.
+ * @ingroup ingress
+ *
+ * @param[in] handle Handle on which to operate.
+ * @return A pointer to start of the packet.
+ */
+static __inline unsigned char*
+NETIO_PKT_CUSTOM_DATA_H(netio_pkt_handle_t handle)
+{
+  return _NETIO_PKT_HANDLE_BASE(handle) + NETIO_PACKET_PADDING;
+}
+
+
+/** Return the length of the packet's custom header.
+ *  A custom header may or may not be present, depending upon the IPP; its
+ *  contents and alignment are also IPP-dependent.  Currently, none of the
+ *  standard IPPs supplied by Tilera produce a custom header.  If present,
+ *  the custom header precedes the L2 header in the packet buffer.
+ *
+ * @ingroup ingress
+ *
+ * @param[in] mda Pointer to packet's standard metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return The length of the packet's custom header, in bytes.
+ */
+static __inline netio_size_t
+NETIO_PKT_CUSTOM_HEADER_LENGTH_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+  /*
+   * Note that we effectively need to extract a quantity from the flags word
+   * which is measured in words, and then turn it into bytes by shifting
+   * it left by 2.  We do this all at once by just shifting right two less
+   * bits, and shifting the mask up two bits.
+   */
+  return ((mda->__flags >> (_NETIO_PKT_CUSTOM_LEN_SHIFT - 2)) &
+          (_NETIO_PKT_CUSTOM_LEN_RMASK << 2));
+}
+
+
+/** Return the length of the packet, starting with the custom header.
+ *  A custom header may or may not be present, depending upon the IPP; its
+ *  contents and alignment are also IPP-dependent.  Currently, none of the
+ *  standard IPPs supplied by Tilera produce a custom header.  If present,
+ *  the custom header precedes the L2 header in the packet buffer.
+ * @ingroup ingress
+ *
+ * @param[in] mda Pointer to packet's standard metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return The length of the packet, in bytes.
+ */
+static __inline netio_size_t
+NETIO_PKT_CUSTOM_LENGTH_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+  return (__NETIO_PKT_NOTIF_HEADER(pkt).bits.__transfer_size -
+          NETIO_PACKET_PADDING);
+}
+
+
+/** Return a pointer to the start of the packet's custom header.
+ *  A custom header may or may not be present, depending upon the IPP; its
+ *  contents and alignment are also IPP-dependent.  Currently, none of the
+ *  standard IPPs supplied by Tilera produce a custom header.  If present,
+ *  the custom header precedes the L2 header in the packet buffer.
+ * @ingroup ingress
+ *
+ * @param[in] mda Pointer to packet's standard metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return A pointer to start of the packet.
+ */
+static __inline unsigned char*
+NETIO_PKT_CUSTOM_DATA_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+  return NETIO_PKT_CUSTOM_DATA_H(NETIO_PKT_HANDLE(pkt));
+}
+
+
+/** Return the length of the packet's L2 (Ethernet plus VLAN or SNAP) header.
+ * @ingroup ingress
+ *
+ * @param[in] mda Pointer to packet's standard metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return The length of the packet's L2 header, in bytes.
+ */
+static __inline netio_size_t
+NETIO_PKT_L2_HEADER_LENGTH_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+  /*
+   * Note that we effectively need to extract a quantity from the flags word
+   * which is measured in words, and then turn it into bytes by shifting
+   * it left by 2.  We do this all at once by just shifting right two less
+   * bits, and shifting the mask up two bits.  We then add two bytes.
+   */
+  return ((mda->__flags >> (_NETIO_PKT_L2_LEN_SHIFT - 2)) &
+          (_NETIO_PKT_L2_LEN_RMASK << 2)) + 2;
+}
+
+
+/** Return the length of the packet, starting with the L2 (Ethernet) header.
+ * @ingroup ingress
+ *
+ * @param[in] mda Pointer to packet's standard metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return The length of the packet, in bytes.
+ */
+static __inline netio_size_t
+NETIO_PKT_L2_LENGTH_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+  return (NETIO_PKT_CUSTOM_LENGTH_M(mda, pkt) -
+          NETIO_PKT_CUSTOM_HEADER_LENGTH_M(mda,pkt));
+}
+
+
+/** Return a pointer to the start of the packet's L2 (Ethernet) header.
+ * @ingroup ingress
+ *
+ * @param[in] mda Pointer to packet's standard metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return A pointer to start of the packet.
+ */
+static __inline unsigned char*
+NETIO_PKT_L2_DATA_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+  return (NETIO_PKT_CUSTOM_DATA_M(mda, pkt) +
+          NETIO_PKT_CUSTOM_HEADER_LENGTH_M(mda, pkt));
+}
+
+
+/** Retrieve the length of the packet, starting with the L3 (generally,
+ *  the IP) header.
+ * @ingroup ingress
+ *
+ * @param[in] mda Pointer to packet's standard metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return Length of the packet's L3 header and data, in bytes.
+ */
+static __inline netio_size_t
+NETIO_PKT_L3_LENGTH_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+  return (NETIO_PKT_L2_LENGTH_M(mda, pkt) -
+          NETIO_PKT_L2_HEADER_LENGTH_M(mda,pkt));
+}
+
+
+/** Return a pointer to the packet's L3 (generally, the IP) header.
+ * @ingroup ingress
+ *
+ * Note that we guarantee word alignment of the L3 header.
+ *
+ * @param[in] mda Pointer to packet's standard metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return A pointer to the packet's L3 header.
+ */
+static __inline unsigned char*
+NETIO_PKT_L3_DATA_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+  return (NETIO_PKT_L2_DATA_M(mda, pkt) +
+          NETIO_PKT_L2_HEADER_LENGTH_M(mda, pkt));
+}
+
+
+/** Return the ordinal of the packet.
+ * @ingroup ingress
+ *
+ * Each packet is given an ordinal number when it is delivered by the IPP.
+ * In the medium term, the ordinal is unique and monotonically increasing,
+ * being incremented by 1 for each packet; the ordinal of the first packet
+ * delivered after the IPP starts is zero.  (Since the ordinal is of finite
+ * size, given enough input packets, it will eventually wrap around to zero;
+ * in the long term, therefore, ordinals are not unique.)  The ordinals
+ * handed out by different IPPs are not disjoint, so two packets from
+ * different IPPs may have identical ordinals.  Packets dropped by the
+ * IPP or by the I/O shim are not assigned ordinals.
+ *
+ * @param[in] mda Pointer to packet's standard metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return The packet's per-IPP packet ordinal.
+ */
+static __inline unsigned int
+NETIO_PKT_ORDINAL_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+  return mda->__packet_ordinal;
+}
+
+
+/** Return the per-group ordinal of the packet.
+ * @ingroup ingress
+ *
+ * Each packet is given a per-group ordinal number when it is
+ * delivered by the IPP. By default, the group is the packet's VLAN,
+ * although IPP can be recompiled to use different values.  In
+ * the medium term, the ordinal is unique and monotonically
+ * increasing, being incremented by 1 for each packet; the ordinal of
+ * the first packet distributed to a particular group is zero.
+ * (Since the ordinal is of finite size, given enough input packets,
+ * it will eventually wrap around to zero; in the long term,
+ * therefore, ordinals are not unique.)  The ordinals handed out by
+ * different IPPs are not disjoint, so two packets from different IPPs
+ * may have identical ordinals; similarly, packets distributed to
+ * different groups may have identical ordinals.  Packets dropped by
+ * the IPP or by the I/O shim are not assigned ordinals.
+ *
+ * @param[in] mda Pointer to packet's standard metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return The packet's per-IPP, per-group ordinal.
+ */
+static __inline unsigned int
+NETIO_PKT_GROUP_ORDINAL_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+  return mda->__group_ordinal;
+}
+
+
+/** Return the VLAN ID assigned to the packet.
+ * @ingroup ingress
+ *
+ * This value is usually contained within the packet header.
+ *
+ * This value will be zero if the packet does not have a VLAN tag, or if
+ * this value was not extracted from the packet.
+ *
+ * @param[in] mda Pointer to packet's standard metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return The packet's VLAN ID.
+ */
+static __inline unsigned short
+NETIO_PKT_VLAN_ID_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+  int vl = (mda->__flags >> _NETIO_PKT_VLAN_SHIFT) & _NETIO_PKT_VLAN_RMASK;
+  unsigned short* pkt_p;
+  int index;
+  unsigned short val;
+
+  if (vl == _NETIO_PKT_VLAN_NONE)
+    return 0;
+
+  pkt_p = (unsigned short*) NETIO_PKT_L2_DATA_M(mda, pkt);
+  index = (mda->__flags >> _NETIO_PKT_TYPE_SHIFT) & _NETIO_PKT_TYPE_RMASK;
+
+  val = pkt_p[(_netio_pkt_info[index] >> _NETIO_PKT_INFO_VLAN_SHIFT) &
+              _NETIO_PKT_INFO_VLAN_RMASK];
+
+#ifdef __TILECC__
+  return (__insn_bytex(val) >> 16) & 0xFFF;
+#else
+  return (__builtin_bswap32(val) >> 16) & 0xFFF;
+#endif
+}
+
+
+/** Return the ethertype of the packet.
+ * @ingroup ingress
+ *
+ * This value is usually contained within the packet header.
+ *
+ * This value is reliable if @ref NETIO_PKT_ETHERTYPE_RECOGNIZED_M()
+ * returns true, and otherwise, may not be well defined.
+ *
+ * @param[in] mda Pointer to packet's standard metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return The packet's ethertype.
+ */
+static __inline unsigned short
+NETIO_PKT_ETHERTYPE_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+  unsigned short* pkt_p = (unsigned short*) NETIO_PKT_L2_DATA_M(mda, pkt);
+  int index = (mda->__flags >> _NETIO_PKT_TYPE_SHIFT) & _NETIO_PKT_TYPE_RMASK;
+
+  unsigned short val =
+    pkt_p[(_netio_pkt_info[index] >> _NETIO_PKT_INFO_ETYPE_SHIFT) &
+          _NETIO_PKT_INFO_ETYPE_RMASK];
+
+  return __builtin_bswap32(val) >> 16;
+}
+
+
+/** Return the flow hash computed on the packet.
+ * @ingroup ingress
+ *
+ * For TCP and UDP packets, this hash is calculated by hashing together
+ * the "5-tuple" values, specifically the source IP address, destination
+ * IP address, protocol type, source port and destination port.
+ * The hash value is intended to be helpful for millions of distinct
+ * flows.
+ *
+ * For IPv4 or IPv6 packets which are neither TCP nor UDP, the flow hash is
+ * derived by hashing together the source and destination IP addresses.
+ *
+ * For MPLS-encapsulated packets, the flow hash is derived by hashing
+ * the first MPLS label.
+ *
+ * For all other packets the flow hash is computed from the source
+ * and destination Ethernet addresses.
+ *
+ * The hash is symmetric, meaning it produces the same value if the
+ * source and destination are swapped. The only exceptions are
+ * tunneling protocols 0x04 (IP in IP Encapsulation), 0x29 (Simple
+ * Internet Protocol), 0x2F (General Routing Encapsulation) and 0x32
+ * (Encap Security Payload), which use only the destination address
+ * since the source address is not meaningful.
+ *
+ * @param[in] mda Pointer to packet's standard metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return The packet's 32-bit flow hash.
+ */
+static __inline unsigned int
+NETIO_PKT_FLOW_HASH_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+  return mda->__flow_hash;
+}
+
+
+/** Return the first word of "user data" for the packet.
+ *
+ * The contents of the user data words depend on the IPP.
+ *
+ * When using the standard ipp1, ipp2, or ipp4 sub-drivers, the first
+ * word of user data contains the least significant bits of the 64-bit
+ * arrival cycle count (see @c get_cycle_count_low()).
+ *
+ * See the <em>System Programmer's Guide</em> for details.
+ *
+ * @ingroup ingress
+ *
+ * @param[in] mda Pointer to packet's standard metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return The packet's first word of "user data".
+ */
+static __inline unsigned int
+NETIO_PKT_USER_DATA_0_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+  return mda->__user_data_0;
+}
+
+
+/** Return the second word of "user data" for the packet.
+ *
+ * The contents of the user data words depend on the IPP.
+ *
+ * When using the standard ipp1, ipp2, or ipp4 sub-drivers, the second
+ * word of user data contains the most significant bits of the 64-bit
+ * arrival cycle count (see @c get_cycle_count_high()).
+ *
+ * See the <em>System Programmer's Guide</em> for details.
+ *
+ * @ingroup ingress
+ *
+ * @param[in] mda Pointer to packet's standard metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return The packet's second word of "user data".
+ */
+static __inline unsigned int
+NETIO_PKT_USER_DATA_1_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+  return mda->__user_data_1;
+}
+
+
+/** Determine whether the L4 (TCP/UDP) checksum was calculated.
+ * @ingroup ingress
+ *
+ * @param[in] mda Pointer to packet's standard metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return Nonzero if the L4 checksum was calculated.
+ */
+static __inline unsigned int
+NETIO_PKT_L4_CSUM_CALCULATED_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+  return !(mda->__flags & _NETIO_PKT_NO_L4_CSUM_MASK);
+}
+
+
+/** Determine whether the L4 (TCP/UDP) checksum was calculated and found to
+ *  be correct.
+ * @ingroup ingress
+ *
+ * @param[in] mda Pointer to packet's standard metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return Nonzero if the checksum was calculated and is correct.
+ */
+static __inline unsigned int
+NETIO_PKT_L4_CSUM_CORRECT_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+  return !(mda->__flags &
+           (_NETIO_PKT_BAD_L4_CSUM_MASK | _NETIO_PKT_NO_L4_CSUM_MASK));
+}
+
+
+/** Determine whether the L3 (IP) checksum was calculated.
+ * @ingroup ingress
+ *
+ * @param[in] mda Pointer to packet's standard metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return Nonzero if the L3 (IP) checksum was calculated.
+*/
+static __inline unsigned int
+NETIO_PKT_L3_CSUM_CALCULATED_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+  return !(mda->__flags & _NETIO_PKT_NO_L3_CSUM_MASK);
+}
+
+
+/** Determine whether the L3 (IP) checksum was calculated and found to be
+ *  correct.
+ * @ingroup ingress
+ *
+ * @param[in] mda Pointer to packet's standard metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return Nonzero if the checksum was calculated and is correct.
+ */
+static __inline unsigned int
+NETIO_PKT_L3_CSUM_CORRECT_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+  return !(mda->__flags &
+           (_NETIO_PKT_BAD_L3_CSUM_MASK | _NETIO_PKT_NO_L3_CSUM_MASK));
+}
+
+
+/** Determine whether the ethertype was recognized and L3 packet data was
+ *  processed.
+ * @ingroup ingress
+ *
+ * @param[in] mda Pointer to packet's standard metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return Nonzero if the ethertype was recognized and L3 packet data was
+ *   processed.
+ */
+static __inline unsigned int
+NETIO_PKT_ETHERTYPE_RECOGNIZED_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+  return !(mda->__flags & _NETIO_PKT_TYPE_UNRECOGNIZED_MASK);
+}
+
+
+/** Retrieve the status of a packet and any errors that may have occurred
+ * during ingress processing (length mismatches, CRC errors, etc.).
+ * @ingroup ingress
+ *
+ * Note that packets for which @ref NETIO_PKT_ETHERTYPE_RECOGNIZED()
+ * returns zero are always reported as underlength, as there is no a priori
+ * means to determine their length.  Normally, applications should use
+ * @ref NETIO_PKT_BAD_M() instead of explicitly checking status with this
+ * function.
+ *
+ * @param[in] mda Pointer to packet's standard metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return The packet's status.
+ */
+static __inline netio_pkt_status_t
+NETIO_PKT_STATUS_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+  return (netio_pkt_status_t) __NETIO_PKT_NOTIF_HEADER(pkt).bits.__status;
+}
+
+
+/** Report whether a packet is bad (i.e., was shorter than expected based on
+ *  its headers, or had a bad CRC).
+ * @ingroup ingress
+ *
+ * Note that this function does not verify L3 or L4 checksums.
+ *
+ * @param[in] mda Pointer to packet's standard metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return Nonzero if the packet is bad and should be discarded.
+ */
+static __inline unsigned int
+NETIO_PKT_BAD_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+  return ((NETIO_PKT_STATUS_M(mda, pkt) & 1) &&
+          (NETIO_PKT_ETHERTYPE_RECOGNIZED_M(mda, pkt) ||
+           NETIO_PKT_STATUS_M(mda, pkt) == NETIO_PKT_STATUS_BAD));
+}
+
+
+/** Return the length of the packet, starting with the L2 (Ethernet) header.
+ * @ingroup egress
+ *
+ * @param[in] mmd Pointer to packet's minimal metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return The length of the packet, in bytes.
+ */
+static __inline netio_size_t
+NETIO_PKT_L2_LENGTH_MM(netio_pkt_minimal_metadata_t* mmd, netio_pkt_t* pkt)
+{
+  return mmd->l2_length;
+}
+
+
+/** Return the length of the L2 (Ethernet) header.
+ * @ingroup egress
+ *
+ * @param[in] mmd Pointer to packet's minimal metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return The length of the packet's L2 header, in bytes.
+ */
+static __inline netio_size_t
+NETIO_PKT_L2_HEADER_LENGTH_MM(netio_pkt_minimal_metadata_t* mmd,
+                              netio_pkt_t* pkt)
+{
+  return mmd->l3_offset - mmd->l2_offset;
+}
+
+
+/** Return the length of the packet, starting with the L3 (IP) header.
+ * @ingroup egress
+ *
+ * @param[in] mmd Pointer to packet's minimal metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return Length of the packet's L3 header and data, in bytes.
+ */
+static __inline netio_size_t
+NETIO_PKT_L3_LENGTH_MM(netio_pkt_minimal_metadata_t* mmd, netio_pkt_t* pkt)
+{
+  return (NETIO_PKT_L2_LENGTH_MM(mmd, pkt) -
+          NETIO_PKT_L2_HEADER_LENGTH_MM(mmd, pkt));
+}
+
+
+/** Return a pointer to the packet's L3 (generally, the IP) header.
+ * @ingroup egress
+ *
+ * Note that we guarantee word alignment of the L3 header.
+ *
+ * @param[in] mmd Pointer to packet's minimal metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return A pointer to the packet's L3 header.
+ */
+static __inline unsigned char*
+NETIO_PKT_L3_DATA_MM(netio_pkt_minimal_metadata_t* mmd, netio_pkt_t* pkt)
+{
+  return _NETIO_PKT_BASE(pkt) + mmd->l3_offset;
+}
+
+
+/** Return a pointer to the packet's L2 (Ethernet) header.
+ * @ingroup egress
+ *
+ * @param[in] mmd Pointer to packet's minimal metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @return A pointer to start of the packet.
+ */
+static __inline unsigned char*
+NETIO_PKT_L2_DATA_MM(netio_pkt_minimal_metadata_t* mmd, netio_pkt_t* pkt)
+{
+  return _NETIO_PKT_BASE(pkt) + mmd->l2_offset;
+}
+
+
+/** Retrieve the status of a packet and any errors that may have occurred
+ * during ingress processing (length mismatches, CRC errors, etc.).
+ * @ingroup ingress
+ *
+ * Note that packets for which @ref NETIO_PKT_ETHERTYPE_RECOGNIZED()
+ * returns zero are always reported as underlength, as there is no a priori
+ * means to determine their length.  Normally, applications should use
+ * @ref NETIO_PKT_BAD() instead of explicitly checking status with this
+ * function.
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return The packet's status.
+ */
+static __inline netio_pkt_status_t
+NETIO_PKT_STATUS(netio_pkt_t* pkt)
+{
+  netio_assert(!pkt->__packet.bits.__minimal);
+
+  return (netio_pkt_status_t) __NETIO_PKT_NOTIF_HEADER(pkt).bits.__status;
+}
+
+
+/** Report whether a packet is bad (i.e., was shorter than expected based on
+ *  its headers, or had a bad CRC).
+ * @ingroup ingress
+ *
+ * Note that this function does not verify L3 or L4 checksums.
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return Nonzero if the packet is bad and should be discarded.
+ */
+static __inline unsigned int
+NETIO_PKT_BAD(netio_pkt_t* pkt)
+{
+  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
+
+  return NETIO_PKT_BAD_M(mda, pkt);
+}
+
+
+/** Return the length of the packet's custom header.
+ *  A custom header may or may not be present, depending upon the IPP; its
+ *  contents and alignment are also IPP-dependent.  Currently, none of the
+ *  standard IPPs supplied by Tilera produce a custom header.  If present,
+ *  the custom header precedes the L2 header in the packet buffer.
+ * @ingroup pktfuncs
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return The length of the packet's custom header, in bytes.
+ */
+static __inline netio_size_t
+NETIO_PKT_CUSTOM_HEADER_LENGTH(netio_pkt_t* pkt)
+{
+  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
+
+  return NETIO_PKT_CUSTOM_HEADER_LENGTH_M(mda, pkt);
+}
+
+
+/** Return the length of the packet, starting with the custom header.
+ *  A custom header may or may not be present, depending upon the IPP; its
+ *  contents and alignment are also IPP-dependent.  Currently, none of the
+ *  standard IPPs supplied by Tilera produce a custom header.  If present,
+ *  the custom header precedes the L2 header in the packet buffer.
+ * @ingroup pktfuncs
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return  The length of the packet, in bytes.
+ */
+static __inline netio_size_t
+NETIO_PKT_CUSTOM_LENGTH(netio_pkt_t* pkt)
+{
+  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
+
+  return NETIO_PKT_CUSTOM_LENGTH_M(mda, pkt);
+}
+
+
+/** Return a pointer to the packet's custom header.
+ *  A custom header may or may not be present, depending upon the IPP; its
+ *  contents and alignment are also IPP-dependent.  Currently, none of the
+ *  standard IPPs supplied by Tilera produce a custom header.  If present,
+ *  the custom header precedes the L2 header in the packet buffer.
+ * @ingroup pktfuncs
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return A pointer to start of the packet.
+ */
+static __inline unsigned char*
+NETIO_PKT_CUSTOM_DATA(netio_pkt_t* pkt)
+{
+  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
+
+  return NETIO_PKT_CUSTOM_DATA_M(mda, pkt);
+}
+
+
+/** Return the length of the packet's L2 (Ethernet plus VLAN or SNAP) header.
+ * @ingroup pktfuncs
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return The length of the packet's L2 header, in bytes.
+ */
+static __inline netio_size_t
+NETIO_PKT_L2_HEADER_LENGTH(netio_pkt_t* pkt)
+{
+  if (NETIO_PKT_IS_MINIMAL(pkt))
+  {
+    netio_pkt_minimal_metadata_t* mmd = NETIO_PKT_MINIMAL_METADATA(pkt);
+
+    return NETIO_PKT_L2_HEADER_LENGTH_MM(mmd, pkt);
+  }
+  else
+  {
+    netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
+
+    return NETIO_PKT_L2_HEADER_LENGTH_M(mda, pkt);
+  }
+}
+
+
+/** Return the length of the packet, starting with the L2 (Ethernet) header.
+ * @ingroup pktfuncs
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return  The length of the packet, in bytes.
+ */
+static __inline netio_size_t
+NETIO_PKT_L2_LENGTH(netio_pkt_t* pkt)
+{
+  if (NETIO_PKT_IS_MINIMAL(pkt))
+  {
+    netio_pkt_minimal_metadata_t* mmd = NETIO_PKT_MINIMAL_METADATA(pkt);
+
+    return NETIO_PKT_L2_LENGTH_MM(mmd, pkt);
+  }
+  else
+  {
+    netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
+
+    return NETIO_PKT_L2_LENGTH_M(mda, pkt);
+  }
+}
+
+
+/** Return a pointer to the packet's L2 (Ethernet) header.
+ * @ingroup pktfuncs
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return A pointer to start of the packet.
+ */
+static __inline unsigned char*
+NETIO_PKT_L2_DATA(netio_pkt_t* pkt)
+{
+  if (NETIO_PKT_IS_MINIMAL(pkt))
+  {
+    netio_pkt_minimal_metadata_t* mmd = NETIO_PKT_MINIMAL_METADATA(pkt);
+
+    return NETIO_PKT_L2_DATA_MM(mmd, pkt);
+  }
+  else
+  {
+    netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
+
+    return NETIO_PKT_L2_DATA_M(mda, pkt);
+  }
+}
+
+
+/** Retrieve the length of the packet, starting with the L3 (generally, the IP)
+ * header.
+ * @ingroup pktfuncs
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return Length of the packet's L3 header and data, in bytes.
+ */
+static __inline netio_size_t
+NETIO_PKT_L3_LENGTH(netio_pkt_t* pkt)
+{
+  if (NETIO_PKT_IS_MINIMAL(pkt))
+  {
+    netio_pkt_minimal_metadata_t* mmd = NETIO_PKT_MINIMAL_METADATA(pkt);
+
+    return NETIO_PKT_L3_LENGTH_MM(mmd, pkt);
+  }
+  else
+  {
+    netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
+
+    return NETIO_PKT_L3_LENGTH_M(mda, pkt);
+  }
+}
+
+
+/** Return a pointer to the packet's L3 (generally, the IP) header.
+ * @ingroup pktfuncs
+ *
+ * Note that we guarantee word alignment of the L3 header.
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return A pointer to the packet's L3 header.
+ */
+static __inline unsigned char*
+NETIO_PKT_L3_DATA(netio_pkt_t* pkt)
+{
+  if (NETIO_PKT_IS_MINIMAL(pkt))
+  {
+    netio_pkt_minimal_metadata_t* mmd = NETIO_PKT_MINIMAL_METADATA(pkt);
+
+    return NETIO_PKT_L3_DATA_MM(mmd, pkt);
+  }
+  else
+  {
+    netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
+
+    return NETIO_PKT_L3_DATA_M(mda, pkt);
+  }
+}
+
+
+/** Return the ordinal of the packet.
+ * @ingroup ingress
+ *
+ * Each packet is given an ordinal number when it is delivered by the IPP.
+ * In the medium term, the ordinal is unique and monotonically increasing,
+ * being incremented by 1 for each packet; the ordinal of the first packet
+ * delivered after the IPP starts is zero.  (Since the ordinal is of finite
+ * size, given enough input packets, it will eventually wrap around to zero;
+ * in the long term, therefore, ordinals are not unique.)  The ordinals
+ * handed out by different IPPs are not disjoint, so two packets from
+ * different IPPs may have identical ordinals.  Packets dropped by the
+ * IPP or by the I/O shim are not assigned ordinals.
+ *
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return The packet's per-IPP packet ordinal.
+ */
+static __inline unsigned int
+NETIO_PKT_ORDINAL(netio_pkt_t* pkt)
+{
+  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
+
+  return NETIO_PKT_ORDINAL_M(mda, pkt);
+}
+
+
+/** Return the per-group ordinal of the packet.
+ * @ingroup ingress
+ *
+ * Each packet is given a per-group ordinal number when it is
+ * delivered by the IPP. By default, the group is the packet's VLAN,
+ * although IPP can be recompiled to use different values.  In
+ * the medium term, the ordinal is unique and monotonically
+ * increasing, being incremented by 1 for each packet; the ordinal of
+ * the first packet distributed to a particular group is zero.
+ * (Since the ordinal is of finite size, given enough input packets,
+ * it will eventually wrap around to zero; in the long term,
+ * therefore, ordinals are not unique.)  The ordinals handed out by
+ * different IPPs are not disjoint, so two packets from different IPPs
+ * may have identical ordinals; similarly, packets distributed to
+ * different groups may have identical ordinals.  Packets dropped by
+ * the IPP or by the I/O shim are not assigned ordinals.
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return The packet's per-IPP, per-group ordinal.
+ */
+static __inline unsigned int
+NETIO_PKT_GROUP_ORDINAL(netio_pkt_t* pkt)
+{
+  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
+
+  return NETIO_PKT_GROUP_ORDINAL_M(mda, pkt);
+}
+
+
+/** Return the VLAN ID assigned to the packet.
+ * @ingroup ingress
+ *
+ * This is usually also contained within the packet header.  If the packet
+ * does not have a VLAN tag, the VLAN ID returned by this function is zero.
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return The packet's VLAN ID.
+ */
+static __inline unsigned short
+NETIO_PKT_VLAN_ID(netio_pkt_t* pkt)
+{
+  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
+
+  return NETIO_PKT_VLAN_ID_M(mda, pkt);
+}
+
+
+/** Return the ethertype of the packet.
+ * @ingroup ingress
+ *
+ * This value is reliable if @ref NETIO_PKT_ETHERTYPE_RECOGNIZED()
+ * returns true, and otherwise, may not be well defined.
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return The packet's ethertype.
+ */
+static __inline unsigned short
+NETIO_PKT_ETHERTYPE(netio_pkt_t* pkt)
+{
+  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
+
+  return NETIO_PKT_ETHERTYPE_M(mda, pkt);
+}
+
+
+/** Return the flow hash computed on the packet.
+ * @ingroup ingress
+ *
+ * For TCP and UDP packets, this hash is calculated by hashing together
+ * the "5-tuple" values, specifically the source IP address, destination
+ * IP address, protocol type, source port and destination port.
+ * The hash value is intended to be helpful for millions of distinct
+ * flows.
+ *
+ * For IPv4 or IPv6 packets which are neither TCP nor UDP, the flow hash is
+ * derived by hashing together the source and destination IP addresses.
+ *
+ * For MPLS-encapsulated packets, the flow hash is derived by hashing
+ * the first MPLS label.
+ *
+ * For all other packets the flow hash is computed from the source
+ * and destination Ethernet addresses.
+ *
+ * The hash is symmetric, meaning it produces the same value if the
+ * source and destination are swapped. The only exceptions are
+ * tunneling protocols 0x04 (IP in IP Encapsulation), 0x29 (Simple
+ * Internet Protocol), 0x2F (General Routing Encapsulation) and 0x32
+ * (Encap Security Payload), which use only the destination address
+ * since the source address is not meaningful.
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return The packet's 32-bit flow hash.
+ */
+static __inline unsigned int
+NETIO_PKT_FLOW_HASH(netio_pkt_t* pkt)
+{
+  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
+
+  return NETIO_PKT_FLOW_HASH_M(mda, pkt);
+}
+
+
+/** Return the first word of "user data" for the packet.
+ *
+ * The contents of the user data words depend on the IPP.
+ *
+ * When using the standard ipp1, ipp2, or ipp4 sub-drivers, the first
+ * word of user data contains the least significant bits of the 64-bit
+ * arrival cycle count (see @c get_cycle_count_low()).
+ *
+ * See the <em>System Programmer's Guide</em> for details.
+ *
+ * @ingroup ingress
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return The packet's first word of "user data".
+ */
+static __inline unsigned int
+NETIO_PKT_USER_DATA_0(netio_pkt_t* pkt)
+{
+  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
+
+  return NETIO_PKT_USER_DATA_0_M(mda, pkt);
+}
+
+
+/** Return the second word of "user data" for the packet.
+ *
+ * The contents of the user data words depend on the IPP.
+ *
+ * When using the standard ipp1, ipp2, or ipp4 sub-drivers, the second
+ * word of user data contains the most significant bits of the 64-bit
+ * arrival cycle count (see @c get_cycle_count_high()).
+ *
+ * See the <em>System Programmer's Guide</em> for details.
+ *
+ * @ingroup ingress
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return The packet's second word of "user data".
+ */
+static __inline unsigned int
+NETIO_PKT_USER_DATA_1(netio_pkt_t* pkt)
+{
+  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
+
+  return NETIO_PKT_USER_DATA_1_M(mda, pkt);
+}
+
+
+/** Determine whether the L4 (TCP/UDP) checksum was calculated.
+ * @ingroup ingress
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return Nonzero if the L4 checksum was calculated.
+ */
+static __inline unsigned int
+NETIO_PKT_L4_CSUM_CALCULATED(netio_pkt_t* pkt)
+{
+  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
+
+  return NETIO_PKT_L4_CSUM_CALCULATED_M(mda, pkt);
+}
+
+
+/** Determine whether the L4 (TCP/UDP) checksum was calculated and found to
+ *  be correct.
+ * @ingroup ingress
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return Nonzero if the checksum was calculated and is correct.
+ */
+static __inline unsigned int
+NETIO_PKT_L4_CSUM_CORRECT(netio_pkt_t* pkt)
+{
+  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
+
+  return NETIO_PKT_L4_CSUM_CORRECT_M(mda, pkt);
+}
+
+
+/** Determine whether the L3 (IP) checksum was calculated.
+ * @ingroup ingress
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return Nonzero if the L3 (IP) checksum was calculated.
+*/
+static __inline unsigned int
+NETIO_PKT_L3_CSUM_CALCULATED(netio_pkt_t* pkt)
+{
+  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
+
+  return NETIO_PKT_L3_CSUM_CALCULATED_M(mda, pkt);
+}
+
+
+/** Determine whether the L3 (IP) checksum was calculated and found to be
+ *  correct.
+ * @ingroup ingress
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return Nonzero if the checksum was calculated and is correct.
+ */
+static __inline unsigned int
+NETIO_PKT_L3_CSUM_CORRECT(netio_pkt_t* pkt)
+{
+  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
+
+  return NETIO_PKT_L3_CSUM_CORRECT_M(mda, pkt);
+}
+
+
+/** Determine whether the Ethertype was recognized and L3 packet data was
+ *  processed.
+ * @ingroup ingress
+ *
+ * @param[in] pkt Packet on which to operate.
+ * @return Nonzero if the Ethertype was recognized and L3 packet data was
+ *   processed.
+ */
+static __inline unsigned int
+NETIO_PKT_ETHERTYPE_RECOGNIZED(netio_pkt_t* pkt)
+{
+  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
+
+  return NETIO_PKT_ETHERTYPE_RECOGNIZED_M(mda, pkt);
+}
+
+
+/** Set an egress packet's L2 length, using a metadata pointer to speed the
+ * computation.
+ * @ingroup egress
+ *
+ * @param[in,out] mmd Pointer to packet's minimal metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @param[in] len Packet L2 length, in bytes.
+ */
+static __inline void
+NETIO_PKT_SET_L2_LENGTH_MM(netio_pkt_minimal_metadata_t* mmd, netio_pkt_t* pkt,
+                           int len)
+{
+  mmd->l2_length = len;
+}
+
+
+/** Set an egress packet's L2 length.
+ * @ingroup egress
+ *
+ * @param[in,out] pkt Packet on which to operate.
+ * @param[in] len Packet L2 length, in bytes.
+ */
+static __inline void
+NETIO_PKT_SET_L2_LENGTH(netio_pkt_t* pkt, int len)
+{
+  netio_pkt_minimal_metadata_t* mmd = NETIO_PKT_MINIMAL_METADATA(pkt);
+
+  NETIO_PKT_SET_L2_LENGTH_MM(mmd, pkt, len);
+}
+
+
+/** Set an egress packet's L2 header length, using a metadata pointer to
+ *  speed the computation.
+ * @ingroup egress
+ *
+ * It is not normally necessary to call this routine; only the L2 length,
+ * not the header length, is needed to transmit a packet.  It may be useful if
+ * the egress packet will later be processed by code which expects to use
+ * functions like @ref NETIO_PKT_L3_DATA() to get a pointer to the L3 payload.
+ *
+ * @param[in,out] mmd Pointer to packet's minimal metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @param[in] len Packet L2 header length, in bytes.
+ */
+static __inline void
+NETIO_PKT_SET_L2_HEADER_LENGTH_MM(netio_pkt_minimal_metadata_t* mmd,
+                                  netio_pkt_t* pkt, int len)
+{
+  mmd->l3_offset = mmd->l2_offset + len;
+}
+
+
+/** Set an egress packet's L2 header length.
+ * @ingroup egress
+ *
+ * It is not normally necessary to call this routine; only the L2 length,
+ * not the header length, is needed to transmit a packet.  It may be useful if
+ * the egress packet will later be processed by code which expects to use
+ * functions like @ref NETIO_PKT_L3_DATA() to get a pointer to the L3 payload.
+ *
+ * @param[in,out] pkt Packet on which to operate.
+ * @param[in] len Packet L2 header length, in bytes.
+ */
+static __inline void
+NETIO_PKT_SET_L2_HEADER_LENGTH(netio_pkt_t* pkt, int len)
+{
+  netio_pkt_minimal_metadata_t* mmd = NETIO_PKT_MINIMAL_METADATA(pkt);
+
+  NETIO_PKT_SET_L2_HEADER_LENGTH_MM(mmd, pkt, len);
+}
+
+
+/** Set up an egress packet for hardware checksum computation, using a
+ *  metadata pointer to speed the operation.
+ * @ingroup egress
+ *
+ *  NetIO provides the ability to automatically calculate a standard
+ *  16-bit Internet checksum on transmitted packets.  The application
+ *  may specify the point in the packet where the checksum starts, the
+ *  number of bytes to be checksummed, and the two bytes in the packet
+ *  which will be replaced with the completed checksum.  (If the range
+ *  of bytes to be checksummed includes the bytes to be replaced, the
+ *  initial values of those bytes will be included in the checksum.)
+ *
+ *  For some protocols, the packet checksum covers data which is not present
+ *  in the packet, or is at least not contiguous to the main data payload.
+ *  For instance, the TCP checksum includes a "pseudo-header" which includes
+ *  the source and destination IP addresses of the packet.  To accommodate
+ *  this, the checksum engine may be "seeded" with an initial value, which
+ *  the application would need to compute based on the specific protocol's
+ *  requirements.  Note that the seed is given in host byte order (little-
+ *  endian), not network byte order (big-endian); code written to compute a
+ *  pseudo-header checksum in network byte order will need to byte-swap it
+ *  before use as the seed.
+ *
+ *  Note that the checksum is computed as part of the transmission process,
+ *  so it will not be present in the packet upon completion of this routine.
+ *
+ * @param[in,out] mmd Pointer to packet's minimal metadata.
+ * @param[in] pkt Packet on which to operate.
+ * @param[in] start Offset within L2 packet of the first byte to include in
+ *   the checksum.
+ * @param[in] length Number of bytes to include in the checksum.
+ *   the checksum.
+ * @param[in] location Offset within L2 packet of the first of the two bytes
+ *   to be replaced with the calculated checksum.
+ * @param[in] seed Initial value of the running checksum before any of the
+ *   packet data is added.
+ */
+static __inline void
+NETIO_PKT_DO_EGRESS_CSUM_MM(netio_pkt_minimal_metadata_t* mmd,
+                            netio_pkt_t* pkt, int start, int length,
+                            int location, uint16_t seed)
+{
+  mmd->csum_start = start;
+  mmd->csum_length = length;
+  mmd->csum_location = location;
+  mmd->csum_seed = seed;
+  mmd->flags |= _NETIO_PKT_NEED_EDMA_CSUM_MASK;
+}
+
+
+/** Set up an egress packet for hardware checksum computation.
+ * @ingroup egress
+ *
+ *  NetIO provides the ability to automatically calculate a standard
+ *  16-bit Internet checksum on transmitted packets.  The application
+ *  may specify the point in the packet where the checksum starts, the
+ *  number of bytes to be checksummed, and the two bytes in the packet
+ *  which will be replaced with the completed checksum.  (If the range
+ *  of bytes to be checksummed includes the bytes to be replaced, the
+ *  initial values of those bytes will be included in the checksum.)
+ *
+ *  For some protocols, the packet checksum covers data which is not present
+ *  in the packet, or is at least not contiguous to the main data payload.
+ *  For instance, the TCP checksum includes a "pseudo-header" which includes
+ *  the source and destination IP addresses of the packet.  To accommodate
+ *  this, the checksum engine may be "seeded" with an initial value, which
+ *  the application would need to compute based on the specific protocol's
+ *  requirements.  Note that the seed is given in host byte order (little-
+ *  endian), not network byte order (big-endian); code written to compute a
+ *  pseudo-header checksum in network byte order will need to byte-swap it
+ *  before use as the seed.
+ *
+ *  Note that the checksum is computed as part of the transmission process,
+ *  so it will not be present in the packet upon completion of this routine.
+ *
+ * @param[in,out] pkt Packet on which to operate.
+ * @param[in] start Offset within L2 packet of the first byte to include in
+ *   the checksum.
+ * @param[in] length Number of bytes to include in the checksum.
+ *   the checksum.
+ * @param[in] location Offset within L2 packet of the first of the two bytes
+ *   to be replaced with the calculated checksum.
+ * @param[in] seed Initial value of the running checksum before any of the
+ *   packet data is added.
+ */
+static __inline void
+NETIO_PKT_DO_EGRESS_CSUM(netio_pkt_t* pkt, int start, int length,
+                         int location, uint16_t seed)
+{
+  netio_pkt_minimal_metadata_t* mmd = NETIO_PKT_MINIMAL_METADATA(pkt);
+
+  NETIO_PKT_DO_EGRESS_CSUM_MM(mmd, pkt, start, length, location, seed);
+}
+
+
+/** Return the number of bytes which could be prepended to a packet, using a
+ *  metadata pointer to speed the operation.
+ *  See @ref netio_populate_prepend_buffer() to get a full description of
+ *  prepending.
+ *
+ * @param[in,out] mda Pointer to packet's standard metadata.
+ * @param[in] pkt Packet on which to operate.
+ */
+static __inline int
+NETIO_PKT_PREPEND_AVAIL_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+  return (pkt->__packet.bits.__offset << 6) +
+         NETIO_PKT_CUSTOM_HEADER_LENGTH_M(mda, pkt);
+}
+
+
+/** Return the number of bytes which could be prepended to a packet, using a
+ *  metadata pointer to speed the operation.
+ *  See @ref netio_populate_prepend_buffer() to get a full description of
+ *  prepending.
+ * @ingroup egress
+ *
+ * @param[in,out] mmd Pointer to packet's minimal metadata.
+ * @param[in] pkt Packet on which to operate.
+ */
+static __inline int
+NETIO_PKT_PREPEND_AVAIL_MM(netio_pkt_minimal_metadata_t* mmd, netio_pkt_t* pkt)
+{
+  return (pkt->__packet.bits.__offset << 6) + mmd->l2_offset;
+}
+
+
+/** Return the number of bytes which could be prepended to a packet.
+ *  See @ref netio_populate_prepend_buffer() to get a full description of
+ *  prepending.
+ * @ingroup egress
+ *
+ * @param[in] pkt Packet on which to operate.
+ */
+static __inline int
+NETIO_PKT_PREPEND_AVAIL(netio_pkt_t* pkt)
+{
+  if (NETIO_PKT_IS_MINIMAL(pkt))
+  {
+    netio_pkt_minimal_metadata_t* mmd = NETIO_PKT_MINIMAL_METADATA(pkt);
+
+    return NETIO_PKT_PREPEND_AVAIL_MM(mmd, pkt);
+  }
+  else
+  {
+    netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
+
+    return NETIO_PKT_PREPEND_AVAIL_M(mda, pkt);
+  }
+}
+
+
+/** Flush a packet's minimal metadata from the cache, using a metadata pointer
+ *  to speed the operation.
+ * @ingroup egress
+ *
+ * @param[in] mmd Pointer to packet's minimal metadata.
+ * @param[in] pkt Packet on which to operate.
+ */
+static __inline void
+NETIO_PKT_FLUSH_MINIMAL_METADATA_MM(netio_pkt_minimal_metadata_t* mmd,
+                                    netio_pkt_t* pkt)
+{
+}
+
+
+/** Invalidate a packet's minimal metadata from the cache, using a metadata
+ *  pointer to speed the operation.
+ * @ingroup egress
+ *
+ * @param[in] mmd Pointer to packet's minimal metadata.
+ * @param[in] pkt Packet on which to operate.
+ */
+static __inline void
+NETIO_PKT_INV_MINIMAL_METADATA_MM(netio_pkt_minimal_metadata_t* mmd,
+                                  netio_pkt_t* pkt)
+{
+}
+
+
+/** Flush and then invalidate a packet's minimal metadata from the cache,
+ *  using a metadata pointer to speed the operation.
+ * @ingroup egress
+ *
+ * @param[in] mmd Pointer to packet's minimal metadata.
+ * @param[in] pkt Packet on which to operate.
+ */
+static __inline void
+NETIO_PKT_FLUSH_INV_MINIMAL_METADATA_MM(netio_pkt_minimal_metadata_t* mmd,
+                                        netio_pkt_t* pkt)
+{
+}
+
+
+/** Flush a packet's metadata from the cache, using a metadata pointer
+ *  to speed the operation.
+ * @ingroup ingress
+ *
+ * @param[in] mda Pointer to packet's minimal metadata.
+ * @param[in] pkt Packet on which to operate.
+ */
+static __inline void
+NETIO_PKT_FLUSH_METADATA_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+}
+
+
+/** Invalidate a packet's metadata from the cache, using a metadata
+ *  pointer to speed the operation.
+ * @ingroup ingress
+ *
+ * @param[in] mda Pointer to packet's metadata.
+ * @param[in] pkt Packet on which to operate.
+ */
+static __inline void
+NETIO_PKT_INV_METADATA_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+}
+
+
+/** Flush and then invalidate a packet's metadata from the cache,
+ *  using a metadata pointer to speed the operation.
+ * @ingroup ingress
+ *
+ * @param[in] mda Pointer to packet's metadata.
+ * @param[in] pkt Packet on which to operate.
+ */
+static __inline void
+NETIO_PKT_FLUSH_INV_METADATA_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
+{
+}
+
+
+/** Flush a packet's minimal metadata from the cache.
+ * @ingroup egress
+ *
+ * @param[in] pkt Packet on which to operate.
+ */
+static __inline void
+NETIO_PKT_FLUSH_MINIMAL_METADATA(netio_pkt_t* pkt)
+{
+}
+
+
+/** Invalidate a packet's minimal metadata from the cache.
+ * @ingroup egress
+ *
+ * @param[in] pkt Packet on which to operate.
+ */
+static __inline void
+NETIO_PKT_INV_MINIMAL_METADATA(netio_pkt_t* pkt)
+{
+}
+
+
+/** Flush and then invalidate a packet's minimal metadata from the cache.
+ * @ingroup egress
+ *
+ * @param[in] pkt Packet on which to operate.
+ */
+static __inline void
+NETIO_PKT_FLUSH_INV_MINIMAL_METADATA(netio_pkt_t* pkt)
+{
+}
+
+
+/** Flush a packet's metadata from the cache.
+ * @ingroup ingress
+ *
+ * @param[in] pkt Packet on which to operate.
+ */
+static __inline void
+NETIO_PKT_FLUSH_METADATA(netio_pkt_t* pkt)
+{
+}
+
+
+/** Invalidate a packet's metadata from the cache.
+ * @ingroup ingress
+ *
+ * @param[in] pkt Packet on which to operate.
+ */
+static __inline void
+NETIO_PKT_INV_METADATA(netio_pkt_t* pkt)
+{
+}
+
+
+/** Flush and then invalidate a packet's metadata from the cache.
+ * @ingroup ingress
+ *
+ * @param[in] pkt Packet on which to operate.
+ */
+static __inline void
+NETIO_PKT_FLUSH_INV_METADATA(netio_pkt_t* pkt)
+{
+}
+
+/** Number of NUMA nodes we can distribute buffers to.
+ * @ingroup setup */
+#define NETIO_NUM_NODE_WEIGHTS  16
+
+/**
+ * @brief An object for specifying the characteristics of NetIO communication
+ * endpoint.
+ *
+ * @ingroup setup
+ *
+ * The @ref netio_input_register() function uses this structure to define
+ * how an application tile will communicate with an IPP.
+ *
+ *
+ * Future updates to NetIO may add new members to this structure,
+ * which can affect the success of the registration operation.  Thus,
+ * if dynamically initializing the structure, applications are urged to
+ * zero it out first, for example:
+ *
+ * @code
+ * netio_input_config_t config;
+ * memset(&config, 0, sizeof (config));
+ * config.flags = NETIO_RECV | NETIO_XMIT_CSUM | NETIO_TAG_NONE;
+ * config.num_receive_packets = NETIO_MAX_RECEIVE_PKTS;
+ * config.queue_id = 0;
+ *     .
+ *     .
+ *     .
+ * @endcode
+ *
+ * since that guarantees that any unused structure members, including
+ * members which did not exist when the application was first developed,
+ * will not have unexpected values.
+ *
+ * If statically initializing the structure, we strongly recommend use of
+ * C99-style named initializers, for example:
+ *
+ * @code
+ * netio_input_config_t config = {
+ *    .flags = NETIO_RECV | NETIO_XMIT_CSUM | NETIO_TAG_NONE,
+ *    .num_receive_packets = NETIO_MAX_RECEIVE_PKTS,
+ *    .queue_id = 0,
+ * },
+ * @endcode
+ *
+ * instead of the old-style structure initialization:
+ *
+ * @code
+ * // Bad example! Currently equivalent to the above, but don't do this.
+ * netio_input_config_t config = {
+ *    NETIO_RECV | NETIO_XMIT_CSUM | NETIO_TAG_NONE, NETIO_MAX_RECEIVE_PKTS, 0
+ * },
+ * @endcode
+ *
+ * since the C99 style requires no changes to the code if elements of the
+ * config structure are rearranged.  (It also makes the initialization much
+ * easier to understand.)
+ *
+ * Except for items which address a particular tile's transmit or receive
+ * characteristics, such as the ::NETIO_RECV flag, applications are advised
+ * to specify the same set of configuration data on all registrations.
+ * This prevents differing results if multiple tiles happen to do their
+ * registration operations in a different order on different invocations of
+ * the application.  This is particularly important for things like link
+ * management flags, and buffer size and homing specifications.
+ *
+ * Unless the ::NETIO_FIXED_BUFFER_VA flag is specified in flags, the NetIO
+ * buffer pool is automatically created and mapped into the application's
+ * virtual address space at an address chosen by the operating system,
+ * using the common memory (cmem) facility in the Tilera Multicore
+ * Components library.  The cmem facility allows multiple processes to gain
+ * access to shared memory which is mapped into each process at an
+ * identical virtual address.  In order for this to work, the processes
+ * must have a common ancestor, which must create the common memory using
+ * tmc_cmem_init().
+ *
+ * In programs using the iLib process creation API, or in programs which use
+ * only one process (which include programs using the pthreads library),
+ * tmc_cmem_init() is called automatically.  All other applications
+ * must call it explicitly, before any child processes which might call
+ * netio_input_register() are created.
+ */
+typedef struct
+{
+  /** Registration characteristics.
+
+      This value determines several characteristics of the registration;
+      flags for different types of behavior are ORed together to make the
+      final flag value.  Generally applications should specify exactly
+      one flag from each of the following categories:
+
+      - Whether the application will be receiving packets on this queue
+        (::NETIO_RECV or ::NETIO_NO_RECV).
+
+      - Whether the application will be transmitting packets on this queue,
+        and if so, whether it will request egress checksum calculation
+        (::NETIO_XMIT, ::NETIO_XMIT_CSUM, or ::NETIO_NO_XMIT).  It is
+        legal to call netio_get_buffer() without one of the XMIT flags,
+        as long as ::NETIO_RECV is specified; in this case, the retrieved
+        buffers must be passed to another tile for transmission.
+
+      - Whether the application expects any vendor-specific tags in
+        its packets' L2 headers (::NETIO_TAG_NONE, ::NETIO_TAG_BRCM,
+        or ::NETIO_TAG_MRVL).  This must match the configuration of the
+        target IPP.
+
+      To accommodate applications written to previous versions of the NetIO
+      interface, none of the flags above are currently required; if omitted,
+      NetIO behaves more or less as if ::NETIO_RECV | ::NETIO_XMIT_CSUM |
+      ::NETIO_TAG_NONE were used.  However, explicit specification of
+      the relevant flags allows NetIO to do a better job of resource
+      allocation, allows earlier detection of certain configuration errors,
+      and may enable advanced features or higher performance in the future,
+      so their use is strongly recommended.
+
+      Note that specifying ::NETIO_NO_RECV along with ::NETIO_NO_XMIT
+      is a special case, intended primarily for use by programs which
+      retrieve network statistics or do link management operations.
+      When these flags are both specified, the resulting queue may not
+      be used with NetIO routines other than netio_get(), netio_set(),
+      and netio_input_unregister().  See @ref link for more information
+      on link management.
+
+      Other flags are optional; their use is described below.
+  */
+  int flags;
+
+  /** Interface name.  This is a string which identifies the specific
+      Ethernet controller hardware to be used.  The format of the string
+      is a device type and a device index, separated by a slash; so,
+      the first 10 Gigabit Ethernet controller is named "xgbe/0", while
+      the second 10/100/1000 Megabit Ethernet controller is named "gbe/1".
+   */
+  const char* interface;
+
+  /** Receive packet queue size.  This specifies the maximum number
+      of ingress packets that can be received on this queue without
+      being retrieved by @ref netio_get_packet().  If the IPP's distribution
+      algorithm calls for a packet to be sent to this queue, and this
+      number of packets are already pending there, the new packet
+      will either be discarded, or sent to another tile registered
+      for the same queue_id (see @ref drops).  This value must
+      be at least ::NETIO_MIN_RECEIVE_PKTS, can always be at least
+      ::NETIO_MAX_RECEIVE_PKTS, and may be larger than that on certain
+      interfaces.
+   */
+  int num_receive_packets;
+
+  /** The queue ID being requested.  Legal values for this range from 0
+      to ::NETIO_MAX_QUEUE_ID, inclusive.  ::NETIO_MAX_QUEUE_ID is always
+      greater than or equal to the number of tiles; this allows one queue
+      for each tile, plus at least one additional queue.  Some applications
+      may wish to use the additional queue as a destination for unwanted
+      packets, since packets delivered to queues for which no tiles have
+      registered are discarded.
+   */
+  unsigned int queue_id;
+
+  /** Maximum number of small send buffers to be held in the local empty
+      buffer cache.  This specifies the size of the area which holds
+      empty small egress buffers requested from the IPP but not yet
+      retrieved via @ref netio_get_buffer().  This value must be greater
+      than zero if the application will ever use @ref netio_get_buffer()
+      to allocate empty small egress buffers; it may be no larger than
+      ::NETIO_MAX_SEND_BUFFERS.  See @ref epp for more details on empty
+      buffer caching.
+   */
+  int num_send_buffers_small_total;
+
+  /** Number of small send buffers to be preallocated at registration.
+      If this value is nonzero, the specified number of empty small egress
+      buffers will be requested from the IPP during the netio_input_register
+      operation; this may speed the execution of @ref netio_get_buffer().
+      This may be no larger than @ref num_send_buffers_small_total.  See @ref
+      epp for more details on empty buffer caching.
+   */
+  int num_send_buffers_small_prealloc;
+
+  /** Maximum number of large send buffers to be held in the local empty
+      buffer cache.  This specifies the size of the area which holds empty
+      large egress buffers requested from the IPP but not yet retrieved via
+      @ref netio_get_buffer().  This value must be greater than zero if the
+      application will ever use @ref netio_get_buffer() to allocate empty
+      large egress buffers; it may be no larger than ::NETIO_MAX_SEND_BUFFERS.
+      See @ref epp for more details on empty buffer caching.
+   */
+  int num_send_buffers_large_total;
+
+  /** Number of large send buffers to be preallocated at registration.
+      If this value is nonzero, the specified number of empty large egress
+      buffers will be requested from the IPP during the netio_input_register
+      operation; this may speed the execution of @ref netio_get_buffer().
+      This may be no larger than @ref num_send_buffers_large_total.  See @ref
+      epp for more details on empty buffer caching.
+   */
+  int num_send_buffers_large_prealloc;
+
+  /** Maximum number of jumbo send buffers to be held in the local empty
+      buffer cache.  This specifies the size of the area which holds empty
+      jumbo egress buffers requested from the IPP but not yet retrieved via
+      @ref netio_get_buffer().  This value must be greater than zero if the
+      application will ever use @ref netio_get_buffer() to allocate empty
+      jumbo egress buffers; it may be no larger than ::NETIO_MAX_SEND_BUFFERS.
+      See @ref epp for more details on empty buffer caching.
+   */
+  int num_send_buffers_jumbo_total;
+
+  /** Number of jumbo send buffers to be preallocated at registration.
+      If this value is nonzero, the specified number of empty jumbo egress
+      buffers will be requested from the IPP during the netio_input_register
+      operation; this may speed the execution of @ref netio_get_buffer().
+      This may be no larger than @ref num_send_buffers_jumbo_total.  See @ref
+      epp for more details on empty buffer caching.
+   */
+  int num_send_buffers_jumbo_prealloc;
+
+  /** Total packet buffer size.  This determines the total size, in bytes,
+      of the NetIO buffer pool.  Note that the maximum number of available
+      buffers of each size is determined during hypervisor configuration
+      (see the <em>System Programmer's Guide</em> for details); this just
+      influences how much host memory is allocated for those buffers.
+
+      The buffer pool is allocated from common memory, which will be
+      automatically initialized if needed.  If your buffer pool is larger
+      than 240 MB, you might need to explicitly call @c tmc_cmem_init(),
+      as described in the Application Libraries Reference Manual (UG227).
+
+      Packet buffers are currently allocated in chunks of 16 MB; this
+      value will be rounded up to the next larger multiple of 16 MB.
+      If this value is zero, a default of 32 MB will be used; this was
+      the value used by previous versions of NetIO.  Note that taking this
+      default also affects the placement of buffers on Linux NUMA nodes.
+      See @ref buffer_node_weights for an explanation of buffer placement.
+
+      In order to successfully allocate packet buffers, Linux must have
+      available huge pages on the relevant Linux NUMA nodes.  See the
+      <em>System Programmer's Guide</em> for information on configuring
+      huge page support in Linux.
+   */
+  uint64_t total_buffer_size;
+
+  /** Buffer placement weighting factors.
+
+      This array specifies the relative amount of buffering to place
+      on each of the available Linux NUMA nodes.  This array is
+      indexed by the NUMA node, and the values in the array are
+      proportional to the amount of buffer space to allocate on that
+      node.
+
+      If memory striping is enabled in the Hypervisor, then there is
+      only one logical NUMA node (node 0). In that case, NetIO will by
+      default ignore the suggested buffer node weights, and buffers
+      will be striped across the physical memory controllers. See
+      UG209 System Programmer's Guide for a description of the
+      hypervisor option that controls memory striping.
+
+      If memory striping is disabled, then there are up to four NUMA
+      nodes, corresponding to the four DDRAM controllers in the TILE
+      processor architecture.  See UG100 Tile Processor Architecture
+      Overview for a diagram showing the location of each of the DDRAM
+      controllers relative to the tile array.
+
+      For instance, if memory striping is disabled, the following
+      configuration strucure:
+
+      @code
+      netio_input_config_t config = {
+            .
+            .
+            .
+        .total_buffer_size = 4 * 16 * 1024 * 1024;
+        .buffer_node_weights = { 1, 0, 1, 0 },
+      },
+      @endcode
+
+      would result in 32 MB of buffers being placed on controller 0, and
+      32 MB on controller 2.  (Since buffers are allocated in units of
+      16 MB, some sets of weights will not be able to be matched exactly.)
+
+      For the weights to be effective, @ref total_buffer_size must be
+      nonzero.  If @ref total_buffer_size is zero, causing the default
+      32 MB of buffer space to be used, then any specified weights will
+      be ignored, and buffers will positioned as they were in previous
+      versions of NetIO:
+
+      - For xgbe/0 and gbe/0, 16 MB of buffers will be placed on controller 1,
+        and the other 16 MB will be placed on controller 2.
+
+      - For xgbe/1 and gbe/1, 16 MB of buffers will be placed on controller 2,
+        and the other 16 MB will be placed on controller 3.
+
+      If @ref total_buffer_size is nonzero, but all weights are zero,
+      then all buffer space will be allocated on Linux NUMA node zero.
+
+      By default, the specified buffer placement is treated as a hint;
+      if sufficient free memory is not available on the specified
+      controllers, the buffers will be allocated elsewhere.  However,
+      if the ::NETIO_STRICT_HOMING flag is specified in @ref flags, then a
+      failure to allocate buffer space exactly as requested will cause the
+      registration operation to fail with an error of ::NETIO_CANNOT_HOME.
+
+      Note that maximal network performance cannot be achieved with
+      only one memory controller.
+   */
+  uint8_t buffer_node_weights[NETIO_NUM_NODE_WEIGHTS];
+
+  /** Fixed virtual address for packet buffers.  Only valid when
+      ::NETIO_FIXED_BUFFER_VA is specified in @ref flags; see the
+      description of that flag for details.
+   */
+  void* fixed_buffer_va;
+
+  /**
+      Maximum number of outstanding send packet requests.  This value is
+      only relevant when an EPP is in use; it determines the number of
+      slots in the EPP's outgoing packet queue which this tile is allowed
+      to consume, and thus the number of packets which may be sent before
+      the sending tile must wait for an acknowledgment from the EPP.
+      Modifying this value is generally only helpful when using @ref
+      netio_send_packet_vector(), where it can help improve performance by
+      allowing a single vector send operation to process more packets.
+      Typically it is not specified, and the default, which divides the
+      outgoing packet slots evenly between all tiles on the chip, is used.
+
+      If a registration asks for more outgoing packet queue slots than are
+      available, ::NETIO_TOOMANY_XMIT will be returned.  The total number
+      of packet queue slots which are available for all tiles for each EPP
+      is subject to change, but is currently ::NETIO_TOTAL_SENDS_OUTSTANDING.
+
+
+      This value is ignored if ::NETIO_XMIT is not specified in flags.
+      If you want to specify a large value here for a specific tile, you are
+      advised to specify NETIO_NO_XMIT on other, non-transmitting tiles so
+      that they do not consume a default number of packet slots.  Any tile
+      transmitting is required to have at least ::NETIO_MIN_SENDS_OUTSTANDING
+      slots allocated to it; values less than that will be silently
+      increased by the NetIO library.
+   */
+  int num_sends_outstanding;
+}
+netio_input_config_t;
+
+
+/** Registration flags; used in the @ref netio_input_config_t structure.
+ * @addtogroup setup
+ */
+/** @{ */
+
+/** Fail a registration request if we can't put packet buffers
+    on the specified memory controllers. */
+#define NETIO_STRICT_HOMING   0x00000002
+
+/** This application expects no tags on its L2 headers. */
+#define NETIO_TAG_NONE        0x00000004
+
+/** This application expects Marvell extended tags on its L2 headers. */
+#define NETIO_TAG_MRVL        0x00000008
+
+/** This application expects Broadcom tags on its L2 headers. */
+#define NETIO_TAG_BRCM        0x00000010
+
+/** This registration may call routines which receive packets. */
+#define NETIO_RECV            0x00000020
+
+/** This registration may not call routines which receive packets. */
+#define NETIO_NO_RECV         0x00000040
+
+/** This registration may call routines which transmit packets. */
+#define NETIO_XMIT            0x00000080
+
+/** This registration may call routines which transmit packets with
+    checksum acceleration. */
+#define NETIO_XMIT_CSUM       0x00000100
+
+/** This registration may not call routines which transmit packets. */
+#define NETIO_NO_XMIT         0x00000200
+
+/** This registration wants NetIO buffers mapped at an application-specified
+    virtual address.
+
+    NetIO buffers are by default created by the TMC common memory facility,
+    which must be configured by a common ancestor of all processes sharing
+    a network interface.  When this flag is specified, NetIO buffers are
+    instead mapped at an address chosen by the application (and specified
+    in @ref netio_input_config_t::fixed_buffer_va).  This allows multiple
+    unrelated but cooperating processes to share a NetIO interface.
+    All processes sharing the same interface must specify this flag,
+    and all must specify the same fixed virtual address.
+
+    @ref netio_input_config_t::fixed_buffer_va must be a
+    multiple of 16 MB, and the packet buffers will occupy @ref
+    netio_input_config_t::total_buffer_size bytes of virtual address
+    space, beginning at that address.  If any of those virtual addresses
+    are currently occupied by other memory objects, like application or
+    shared library code or data, @ref netio_input_register() will return
+    ::NETIO_FAULT.  While it is impossible to provide a fixed_buffer_va
+    which will work for all applications, a good first guess might be to
+    use 0xb0000000 minus @ref netio_input_config_t::total_buffer_size.
+    If that fails, it might be helpful to consult the running application's
+    virtual address description file (/proc/<em>pid</em>/maps) to see
+    which regions of virtual address space are available.
+ */
+#define NETIO_FIXED_BUFFER_VA 0x00000400
+
+/** This registration call will not complete unless the network link
+    is up.  The process will wait several seconds for this to happen (the
+    precise interval is link-dependent), but if the link does not come up,
+    ::NETIO_LINK_DOWN will be returned.  This flag is the default if
+    ::NETIO_NOREQUIRE_LINK_UP is not specified.  Note that this flag by
+    itself does not request that the link be brought up; that can be done
+    with the ::NETIO_AUTO_LINK_UPDN or ::NETIO_AUTO_LINK_UP flags (the
+    latter is the default if no NETIO_AUTO_LINK_xxx flags are specified),
+    or by explicitly setting the link's desired state via netio_set().
+    If the link is not brought up by one of those methods, and this flag
+    is specified, the registration operation will return ::NETIO_LINK_DOWN.
+    This flag is ignored if it is specified along with ::NETIO_NO_XMIT and
+    ::NETIO_NO_RECV.  See @ref link for more information on link
+    management.
+ */
+#define NETIO_REQUIRE_LINK_UP    0x00000800
+
+/** This registration call will complete even if the network link is not up.
+    Whenever the link is not up, packets will not be sent or received:
+    netio_get_packet() will return ::NETIO_NOPKT once all queued packets
+    have been drained, and netio_send_packet() and similar routines will
+    return NETIO_QUEUE_FULL once the outgoing packet queue in the EPP
+    or the I/O shim is full.  See @ref link for more information on link
+    management.
+ */
+#define NETIO_NOREQUIRE_LINK_UP  0x00001000
+
+#ifndef __DOXYGEN__
+/*
+ * These are part of the implementation of the NETIO_AUTO_LINK_xxx flags,
+ * but should not be used directly by applications, and are thus not
+ * documented.
+ */
+#define _NETIO_AUTO_UP        0x00002000
+#define _NETIO_AUTO_DN        0x00004000
+#define _NETIO_AUTO_PRESENT   0x00008000
+#endif
+
+/** Set the desired state of the link to up, allowing any speeds which are
+    supported by the link hardware, as part of this registration operation.
+    Do not take down the link automatically.  This is the default if
+    no other NETIO_AUTO_LINK_xxx flags are specified.  This flag is ignored
+    if it is specified along with ::NETIO_NO_XMIT and ::NETIO_NO_RECV.
+    See @ref link for more information on link management.
+ */
+#define NETIO_AUTO_LINK_UP     (_NETIO_AUTO_PRESENT | _NETIO_AUTO_UP)
+
+/** Set the desired state of the link to up, allowing any speeds which are
+    supported by the link hardware, as part of this registration operation.
+    Set the desired state of the link to down the next time no tiles are
+    registered for packet reception or transmission.  This flag is ignored
+    if it is specified along with ::NETIO_NO_XMIT and ::NETIO_NO_RECV.
+    See @ref link for more information on link management.
+ */
+#define NETIO_AUTO_LINK_UPDN   (_NETIO_AUTO_PRESENT | _NETIO_AUTO_UP | \
+                                _NETIO_AUTO_DN)
+
+/** Set the desired state of the link to down the next time no tiles are
+    registered for packet reception or transmission.  This flag is ignored
+    if it is specified along with ::NETIO_NO_XMIT and ::NETIO_NO_RECV.
+    See @ref link for more information on link management.
+ */
+#define NETIO_AUTO_LINK_DN     (_NETIO_AUTO_PRESENT | _NETIO_AUTO_DN)
+
+/** Do not bring up the link automatically as part of this registration
+    operation.  Do not take down the link automatically.  This flag
+    is ignored if it is specified along with ::NETIO_NO_XMIT and
+    ::NETIO_NO_RECV.  See @ref link for more information on link management.
+  */
+#define NETIO_AUTO_LINK_NONE   _NETIO_AUTO_PRESENT
+
+
+/** Minimum number of receive packets. */
+#define NETIO_MIN_RECEIVE_PKTS            16
+
+/** Lower bound on the maximum number of receive packets; may be higher
+    than this on some interfaces. */
+#define NETIO_MAX_RECEIVE_PKTS           128
+
+/** Maximum number of send buffers, per packet size. */
+#define NETIO_MAX_SEND_BUFFERS            16
+
+/** Number of EPP queue slots, and thus outstanding sends, per EPP. */
+#define NETIO_TOTAL_SENDS_OUTSTANDING   2015
+
+/** Minimum number of EPP queue slots, and thus outstanding sends, per
+ *  transmitting tile. */
+#define NETIO_MIN_SENDS_OUTSTANDING       16
+
+
+/**@}*/
+
+#ifndef __DOXYGEN__
+
+/**
+ * An object for providing Ethernet packets to a process.
+ */
+struct __netio_queue_impl_t;
+
+/**
+ * An object for managing the user end of a NetIO queue.
+ */
+struct __netio_queue_user_impl_t;
+
+#endif /* !__DOXYGEN__ */
+
+
+/** A netio_queue_t describes a NetIO communications endpoint.
+ * @ingroup setup
+ */
+typedef struct
+{
+#ifdef __DOXYGEN__
+  uint8_t opaque[8];                 /**< This is an opaque structure. */
+#else
+  struct __netio_queue_impl_t* __system_part;    /**< The system part. */
+  struct __netio_queue_user_impl_t* __user_part; /**< The user part. */
+#ifdef _NETIO_PTHREAD
+  _netio_percpu_mutex_t lock;                    /**< Queue lock. */
+#endif
+#endif
+}
+netio_queue_t;
+
+
+/**
+ * @brief Packet send context.
+ *
+ * @ingroup egress
+ *
+ * Packet send context for use with netio_send_packet_prepare and _commit.
+ */
+typedef struct
+{
+#ifdef __DOXYGEN__
+  uint8_t opaque[44];   /**< This is an opaque structure. */
+#else
+  uint8_t flags;        /**< Defined below */
+  uint8_t datalen;      /**< Number of valid words pointed to by data. */
+  uint32_t request[9];  /**< Request to be sent to the EPP or shim.  Note
+                             that this is smaller than the 11-word maximum
+                             request size, since some constant values are
+                             not saved in the context. */
+  uint32_t *data;       /**< Data to be sent to the EPP or shim via IDN. */
+#endif
+}
+netio_send_pkt_context_t;
+
+
+#ifndef __DOXYGEN__
+#define SEND_PKT_CTX_USE_EPP   1  /**< We're sending to an EPP. */
+#define SEND_PKT_CTX_SEND_CSUM 2  /**< Request includes a checksum. */
+#endif
+
+/**
+ * @brief Packet vector entry.
+ *
+ * @ingroup egress
+ *
+ * This data structure is used with netio_send_packet_vector() to send multiple
+ * packets with one NetIO call.  The structure should be initialized by
+ * calling netio_pkt_vector_set(), rather than by setting the fields
+ * directly.
+ *
+ * This structure is guaranteed to be a power of two in size, no
+ * bigger than one L2 cache line, and to be aligned modulo its size.
+ */
+typedef struct
+#ifndef __DOXYGEN__
+__attribute__((aligned(8)))
+#endif
+{
+  /** Reserved for use by the user application.  When initialized with
+   *  the netio_set_pkt_vector_entry() function, this field is guaranteed
+   *  to be visible to readers only after all other fields are already
+   *  visible.  This way it can be used as a valid flag or generation
+   *  counter. */
+  uint8_t user_data;
+
+  /* Structure members below this point should not be accessed directly by
+   * applications, as they may change in the future. */
+
+  /** Low 8 bits of the packet address to send.  The high bits are
+   *  acquired from the 'handle' field. */
+  uint8_t buffer_address_low;
+
+  /** Number of bytes to transmit. */
+  uint16_t size;
+
+  /** The raw handle from a netio_pkt_t.  If this is NETIO_PKT_HANDLE_NONE,
+   *  this vector entry will be skipped and no packet will be transmitted. */
+  netio_pkt_handle_t handle;
+}
+netio_pkt_vector_entry_t;
+
+
+/**
+ * @brief Initialize fields in a packet vector entry.
+ *
+ * @ingroup egress
+ *
+ * @param[out] v Pointer to the vector entry to be initialized.
+ * @param[in] pkt Packet to be transmitted when the vector entry is passed to
+ *        netio_send_packet_vector().  Note that the packet's attributes
+ *        (e.g., its L2 offset and length) are captured at the time this
+ *        routine is called; subsequent changes in those attributes will not
+ *        be reflected in the packet which is actually transmitted.
+ *        Changes in the packet's contents, however, will be so reflected.
+ *        If this is NULL, no packet will be transmitted.
+ * @param[in] user_data User data to be set in the vector entry.
+ *        This function guarantees that the "user_data" field will become
+ *        visible to a reader only after all other fields have become visible.
+ *        This allows a structure in a ring buffer to be written and read
+ *        by a polling reader without any locks or other synchronization.
+ */
+static __inline void
+netio_pkt_vector_set(volatile netio_pkt_vector_entry_t* v, netio_pkt_t* pkt,
+                     uint8_t user_data)
+{
+  if (pkt)
+  {
+    if (NETIO_PKT_IS_MINIMAL(pkt))
+    {
+      netio_pkt_minimal_metadata_t* mmd =
+        (netio_pkt_minimal_metadata_t*) &pkt->__metadata;
+      v->buffer_address_low = (uintptr_t) NETIO_PKT_L2_DATA_MM(mmd, pkt) & 0xFF;
+      v->size = NETIO_PKT_L2_LENGTH_MM(mmd, pkt);
+    }
+    else
+    {
+      netio_pkt_metadata_t* mda = &pkt->__metadata;
+      v->buffer_address_low = (uintptr_t) NETIO_PKT_L2_DATA_M(mda, pkt) & 0xFF;
+      v->size = NETIO_PKT_L2_LENGTH_M(mda, pkt);
+    }
+    v->handle.word = pkt->__packet.word;
+  }
+  else
+  {
+    v->handle.word = 0;   /* Set handle to NETIO_PKT_HANDLE_NONE. */
+  }
+
+  __asm__("" : : : "memory");
+
+  v->user_data = user_data;
+}
+
+
+/**
+ * Flags and structures for @ref netio_get() and @ref netio_set().
+ * @ingroup config
+ */
+
+/** @{ */
+/** Parameter class; addr is a NETIO_PARAM_xxx value. */
+#define NETIO_PARAM       0
+/** Interface MAC address. This address is only valid with @ref netio_get().
+ *  The value is a 6-byte MAC address.  Depending upon the overall system
+ *  design, a MAC address may or may not be available for each interface. */
+#define NETIO_PARAM_MAC        0
+
+/** Determine whether to suspend output on the receipt of pause frames.
+ *  If the value is nonzero, the I/O shim will suspend output when a pause
+ *  frame is received.  If the value is zero, pause frames will be ignored. */
+#define NETIO_PARAM_PAUSE_IN   1
+
+/** Determine whether to send pause frames if the I/O shim packet FIFOs are
+ *  nearly full.  If the value is zero, pause frames are not sent.  If
+ *  the value is nonzero, it is the delay value which will be sent in any
+ *  pause frames which are output, in units of 512 bit times. */
+#define NETIO_PARAM_PAUSE_OUT  2
+
+/** Jumbo frame support.  The value is a 4-byte integer.  If the value is
+ *  nonzero, the MAC will accept frames of up to 10240 bytes.  If the value
+ *  is zero, the MAC will only accept frames of up to 1544 bytes. */
+#define NETIO_PARAM_JUMBO      3
+
+/** I/O shim's overflow statistics register.  The value is two 16-bit integers.
+ *  The first 16-bit value (or the low 16 bits, if the value is treated as a
+ *  32-bit number) is the count of packets which were completely dropped and
+ *  not delivered by the shim.  The second 16-bit value (or the high 16 bits,
+ *  if the value is treated as a 32-bit number) is the count of packets
+ *  which were truncated and thus only partially delivered by the shim.  This
+ *  register is automatically reset to zero after it has been read.
+ */
+#define NETIO_PARAM_OVERFLOW   4
+
+/** IPP statistics.  This address is only valid with @ref netio_get().  The
+ *  value is a netio_stat_t structure.  Unlike the I/O shim statistics, the
+ *  IPP statistics are not all reset to zero on read; see the description
+ *  of the netio_stat_t for details. */
+#define NETIO_PARAM_STAT 5
+
+/** Possible link state.  The value is a combination of "NETIO_LINK_xxx"
+ *  flags.  With @ref netio_get(), this will indicate which flags are
+ *  actually supported by the hardware.
+ *
+ *  For historical reasons, specifying this value to netio_set() will have
+ *  the same behavior as using ::NETIO_PARAM_LINK_CONFIG, but this usage is
+ *  discouraged.
+ */
+#define NETIO_PARAM_LINK_POSSIBLE_STATE 6
+
+/** Link configuration. The value is a combination of "NETIO_LINK_xxx" flags.
+ *  With @ref netio_set(), this will attempt to immediately bring up the
+ *  link using whichever of the requested flags are supported by the
+ *  hardware, or take down the link if the flags are zero; if this is
+ *  not possible, an error will be returned.  Many programs will want
+ *  to use ::NETIO_PARAM_LINK_DESIRED_STATE instead.
+ *
+ *  For historical reasons, specifying this value to netio_get() will
+ *  have the same behavior as using ::NETIO_PARAM_LINK_POSSIBLE_STATE,
+ *  but this usage is discouraged.
+ */
+#define NETIO_PARAM_LINK_CONFIG NETIO_PARAM_LINK_POSSIBLE_STATE
+
+/** Current link state. This address is only valid with @ref netio_get().
+ *  The value is zero or more of the "NETIO_LINK_xxx" flags, ORed together.
+ *  If the link is down, the value ANDed with NETIO_LINK_SPEED will be
+ *  zero; if the link is up, the value ANDed with NETIO_LINK_SPEED will
+ *  result in exactly one of the NETIO_LINK_xxx values, indicating the
+ *  current speed. */
+#define NETIO_PARAM_LINK_CURRENT_STATE 7
+
+/** Variant symbol for current state, retained for compatibility with
+ *  pre-MDE-2.1 programs. */
+#define NETIO_PARAM_LINK_STATUS NETIO_PARAM_LINK_CURRENT_STATE
+
+/** Packet Coherence protocol. This address is only valid with @ref netio_get().
+ *  The value is nonzero if the interface is configured for cache-coherent DMA.
+ */
+#define NETIO_PARAM_COHERENT 8
+
+/** Desired link state. The value is a conbination of "NETIO_LINK_xxx"
+ *  flags, which specify the desired state for the link.  With @ref
+ *  netio_set(), this will, in the background, attempt to bring up the link
+ *  using whichever of the requested flags are reasonable, or take down the
+ *  link if the flags are zero.  The actual link up or down operation may
+ *  happen after this call completes.  If the link state changes in the
+ *  future, the system will continue to try to get back to the desired link
+ *  state; for instance, if the link is brought up successfully, and then
+ *  the network cable is disconnected, the link will go down.  However, the
+ *  desired state of the link is still up, so if the cable is reconnected,
+ *  the link will be brought up again.
+ *
+ *  With @ref netio_get(), this will indicate the desired state for the
+ *  link, as set with a previous netio_set() call, or implicitly by a
+ *  netio_input_register() or netio_input_unregister() operation.  This may
+ *  not reflect the current state of the link; to get that, use
+ *  ::NETIO_PARAM_LINK_CURRENT_STATE. */
+#define NETIO_PARAM_LINK_DESIRED_STATE 9
+
+/** NetIO statistics structure.  Retrieved using the ::NETIO_PARAM_STAT
+ *  address passed to @ref netio_get(). */
+typedef struct
+{
+  /** Number of packets which have been received by the IPP and forwarded
+   *  to a tile's receive queue for processing.  This value wraps at its
+   *  maximum, and is not cleared upon read. */
+  uint32_t packets_received;
+
+  /** Number of packets which have been dropped by the IPP, because they could
+   *  not be received, or could not be forwarded to a tile.  The former happens
+   *  when the IPP does not have a free packet buffer of suitable size for an
+   *  incoming frame.  The latter happens when all potential destination tiles
+   *  for a packet, as defined by the group, bucket, and queue configuration,
+   *  have full receive queues.   This value wraps at its maximum, and is not
+   *  cleared upon read. */
+  uint32_t packets_dropped;
+
+  /*
+   * Note: the #defines after each of the following four one-byte values
+   * denote their location within the third word of the netio_stat_t.  They
+   * are intended for use only by the IPP implementation and are thus omitted
+   * from the Doxygen output.
+   */
+
+  /** Number of packets dropped because no worker was able to accept a new
+   *  packet.  This value saturates at its maximum, and is cleared upon
+   *  read. */
+  uint8_t drops_no_worker;
+#ifndef __DOXYGEN__
+#define NETIO_STAT_DROPS_NO_WORKER   0
+#endif
+
+  /** Number of packets dropped because no small buffers were available.
+   *  This value saturates at its maximum, and is cleared upon read. */
+  uint8_t drops_no_smallbuf;
+#ifndef __DOXYGEN__
+#define NETIO_STAT_DROPS_NO_SMALLBUF 1
+#endif
+
+  /** Number of packets dropped because no large buffers were available.
+   *  This value saturates at its maximum, and is cleared upon read. */
+  uint8_t drops_no_largebuf;
+#ifndef __DOXYGEN__
+#define NETIO_STAT_DROPS_NO_LARGEBUF 2
+#endif
+
+  /** Number of packets dropped because no jumbo buffers were available.
+   *  This value saturates at its maximum, and is cleared upon read. */
+  uint8_t drops_no_jumbobuf;
+#ifndef __DOXYGEN__
+#define NETIO_STAT_DROPS_NO_JUMBOBUF 3
+#endif
+}
+netio_stat_t;
+
+
+/** Link can run, should run, or is running at 10 Mbps. */
+#define NETIO_LINK_10M         0x01
+
+/** Link can run, should run, or is running at 100 Mbps. */
+#define NETIO_LINK_100M        0x02
+
+/** Link can run, should run, or is running at 1 Gbps. */
+#define NETIO_LINK_1G          0x04
+
+/** Link can run, should run, or is running at 10 Gbps. */
+#define NETIO_LINK_10G         0x08
+
+/** Link should run at the highest speed supported by the link and by
+ *  the device connected to the link.  Only usable as a value for
+ *  the link's desired state; never returned as a value for the current
+ *  or possible states. */
+#define NETIO_LINK_ANYSPEED    0x10
+
+/** All legal link speeds. */
+#define NETIO_LINK_SPEED  (NETIO_LINK_10M  | \
+                           NETIO_LINK_100M | \
+                           NETIO_LINK_1G   | \
+                           NETIO_LINK_10G  | \
+                           NETIO_LINK_ANYSPEED)
+
+
+/** MAC register class.  Addr is a register offset within the MAC.
+ *  Registers within the XGbE and GbE MACs are documented in the Tile
+ *  Processor I/O Device Guide (UG104). MAC registers start at address
+ *  0x4000, and do not include the MAC_INTERFACE registers. */
+#define NETIO_MAC             1
+
+/** MDIO register class (IEEE 802.3 clause 22 format).  Addr is the "addr"
+ *  member of a netio_mdio_addr_t structure. */
+#define NETIO_MDIO            2
+
+/** MDIO register class (IEEE 802.3 clause 45 format).  Addr is the "addr"
+ *  member of a netio_mdio_addr_t structure. */
+#define NETIO_MDIO_CLAUSE45   3
+
+/** NetIO MDIO address type.  Retrieved or provided using the ::NETIO_MDIO
+ *  address passed to @ref netio_get() or @ref netio_set(). */
+typedef union
+{
+  struct
+  {
+    unsigned int reg:16;  /**< MDIO register offset.  For clause 22 access,
+                               must be less than 32. */
+    unsigned int phy:5;   /**< Which MDIO PHY to access. */
+    unsigned int dev:5;   /**< Which MDIO device to access within that PHY.
+                               Applicable for clause 45 access only; ignored
+                               for clause 22 access. */
+  }
+  bits;                   /**< Container for bitfields. */
+  uint64_t addr;          /**< Value to pass to @ref netio_get() or
+                           *   @ref netio_set(). */
+}
+netio_mdio_addr_t;
+
+/** @} */
+
+#endif /* __NETIO_INTF_H__ */
index 112b1e248f0555985109e921616265c926dd16a7..b4c8e8ec45dc7fa041befe4d12e56c4d94236f8f 100644 (file)
@@ -15,3 +15,4 @@ obj-$(CONFIG_SMP)             += smpboot.o smp.o tlb.o
 obj-$(CONFIG_MODULES)          += module.o
 obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
 obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel.o
+obj-$(CONFIG_PCI)              += pci.o
index 543d6a33aa26f6c02f7f41f59fcdceea1729bcd8..dbb0dfc7beceb10eaa25fd4b73579cdc620334c5 100644 (file)
@@ -290,12 +290,12 @@ long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
        return ret;
 }
 
+/* The assembly shim for this function arranges to ignore the return value. */
 long compat_sys_rt_sigreturn(struct pt_regs *regs)
 {
        struct compat_rt_sigframe __user *frame =
                (struct compat_rt_sigframe __user *) compat_ptr(regs->sp);
        sigset_t set;
-       long r0;
 
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
@@ -308,13 +308,13 @@ long compat_sys_rt_sigreturn(struct pt_regs *regs)
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
 
-       if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
+       if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
                goto badframe;
 
        if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0)
                goto badframe;
 
-       return r0;
+       return 0;
 
 badframe:
        force_sig(SIGSEGV, current);
index f5821626247fee9891d47eca123b26440f6c025c..5eed4a02bf62335e17a39f663cd4485869f44ea5 100644 (file)
@@ -1342,8 +1342,8 @@ handle_syscall:
        lw      r20, r20
 
        /* Jump to syscall handler. */
-       jalr    r20; .Lhandle_syscall_link:
-       FEEDBACK_REENTER(handle_syscall)
+       jalr    r20
+.Lhandle_syscall_link: /* value of "lr" after "jalr r20" above */
 
        /*
         * Write our r0 onto the stack so it gets restored instead
@@ -1352,6 +1352,9 @@ handle_syscall:
        PTREGS_PTR(r29, PTREGS_OFFSET_REG(0))
        sw      r29, r0
 
+.Lsyscall_sigreturn_skip:
+       FEEDBACK_REENTER(handle_syscall)
+
        /* Do syscall trace again, if requested. */
        lw      r30, r31
        andi    r30, r30, _TIF_SYSCALL_TRACE
@@ -1536,9 +1539,24 @@ STD_ENTRY_LOCAL(bad_intr)
        };                                              \
        STD_ENDPROC(_##x)
 
+/*
+ * Special-case sigreturn to not write r0 to the stack on return.
+ * This is technically more efficient, but it also avoids difficulties
+ * in the 64-bit OS when handling 32-bit compat code, since we must not
+ * sign-extend r0 for the sigreturn return-value case.
+ */
+#define PTREGS_SYSCALL_SIGRETURN(x, reg)                \
+       STD_ENTRY(_##x);                                \
+       addli   lr, lr, .Lsyscall_sigreturn_skip - .Lhandle_syscall_link; \
+       {                                               \
+        PTREGS_PTR(reg, PTREGS_OFFSET_BASE);           \
+        j      x                                       \
+       };                                              \
+       STD_ENDPROC(_##x)
+
 PTREGS_SYSCALL(sys_execve, r3)
 PTREGS_SYSCALL(sys_sigaltstack, r2)
-PTREGS_SYSCALL(sys_rt_sigreturn, r0)
+PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0)
 PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1)
 
 /* Save additional callee-saves to pt_regs, put address in r4 and jump. */
diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c
new file mode 100644 (file)
index 0000000..a1ee25b
--- /dev/null
@@ -0,0 +1,621 @@
+/*
+ * Copyright 2010 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is 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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/capability.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/bootmem.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#include <asm/processor.h>
+#include <asm/sections.h>
+#include <asm/byteorder.h>
+#include <asm/hv_driver.h>
+#include <hv/drv_pcie_rc_intf.h>
+
+
+/*
+ * Initialization flow and process
+ * -------------------------------
+ *
+ * This files containes the routines to search for PCI buses,
+ * enumerate the buses, and configure any attached devices.
+ *
+ * There are two entry points here:
+ * 1) tile_pci_init
+ *    This sets up the pci_controller structs, and opens the
+ *    FDs to the hypervisor.  This is called from setup_arch() early
+ *    in the boot process.
+ * 2) pcibios_init
+ *    This probes the PCI bus(es) for any attached hardware.  It's
+ *    called by subsys_initcall.  All of the real work is done by the
+ *    generic Linux PCI layer.
+ *
+ */
+
+/*
+ * This flag tells if the platform is TILEmpower that needs
+ * special configuration for the PLX switch chip.
+ */
+int __write_once tile_plx_gen1;
+
+static struct pci_controller controllers[TILE_NUM_PCIE];
+static int num_controllers;
+
+static struct pci_ops tile_cfg_ops;
+
+
+/*
+ * We don't need to worry about the alignment of resources.
+ */
+resource_size_t pcibios_align_resource(void *data, const struct resource *res,
+                           resource_size_t size, resource_size_t align)
+{
+       return res->start;
+}
+EXPORT_SYMBOL(pcibios_align_resource);
+
+/*
+ * Open a FD to the hypervisor PCI device.
+ *
+ * controller_id is the controller number, config type is 0 or 1 for
+ * config0 or config1 operations.
+ */
+static int __init tile_pcie_open(int controller_id, int config_type)
+{
+       char filename[32];
+       int fd;
+
+       sprintf(filename, "pcie/%d/config%d", controller_id, config_type);
+
+       fd = hv_dev_open((HV_VirtAddr)filename, 0);
+
+       return fd;
+}
+
+
+/*
+ * Get the IRQ numbers from the HV and set up the handlers for them.
+ */
+static int __init tile_init_irqs(int controller_id,
+                                struct pci_controller *controller)
+{
+       char filename[32];
+       int fd;
+       int ret;
+       int x;
+       struct pcie_rc_config rc_config;
+
+       sprintf(filename, "pcie/%d/ctl", controller_id);
+       fd = hv_dev_open((HV_VirtAddr)filename, 0);
+       if (fd < 0) {
+               pr_err("PCI: hv_dev_open(%s) failed\n", filename);
+               return -1;
+       }
+       ret = hv_dev_pread(fd, 0, (HV_VirtAddr)(&rc_config),
+                          sizeof(rc_config), PCIE_RC_CONFIG_MASK_OFF);
+       hv_dev_close(fd);
+       if (ret != sizeof(rc_config)) {
+               pr_err("PCI: wanted %zd bytes, got %d\n",
+                      sizeof(rc_config), ret);
+               return -1;
+       }
+       /* Record irq_base so that we can map INTx to IRQ # later. */
+       controller->irq_base = rc_config.intr;
+
+       for (x = 0; x < 4; x++)
+               tile_irq_activate(rc_config.intr + x,
+                                 TILE_IRQ_HW_CLEAR);
+
+       if (rc_config.plx_gen1)
+               controller->plx_gen1 = 1;
+
+       return 0;
+}
+
+/*
+ * First initialization entry point, called from setup_arch().
+ *
+ * Find valid controllers and fill in pci_controller structs for each
+ * of them.
+ *
+ * Returns the number of controllers discovered.
+ */
+int __init tile_pci_init(void)
+{
+       int i;
+
+       pr_info("PCI: Searching for controllers...\n");
+
+       /* Do any configuration we need before using the PCIe */
+
+       for (i = 0; i < TILE_NUM_PCIE; i++) {
+               int hv_cfg_fd0 = -1;
+               int hv_cfg_fd1 = -1;
+               int hv_mem_fd = -1;
+               char name[32];
+               struct pci_controller *controller;
+
+               /*
+                * Open the fd to the HV.  If it fails then this
+                * device doesn't exist.
+                */
+               hv_cfg_fd0 = tile_pcie_open(i, 0);
+               if (hv_cfg_fd0 < 0)
+                       continue;
+               hv_cfg_fd1 = tile_pcie_open(i, 1);
+               if (hv_cfg_fd1 < 0) {
+                       pr_err("PCI: Couldn't open config fd to HV "
+                           "for controller %d\n", i);
+                       goto err_cont;
+               }
+
+               sprintf(name, "pcie/%d/mem", i);
+               hv_mem_fd = hv_dev_open((HV_VirtAddr)name, 0);
+               if (hv_mem_fd < 0) {
+                       pr_err("PCI: Could not open mem fd to HV!\n");
+                       goto err_cont;
+               }
+
+               pr_info("PCI: Found PCI controller #%d\n", i);
+
+               controller = &controllers[num_controllers];
+
+               if (tile_init_irqs(i, controller)) {
+                       pr_err("PCI: Could not initialize "
+                              "IRQs, aborting.\n");
+                       goto err_cont;
+               }
+
+               controller->index = num_controllers;
+               controller->hv_cfg_fd[0] = hv_cfg_fd0;
+               controller->hv_cfg_fd[1] = hv_cfg_fd1;
+               controller->hv_mem_fd = hv_mem_fd;
+               controller->first_busno = 0;
+               controller->last_busno = 0xff;
+               controller->ops = &tile_cfg_ops;
+
+               num_controllers++;
+               continue;
+
+err_cont:
+               if (hv_cfg_fd0 >= 0)
+                       hv_dev_close(hv_cfg_fd0);
+               if (hv_cfg_fd1 >= 0)
+                       hv_dev_close(hv_cfg_fd1);
+               if (hv_mem_fd >= 0)
+                       hv_dev_close(hv_mem_fd);
+               continue;
+       }
+
+       /*
+        * Before using the PCIe, see if we need to do any platform-specific
+        * configuration, such as the PLX switch Gen 1 issue on TILEmpower.
+        */
+       for (i = 0; i < num_controllers; i++) {
+               struct pci_controller *controller = &controllers[i];
+
+               if (controller->plx_gen1)
+                       tile_plx_gen1 = 1;
+       }
+
+       return num_controllers;
+}
+
+/*
+ * (pin - 1) converts from the PCI standard's [1:4] convention to
+ * a normal [0:3] range.
+ */
+static int tile_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       struct pci_controller *controller =
+               (struct pci_controller *)dev->sysdata;
+       return (pin - 1) + controller->irq_base;
+}
+
+
+static void __init fixup_read_and_payload_sizes(void)
+{
+       struct pci_dev *dev = NULL;
+       int smallest_max_payload = 0x1; /* Tile maxes out at 256 bytes. */
+       int max_read_size = 0x2; /* Limit to 512 byte reads. */
+       u16 new_values;
+
+       /* Scan for the smallest maximum payload size. */
+       while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+               int pcie_caps_offset;
+               u32 devcap;
+               int max_payload;
+
+               pcie_caps_offset = pci_find_capability(dev, PCI_CAP_ID_EXP);
+               if (pcie_caps_offset == 0)
+                       continue;
+
+               pci_read_config_dword(dev, pcie_caps_offset + PCI_EXP_DEVCAP,
+                                     &devcap);
+               max_payload = devcap & PCI_EXP_DEVCAP_PAYLOAD;
+               if (max_payload < smallest_max_payload)
+                       smallest_max_payload = max_payload;
+       }
+
+       /* Now, set the max_payload_size for all devices to that value. */
+       new_values = (max_read_size << 12) | (smallest_max_payload << 5);
+       while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+               int pcie_caps_offset;
+               u16 devctl;
+
+               pcie_caps_offset = pci_find_capability(dev, PCI_CAP_ID_EXP);
+               if (pcie_caps_offset == 0)
+                       continue;
+
+               pci_read_config_word(dev, pcie_caps_offset + PCI_EXP_DEVCTL,
+                                    &devctl);
+               devctl &= ~(PCI_EXP_DEVCTL_PAYLOAD | PCI_EXP_DEVCTL_READRQ);
+               devctl |= new_values;
+               pci_write_config_word(dev, pcie_caps_offset + PCI_EXP_DEVCTL,
+                                     devctl);
+       }
+}
+
+
+/*
+ * Second PCI initialization entry point, called by subsys_initcall.
+ *
+ * The controllers have been set up by the time we get here, by a call to
+ * tile_pci_init.
+ */
+static int __init pcibios_init(void)
+{
+       int i;
+
+       pr_info("PCI: Probing PCI hardware\n");
+
+       /*
+        * Delay a bit in case devices aren't ready.  Some devices are
+        * known to require at least 20ms here, but we use a more
+        * conservative value.
+        */
+       mdelay(250);
+
+       /* Scan all of the recorded PCI controllers.  */
+       for (i = 0; i < num_controllers; i++) {
+               struct pci_controller *controller = &controllers[i];
+               struct pci_bus *bus;
+
+               pr_info("PCI: initializing controller #%d\n", i);
+
+               /*
+                * This comes from the generic Linux PCI driver.
+                *
+                * It reads the PCI tree for this bus into the Linux
+                * data structures.
+                *
+                * This is inlined in linux/pci.h and calls into
+                * pci_scan_bus_parented() in probe.c.
+                */
+               bus = pci_scan_bus(0, controller->ops, controller);
+               controller->root_bus = bus;
+               controller->last_busno = bus->subordinate;
+
+       }
+
+       /* Do machine dependent PCI interrupt routing */
+       pci_fixup_irqs(pci_common_swizzle, tile_map_irq);
+
+       /*
+        * This comes from the generic Linux PCI driver.
+        *
+        * It allocates all of the resources (I/O memory, etc)
+        * associated with the devices read in above.
+        */
+
+       pci_assign_unassigned_resources();
+
+       /* Configure the max_read_size and max_payload_size values. */
+       fixup_read_and_payload_sizes();
+
+       /* Record the I/O resources in the PCI controller structure. */
+       for (i = 0; i < num_controllers; i++) {
+               struct pci_bus *root_bus = controllers[i].root_bus;
+               struct pci_bus *next_bus;
+               struct pci_dev *dev;
+
+               list_for_each_entry(dev, &root_bus->devices, bus_list) {
+                       /* Find the PCI host controller, ie. the 1st bridge. */
+                       if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
+                               (PCI_SLOT(dev->devfn) == 0)) {
+                               next_bus = dev->subordinate;
+                               controllers[i].mem_resources[0] =
+                                       *next_bus->resource[0];
+                               controllers[i].mem_resources[1] =
+                                        *next_bus->resource[1];
+                               controllers[i].mem_resources[2] =
+                                        *next_bus->resource[2];
+
+                               break;
+                       }
+               }
+
+       }
+
+       return 0;
+}
+subsys_initcall(pcibios_init);
+
+/*
+ * No bus fixups needed.
+ */
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+{
+       /* Nothing needs to be done. */
+}
+
+/*
+ * This can be called from the generic PCI layer, but doesn't need to
+ * do anything.
+ */
+char __devinit *pcibios_setup(char *str)
+{
+       /* Nothing needs to be done. */
+       return str;
+}
+
+/*
+ * This is called from the generic Linux layer.
+ */
+void __init pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+       pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
+
+/*
+ * Enable memory and/or address decoding, as appropriate, for the
+ * device described by the 'dev' struct.
+ *
+ * This is called from the generic PCI layer, and can be called
+ * for bridges or endpoints.
+ */
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+       u16 cmd, old_cmd;
+       u8 header_type;
+       int i;
+       struct resource *r;
+
+       pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
+
+       pci_read_config_word(dev, PCI_COMMAND, &cmd);
+       old_cmd = cmd;
+       if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
+               /*
+                * For bridges, we enable both memory and I/O decoding
+                * in call cases.
+                */
+               cmd |= PCI_COMMAND_IO;
+               cmd |= PCI_COMMAND_MEMORY;
+       } else {
+               /*
+                * For endpoints, we enable memory and/or I/O decoding
+                * only if they have a memory resource of that type.
+                */
+               for (i = 0; i < 6; i++) {
+                       r = &dev->resource[i];
+                       if (r->flags & IORESOURCE_UNSET) {
+                               pr_err("PCI: Device %s not available "
+                                      "because of resource collisions\n",
+                                      pci_name(dev));
+                               return -EINVAL;
+                       }
+                       if (r->flags & IORESOURCE_IO)
+                               cmd |= PCI_COMMAND_IO;
+                       if (r->flags & IORESOURCE_MEM)
+                               cmd |= PCI_COMMAND_MEMORY;
+               }
+       }
+
+       /*
+        * We only write the command if it changed.
+        */
+       if (cmd != old_cmd)
+               pci_write_config_word(dev, PCI_COMMAND, cmd);
+       return 0;
+}
+
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
+{
+       unsigned long start = pci_resource_start(dev, bar);
+       unsigned long len = pci_resource_len(dev, bar);
+       unsigned long flags = pci_resource_flags(dev, bar);
+
+       if (!len)
+               return NULL;
+       if (max && len > max)
+               len = max;
+
+       if (!(flags & IORESOURCE_MEM)) {
+               pr_info("PCI: Trying to map invalid resource %#lx\n", flags);
+               start = 0;
+       }
+
+       return (void __iomem *)start;
+}
+EXPORT_SYMBOL(pci_iomap);
+
+
+/****************************************************************
+ *
+ * Tile PCI config space read/write routines
+ *
+ ****************************************************************/
+
+/*
+ * These are the normal read and write ops
+ * These are expanded with macros from  pci_bus_read_config_byte() etc.
+ *
+ * devfn is the combined PCI slot & function.
+ *
+ * offset is in bytes, from the start of config space for the
+ * specified bus & slot.
+ */
+
+static int __devinit tile_cfg_read(struct pci_bus *bus,
+                                  unsigned int devfn,
+                                  int offset,
+                                  int size,
+                                  u32 *val)
+{
+       struct pci_controller *controller = bus->sysdata;
+       int busnum = bus->number & 0xff;
+       int slot = (devfn >> 3) & 0x1f;
+       int function = devfn & 0x7;
+       u32 addr;
+       int config_mode = 1;
+
+       /*
+        * There is no bridge between the Tile and bus 0, so we
+        * use config0 to talk to bus 0.
+        *
+        * If we're talking to a bus other than zero then we
+        * must have found a bridge.
+        */
+       if (busnum == 0) {
+               /*
+                * We fake an empty slot for (busnum == 0) && (slot > 0),
+                * since there is only one slot on bus 0.
+                */
+               if (slot) {
+                       *val = 0xFFFFFFFF;
+                       return 0;
+               }
+               config_mode = 0;
+       }
+
+       addr = busnum << 20;            /* Bus in 27:20 */
+       addr |= slot << 15;             /* Slot (device) in 19:15 */
+       addr |= function << 12;         /* Function is in 14:12 */
+       addr |= (offset & 0xFFF);       /* byte address in 0:11 */
+
+       return hv_dev_pread(controller->hv_cfg_fd[config_mode], 0,
+                           (HV_VirtAddr)(val), size, addr);
+}
+
+
+/*
+ * See tile_cfg_read() for relevent comments.
+ * Note that "val" is the value to write, not a pointer to that value.
+ */
+static int __devinit tile_cfg_write(struct pci_bus *bus,
+                                   unsigned int devfn,
+                                   int offset,
+                                   int size,
+                                   u32 val)
+{
+       struct pci_controller *controller = bus->sysdata;
+       int busnum = bus->number & 0xff;
+       int slot = (devfn >> 3) & 0x1f;
+       int function = devfn & 0x7;
+       u32 addr;
+       int config_mode = 1;
+       HV_VirtAddr valp = (HV_VirtAddr)&val;
+
+       /*
+        * For bus 0 slot 0 we use config 0 accesses.
+        */
+       if (busnum == 0) {
+               /*
+                * We fake an empty slot for (busnum == 0) && (slot > 0),
+                * since there is only one slot on bus 0.
+                */
+               if (slot)
+                       return 0;
+               config_mode = 0;
+       }
+
+       addr = busnum << 20;            /* Bus in 27:20 */
+       addr |= slot << 15;             /* Slot (device) in 19:15 */
+       addr |= function << 12;         /* Function is in 14:12 */
+       addr |= (offset & 0xFFF);       /* byte address in 0:11 */
+
+#ifdef __BIG_ENDIAN
+       /* Point to the correct part of the 32-bit "val". */
+       valp += 4 - size;
+#endif
+
+       return hv_dev_pwrite(controller->hv_cfg_fd[config_mode], 0,
+                            valp, size, addr);
+}
+
+
+static struct pci_ops tile_cfg_ops = {
+       .read =         tile_cfg_read,
+       .write =        tile_cfg_write,
+};
+
+
+/*
+ * In the following, each PCI controller's mem_resources[1]
+ * represents its (non-prefetchable) PCI memory resource.
+ * mem_resources[0] and mem_resources[2] refer to its PCI I/O and
+ * prefetchable PCI memory resources, respectively.
+ * For more details, see pci_setup_bridge() in setup-bus.c.
+ * By comparing the target PCI memory address against the
+ * end address of controller 0, we can determine the controller
+ * that should accept the PCI memory access.
+ */
+#define TILE_READ(size, type)                                          \
+type _tile_read##size(unsigned long addr)                              \
+{                                                                      \
+       type val;                                                       \
+       int idx = 0;                                                    \
+       if (addr > controllers[0].mem_resources[1].end &&               \
+           addr > controllers[0].mem_resources[2].end)                 \
+               idx = 1;                                                \
+       if (hv_dev_pread(controllers[idx].hv_mem_fd, 0,                 \
+                        (HV_VirtAddr)(&val), sizeof(type), addr))      \
+               pr_err("PCI: read %zd bytes at 0x%lX failed\n",         \
+                      sizeof(type), addr);                             \
+       return val;                                                     \
+}                                                                      \
+EXPORT_SYMBOL(_tile_read##size)
+
+TILE_READ(b, u8);
+TILE_READ(w, u16);
+TILE_READ(l, u32);
+TILE_READ(q, u64);
+
+#define TILE_WRITE(size, type)                                         \
+void _tile_write##size(type val, unsigned long addr)                   \
+{                                                                      \
+       int idx = 0;                                                    \
+       if (addr > controllers[0].mem_resources[1].end &&               \
+           addr > controllers[0].mem_resources[2].end)                 \
+               idx = 1;                                                \
+       if (hv_dev_pwrite(controllers[idx].hv_mem_fd, 0,                \
+                         (HV_VirtAddr)(&val), sizeof(type), addr))     \
+               pr_err("PCI: write %zd bytes at 0x%lX failed\n",        \
+                      sizeof(type), addr);                             \
+}                                                                      \
+EXPORT_SYMBOL(_tile_write##size)
+
+TILE_WRITE(b, u8);
+TILE_WRITE(w, u16);
+TILE_WRITE(l, u32);
+TILE_WRITE(q, u64);
index 8430f45daea6bce566cc0980db85f0d0b213af72..e90eb53173b0b5e1c2f7c3ba60ad4be38940a34d 100644 (file)
@@ -211,6 +211,13 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
        childregs->regs[0] = 0;         /* return value is zero */
        childregs->sp = sp;  /* override with new user stack pointer */
 
+       /*
+        * If CLONE_SETTLS is set, set "tp" in the new task to "r4",
+        * which is passed in as arg #5 to sys_clone().
+        */
+       if (clone_flags & CLONE_SETTLS)
+               childregs->tp = regs->regs[4];
+
        /*
         * Copy the callee-saved registers from the passed pt_regs struct
         * into the context-switch callee-saved registers area.
@@ -539,6 +546,7 @@ struct task_struct *__sched _switch_to(struct task_struct *prev,
        return __switch_to(prev, next, next_current_ksp0(next));
 }
 
+/* Note there is an implicit fifth argument if (clone_flags & CLONE_SETTLS). */
 SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
                void __user *, parent_tidptr, void __user *, child_tidptr,
                struct pt_regs *, regs)
index fb0b3cbeae149081a5b3011f0230fbd48f4d56dd..f18573643ed1e940c34af318e2ecf81a949be92e 100644 (file)
@@ -840,7 +840,7 @@ static int __init topology_init(void)
        for_each_online_node(i)
                register_one_node(i);
 
-       for_each_present_cpu(i)
+       for (i = 0; i < smp_height * smp_width; ++i)
                register_cpu(&cpu_devices[i], i);
 
        return 0;
index 757407e36696688d59810453b1ffca8da8522a62..1260321155f1d591b85131f44d9c72ad31122626 100644 (file)
@@ -52,7 +52,7 @@ SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss,
  */
 
 int restore_sigcontext(struct pt_regs *regs,
-                      struct sigcontext __user *sc, long *pr0)
+                      struct sigcontext __user *sc)
 {
        int err = 0;
        int i;
@@ -75,17 +75,15 @@ int restore_sigcontext(struct pt_regs *regs,
 
        regs->faultnum = INT_SWINT_1_SIGRETURN;
 
-       err |= __get_user(*pr0, &sc->gregs[0]);
        return err;
 }
 
-/* sigreturn() returns long since it restores r0 in the interrupted code. */
+/* The assembly shim for this function arranges to ignore the return value. */
 SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)
 {
        struct rt_sigframe __user *frame =
                (struct rt_sigframe __user *)(regs->sp);
        sigset_t set;
-       long r0;
 
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
@@ -98,13 +96,13 @@ SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
 
-       if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
+       if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
                goto badframe;
 
        if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)
                goto badframe;
 
-       return r0;
+       return 0;
 
 badframe:
        force_sig(SIGSEGV, current);
index 6235283b4859e031b22d5a168ef611fc0b4368c8..cc3d9badf03057d2a2ec38d74b6b6bf57c24d592 100644 (file)
 
 void *memchr(const void *s, int c, size_t n)
 {
+       const uint32_t *last_word_ptr;
+       const uint32_t *p;
+       const char *last_byte_ptr;
+       uintptr_t s_int;
+       uint32_t goal, before_mask, v, bits;
+       char *ret;
+
+       if (__builtin_expect(n == 0, 0)) {
+               /* Don't dereference any memory if the array is empty. */
+               return NULL;
+       }
+
        /* Get an aligned pointer. */
-       const uintptr_t s_int = (uintptr_t) s;
-       const uint32_t *p = (const uint32_t *)(s_int & -4);
+       s_int = (uintptr_t) s;
+       p = (const uint32_t *)(s_int & -4);
 
        /* Create four copies of the byte for which we are looking. */
-       const uint32_t goal = 0x01010101 * (uint8_t) c;
+       goal = 0x01010101 * (uint8_t) c;
 
        /* Read the first word, but munge it so that bytes before the array
         * will not match goal.
@@ -31,23 +43,14 @@ void *memchr(const void *s, int c, size_t n)
         * Note that this shift count expression works because we know
         * shift counts are taken mod 32.
         */
-       const uint32_t before_mask = (1 << (s_int << 3)) - 1;
-       uint32_t v = (*p | before_mask) ^ (goal & before_mask);
+       before_mask = (1 << (s_int << 3)) - 1;
+       v = (*p | before_mask) ^ (goal & before_mask);
 
        /* Compute the address of the last byte. */
-       const char *const last_byte_ptr = (const char *)s + n - 1;
+       last_byte_ptr = (const char *)s + n - 1;
 
        /* Compute the address of the word containing the last byte. */
-       const uint32_t *const last_word_ptr =
-           (const uint32_t *)((uintptr_t) last_byte_ptr & -4);
-
-       uint32_t bits;
-       char *ret;
-
-       if (__builtin_expect(n == 0, 0)) {
-               /* Don't dereference any memory if the array is empty. */
-               return NULL;
-       }
+       last_word_ptr = (const uint32_t *)((uintptr_t) last_byte_ptr & -4);
 
        while ((bits = __insn_seqb(v, goal)) == 0) {
                if (__builtin_expect(p == last_word_ptr, 0)) {
index 485e24d62c6bfd5658727d3873ab488e27732d8d..5cd1c4004ecaee49ce19cd55782b8161cf2c5ffc 100644 (file)
@@ -167,23 +167,30 @@ void arch_write_lock_slow(arch_rwlock_t *rwlock, u32 val)
         * when we compare them.
         */
        u32 my_ticket_;
+       u32 iterations = 0;
 
-       /* Take out the next ticket; this will also stop would-be readers. */
-       if (val & 1)
-               val = get_rwlock(rwlock);
-       rwlock->lock = __insn_addb(val, 1 << WR_NEXT_SHIFT);
+       /*
+        * Wait until there are no readers, then bump up the next
+        * field and capture the ticket value.
+        */
+       for (;;) {
+               if (!(val & 1)) {
+                       if ((val >> RD_COUNT_SHIFT) == 0)
+                               break;
+                       rwlock->lock = val;
+               }
+               delay_backoff(iterations++);
+               val = __insn_tns((int *)&rwlock->lock);
+       }
 
-       /* Extract my ticket value from the original word. */
+       /* Take out the next ticket and extract my ticket value. */
+       rwlock->lock = __insn_addb(val, 1 << WR_NEXT_SHIFT);
        my_ticket_ = val >> WR_NEXT_SHIFT;
 
-       /*
-        * Wait until the "current" field matches our ticket, and
-        * there are no remaining readers.
-        */
+       /* Wait until the "current" field matches our ticket. */
        for (;;) {
                u32 curr_ = val >> WR_CURR_SHIFT;
-               u32 readers = val >> RD_COUNT_SHIFT;
-               u32 delta = ((my_ticket_ - curr_) & WR_MASK) + !!readers;
+               u32 delta = ((my_ticket_ - curr_) & WR_MASK);
                if (likely(delta == 0))
                        break;
 
index 7f7338c90784e01489be21b91e269ce85d757d21..1664cce7b0ac5774313ed2805b58f6cac8058279 100644 (file)
@@ -727,6 +727,9 @@ struct winch {
 
 static void free_winch(struct winch *winch, int free_irq_ok)
 {
+       if (free_irq_ok)
+               free_irq(WINCH_IRQ, winch);
+
        list_del(&winch->list);
 
        if (winch->pid != -1)
@@ -735,8 +738,6 @@ static void free_winch(struct winch *winch, int free_irq_ok)
                os_close_file(winch->fd);
        if (winch->stack != 0)
                free_stack(winch->stack, 0);
-       if (free_irq_ok)
-               free_irq(WINCH_IRQ, winch);
        kfree(winch);
 }
 
index e8327686d3c55d86adb19b3c9c83bc9869e5c3cf..e330da21b84f0636751b7e18e921ecff9cc31f55 100644 (file)
@@ -21,7 +21,7 @@ config X86
        select HAVE_UNSTABLE_SCHED_CLOCK
        select HAVE_IDE
        select HAVE_OPROFILE
-       select HAVE_PERF_EVENTS if (!M386 && !M486)
+       select HAVE_PERF_EVENTS
        select HAVE_IRQ_WORK
        select HAVE_IOREMAP_PROT
        select HAVE_KPROBES
index 23f315c9f21560a10f4202676e75e4181a9c7f4a..325c05294fc40dfc662a52187eba92516e568e94 100644 (file)
@@ -355,7 +355,7 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
        if (heap > 0x3fffffffffffUL)
                error("Destination address too large");
 #else
-       if (heap > ((-__PAGE_OFFSET-(512<<20)-1) & 0x7fffffff))
+       if (heap > ((-__PAGE_OFFSET-(128<<20)-1) & 0x7fffffff))
                error("Destination address too large");
 #endif
 #ifndef CONFIG_RELOCATABLE
index cbcc8d8ea93a9144471fede4aeca15bdb4780203..7a6e68e4f748fc2db4af59f42d4c1caad9460060 100644 (file)
@@ -10,6 +10,7 @@
  * by the Free Software Foundation.
  */
 
+#include <linux/err.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
index 5be1542fbfaf73bfccd03a101e94a1cca47d36b0..e99d55d74df5023d72b763ca244c9d17bbd1dd53 100644 (file)
@@ -72,6 +72,9 @@ struct e820map {
 #define BIOS_BEGIN             0x000a0000
 #define BIOS_END               0x00100000
 
+#define BIOS_ROM_BASE          0xffe00000
+#define BIOS_ROM_END           0xffffffff
+
 #ifdef __KERNEL__
 /* see comment in arch/x86/kernel/e820.c */
 extern struct e820map e820;
index 4d293dced62f4c178cd19e6cb2eae882678afb33..9479a037419fe1358a96cece0d877a269c71e365 100644 (file)
@@ -216,8 +216,8 @@ static inline unsigned long virt_to_fix(const unsigned long vaddr)
 }
 
 /* Return an pointer with offset calculated */
-static inline unsigned long __set_fixmap_offset(enum fixed_addresses idx,
-                               phys_addr_t phys, pgprot_t flags)
+static __always_inline unsigned long
+__set_fixmap_offset(enum fixed_addresses idx, phys_addr_t phys, pgprot_t flags)
 {
        __set_fixmap(idx, phys, flags);
        return fix_to_virt(idx) + (phys & (PAGE_SIZE - 1));
index 9e6fe391094e545eb41b9fa295df93a827c1fa30..f702f82aa1ebf5df3905ca32ac9326be76c03b91 100644 (file)
@@ -79,7 +79,7 @@
 #define KVM_NUM_MMU_PAGES (1 << KVM_MMU_HASH_SHIFT)
 #define KVM_MIN_FREE_MMU_PAGES 5
 #define KVM_REFILL_PAGES 25
-#define KVM_MAX_CPUID_ENTRIES 40
+#define KVM_MAX_CPUID_ENTRIES 80
 #define KVM_NR_FIXED_MTRR_REGION 88
 #define KVM_NR_VAR_MTRR 8
 
index 3ea3dc4870474bdbbb7d0a14e1c43e52c428ddd4..6b89f5e860214266d7270160f739e9a9be290802 100644 (file)
 #define FAM10H_MMIO_CONF_ENABLE                (1<<0)
 #define FAM10H_MMIO_CONF_BUSRANGE_MASK 0xf
 #define FAM10H_MMIO_CONF_BUSRANGE_SHIFT 2
-#define FAM10H_MMIO_CONF_BASE_MASK     0xfffffff
+#define FAM10H_MMIO_CONF_BASE_MASK     0xfffffffULL
 #define FAM10H_MMIO_CONF_BASE_SHIFT    20
 #define MSR_FAM10H_NODE_ID             0xc001100c
 
index 18e3b8a8709f9def52af32b8f27b05afbdd7a4ae..ef9975812c77f0702cc9fb2a1fb616b9cb1b8053 100644 (file)
@@ -824,27 +824,27 @@ static __always_inline void arch_spin_unlock(struct arch_spinlock *lock)
 #define __PV_IS_CALLEE_SAVE(func)                      \
        ((struct paravirt_callee_save) { func })
 
-static inline unsigned long arch_local_save_flags(void)
+static inline notrace unsigned long arch_local_save_flags(void)
 {
        return PVOP_CALLEE0(unsigned long, pv_irq_ops.save_fl);
 }
 
-static inline void arch_local_irq_restore(unsigned long f)
+static inline notrace void arch_local_irq_restore(unsigned long f)
 {
        PVOP_VCALLEE1(pv_irq_ops.restore_fl, f);
 }
 
-static inline void arch_local_irq_disable(void)
+static inline notrace void arch_local_irq_disable(void)
 {
        PVOP_VCALLEE0(pv_irq_ops.irq_disable);
 }
 
-static inline void arch_local_irq_enable(void)
+static inline notrace void arch_local_irq_enable(void)
 {
        PVOP_VCALLEE0(pv_irq_ops.irq_enable);
 }
 
-static inline unsigned long arch_local_irq_save(void)
+static inline notrace unsigned long arch_local_irq_save(void)
 {
        unsigned long f;
 
index 7f7e577a0e39cfca111c5a0b4718480b01c86170..31d84acc15125646018914b51a758821ec796590 100644 (file)
@@ -11,6 +11,7 @@ unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src);
 void pvclock_read_wallclock(struct pvclock_wall_clock *wall,
                            struct pvclock_vcpu_time_info *vcpu,
                            struct timespec *ts);
+void pvclock_resume(void);
 
 /*
  * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction,
index e969f691cbfde23c6ffd53a540d0e3841084255d..a501741c2335a854fa43d14f73761d8bf8f9c82e 100644 (file)
@@ -199,6 +199,8 @@ union uvh_apicid {
 #define UVH_APICID             0x002D0E00L
 #define UV_APIC_PNODE_SHIFT    6
 
+#define UV_APICID_HIBIT_MASK   0xffff0000
+
 /* Local Bus from cpu's perspective */
 #define LOCAL_BUS_BASE         0x1c00000
 #define LOCAL_BUS_SIZE         (4 * 1024 * 1024)
@@ -491,8 +493,10 @@ static inline void uv_set_cpu_scir_bits(int cpu, unsigned char value)
        }
 }
 
+extern unsigned int uv_apicid_hibits;
 static unsigned long uv_hub_ipi_value(int apicid, int vector, int mode)
 {
+       apicid |= uv_apicid_hibits;
        return (1UL << UVH_IPI_INT_SEND_SHFT) |
                        ((apicid) << UVH_IPI_INT_APIC_ID_SHFT) |
                        (mode << UVH_IPI_INT_DELIVERY_MODE_SHFT) |
index 6d90adf4428a03d90d183dcd1a77cb2b630fc8e2..20cafeac7455594d73a3bc6837da0a34fcdee3eb 100644 (file)
@@ -5,7 +5,7 @@
  *
  * SGI UV MMR definitions
  *
- * Copyright (C) 2007-2008 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2007-2010 Silicon Graphics, Inc. All rights reserved.
  */
 
 #ifndef _ASM_X86_UV_UV_MMRS_H
@@ -753,6 +753,23 @@ union uvh_lb_bau_sb_descriptor_base_u {
     } s;
 };
 
+/* ========================================================================= */
+/*                   UVH_LB_TARGET_PHYSICAL_APIC_ID_MASK                     */
+/* ========================================================================= */
+#define UVH_LB_TARGET_PHYSICAL_APIC_ID_MASK 0x320130UL
+#define UVH_LB_TARGET_PHYSICAL_APIC_ID_MASK_32 0x009f0
+
+#define UVH_LB_TARGET_PHYSICAL_APIC_ID_MASK_BIT_ENABLES_SHFT 0
+#define UVH_LB_TARGET_PHYSICAL_APIC_ID_MASK_BIT_ENABLES_MASK 0x00000000ffffffffUL
+
+union uvh_lb_target_physical_apic_id_mask_u {
+       unsigned long v;
+       struct uvh_lb_target_physical_apic_id_mask_s {
+               unsigned long bit_enables : 32;  /* RW */
+               unsigned long rsvd_32_63  : 32;  /*    */
+       } s;
+};
+
 /* ========================================================================= */
 /*                               UVH_NODE_ID                                 */
 /* ========================================================================= */
index e8506c1f0c55115e8282ef5b8177b824f88df282..1c10c88ee4e1a5154168b4b35a6ba34857687fc9 100644 (file)
@@ -61,9 +61,9 @@ DEFINE_GUEST_HANDLE(void);
 #define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START)
 #endif
 
-#ifndef machine_to_phys_mapping
-#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
-#endif
+#define MACH2PHYS_VIRT_START  mk_unsigned_long(__MACH2PHYS_VIRT_START)
+#define MACH2PHYS_VIRT_END    mk_unsigned_long(__MACH2PHYS_VIRT_END)
+#define MACH2PHYS_NR_ENTRIES  ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>__MACH2PHYS_SHIFT)
 
 /* Maximum number of virtual CPUs in multi-processor guests. */
 #define MAX_VIRT_CPUS 32
index 42a7e004ae5ca5372553fec8a9059378ab6a55c4..8413688b2571d760f77d918713b758345bdece0a 100644 (file)
 /* And the trap vector is... */
 #define TRAP_INSTR "int $0x82"
 
+#define __MACH2PHYS_VIRT_START 0xF5800000
+#define __MACH2PHYS_VIRT_END   0xF6800000
+
+#define __MACH2PHYS_SHIFT      2
+
 /*
  * Virtual addresses beyond this are not modifiable by guest OSes. The
  * machine->physical mapping table starts at this address, read-only.
index 100d2662b97c3c8a821fc6039e93a06b7a2924c7..839a4811cf983630faa5b724277aafacfefe36cb 100644 (file)
 #define __HYPERVISOR_VIRT_END   0xFFFF880000000000
 #define __MACH2PHYS_VIRT_START  0xFFFF800000000000
 #define __MACH2PHYS_VIRT_END    0xFFFF804000000000
-
-#ifndef HYPERVISOR_VIRT_START
-#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START)
-#define HYPERVISOR_VIRT_END   mk_unsigned_long(__HYPERVISOR_VIRT_END)
-#endif
-
-#define MACH2PHYS_VIRT_START  mk_unsigned_long(__MACH2PHYS_VIRT_START)
-#define MACH2PHYS_VIRT_END    mk_unsigned_long(__MACH2PHYS_VIRT_END)
-#define MACH2PHYS_NR_ENTRIES  ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>3)
-#ifndef machine_to_phys_mapping
-#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
-#endif
+#define __MACH2PHYS_SHIFT       3
 
 /*
  * int HYPERVISOR_set_segment_base(unsigned int which, unsigned long base)
index dd8c1414b3d57540d374fee9d923947aaa57ceb1..8760cc60a21c8af5bcc7be1993bdf0b67c0eeb06 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <linux/pfn.h>
+#include <linux/mm.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -35,6 +36,8 @@ typedef struct xpaddr {
 #define MAX_DOMAIN_PAGES                                               \
     ((unsigned long)((u64)CONFIG_XEN_MAX_DOMAIN_MEMORY * 1024 * 1024 * 1024 / PAGE_SIZE))
 
+extern unsigned long *machine_to_phys_mapping;
+extern unsigned int   machine_to_phys_order;
 
 extern unsigned long get_phys_to_machine(unsigned long pfn);
 extern bool set_phys_to_machine(unsigned long pfn, unsigned long mfn);
@@ -69,10 +72,8 @@ static inline unsigned long mfn_to_pfn(unsigned long mfn)
        if (xen_feature(XENFEAT_auto_translated_physmap))
                return mfn;
 
-#if 0
        if (unlikely((mfn >> machine_to_phys_order) != 0))
-               return max_mapnr;
-#endif
+               return ~0;
 
        pfn = 0;
        /*
index 9e13763b609242e0c5429a364be461a7e8fc2594..1e994754d323f400b85c5d1d7350c6e52a702ff9 100644 (file)
@@ -45,6 +45,7 @@ obj-y                 += pci-dma.o quirks.o i8237.o topology.o kdebugfs.o
 obj-y                  += alternative.o i8253.o pci-nommu.o hw_breakpoint.o
 obj-y                  += tsc.o io_delay.o rtc.o
 obj-y                  += pci-iommu_table.o
+obj-y                  += resource.o
 
 obj-$(CONFIG_X86_TRAMPOLINE)   += trampoline.o
 obj-y                          += process.o
index 3f838d537392b4ddb6d061e82bbf1ce8a2a3b9d2..78218135b48e6169d155fb4a097e5b6c8e30e53a 100644 (file)
@@ -1389,6 +1389,14 @@ void __cpuinit end_local_APIC_setup(void)
 
        setup_apic_nmi_watchdog(NULL);
        apic_pm_activate();
+
+       /*
+        * Now that local APIC setup is completed for BP, configure the fault
+        * handling for interrupt remapping.
+        */
+       if (!smp_processor_id() && intr_remapping_enabled)
+               enable_drhd_fault_handling();
+
 }
 
 #ifdef CONFIG_X86_X2APIC
index cefd6942f0e9198e260559c436f443e861ffb011..62f6e1e55b90d7f9a2bc460e73ba8895da23c4ff 100644 (file)
 #include <linux/nmi.h>
 #include <linux/module.h>
 
-/* For reliability, we're prepared to waste bits here. */
-static DECLARE_BITMAP(backtrace_mask, NR_CPUS) __read_mostly;
-
 u64 hw_nmi_get_sample_period(void)
 {
        return (u64)(cpu_khz) * 1000 * 60;
 }
 
 #ifdef ARCH_HAS_NMI_WATCHDOG
+
+/* For reliability, we're prepared to waste bits here. */
+static DECLARE_BITMAP(backtrace_mask, NR_CPUS) __read_mostly;
+
 void arch_trigger_all_cpu_backtrace(void)
 {
        int i;
index 7cc0a721f628c302d0d420ba0bf3af1945d5a1c0..fadcd743a74f8bdcd5effbaf7e28b01ea3003532 100644 (file)
@@ -2430,13 +2430,12 @@ static void ack_apic_level(struct irq_data *data)
 {
        struct irq_cfg *cfg = data->chip_data;
        int i, do_unmask_irq = 0, irq = data->irq;
-       struct irq_desc *desc = irq_to_desc(irq);
        unsigned long v;
 
        irq_complete_move(cfg);
 #ifdef CONFIG_GENERIC_PENDING_IRQ
        /* If we are moving the irq we need to mask it */
-       if (unlikely(desc->status & IRQ_MOVE_PENDING)) {
+       if (unlikely(irq_to_desc(irq)->status & IRQ_MOVE_PENDING)) {
                do_unmask_irq = 1;
                mask_ioapic(cfg);
        }
@@ -3413,6 +3412,7 @@ dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
        msg.data |= MSI_DATA_VECTOR(cfg->vector);
        msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
        msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+       msg.address_hi = MSI_ADDR_BASE_HI | MSI_ADDR_EXT_DEST_ID(dest);
 
        dmar_msi_write(irq, &msg);
 
index f9e4e6a54073e3d901d0475da9c5deceb21d55d8..d8c4a6feb2862f3a967f7eb4dcc4f503f2dac2f8 100644 (file)
@@ -79,13 +79,6 @@ void __init default_setup_apic_routing(void)
                /* need to update phys_pkg_id */
                apic->phys_pkg_id = apicid_phys_pkg_id;
        }
-
-       /*
-        * Now that apic routing model is selected, configure the
-        * fault handling for intr remapping.
-        */
-       if (intr_remapping_enabled)
-               enable_drhd_fault_handling();
 }
 
 /* Same for both flat and physical. */
index 194539aea1757d79058e3ec17acbeaa68ae6432f..c1c52c341f40a607be5b252746db31f36b8dc561 100644 (file)
@@ -44,6 +44,8 @@ static u64 gru_start_paddr, gru_end_paddr;
 static union uvh_apicid uvh_apicid;
 int uv_min_hub_revision_id;
 EXPORT_SYMBOL_GPL(uv_min_hub_revision_id);
+unsigned int uv_apicid_hibits;
+EXPORT_SYMBOL_GPL(uv_apicid_hibits);
 static DEFINE_SPINLOCK(uv_nmi_lock);
 
 static inline bool is_GRU_range(u64 start, u64 end)
@@ -85,6 +87,23 @@ static void __init early_get_apic_pnode_shift(void)
                uvh_apicid.s.pnode_shift = UV_APIC_PNODE_SHIFT;
 }
 
+/*
+ * Add an extra bit as dictated by bios to the destination apicid of
+ * interrupts potentially passing through the UV HUB.  This prevents
+ * a deadlock between interrupts and IO port operations.
+ */
+static void __init uv_set_apicid_hibit(void)
+{
+       union uvh_lb_target_physical_apic_id_mask_u apicid_mask;
+       unsigned long *mmr;
+
+       mmr = early_ioremap(UV_LOCAL_MMR_BASE |
+               UVH_LB_TARGET_PHYSICAL_APIC_ID_MASK, sizeof(*mmr));
+       apicid_mask.v = *mmr;
+       early_iounmap(mmr, sizeof(*mmr));
+       uv_apicid_hibits = apicid_mask.s.bit_enables & UV_APICID_HIBIT_MASK;
+}
+
 static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 {
        int nodeid;
@@ -102,6 +121,7 @@ static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
                        __get_cpu_var(x2apic_extra_bits) =
                                nodeid << (uvh_apicid.s.pnode_shift - 1);
                        uv_system_type = UV_NON_UNIQUE_APIC;
+                       uv_set_apicid_hibit();
                        return 1;
                }
        }
@@ -155,6 +175,7 @@ static int __cpuinit uv_wakeup_secondary(int phys_apicid, unsigned long start_ri
        int pnode;
 
        pnode = uv_apicid_to_pnode(phys_apicid);
+       phys_apicid |= uv_apicid_hibits;
        val = (1UL << UVH_IPI_INT_SEND_SHFT) |
            (phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) |
            ((start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) |
@@ -236,7 +257,7 @@ static unsigned int uv_cpu_mask_to_apicid(const struct cpumask *cpumask)
        int cpu = cpumask_first(cpumask);
 
        if ((unsigned)cpu < nr_cpu_ids)
-               return per_cpu(x86_cpu_to_apicid, cpu);
+               return per_cpu(x86_cpu_to_apicid, cpu) | uv_apicid_hibits;
        else
                return BAD_APICID;
 }
@@ -255,7 +276,7 @@ uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
                if (cpumask_test_cpu(cpu, cpu_online_mask))
                        break;
        }
-       return per_cpu(x86_cpu_to_apicid, cpu);
+       return per_cpu(x86_cpu_to_apicid, cpu) | uv_apicid_hibits;
 }
 
 static unsigned int x2apic_get_apic_id(unsigned long x)
index ed6310183efb4337de7489362b350f81031ca2c8..6d75b9145b13f0e68a106acd76b0d458c827d099 100644 (file)
@@ -381,6 +381,20 @@ static void release_pmc_hardware(void) {}
 
 #endif
 
+static bool check_hw_exists(void)
+{
+       u64 val, val_new = 0;
+       int ret = 0;
+
+       val = 0xabcdUL;
+       ret |= checking_wrmsrl(x86_pmu.perfctr, val);
+       ret |= rdmsrl_safe(x86_pmu.perfctr, &val_new);
+       if (ret || val != val_new)
+               return false;
+
+       return true;
+}
+
 static void reserve_ds_buffers(void);
 static void release_ds_buffers(void);
 
@@ -1372,6 +1386,12 @@ void __init init_hw_perf_events(void)
 
        pmu_check_apic();
 
+       /* sanity check that the hardware exists or is emulated */
+       if (!check_hw_exists()) {
+               pr_cont("Broken PMU hardware detected, software events only.\n");
+               return;
+       }
+
        pr_cont("%s PMU driver.\n", x86_pmu.name);
 
        if (x86_pmu.quirks)
index 59e175e89599c96462707f8fe368a86405e9bce4..591e60104278e41445fd7069e5f05d8cc5680a07 100644 (file)
@@ -395,7 +395,7 @@ sysenter_past_esp:
         * A tiny bit of offset fixup is necessary - 4*4 means the 4 words
         * pushed above; +8 corresponds to copy_thread's esp0 setting.
         */
-       pushl_cfi (TI_sysenter_return-THREAD_SIZE_asm+8+4*4)(%esp)
+       pushl_cfi ((TI_sysenter_return)-THREAD_SIZE_asm+8+4*4)(%esp)
        CFI_REL_OFFSET eip, 0
 
        pushl_cfi %eax
index fe2690d71c0c9f1d27be243f2ca12183a6705357..e3ba417e869766bb258ef489aa389f4933abf2a3 100644 (file)
@@ -295,6 +295,7 @@ ENDPROC(native_usergs_sysret64)
        .endm
 
 /* save partial stack frame */
+       .pushsection .kprobes.text, "ax"
 ENTRY(save_args)
        XCPT_FRAME
        cld
@@ -334,6 +335,7 @@ ENTRY(save_args)
        ret
        CFI_ENDPROC
 END(save_args)
+       .popsection
 
 ENTRY(save_rest)
        PARTIAL_FRAME 1 REST_SKIP+8
index bcece91dd3116a14fa58af5c5216dbce20daa3e5..c0dbd9ac24f0d5cf7e87f8f0439275656b877f73 100644 (file)
 #define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD)
 #endif
 
+/* Number of possible pages in the lowmem region */
+LOWMEM_PAGES = (((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT)
+       
 /* Enough space to fit pagetables for the low memory linear map */
-MAPPING_BEYOND_END = \
-       PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT
+MAPPING_BEYOND_END = PAGE_TABLE_SIZE(LOWMEM_PAGES) << PAGE_SHIFT
 
 /*
  * Worst-case size of the kernel mapping we need to make:
- * the worst-case size of the kernel itself, plus the extra we need
- * to map for the linear map.
+ * a relocatable kernel can live anywhere in lowmem, so we need to be able
+ * to map all of lowmem.
  */
-KERNEL_PAGES = (KERNEL_IMAGE_SIZE + MAPPING_BEYOND_END)>>PAGE_SHIFT
+KERNEL_PAGES = LOWMEM_PAGES
 
 INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE_asm
 RESERVE_BRK(pagetables, INIT_MAP_SIZE)
@@ -620,13 +622,13 @@ ENTRY(initial_code)
 __PAGE_ALIGNED_BSS
        .align PAGE_SIZE_asm
 #ifdef CONFIG_X86_PAE
-initial_pg_pmd:
+ENTRY(initial_pg_pmd)
        .fill 1024*KPMDS,4,0
 #else
 ENTRY(initial_page_table)
        .fill 1024,4,0
 #endif
-initial_pg_fixmap:
+ENTRY(initial_pg_fixmap)
        .fill 1024,4,0
 ENTRY(empty_zero_page)
        .fill 4096,1,0
index ae03cab4352e8535946a835787c83e5c8563079b..4ff5968f12d295ac00a55ecbbae06dd97675a6c9 100644 (file)
@@ -27,6 +27,9 @@
 #define HPET_DEV_FSB_CAP               0x1000
 #define HPET_DEV_PERI_CAP              0x2000
 
+#define HPET_MIN_CYCLES                        128
+#define HPET_MIN_PROG_DELTA            (HPET_MIN_CYCLES + (HPET_MIN_CYCLES >> 1))
+
 #define EVT_TO_HPET_DEV(evt) container_of(evt, struct hpet_dev, evt)
 
 /*
@@ -299,8 +302,9 @@ static void hpet_legacy_clockevent_register(void)
        /* Calculate the min / max delta */
        hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
                                                           &hpet_clockevent);
-       /* 5 usec minimum reprogramming delta. */
-       hpet_clockevent.min_delta_ns = 5000;
+       /* Setup minimum reprogramming delta. */
+       hpet_clockevent.min_delta_ns = clockevent_delta2ns(HPET_MIN_PROG_DELTA,
+                                                          &hpet_clockevent);
 
        /*
         * Start hpet with the boot cpu mask and make it
@@ -393,22 +397,24 @@ static int hpet_next_event(unsigned long delta,
         * the wraparound into account) nor a simple count down event
         * mode. Further the write to the comparator register is
         * delayed internally up to two HPET clock cycles in certain
-        * chipsets (ATI, ICH9,10). We worked around that by reading
-        * back the compare register, but that required another
-        * workaround for ICH9,10 chips where the first readout after
-        * write can return the old stale value. We already have a
-        * minimum delta of 5us enforced, but a NMI or SMI hitting
+        * chipsets (ATI, ICH9,10). Some newer AMD chipsets have even
+        * longer delays. We worked around that by reading back the
+        * compare register, but that required another workaround for
+        * ICH9,10 chips where the first readout after write can
+        * return the old stale value. We already had a minimum
+        * programming delta of 5us enforced, but a NMI or SMI hitting
         * between the counter readout and the comparator write can
         * move us behind that point easily. Now instead of reading
         * the compare register back several times, we make the ETIME
         * decision based on the following: Return ETIME if the
-        * counter value after the write is less than 8 HPET cycles
+        * counter value after the write is less than HPET_MIN_CYCLES
         * away from the event or if the counter is already ahead of
-        * the event.
+        * the event. The minimum programming delta for the generic
+        * clockevents code is set to 1.5 * HPET_MIN_CYCLES.
         */
        res = (s32)(cnt - hpet_readl(HPET_COUNTER));
 
-       return res < 8 ? -ETIME : 0;
+       return res < HPET_MIN_CYCLES ? -ETIME : 0;
 }
 
 static void hpet_legacy_set_mode(enum clock_event_mode mode,
index ff15c9dcc25de8be8144fd4d15f1dfd3069314e4..42c59425450727284615b2a920611e21047ce715 100644 (file)
@@ -433,6 +433,10 @@ static int __kprobes hw_breakpoint_handler(struct die_args *args)
        dr6_p = (unsigned long *)ERR_PTR(args->err);
        dr6 = *dr6_p;
 
+       /* If it's a single step, TRAP bits are random */
+       if (dr6 & DR_STEP)
+               return NOTIFY_DONE;
+
        /* Do an early return if no trap bits are set in DR6 */
        if ((dr6 & DR_TRAP_BITS) == 0)
                return NOTIFY_DONE;
index ec592caac4b4e11b5d7ac0bc2986d6617ac4b90b..cd21b654dec6c70382b68ab29f4364ab60ff4e88 100644 (file)
@@ -315,14 +315,18 @@ static void kgdb_remove_all_hw_break(void)
                if (!breakinfo[i].enabled)
                        continue;
                bp = *per_cpu_ptr(breakinfo[i].pev, cpu);
-               if (bp->attr.disabled == 1)
+               if (!bp->attr.disabled) {
+                       arch_uninstall_hw_breakpoint(bp);
+                       bp->attr.disabled = 1;
                        continue;
+               }
                if (dbg_is_early)
                        early_dr7 &= ~encode_dr7(i, breakinfo[i].len,
                                                 breakinfo[i].type);
-               else
-                       arch_uninstall_hw_breakpoint(bp);
-               bp->attr.disabled = 1;
+               else if (hw_break_release_slot(i))
+                       printk(KERN_ERR "KGDB: hw bpt remove failed %lx\n",
+                              breakinfo[i].addr);
+               breakinfo[i].enabled = 0;
        }
 }
 
index 6da143c2a6b8b27f03a611bad88047879c80f3bf..ac861b8348e2d9dd3f863dece898a2974d7bff51 100644 (file)
@@ -25,7 +25,6 @@ struct pci_hostbridge_probe {
 };
 
 static u64 __cpuinitdata fam10h_pci_mmconf_base;
-static int __cpuinitdata fam10h_pci_mmconf_base_status;
 
 static struct pci_hostbridge_probe pci_probes[] __cpuinitdata = {
        { 0, 0x18, PCI_VENDOR_ID_AMD, 0x1200 },
@@ -44,10 +43,12 @@ static int __cpuinit cmp_range(const void *x1, const void *x2)
        return start1 - start2;
 }
 
-/*[47:0] */
-/* need to avoid (0xfd<<32) and (0xfe<<32), ht used space */
+#define MMCONF_UNIT (1ULL << FAM10H_MMIO_CONF_BASE_SHIFT)
+#define MMCONF_MASK (~(MMCONF_UNIT - 1))
+#define MMCONF_SIZE (MMCONF_UNIT << 8)
+/* need to avoid (0xfd<<32), (0xfe<<32), and (0xff<<32), ht used space */
 #define FAM10H_PCI_MMCONF_BASE (0xfcULL<<32)
-#define BASE_VALID(b) ((b != (0xfdULL << 32)) && (b != (0xfeULL << 32)))
+#define BASE_VALID(b) ((b) + MMCONF_SIZE <= (0xfdULL<<32) || (b) >= (1ULL<<40))
 static void __cpuinit get_fam10h_pci_mmconf_base(void)
 {
        int i;
@@ -64,12 +65,11 @@ static void __cpuinit get_fam10h_pci_mmconf_base(void)
        struct range range[8];
 
        /* only try to get setting from BSP */
-       /* -1 or 1 */
-       if (fam10h_pci_mmconf_base_status)
+       if (fam10h_pci_mmconf_base)
                return;
 
        if (!early_pci_allowed())
-               goto fail;
+               return;
 
        found = 0;
        for (i = 0; i < ARRAY_SIZE(pci_probes); i++) {
@@ -91,7 +91,7 @@ static void __cpuinit get_fam10h_pci_mmconf_base(void)
        }
 
        if (!found)
-               goto fail;
+               return;
 
        /* SYS_CFG */
        address = MSR_K8_SYSCFG;
@@ -99,16 +99,16 @@ static void __cpuinit get_fam10h_pci_mmconf_base(void)
 
        /* TOP_MEM2 is not enabled? */
        if (!(val & (1<<21))) {
-               tom2 = 0;
+               tom2 = 1ULL << 32;
        } else {
                /* TOP_MEM2 */
                address = MSR_K8_TOP_MEM2;
                rdmsrl(address, val);
-               tom2 = val & (0xffffULL<<32);
+               tom2 = max(val & 0xffffff800000ULL, 1ULL << 32);
        }
 
        if (base <= tom2)
-               base = tom2 + (1ULL<<32);
+               base = (tom2 + 2 * MMCONF_UNIT - 1) & MMCONF_MASK;
 
        /*
         * need to check if the range is in the high mmio range that is
@@ -123,11 +123,11 @@ static void __cpuinit get_fam10h_pci_mmconf_base(void)
                if (!(reg & 3))
                        continue;
 
-               start = (((u64)reg) << 8) & (0xffULL << 32); /* 39:16 on 31:8*/
+               start = (u64)(reg & 0xffffff00) << 8; /* 39:16 on 31:8*/
                reg = read_pci_config(bus, slot, 1, 0x84 + (i << 3));
-               end = (((u64)reg) << 8) & (0xffULL << 32); /* 39:16 on 31:8*/
+               end = ((u64)(reg & 0xffffff00) << 8) | 0xffff; /* 39:16 on 31:8*/
 
-               if (!end)
+               if (end < tom2)
                        continue;
 
                range[hi_mmio_num].start = start;
@@ -143,32 +143,27 @@ static void __cpuinit get_fam10h_pci_mmconf_base(void)
 
        if (range[hi_mmio_num - 1].end < base)
                goto out;
-       if (range[0].start > base)
+       if (range[0].start > base + MMCONF_SIZE)
                goto out;
 
        /* need to find one window */
-       base = range[0].start - (1ULL << 32);
+       base = (range[0].start & MMCONF_MASK) - MMCONF_UNIT;
        if ((base > tom2) && BASE_VALID(base))
                goto out;
-       base = range[hi_mmio_num - 1].end + (1ULL << 32);
-       if ((base > tom2) && BASE_VALID(base))
+       base = (range[hi_mmio_num - 1].end + MMCONF_UNIT) & MMCONF_MASK;
+       if (BASE_VALID(base))
                goto out;
        /* need to find window between ranges */
-       if (hi_mmio_num > 1)
-       for (i = 0; i < hi_mmio_num - 1; i++) {
-               if (range[i + 1].start > (range[i].end + (1ULL << 32))) {
-                       base = range[i].end + (1ULL << 32);
-                       if ((base > tom2) && BASE_VALID(base))
-                               goto out;
-               }
+       for (i = 1; i < hi_mmio_num; i++) {
+               base = (range[i - 1].end + MMCONF_UNIT) & MMCONF_MASK;
+               val = range[i].start & MMCONF_MASK;
+               if (val >= base + MMCONF_SIZE && BASE_VALID(base))
+                       goto out;
        }
-
-fail:
-       fam10h_pci_mmconf_base_status = -1;
        return;
+
 out:
        fam10h_pci_mmconf_base = base;
-       fam10h_pci_mmconf_base_status = 1;
 }
 
 void __cpuinit fam10h_check_enable_mmcfg(void)
@@ -190,11 +185,10 @@ void __cpuinit fam10h_check_enable_mmcfg(void)
 
                /* only trust the one handle 256 buses, if acpi=off */
                if (!acpi_pci_disabled || busnbits >= 8) {
-                       u64 base;
-                       base = val & (0xffffULL << 32);
-                       if (fam10h_pci_mmconf_base_status <= 0) {
+                       u64 base = val & MMCONF_MASK;
+
+                       if (!fam10h_pci_mmconf_base) {
                                fam10h_pci_mmconf_base = base;
-                               fam10h_pci_mmconf_base_status = 1;
                                return;
                        } else if (fam10h_pci_mmconf_base ==  base)
                                return;
@@ -206,8 +200,10 @@ void __cpuinit fam10h_check_enable_mmcfg(void)
         * with 256 buses
         */
        get_fam10h_pci_mmconf_base();
-       if (fam10h_pci_mmconf_base_status <= 0)
+       if (!fam10h_pci_mmconf_base) {
+               pci_probe &= ~PCI_CHECK_ENABLE_AMD_MMCONF;
                return;
+       }
 
        printk(KERN_INFO "Enable MMCONFIG on AMD Family 10h\n");
        val &= ~((FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT) |
index 008b91eefa188139f57f7b77de6c7aef6240ef08..42eb3300dfc6c35630aab267e051678f1a677e59 100644 (file)
@@ -83,6 +83,11 @@ unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src)
 
 static atomic64_t last_value = ATOMIC64_INIT(0);
 
+void pvclock_resume(void)
+{
+       atomic64_set(&last_value, 0);
+}
+
 cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src)
 {
        struct pvclock_shadow_time shadow;
diff --git a/arch/x86/kernel/resource.c b/arch/x86/kernel/resource.c
new file mode 100644 (file)
index 0000000..2a26819
--- /dev/null
@@ -0,0 +1,48 @@
+#include <linux/ioport.h>
+#include <asm/e820.h>
+
+static void resource_clip(struct resource *res, resource_size_t start,
+                         resource_size_t end)
+{
+       resource_size_t low = 0, high = 0;
+
+       if (res->end < start || res->start > end)
+               return;         /* no conflict */
+
+       if (res->start < start)
+               low = start - res->start;
+
+       if (res->end > end)
+               high = res->end - end;
+
+       /* Keep the area above or below the conflict, whichever is larger */
+       if (low > high)
+               res->end = start - 1;
+       else
+               res->start = end + 1;
+}
+
+static void remove_e820_regions(struct resource *avail)
+{
+       int i;
+       struct e820entry *entry;
+
+       for (i = 0; i < e820.nr_map; i++) {
+               entry = &e820.map[i];
+
+               resource_clip(avail, entry->addr,
+                             entry->addr + entry->size - 1);
+       }
+}
+
+void arch_remove_reservations(struct resource *avail)
+{
+       /* Trim out BIOS areas (low 1MB and high 2MB) and E820 regions */
+       if (avail->flags & IORESOURCE_MEM) {
+               if (avail->start < BIOS_END)
+                       avail->start = BIOS_END;
+               resource_clip(avail, BIOS_ROM_BASE, BIOS_ROM_END);
+
+               remove_e820_regions(avail);
+       }
+}
index 21c6746338afef0949e89f8b2c0442654401546e..85268f8eadf667c6034c06882ed661cb7d03e4a8 100644 (file)
@@ -769,7 +769,6 @@ void __init setup_arch(char **cmdline_p)
 
        x86_init.oem.arch_setup();
 
-       resource_alloc_from_bottom = 0;
        iomem_resource.end = (1ULL << boot_cpu_data.x86_phys_bits) - 1;
        setup_memory_map();
        parse_setup_data();
index 9c253bd65e24ba3e803b044fca3ad57224a41c52..547128546cc3bd4644a189955c1b804f5c150770 100644 (file)
@@ -394,7 +394,8 @@ static void __init setup_xstate_init(void)
         * Setup init_xstate_buf to represent the init state of
         * all the features managed by the xsave
         */
-       init_xstate_buf = alloc_bootmem(xstate_size);
+       init_xstate_buf = alloc_bootmem_align(xstate_size,
+                                             __alignof__(struct xsave_struct));
        init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT;
 
        clts();
index 82e144a4e514249c140f5c28a8bd0df00869b5ca..b81a9b7c2ca486f3faa8d8c8314ef4e1115e69e3 100644 (file)
@@ -3395,6 +3395,7 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
        vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip;
 
        load_host_msrs(vcpu);
+       kvm_load_ldt(ldt_selector);
        loadsegment(fs, fs_selector);
 #ifdef CONFIG_X86_64
        load_gs_index(gs_selector);
@@ -3402,7 +3403,6 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
 #else
        loadsegment(gs, gs_selector);
 #endif
-       kvm_load_ldt(ldt_selector);
 
        reload_tss(vcpu);
 
@@ -3494,6 +3494,10 @@ static void svm_cpuid_update(struct kvm_vcpu *vcpu)
 static void svm_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry)
 {
        switch (func) {
+       case 0x00000001:
+               /* Mask out xsave bit as long as it is not supported by SVM */
+               entry->ecx &= ~(bit(X86_FEATURE_XSAVE));
+               break;
        case 0x80000001:
                if (nested)
                        entry->ecx |= (1 << 2); /* Set SVM bit */
index 8da0e45ff7c9cde22d424583adbb2786cf78a72a..81fcbe9515c59d7e68734d2d4c53fa23bb72624a 100644 (file)
@@ -821,10 +821,9 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu)
 #endif
 
 #ifdef CONFIG_X86_64
-       if (is_long_mode(&vmx->vcpu)) {
-               rdmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base);
+       rdmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base);
+       if (is_long_mode(&vmx->vcpu))
                wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base);
-       }
 #endif
        for (i = 0; i < vmx->save_nmsrs; ++i)
                kvm_set_shared_msr(vmx->guest_msrs[i].index,
@@ -839,23 +838,23 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx)
 
        ++vmx->vcpu.stat.host_state_reload;
        vmx->host_state.loaded = 0;
-       if (vmx->host_state.fs_reload_needed)
-               loadsegment(fs, vmx->host_state.fs_sel);
+#ifdef CONFIG_X86_64
+       if (is_long_mode(&vmx->vcpu))
+               rdmsrl(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base);
+#endif
        if (vmx->host_state.gs_ldt_reload_needed) {
                kvm_load_ldt(vmx->host_state.ldt_sel);
 #ifdef CONFIG_X86_64
                load_gs_index(vmx->host_state.gs_sel);
-               wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs);
 #else
                loadsegment(gs, vmx->host_state.gs_sel);
 #endif
        }
+       if (vmx->host_state.fs_reload_needed)
+               loadsegment(fs, vmx->host_state.fs_sel);
        reload_tss();
 #ifdef CONFIG_X86_64
-       if (is_long_mode(&vmx->vcpu)) {
-               rdmsrl(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base);
-               wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base);
-       }
+       wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base);
 #endif
        if (current_thread_info()->status & TS_USEDFPU)
                clts();
@@ -4228,11 +4227,6 @@ static int vmx_get_lpage_level(void)
                return PT_PDPE_LEVEL;
 }
 
-static inline u32 bit(int bitno)
-{
-       return 1 << (bitno & 31);
-}
-
 static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpuid_entry2 *best;
index cdac9e592aa53ee84b7e184900601ab4730354e5..b989e1f1e5d36b732d1d9c864f369b39a7459105 100644 (file)
@@ -155,11 +155,6 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
 
 u64 __read_mostly host_xcr0;
 
-static inline u32 bit(int bitno)
-{
-       return 1 << (bitno & 31);
-}
-
 static void kvm_on_user_return(struct user_return_notifier *urn)
 {
        unsigned slot;
@@ -4569,9 +4564,11 @@ static void kvm_timer_init(void)
 #ifdef CONFIG_CPU_FREQ
                struct cpufreq_policy policy;
                memset(&policy, 0, sizeof(policy));
-               cpufreq_get_policy(&policy, get_cpu());
+               cpu = get_cpu();
+               cpufreq_get_policy(&policy, cpu);
                if (policy.cpuinfo.max_freq)
                        max_tsc_khz = policy.cpuinfo.max_freq;
+               put_cpu();
 #endif
                cpufreq_register_notifier(&kvmclock_cpufreq_notifier_block,
                                          CPUFREQ_TRANSITION_NOTIFIER);
@@ -5522,6 +5519,8 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
 
        mmu_reset_needed |= kvm_read_cr4(vcpu) != sregs->cr4;
        kvm_x86_ops->set_cr4(vcpu, sregs->cr4);
+       if (sregs->cr4 & X86_CR4_OSXSAVE)
+               update_cpuid(vcpu);
        if (!is_long_mode(vcpu) && is_pae(vcpu)) {
                load_pdptrs(vcpu, vcpu->arch.walk_mmu, vcpu->arch.cr3);
                mmu_reset_needed = 1;
index 2cea414489f37caa75876e7a186e00ac93937ec1..c600da830ce0e412fa4b60365909792a9b916a4d 100644 (file)
@@ -70,6 +70,11 @@ static inline int is_paging(struct kvm_vcpu *vcpu)
        return kvm_read_cr0_bits(vcpu, X86_CR0_PG);
 }
 
+static inline u32 bit(int bitno)
+{
+       return 1 << (bitno & 31);
+}
+
 void kvm_before_handle_nmi(struct kvm_vcpu *vcpu);
 void kvm_after_handle_nmi(struct kvm_vcpu *vcpu);
 int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq);
index 73b1e1a1f4891708a8714570e36ce62b15ba6fc7..4996cf5f73a07db446c2fe3e1c9fe7070662b741 100644 (file)
@@ -531,7 +531,10 @@ static void lguest_write_cr3(unsigned long cr3)
 {
        lguest_data.pgdir = cr3;
        lazy_hcall1(LHCALL_NEW_PGTABLE, cr3);
-       cr3_changed = true;
+
+       /* These two page tables are simple, linear, and used during boot */
+       if (cr3 != __pa(swapper_pg_dir) && cr3 != __pa(initial_page_table))
+               cr3_changed = true;
 }
 
 static unsigned long lguest_read_cr3(void)
@@ -703,9 +706,9 @@ static void lguest_set_pmd(pmd_t *pmdp, pmd_t pmdval)
  * to forget all of them.  Fortunately, this is very rare.
  *
  * ... except in early boot when the kernel sets up the initial pagetables,
- * which makes booting astonishingly slow: 1.83 seconds!  So we don't even tell
- * the Host anything changed until we've done the first page table switch,
- * which brings boot back to 0.25 seconds.
+ * which makes booting astonishingly slow: 48 seconds!  So we don't even tell
+ * the Host anything changed until we've done the first real page table switch,
+ * which brings boot back to 4.3 seconds.
  */
 static void lguest_set_pte(pte_t *ptep, pte_t pteval)
 {
@@ -1002,7 +1005,7 @@ static void lguest_time_init(void)
        clockevents_register_device(&lguest_clockevent);
 
        /* Finally, we unblock the timer interrupt. */
-       enable_lguest_irq(0);
+       clear_bit(0, lguest_data.blocked_interrupts);
 }
 
 /*
@@ -1349,9 +1352,6 @@ __init void lguest_init(void)
         */
        switch_to_new_gdt(0);
 
-       /* We actually boot with all memory mapped, but let's say 128MB. */
-       max_pfn_mapped = (128*1024*1024) >> PAGE_SHIFT;
-
        /*
         * The Host<->Guest Switcher lives at the top of our address space, and
         * the Host told us how big it is when we made LGUEST_INIT hypercall:
index 4f420c2f2d5534ea4ac5af20292e25c4346c3cda..e7d5382ef26344534b0883a11d02b19a82d4a9cd 100644 (file)
@@ -4,6 +4,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/processor-flags.h>
+#include <asm/pgtable.h>
 
 /*G:020
  * Our story starts with the kernel booting into startup_32 in
@@ -37,9 +38,113 @@ ENTRY(lguest_entry)
        /* Set up the initial stack so we can run C code. */
        movl $(init_thread_union+THREAD_SIZE),%esp
 
+       call init_pagetables
+
        /* Jumps are relative: we're running __PAGE_OFFSET too low. */
        jmp lguest_init+__PAGE_OFFSET
 
+/*
+ * Initialize page tables.  This creates a PDE and a set of page
+ * tables, which are located immediately beyond __brk_base.  The variable
+ * _brk_end is set up to point to the first "safe" location.
+ * Mappings are created both at virtual address 0 (identity mapping)
+ * and PAGE_OFFSET for up to _end.
+ *
+ * FIXME: This code is taken verbatim from arch/x86/kernel/head_32.S: they
+ * don't have a stack at this point, so we can't just use call and ret.
+ */
+init_pagetables:
+#if PTRS_PER_PMD > 1
+#define PAGE_TABLE_SIZE(pages) (((pages) / PTRS_PER_PMD) + PTRS_PER_PGD)
+#else
+#define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD)
+#endif
+#define pa(X) ((X) - __PAGE_OFFSET)
+
+/* Enough space to fit pagetables for the low memory linear map */
+MAPPING_BEYOND_END = \
+       PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT
+#ifdef CONFIG_X86_PAE
+
+       /*
+        * In PAE mode initial_page_table is statically defined to contain
+        * enough entries to cover the VMSPLIT option (that is the top 1, 2 or 3
+        * entries). The identity mapping is handled by pointing two PGD entries
+        * to the first kernel PMD.
+        *
+        * Note the upper half of each PMD or PTE are always zero at this stage.
+        */
+
+#define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */
+
+       xorl %ebx,%ebx                          /* %ebx is kept at zero */
+
+       movl $pa(__brk_base), %edi
+       movl $pa(initial_pg_pmd), %edx
+       movl $PTE_IDENT_ATTR, %eax
+10:
+       leal PDE_IDENT_ATTR(%edi),%ecx          /* Create PMD entry */
+       movl %ecx,(%edx)                        /* Store PMD entry */
+                                               /* Upper half already zero */
+       addl $8,%edx
+       movl $512,%ecx
+11:
+       stosl
+       xchgl %eax,%ebx
+       stosl
+       xchgl %eax,%ebx
+       addl $0x1000,%eax
+       loop 11b
+
+       /*
+        * End condition: we must map up to the end + MAPPING_BEYOND_END.
+        */
+       movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp
+       cmpl %ebp,%eax
+       jb 10b
+1:
+       addl $__PAGE_OFFSET, %edi
+       movl %edi, pa(_brk_end)
+       shrl $12, %eax
+       movl %eax, pa(max_pfn_mapped)
+
+       /* Do early initialization of the fixmap area */
+       movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
+       movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8)
+#else  /* Not PAE */
+
+page_pde_offset = (__PAGE_OFFSET >> 20);
+
+       movl $pa(__brk_base), %edi
+       movl $pa(initial_page_table), %edx
+       movl $PTE_IDENT_ATTR, %eax
+10:
+       leal PDE_IDENT_ATTR(%edi),%ecx          /* Create PDE entry */
+       movl %ecx,(%edx)                        /* Store identity PDE entry */
+       movl %ecx,page_pde_offset(%edx)         /* Store kernel PDE entry */
+       addl $4,%edx
+       movl $1024, %ecx
+11:
+       stosl
+       addl $0x1000,%eax
+       loop 11b
+       /*
+        * End condition: we must map up to the end + MAPPING_BEYOND_END.
+        */
+       movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp
+       cmpl %ebp,%eax
+       jb 10b
+       addl $__PAGE_OFFSET, %edi
+       movl %edi, pa(_brk_end)
+       shrl $12, %eax
+       movl %eax, pa(max_pfn_mapped)
+
+       /* Do early initialization of the fixmap area */
+       movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
+       movl %eax,pa(initial_page_table+0xffc)
+#endif
+       ret
+
 /*G:055
  * We create a macro which puts the assembler code between lgstart_ and lgend_
  * markers.  These templates are put in the .text section: they can't be
index 12cdbb17ad181dfac805d60f4991ee1eacfb935c..6acc724d5d8ff759f93290a2591c84945f9e6bd2 100644 (file)
@@ -223,7 +223,7 @@ void native_flush_tlb_others(const struct cpumask *cpumask,
 
 static void __cpuinit calculate_tlb_offset(void)
 {
-       int cpu, node, nr_node_vecs;
+       int cpu, node, nr_node_vecs, idx = 0;
        /*
         * we are changing tlb_vector_offset for each CPU in runtime, but this
         * will not cause inconsistency, as the write is atomic under X86. we
@@ -239,7 +239,7 @@ static void __cpuinit calculate_tlb_offset(void)
                nr_node_vecs = NUM_INVALIDATE_TLB_VECTORS/nr_online_nodes;
 
        for_each_online_node(node) {
-               int node_offset = (node % NUM_INVALIDATE_TLB_VECTORS) *
+               int node_offset = (idx % NUM_INVALIDATE_TLB_VECTORS) *
                        nr_node_vecs;
                int cpu_offset = 0;
                for_each_cpu(cpu, cpumask_of_node(node)) {
@@ -248,6 +248,7 @@ static void __cpuinit calculate_tlb_offset(void)
                        cpu_offset++;
                        cpu_offset = cpu_offset % nr_node_vecs;
                }
+               idx++;
        }
 }
 
index c4bb261c106e16eaeab09092a9942418dba61133..b1805b78842fec1efd9da3a1cebfca74c4b25371 100644 (file)
@@ -65,21 +65,13 @@ pcibios_align_resource(void *data, const struct resource *res,
                        resource_size_t size, resource_size_t align)
 {
        struct pci_dev *dev = data;
-       resource_size_t start = round_down(res->end - size + 1, align);
+       resource_size_t start = res->start;
 
        if (res->flags & IORESOURCE_IO) {
-
-               /*
-                * If we're avoiding ISA aliases, the largest contiguous I/O
-                * port space is 256 bytes.  Clearing bits 9 and 10 preserves
-                * all 256-byte and smaller alignments, so the result will
-                * still be correctly aligned.
-                */
-               if (!skip_isa_ioresource_align(dev))
-                       start &= ~0x300;
-       } else if (res->flags & IORESOURCE_MEM) {
-               if (start < BIOS_END)
-                       start = res->end;       /* fail; no space */
+               if (skip_isa_ioresource_align(dev))
+                       return start;
+               if (start & 0x300)
+                       start = (start + 0x3ff) & ~0x3ff;
        }
        return start;
 }
index d7b5109f7a9c28b05e120da3eec295b1716f543e..25cd4a07d09f78cbe850733f0d2d36d98fe5d176 100644 (file)
@@ -70,6 +70,9 @@ static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi,
 struct xen_pci_frontend_ops *xen_pci_frontend;
 EXPORT_SYMBOL_GPL(xen_pci_frontend);
 
+#define XEN_PIRQ_MSI_DATA  (MSI_DATA_TRIGGER_EDGE | \
+               MSI_DATA_LEVEL_ASSERT | (3 << 8) | MSI_DATA_VECTOR(0))
+
 static void xen_msi_compose_msg(struct pci_dev *pdev, unsigned int pirq,
                struct msi_msg *msg)
 {
@@ -83,12 +86,7 @@ static void xen_msi_compose_msg(struct pci_dev *pdev, unsigned int pirq,
                MSI_ADDR_REDIRECTION_CPU |
                MSI_ADDR_DEST_ID(pirq);
 
-       msg->data =
-               MSI_DATA_TRIGGER_EDGE |
-               MSI_DATA_LEVEL_ASSERT |
-               /* delivery mode reserved */
-               (3 << 8) |
-               MSI_DATA_VECTOR(0);
+       msg->data = XEN_PIRQ_MSI_DATA;
 }
 
 static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
@@ -98,8 +96,23 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
        struct msi_msg msg;
 
        list_for_each_entry(msidesc, &dev->msi_list, list) {
+               __read_msi_msg(msidesc, &msg);
+               pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) |
+                       ((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff);
+               if (xen_irq_from_pirq(pirq) >= 0 && msg.data == XEN_PIRQ_MSI_DATA) {
+                       xen_allocate_pirq_msi((type == PCI_CAP_ID_MSIX) ?
+                                       "msi-x" : "msi", &irq, &pirq, XEN_ALLOC_IRQ);
+                       if (irq < 0)
+                               goto error;
+                       ret = set_irq_msi(irq, msidesc);
+                       if (ret < 0)
+                               goto error_while;
+                       printk(KERN_DEBUG "xen: msi already setup: msi --> irq=%d"
+                                       " pirq=%d\n", irq, pirq);
+                       return 0;
+               }
                xen_allocate_pirq_msi((type == PCI_CAP_ID_MSIX) ?
-                               "msi-x" : "msi", &irq, &pirq);
+                               "msi-x" : "msi", &irq, &pirq, (XEN_ALLOC_IRQ | XEN_ALLOC_PIRQ));
                if (irq < 0 || pirq < 0)
                        goto error;
                printk(KERN_DEBUG "xen: msi --> irq=%d, pirq=%d\n", irq, pirq);
index a318194002b56c3a953df57a9664c5f02745d2ba..ba9caa808a9c1b42c6a616968c57e96769039314 100644 (file)
@@ -1455,7 +1455,7 @@ static void __init uv_init_uvhub(int uvhub, int vector)
         * the below initialization can't be in firmware because the
         * messaging IRQ will be determined by the OS
         */
-       apicid = uvhub_to_first_apicid(uvhub);
+       apicid = uvhub_to_first_apicid(uvhub) | uv_apicid_hibits;
        uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG,
                                      ((apicid << 32) | vector));
 }
index 56e421bc379b19931d4db718b35e3b92e71c3d5e..9daf5d1af9f190015b8b9be646aac14cbe6c2c44 100644 (file)
@@ -89,6 +89,7 @@ static void uv_rtc_send_IPI(int cpu)
 
        apicid = cpu_physical_id(cpu);
        pnode = uv_apicid_to_pnode(apicid);
+       apicid |= uv_apicid_hibits;
        val = (1UL << UVH_IPI_INT_SEND_SHFT) |
              (apicid << UVH_IPI_INT_APIC_ID_SHFT) |
              (X86_PLATFORM_IPI_VECTOR << UVH_IPI_INT_VECTOR_SHFT);
@@ -107,6 +108,7 @@ static int uv_intr_pending(int pnode)
 static int uv_setup_intr(int cpu, u64 expires)
 {
        u64 val;
+       unsigned long apicid = cpu_physical_id(cpu) | uv_apicid_hibits;
        int pnode = uv_cpu_to_pnode(cpu);
 
        uv_write_global_mmr64(pnode, UVH_RTC1_INT_CONFIG,
@@ -117,7 +119,7 @@ static int uv_setup_intr(int cpu, u64 expires)
                UVH_EVENT_OCCURRED0_RTC1_MASK);
 
        val = (X86_PLATFORM_IPI_VECTOR << UVH_RTC1_INT_CONFIG_VECTOR_SHFT) |
-               ((u64)cpu_physical_id(cpu) << UVH_RTC1_INT_CONFIG_APIC_ID_SHFT);
+               ((u64)apicid << UVH_RTC1_INT_CONFIG_APIC_ID_SHFT);
 
        /* Set configuration */
        uv_write_global_mmr64(pnode, UVH_RTC1_INT_CONFIG, val);
index 4a2afa1bac51f58d35e27ff6ffd18c4efc064f4b..b6552b189bcdbb43b1f3627616f1f69d488f9efa 100644 (file)
@@ -25,7 +25,7 @@ targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y)
 
 export CPPFLAGS_vdso.lds += -P -C
 
-VDSO_LDFLAGS_vdso.lds = -m elf_x86_64 -Wl,-soname=linux-vdso.so.1 \
+VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
                        -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
 
 $(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so
@@ -69,7 +69,7 @@ vdso32.so-$(VDSO32-y)         += sysenter
 vdso32-images                  = $(vdso32.so-y:%=vdso32-%.so)
 
 CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds)
-VDSO_LDFLAGS_vdso32.lds = -m elf_i386 -Wl,-soname=linux-gate.so.1
+VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-soname=linux-gate.so.1
 
 # This makes sure the $(obj) subdirectory exists even though vdso32/
 # is not a kbuild sub-make subdirectory.
index 235c0f4d3861da6f1c9d64ded710c7c2176cf895..44dcad43989dc983af51863fac28677e2cfdaaee 100644 (file)
@@ -75,6 +75,11 @@ DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info);
 enum xen_domain_type xen_domain_type = XEN_NATIVE;
 EXPORT_SYMBOL_GPL(xen_domain_type);
 
+unsigned long *machine_to_phys_mapping = (void *)MACH2PHYS_VIRT_START;
+EXPORT_SYMBOL(machine_to_phys_mapping);
+unsigned int   machine_to_phys_order;
+EXPORT_SYMBOL(machine_to_phys_order);
+
 struct start_info *xen_start_info;
 EXPORT_SYMBOL_GPL(xen_start_info);
 
@@ -1016,10 +1021,6 @@ static void xen_reboot(int reason)
 {
        struct sched_shutdown r = { .reason = reason };
 
-#ifdef CONFIG_SMP
-       stop_other_cpus();
-#endif
-
        if (HYPERVISOR_sched_op(SCHEDOP_shutdown, &r))
                BUG();
 }
@@ -1090,6 +1091,8 @@ static void __init xen_setup_stackprotector(void)
 /* First C function to be called on Xen boot */
 asmlinkage void __init xen_start_kernel(void)
 {
+       struct physdev_set_iopl set_iopl;
+       int rc;
        pgd_t *pgd;
 
        if (!xen_start_info)
@@ -1097,6 +1100,8 @@ asmlinkage void __init xen_start_kernel(void)
 
        xen_domain_type = XEN_PV_DOMAIN;
 
+       xen_setup_machphys_mapping();
+
        /* Install Xen paravirt ops */
        pv_info = xen_info;
        pv_init_ops = xen_init_ops;
@@ -1191,8 +1196,6 @@ asmlinkage void __init xen_start_kernel(void)
        /* Allocate and initialize top and mid mfn levels for p2m structure */
        xen_build_mfn_list_list();
 
-       init_mm.pgd = pgd;
-
        /* keep using Xen gdt for now; no urgent need to change it */
 
 #ifdef CONFIG_X86_32
@@ -1202,10 +1205,18 @@ asmlinkage void __init xen_start_kernel(void)
 #else
        pv_info.kernel_rpl = 0;
 #endif
-
        /* set the limit of our address space */
        xen_reserve_top();
 
+       /* We used to do this in xen_arch_setup, but that is too late on AMD
+        * were early_cpu_init (run before ->arch_setup()) calls early_amd_init
+        * which pokes 0xcf8 port.
+        */
+       set_iopl.iopl = 1;
+       rc = HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl);
+       if (rc != 0)
+               xen_raw_printk("physdev_op failed %d\n", rc);
+
 #ifdef CONFIG_X86_32
        /* set up basic CPUID stuff */
        cpu_detect(&new_cpu_data);
index 21ed8d7f75a5aa6fa85970d177979457d6b94d5c..44924e551fde2566989ce6aa6cc886447686b977 100644 (file)
@@ -2034,6 +2034,20 @@ static __init void xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn)
        set_page_prot(pmd, PAGE_KERNEL_RO);
 }
 
+void __init xen_setup_machphys_mapping(void)
+{
+       struct xen_machphys_mapping mapping;
+       unsigned long machine_to_phys_nr_ents;
+
+       if (HYPERVISOR_memory_op(XENMEM_machphys_mapping, &mapping) == 0) {
+               machine_to_phys_mapping = (unsigned long *)mapping.v_start;
+               machine_to_phys_nr_ents = mapping.max_mfn + 1;
+       } else {
+               machine_to_phys_nr_ents = MACH2PHYS_NR_ENTRIES;
+       }
+       machine_to_phys_order = fls(machine_to_phys_nr_ents - 1);
+}
+
 #ifdef CONFIG_X86_64
 static void convert_pfn_mfn(void *v)
 {
@@ -2119,44 +2133,83 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd,
        return pgd;
 }
 #else  /* !CONFIG_X86_64 */
-static RESERVE_BRK_ARRAY(pmd_t, level2_kernel_pgt, PTRS_PER_PMD);
+static RESERVE_BRK_ARRAY(pmd_t, initial_kernel_pmd, PTRS_PER_PMD);
+static RESERVE_BRK_ARRAY(pmd_t, swapper_kernel_pmd, PTRS_PER_PMD);
+
+static __init void xen_write_cr3_init(unsigned long cr3)
+{
+       unsigned long pfn = PFN_DOWN(__pa(swapper_pg_dir));
+
+       BUG_ON(read_cr3() != __pa(initial_page_table));
+       BUG_ON(cr3 != __pa(swapper_pg_dir));
+
+       /*
+        * We are switching to swapper_pg_dir for the first time (from
+        * initial_page_table) and therefore need to mark that page
+        * read-only and then pin it.
+        *
+        * Xen disallows sharing of kernel PMDs for PAE
+        * guests. Therefore we must copy the kernel PMD from
+        * initial_page_table into a new kernel PMD to be used in
+        * swapper_pg_dir.
+        */
+       swapper_kernel_pmd =
+               extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE);
+       memcpy(swapper_kernel_pmd, initial_kernel_pmd,
+              sizeof(pmd_t) * PTRS_PER_PMD);
+       swapper_pg_dir[KERNEL_PGD_BOUNDARY] =
+               __pgd(__pa(swapper_kernel_pmd) | _PAGE_PRESENT);
+       set_page_prot(swapper_kernel_pmd, PAGE_KERNEL_RO);
+
+       set_page_prot(swapper_pg_dir, PAGE_KERNEL_RO);
+       xen_write_cr3(cr3);
+       pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, pfn);
+
+       pin_pagetable_pfn(MMUEXT_UNPIN_TABLE,
+                         PFN_DOWN(__pa(initial_page_table)));
+       set_page_prot(initial_page_table, PAGE_KERNEL);
+       set_page_prot(initial_kernel_pmd, PAGE_KERNEL);
+
+       pv_mmu_ops.write_cr3 = &xen_write_cr3;
+}
 
 __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd,
                                         unsigned long max_pfn)
 {
        pmd_t *kernel_pmd;
 
-       level2_kernel_pgt = extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE);
+       initial_kernel_pmd =
+               extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE);
 
        max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->pt_base) +
                                  xen_start_info->nr_pt_frames * PAGE_SIZE +
                                  512*1024);
 
        kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd);
-       memcpy(level2_kernel_pgt, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD);
+       memcpy(initial_kernel_pmd, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD);
 
-       xen_map_identity_early(level2_kernel_pgt, max_pfn);
+       xen_map_identity_early(initial_kernel_pmd, max_pfn);
 
-       memcpy(swapper_pg_dir, pgd, sizeof(pgd_t) * PTRS_PER_PGD);
-       set_pgd(&swapper_pg_dir[KERNEL_PGD_BOUNDARY],
-                       __pgd(__pa(level2_kernel_pgt) | _PAGE_PRESENT));
+       memcpy(initial_page_table, pgd, sizeof(pgd_t) * PTRS_PER_PGD);
+       initial_page_table[KERNEL_PGD_BOUNDARY] =
+               __pgd(__pa(initial_kernel_pmd) | _PAGE_PRESENT);
 
-       set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO);
-       set_page_prot(swapper_pg_dir, PAGE_KERNEL_RO);
+       set_page_prot(initial_kernel_pmd, PAGE_KERNEL_RO);
+       set_page_prot(initial_page_table, PAGE_KERNEL_RO);
        set_page_prot(empty_zero_page, PAGE_KERNEL_RO);
 
        pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd)));
 
-       xen_write_cr3(__pa(swapper_pg_dir));
-
-       pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(swapper_pg_dir)));
+       pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE,
+                         PFN_DOWN(__pa(initial_page_table)));
+       xen_write_cr3(__pa(initial_page_table));
 
        memblock_x86_reserve_range(__pa(xen_start_info->pt_base),
                      __pa(xen_start_info->pt_base +
                           xen_start_info->nr_pt_frames * PAGE_SIZE),
                      "XEN PAGETABLES");
 
-       return swapper_pg_dir;
+       return initial_page_table;
 }
 #endif /* CONFIG_X86_64 */
 
@@ -2290,7 +2343,11 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = {
        .write_cr2 = xen_write_cr2,
 
        .read_cr3 = xen_read_cr3,
+#ifdef CONFIG_X86_32
+       .write_cr3 = xen_write_cr3_init,
+#else
        .write_cr3 = xen_write_cr3,
+#endif
 
        .flush_tlb_user = xen_flush_tlb,
        .flush_tlb_kernel = xen_flush_tlb,
@@ -2358,8 +2415,6 @@ void __init xen_init_mmu_ops(void)
        x86_init.paging.pagetable_setup_done = xen_pagetable_setup_done;
        pv_mmu_ops = xen_mmu_ops;
 
-       vmap_lazy_unmap = false;
-
        memset(dummy_mapping, 0xff, PAGE_SIZE);
 }
 
@@ -2627,7 +2682,8 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
 
        prot = __pgprot(pgprot_val(prot) | _PAGE_IOMAP);
 
-       vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
+       BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_RESERVED | VM_IO)) ==
+                               (VM_PFNMAP | VM_RESERVED | VM_IO)));
 
        rmd.mfn = mfn;
        rmd.prot = prot;
index 0f456386cce5dc3a0c08ed45bfaf0a268be25819..25c52f94a27c788232ec7b6582c4ba776d1dbfb5 100644 (file)
@@ -68,7 +68,7 @@ static int __init check_platform_magic(void)
        return 0;
 }
 
-void __init xen_unplug_emulated_devices(void)
+void xen_unplug_emulated_devices(void)
 {
        int r;
 
index 769c4b01fa32e11f01e3a77a37d42f4c8ab13207..b5a7f928234b064b34a0b9d2c8d2f9d869e7c635 100644 (file)
@@ -23,7 +23,6 @@
 #include <xen/interface/callback.h>
 #include <xen/interface/memory.h>
 #include <xen/interface/physdev.h>
-#include <xen/interface/memory.h>
 #include <xen/features.h>
 
 #include "xen-ops.h"
@@ -182,24 +181,21 @@ char * __init xen_memory_setup(void)
        for (i = 0; i < memmap.nr_entries; i++) {
                unsigned long long end = map[i].addr + map[i].size;
 
-               if (map[i].type == E820_RAM) {
-                       if (map[i].addr < mem_end && end > mem_end) {
-                               /* Truncate region to max_mem. */
-                               u64 delta = end - mem_end;
+               if (map[i].type == E820_RAM && end > mem_end) {
+                       /* RAM off the end - may be partially included */
+                       u64 delta = min(map[i].size, end - mem_end);
 
-                               map[i].size -= delta;
-                               extra_pages += PFN_DOWN(delta);
+                       map[i].size -= delta;
+                       end -= delta;
 
-                               end = mem_end;
-                       }
+                       extra_pages += PFN_DOWN(delta);
                }
 
-               if (end > xen_extra_mem_start)
+               if (map[i].size > 0 && end > xen_extra_mem_start)
                        xen_extra_mem_start = end;
 
-               /* If region is non-RAM or below mem_end, add what remains */
-               if ((map[i].type != E820_RAM || map[i].addr < mem_end) &&
-                   map[i].size > 0)
+               /* Add region if any remains */
+               if (map[i].size > 0)
                        e820_add_region(map[i].addr, map[i].size, map[i].type);
        }
 
@@ -248,26 +244,11 @@ char * __init xen_memory_setup(void)
        else
                extra_pages = 0;
 
-       if (!xen_initial_domain())
-               xen_add_extra_mem(extra_pages);
+       xen_add_extra_mem(extra_pages);
 
        return "Xen";
 }
 
-static void xen_idle(void)
-{
-       local_irq_disable();
-
-       if (need_resched())
-               local_irq_enable();
-       else {
-               current_thread_info()->status &= ~TS_POLLING;
-               smp_mb__after_clear_bit();
-               safe_halt();
-               current_thread_info()->status |= TS_POLLING;
-       }
-}
-
 /*
  * Set the bit indicating "nosegneg" library variants should be used.
  * We only need to bother in pure 32-bit mode; compat 32-bit processes
@@ -337,9 +318,6 @@ void __cpuinit xen_enable_syscall(void)
 
 void __init xen_arch_setup(void)
 {
-       struct physdev_set_iopl set_iopl;
-       int rc;
-
        xen_panic_handler_init();
 
        HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_4gb_segments);
@@ -356,11 +334,6 @@ void __init xen_arch_setup(void)
        xen_enable_sysenter();
        xen_enable_syscall();
 
-       set_iopl.iopl = 1;
-       rc = HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl);
-       if (rc != 0)
-               printk(KERN_INFO "physdev_op failed %d\n", rc);
-
 #ifdef CONFIG_ACPI
        if (!(xen_start_info->flags & SIF_INITDOMAIN)) {
                printk(KERN_INFO "ACPI in unprivileged domain disabled\n");
@@ -372,7 +345,11 @@ void __init xen_arch_setup(void)
               MAX_GUEST_CMDLINE > COMMAND_LINE_SIZE ?
               COMMAND_LINE_SIZE : MAX_GUEST_CMDLINE);
 
-       pm_idle = xen_idle;
+       /* Set up idle, making sure it calls safe_halt() pvop */
+#ifdef CONFIG_X86_32
+       boot_cpu_data.hlt_works_ok = 1;
+#endif
+       pm_idle = default_idle;
 
        fiddle_vdso();
 }
index 1d789d56877cd509a11a4aff08f38952b892c79f..9bbd63a129b5869a4842238423217d620b26d79b 100644 (file)
@@ -31,6 +31,7 @@ void xen_hvm_post_suspend(int suspend_cancelled)
        int cpu;
        xen_hvm_init_shared_info();
        xen_callback_vector();
+       xen_unplug_emulated_devices();
        if (xen_feature(XENFEAT_hvm_safe_pvclock)) {
                for_each_online_cpu(cpu) {
                        xen_setup_runstate_info(cpu);
index b2bb5aa3b0540e42847a7664aa529cf5d2c0fb83..5da5e53fb94c20bf6c244dce734e515c92d10b34 100644 (file)
@@ -426,6 +426,8 @@ void xen_timer_resume(void)
 {
        int cpu;
 
+       pvclock_resume();
+
        if (xen_clockevent != &xen_vcpuop_clockevent)
                return;
 
index 64044747348efb3535461a67610621d9067767e3..9d41bf985757973ece1288bd27b84d6c7af6622c 100644 (file)
@@ -43,7 +43,7 @@ void xen_vcpu_restore(void);
 
 void xen_callback_vector(void);
 void xen_hvm_init_shared_info(void);
-void __init xen_unplug_emulated_devices(void);
+void xen_unplug_emulated_devices(void);
 
 void __init xen_build_dynamic_phys_to_machine(void);
 
index 5d5dbe47c2285ee7ccb5f3ca784f9cdb8cb6df3e..e663ac2d8e68f70ff17ce274f3cebec16c1dd18c 100644 (file)
@@ -201,12 +201,13 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
        for (i = 0; i < iov_count; i++) {
                unsigned long uaddr = (unsigned long)iov[i].iov_base;
 
+               if (!iov[i].iov_len)
+                       return -EINVAL;
+
                if (uaddr & queue_dma_alignment(q)) {
                        unaligned = 1;
                        break;
                }
-               if (!iov[i].iov_len)
-                       return -EINVAL;
        }
 
        if (unaligned || (q->dma_pad_mask & len) || map_data)
index 77b7c26df6b50fea7a38ba0825d91583f1c4031c..74bc4a768f32e0f01e5c43f100f8663eea34c3a4 100644 (file)
@@ -21,7 +21,7 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
                return 0;
 
        fbio = bio;
-       cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
+       cluster = blk_queue_cluster(q);
        seg_size = 0;
        nr_phys_segs = 0;
        for_each_bio(bio) {
@@ -87,7 +87,7 @@ EXPORT_SYMBOL(blk_recount_segments);
 static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,
                                   struct bio *nxt)
 {
-       if (!test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags))
+       if (!blk_queue_cluster(q))
                return 0;
 
        if (bio->bi_seg_back_size + nxt->bi_seg_front_size >
@@ -123,7 +123,7 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
        int nsegs, cluster;
 
        nsegs = 0;
-       cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
+       cluster = blk_queue_cluster(q);
 
        /*
         * for each bio in rq
index 701859fb9647c31a505f0218800744e3e6d0a775..36c8c1f2af18088fb5fa34f4889d2fead2556600 100644 (file)
@@ -126,7 +126,7 @@ void blk_set_default_limits(struct queue_limits *lim)
        lim->alignment_offset = 0;
        lim->io_opt = 0;
        lim->misaligned = 0;
-       lim->no_cluster = 0;
+       lim->cluster = 1;
 }
 EXPORT_SYMBOL(blk_set_default_limits);
 
@@ -229,8 +229,8 @@ void blk_queue_bounce_limit(struct request_queue *q, u64 dma_mask)
 EXPORT_SYMBOL(blk_queue_bounce_limit);
 
 /**
- * blk_queue_max_hw_sectors - set max sectors for a request for this queue
- * @q:  the request queue for the device
+ * blk_limits_max_hw_sectors - set hard and soft limit of max sectors for request
+ * @limits: the queue limits
  * @max_hw_sectors:  max hardware sectors in the usual 512b unit
  *
  * Description:
@@ -244,7 +244,7 @@ EXPORT_SYMBOL(blk_queue_bounce_limit);
  *    per-device basis in /sys/block/<device>/queue/max_sectors_kb.
  *    The soft limit can not exceed max_hw_sectors.
  **/
-void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_sectors)
+void blk_limits_max_hw_sectors(struct queue_limits *limits, unsigned int max_hw_sectors)
 {
        if ((max_hw_sectors << 9) < PAGE_CACHE_SIZE) {
                max_hw_sectors = 1 << (PAGE_CACHE_SHIFT - 9);
@@ -252,9 +252,23 @@ void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_secto
                       __func__, max_hw_sectors);
        }
 
-       q->limits.max_hw_sectors = max_hw_sectors;
-       q->limits.max_sectors = min_t(unsigned int, max_hw_sectors,
-                                     BLK_DEF_MAX_SECTORS);
+       limits->max_hw_sectors = max_hw_sectors;
+       limits->max_sectors = min_t(unsigned int, max_hw_sectors,
+                                   BLK_DEF_MAX_SECTORS);
+}
+EXPORT_SYMBOL(blk_limits_max_hw_sectors);
+
+/**
+ * blk_queue_max_hw_sectors - set max sectors for a request for this queue
+ * @q:  the request queue for the device
+ * @max_hw_sectors:  max hardware sectors in the usual 512b unit
+ *
+ * Description:
+ *    See description for blk_limits_max_hw_sectors().
+ **/
+void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_sectors)
+{
+       blk_limits_max_hw_sectors(&q->limits, max_hw_sectors);
 }
 EXPORT_SYMBOL(blk_queue_max_hw_sectors);
 
@@ -464,15 +478,6 @@ EXPORT_SYMBOL(blk_queue_io_opt);
 void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b)
 {
        blk_stack_limits(&t->limits, &b->limits, 0);
-
-       if (!t->queue_lock)
-               WARN_ON_ONCE(1);
-       else if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) {
-               unsigned long flags;
-               spin_lock_irqsave(t->queue_lock, flags);
-               queue_flag_clear(QUEUE_FLAG_CLUSTER, t);
-               spin_unlock_irqrestore(t->queue_lock, flags);
-       }
 }
 EXPORT_SYMBOL(blk_queue_stack_limits);
 
@@ -545,7 +550,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
        t->io_min = max(t->io_min, b->io_min);
        t->io_opt = lcm(t->io_opt, b->io_opt);
 
-       t->no_cluster |= b->no_cluster;
+       t->cluster &= b->cluster;
        t->discard_zeroes_data &= b->discard_zeroes_data;
 
        /* Physical block size a multiple of the logical block size? */
@@ -641,7 +646,6 @@ void disk_stack_limits(struct gendisk *disk, struct block_device *bdev,
                       sector_t offset)
 {
        struct request_queue *t = disk->queue;
-       struct request_queue *b = bdev_get_queue(bdev);
 
        if (bdev_stack_limits(&t->limits, bdev, offset >> 9) < 0) {
                char top[BDEVNAME_SIZE], bottom[BDEVNAME_SIZE];
@@ -652,17 +656,6 @@ void disk_stack_limits(struct gendisk *disk, struct block_device *bdev,
                printk(KERN_NOTICE "%s: Warning: Device %s is misaligned\n",
                       top, bottom);
        }
-
-       if (!t->queue_lock)
-               WARN_ON_ONCE(1);
-       else if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) {
-               unsigned long flags;
-
-               spin_lock_irqsave(t->queue_lock, flags);
-               if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags))
-                       queue_flag_clear(QUEUE_FLAG_CLUSTER, t);
-               spin_unlock_irqrestore(t->queue_lock, flags);
-       }
 }
 EXPORT_SYMBOL(disk_stack_limits);
 
index 013457f47fdc8b12eded858c852f588884b962c5..41fb69150b4d3c6758b0f5da6ff2005d4d7a0a3f 100644 (file)
@@ -119,7 +119,7 @@ static ssize_t queue_max_integrity_segments_show(struct request_queue *q, char *
 
 static ssize_t queue_max_segment_size_show(struct request_queue *q, char *page)
 {
-       if (test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags))
+       if (blk_queue_cluster(q))
                return queue_var_show(queue_max_segment_size(q), (page));
 
        return queue_var_show(PAGE_CACHE_SIZE, (page));
index 56ad4531b41234f87485e4f4bca5ca84d4d10dc1..381b09bb562b277620479fa92313cc6631995630 100644 (file)
@@ -355,6 +355,12 @@ throtl_start_new_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw)
                        tg->slice_end[rw], jiffies);
 }
 
+static inline void throtl_set_slice_end(struct throtl_data *td,
+               struct throtl_grp *tg, bool rw, unsigned long jiffy_end)
+{
+       tg->slice_end[rw] = roundup(jiffy_end, throtl_slice);
+}
+
 static inline void throtl_extend_slice(struct throtl_data *td,
                struct throtl_grp *tg, bool rw, unsigned long jiffy_end)
 {
@@ -391,6 +397,16 @@ throtl_trim_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw)
        if (throtl_slice_used(td, tg, rw))
                return;
 
+       /*
+        * A bio has been dispatched. Also adjust slice_end. It might happen
+        * that initially cgroup limit was very low resulting in high
+        * slice_end, but later limit was bumped up and bio was dispached
+        * sooner, then we need to reduce slice_end. A high bogus slice_end
+        * is bad because it does not allow new slice to start.
+        */
+
+       throtl_set_slice_end(td, tg, rw, jiffies + throtl_slice);
+
        time_elapsed = jiffies - tg->slice_start[rw];
 
        nr_slices = time_elapsed / throtl_slice;
@@ -645,7 +661,7 @@ static int throtl_dispatch_tg(struct throtl_data *td, struct throtl_grp *tg,
 {
        unsigned int nr_reads = 0, nr_writes = 0;
        unsigned int max_nr_reads = throtl_grp_quantum*3/4;
-       unsigned int max_nr_writes = throtl_grp_quantum - nr_reads;
+       unsigned int max_nr_writes = throtl_grp_quantum - max_nr_reads;
        struct bio *bio;
 
        /* Try to dispatch 75% READS and 25% WRITES */
@@ -709,26 +725,21 @@ static void throtl_process_limit_change(struct throtl_data *td)
        struct throtl_grp *tg;
        struct hlist_node *pos, *n;
 
-       /*
-        * Make sure atomic_inc() effects from
-        * throtl_update_blkio_group_read_bps(), group of functions are
-        * visible.
-        * Is this required or smp_mb__after_atomic_inc() was suffcient
-        * after the atomic_inc().
-        */
-       smp_rmb();
        if (!atomic_read(&td->limits_changed))
                return;
 
        throtl_log(td, "limit changed =%d", atomic_read(&td->limits_changed));
 
-       hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) {
-               /*
-                * Do I need an smp_rmb() here to make sure tg->limits_changed
-                * update is visible. I am relying on smp_rmb() at the
-                * beginning of function and not putting a new one here.
-                */
+       /*
+        * Make sure updates from throtl_update_blkio_group_read_bps() group
+        * of functions to tg->limits_changed are visible. We do not
+        * want update td->limits_changed to be visible but update to
+        * tg->limits_changed not being visible yet on this cpu. Hence
+        * the read barrier.
+        */
+       smp_rmb();
 
+       hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) {
                if (throtl_tg_on_rr(tg) && tg->limits_changed) {
                        throtl_log_tg(td, tg, "limit change rbps=%llu wbps=%llu"
                                " riops=%u wiops=%u", tg->bps[READ],
index f20d6a789d484591e9fdb5642fa893c233c2b9b0..0c8b64a16484721308587c7a6b635344a9144a1e 100644 (file)
@@ -250,6 +250,14 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm,
        int ret, rw;
        unsigned int dxfer_len;
        void *dxferp = NULL;
+       struct bsg_class_device *bcd = &q->bsg_dev;
+
+       /* if the LLD has been removed then the bsg_unregister_queue will
+        * eventually be called and the class_dev was freed, so we can no
+        * longer use this request_queue. Return no such address.
+        */
+       if (!bcd->class_dev)
+               return ERR_PTR(-ENXIO);
 
        dprintk("map hdr %llx/%u %llx/%u\n", (unsigned long long) hdr->dout_xferp,
                hdr->dout_xfer_len, (unsigned long long) hdr->din_xferp,
index ba9afeaa23acfb676021c86432fd89b45f8ba5cf..25d3aaebc10d4d86238c0af67bcb01976b6dcd65 100644 (file)
@@ -100,24 +100,7 @@ static const struct file_operations acpi_ac_fops = {
        .release = single_release,
 };
 #endif
-static int get_ac_property(struct power_supply *psy,
-                          enum power_supply_property psp,
-                          union power_supply_propval *val)
-{
-       struct acpi_ac *ac = to_acpi_ac(psy);
-       switch (psp) {
-       case POWER_SUPPLY_PROP_ONLINE:
-               val->intval = ac->state;
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
 
-static enum power_supply_property ac_props[] = {
-       POWER_SUPPLY_PROP_ONLINE,
-};
 /* --------------------------------------------------------------------------
                                AC Adapter Management
    -------------------------------------------------------------------------- */
@@ -140,6 +123,35 @@ static int acpi_ac_get_state(struct acpi_ac *ac)
        return 0;
 }
 
+/* --------------------------------------------------------------------------
+                            sysfs I/F
+   -------------------------------------------------------------------------- */
+static int get_ac_property(struct power_supply *psy,
+                          enum power_supply_property psp,
+                          union power_supply_propval *val)
+{
+       struct acpi_ac *ac = to_acpi_ac(psy);
+
+       if (!ac)
+               return -ENODEV;
+
+       if (acpi_ac_get_state(ac))
+               return -ENODEV;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_ONLINE:
+               val->intval = ac->state;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static enum power_supply_property ac_props[] = {
+       POWER_SUPPLY_PROP_ONLINE,
+};
+
 #ifdef CONFIG_ACPI_PROCFS_POWER
 /* --------------------------------------------------------------------------
                               FS Interface (/proc)
index 1211c03149e8c7c258fee89dd1109e1e6b901c26..5850d320404c35b9c7318eb0619ae54c7e32a30b 100644 (file)
@@ -86,7 +86,7 @@ static struct erst_erange {
  * It is used to provide exclusive accessing for ERST Error Log
  * Address Range too.
  */
-static DEFINE_SPINLOCK(erst_lock);
+static DEFINE_RAW_SPINLOCK(erst_lock);
 
 static inline int erst_errno(int command_status)
 {
@@ -421,9 +421,9 @@ ssize_t erst_get_record_count(void)
        if (erst_disable)
                return -ENODEV;
 
-       spin_lock_irqsave(&erst_lock, flags);
+       raw_spin_lock_irqsave(&erst_lock, flags);
        count = __erst_get_record_count();
-       spin_unlock_irqrestore(&erst_lock, flags);
+       raw_spin_unlock_irqrestore(&erst_lock, flags);
 
        return count;
 }
@@ -456,9 +456,9 @@ int erst_get_next_record_id(u64 *record_id)
        if (erst_disable)
                return -ENODEV;
 
-       spin_lock_irqsave(&erst_lock, flags);
+       raw_spin_lock_irqsave(&erst_lock, flags);
        rc = __erst_get_next_record_id(record_id);
-       spin_unlock_irqrestore(&erst_lock, flags);
+       raw_spin_unlock_irqrestore(&erst_lock, flags);
 
        return rc;
 }
@@ -624,17 +624,17 @@ int erst_write(const struct cper_record_header *record)
                return -EINVAL;
 
        if (erst_erange.attr & ERST_RANGE_NVRAM) {
-               if (!spin_trylock_irqsave(&erst_lock, flags))
+               if (!raw_spin_trylock_irqsave(&erst_lock, flags))
                        return -EBUSY;
                rc = __erst_write_to_nvram(record);
-               spin_unlock_irqrestore(&erst_lock, flags);
+               raw_spin_unlock_irqrestore(&erst_lock, flags);
                return rc;
        }
 
        if (record->record_length > erst_erange.size)
                return -EINVAL;
 
-       if (!spin_trylock_irqsave(&erst_lock, flags))
+       if (!raw_spin_trylock_irqsave(&erst_lock, flags))
                return -EBUSY;
        memcpy(erst_erange.vaddr, record, record->record_length);
        rcd_erange = erst_erange.vaddr;
@@ -642,7 +642,7 @@ int erst_write(const struct cper_record_header *record)
        memcpy(&rcd_erange->persistence_information, "ER", 2);
 
        rc = __erst_write_to_storage(0);
-       spin_unlock_irqrestore(&erst_lock, flags);
+       raw_spin_unlock_irqrestore(&erst_lock, flags);
 
        return rc;
 }
@@ -696,9 +696,9 @@ ssize_t erst_read(u64 record_id, struct cper_record_header *record,
        if (erst_disable)
                return -ENODEV;
 
-       spin_lock_irqsave(&erst_lock, flags);
+       raw_spin_lock_irqsave(&erst_lock, flags);
        len = __erst_read(record_id, record, buflen);
-       spin_unlock_irqrestore(&erst_lock, flags);
+       raw_spin_unlock_irqrestore(&erst_lock, flags);
        return len;
 }
 EXPORT_SYMBOL_GPL(erst_read);
@@ -719,20 +719,20 @@ ssize_t erst_read_next(struct cper_record_header *record, size_t buflen)
        if (erst_disable)
                return -ENODEV;
 
-       spin_lock_irqsave(&erst_lock, flags);
+       raw_spin_lock_irqsave(&erst_lock, flags);
        rc = __erst_get_next_record_id(&record_id);
        if (rc) {
-               spin_unlock_irqrestore(&erst_lock, flags);
+               raw_spin_unlock_irqrestore(&erst_lock, flags);
                return rc;
        }
        /* no more record */
        if (record_id == APEI_ERST_INVALID_RECORD_ID) {
-               spin_unlock_irqrestore(&erst_lock, flags);
+               raw_spin_unlock_irqrestore(&erst_lock, flags);
                return 0;
        }
 
        len = __erst_read(record_id, record, buflen);
-       spin_unlock_irqrestore(&erst_lock, flags);
+       raw_spin_unlock_irqrestore(&erst_lock, flags);
 
        return len;
 }
@@ -746,12 +746,12 @@ int erst_clear(u64 record_id)
        if (erst_disable)
                return -ENODEV;
 
-       spin_lock_irqsave(&erst_lock, flags);
+       raw_spin_lock_irqsave(&erst_lock, flags);
        if (erst_erange.attr & ERST_RANGE_NVRAM)
                rc = __erst_clear_from_nvram(record_id);
        else
                rc = __erst_clear_from_storage(record_id);
-       spin_unlock_irqrestore(&erst_lock, flags);
+       raw_spin_unlock_irqrestore(&erst_lock, flags);
 
        return rc;
 }
index 1a3508a7fe03f157c2e0144727bbeb5c244d2a46..daa7bc63f1d4bad00fd988ddcce3681fdc74f804 100644 (file)
@@ -46,9 +46,9 @@ EXPORT_SYMBOL_GPL(hest_disable);
 
 /* HEST table parsing */
 
-static struct acpi_table_hest *hest_tab;
+static struct acpi_table_hest *__read_mostly hest_tab;
 
-static int hest_esrc_len_tab[ACPI_HEST_TYPE_RESERVED] = {
+static const int hest_esrc_len_tab[ACPI_HEST_TYPE_RESERVED] = {
        [ACPI_HEST_TYPE_IA32_CHECK] = -1,       /* need further calculation */
        [ACPI_HEST_TYPE_IA32_CORRECTED_CHECK] = -1,
        [ACPI_HEST_TYPE_IA32_NMI] = sizeof(struct acpi_hest_ia_nmi),
@@ -126,7 +126,7 @@ struct ghes_arr {
        unsigned int count;
 };
 
-static int hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void *data)
+static int __init hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void *data)
 {
        int *count = data;
 
@@ -135,7 +135,7 @@ static int hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void *data)
        return 0;
 }
 
-static int hest_parse_ghes(struct acpi_hest_header *hest_hdr, void *data)
+static int __init hest_parse_ghes(struct acpi_hest_header *hest_hdr, void *data)
 {
        struct platform_device *ghes_dev;
        struct ghes_arr *ghes_arr = data;
@@ -165,7 +165,7 @@ err:
        return rc;
 }
 
-static int hest_ghes_dev_register(unsigned int ghes_count)
+static int __init hest_ghes_dev_register(unsigned int ghes_count)
 {
        int rc, i;
        struct ghes_arr ghes_arr;
index 95649d373071ac93d14bbbb478db1ab4a8cdb801..9fb9d5ac939db1c071c4cdcaa7fba49364236e25 100644 (file)
@@ -130,6 +130,8 @@ struct acpi_battery {
        unsigned long flags;
 };
 
+static int acpi_battery_update(struct acpi_battery *battery);
+
 #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
 
 inline int acpi_battery_present(struct acpi_battery *battery)
@@ -184,6 +186,9 @@ static int acpi_battery_get_property(struct power_supply *psy,
        int ret = 0;
        struct acpi_battery *battery = to_acpi_battery(psy);
 
+       if (acpi_battery_update(battery))
+               return -ENODEV;
+
        if (acpi_battery_present(battery)) {
                /* run battery update only if it is present */
                acpi_battery_get_state(battery);
index 372ff80b7b0c93f88f6f2ea9e100c0fdd2aaf6bf..302b31ed31f1ea099faa48b989114e9c99dc1485 100644 (file)
@@ -934,6 +934,9 @@ static struct dmi_system_id __initdata ec_dmi_table[] = {
        ec_flag_msi, "MSI hardware", {
        DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-Star")}, NULL},
        {
+       ec_flag_msi, "MSI hardware", {
+       DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR")}, NULL},
+       {
        ec_validate_ecdt, "ASUS hardware", {
        DMI_MATCH(DMI_BIOS_VENDOR, "ASUS") }, NULL},
        {},
index 966feddf6b1ba29457fde294223018ad23666e39..055d7b701fff16d18fe5de5ea243ba8ec477e3ec 100644 (file)
@@ -110,9 +110,6 @@ struct acpi_ioremap {
 static LIST_HEAD(acpi_ioremaps);
 static DEFINE_SPINLOCK(acpi_ioremap_lock);
 
-#define        OSI_STRING_LENGTH_MAX 64        /* arbitrary */
-static char osi_setup_string[OSI_STRING_LENGTH_MAX];
-
 static void __init acpi_osi_setup_late(void);
 
 /*
@@ -152,8 +149,7 @@ static struct osi_linux {
        unsigned int    enable:1;
        unsigned int    dmi:1;
        unsigned int    cmdline:1;
-       unsigned int    known:1;
-} osi_linux = { 0, 0, 0, 0};
+} osi_linux = {0, 0, 0};
 
 static u32 acpi_osi_handler(acpi_string interface, u32 supported)
 {
@@ -1055,13 +1051,53 @@ static int __init acpi_os_name_setup(char *str)
 
 __setup("acpi_os_name=", acpi_os_name_setup);
 
+#define        OSI_STRING_LENGTH_MAX 64        /* arbitrary */
+#define        OSI_STRING_ENTRIES_MAX 16       /* arbitrary */
+
+struct osi_setup_entry {
+       char string[OSI_STRING_LENGTH_MAX];
+       bool enable;
+};
+
+static struct osi_setup_entry __initdata osi_setup_entries[OSI_STRING_ENTRIES_MAX];
+
+void __init acpi_osi_setup(char *str)
+{
+       struct osi_setup_entry *osi;
+       bool enable = true;
+       int i;
+
+       if (!acpi_gbl_create_osi_method)
+               return;
+
+       if (str == NULL || *str == '\0') {
+               printk(KERN_INFO PREFIX "_OSI method disabled\n");
+               acpi_gbl_create_osi_method = FALSE;
+               return;
+       }
+
+       if (*str == '!') {
+               str++;
+               enable = false;
+       }
+
+       for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
+               osi = &osi_setup_entries[i];
+               if (!strcmp(osi->string, str)) {
+                       osi->enable = enable;
+                       break;
+               } else if (osi->string[0] == '\0') {
+                       osi->enable = enable;
+                       strncpy(osi->string, str, OSI_STRING_LENGTH_MAX);
+                       break;
+               }
+       }
+}
+
 static void __init set_osi_linux(unsigned int enable)
 {
-       if (osi_linux.enable != enable) {
+       if (osi_linux.enable != enable)
                osi_linux.enable = enable;
-               printk(KERN_NOTICE PREFIX "%sed _OSI(Linux)\n",
-                       enable ? "Add": "Delet");
-       }
 
        if (osi_linux.enable)
                acpi_osi_setup("Linux");
@@ -1073,7 +1109,8 @@ static void __init set_osi_linux(unsigned int enable)
 
 static void __init acpi_cmdline_osi_linux(unsigned int enable)
 {
-       osi_linux.cmdline = 1;  /* cmdline set the default */
+       osi_linux.cmdline = 1;  /* cmdline set the default and override DMI */
+       osi_linux.dmi = 0;
        set_osi_linux(enable);
 
        return;
@@ -1081,15 +1118,12 @@ static void __init acpi_cmdline_osi_linux(unsigned int enable)
 
 void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d)
 {
-       osi_linux.dmi = 1;      /* DMI knows that this box asks OSI(Linux) */
-
        printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
 
        if (enable == -1)
                return;
 
-       osi_linux.known = 1;    /* DMI knows which OSI(Linux) default needed */
-
+       osi_linux.dmi = 1;      /* DMI knows that this box asks OSI(Linux) */
        set_osi_linux(enable);
 
        return;
@@ -1104,37 +1138,44 @@ void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d)
  */
 static void __init acpi_osi_setup_late(void)
 {
-       char *str = osi_setup_string;
+       struct osi_setup_entry *osi;
+       char *str;
+       int i;
+       acpi_status status;
 
-       if (*str == '\0')
-               return;
+       for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
+               osi = &osi_setup_entries[i];
+               str = osi->string;
 
-       if (!strcmp("!Linux", str)) {
-               acpi_cmdline_osi_linux(0);      /* !enable */
-       } else if (*str == '!') {
-               if (acpi_remove_interface(++str) == AE_OK)
-                       printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str);
-       } else if (!strcmp("Linux", str)) {
-               acpi_cmdline_osi_linux(1);      /* enable */
-       } else {
-               if (acpi_install_interface(str) == AE_OK)
-                       printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str);
+               if (*str == '\0')
+                       break;
+               if (osi->enable) {
+                       status = acpi_install_interface(str);
+
+                       if (ACPI_SUCCESS(status))
+                               printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str);
+               } else {
+                       status = acpi_remove_interface(str);
+
+                       if (ACPI_SUCCESS(status))
+                               printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str);
+               }
        }
 }
 
-int __init acpi_osi_setup(char *str)
+static int __init osi_setup(char *str)
 {
-       if (str == NULL || *str == '\0') {
-               printk(KERN_INFO PREFIX "_OSI method disabled\n");
-               acpi_gbl_create_osi_method = FALSE;
-       } else {
-               strncpy(osi_setup_string, str, OSI_STRING_LENGTH_MAX);
-       }
+       if (str && !strcmp("Linux", str))
+               acpi_cmdline_osi_linux(1);
+       else if (str && !strcmp("!Linux", str))
+               acpi_cmdline_osi_linux(0);
+       else
+               acpi_osi_setup(str);
 
        return 1;
 }
 
-__setup("acpi_osi=", acpi_osi_setup);
+__setup("acpi_osi=", osi_setup);
 
 /* enable serialization to combat AE_ALREADY_EXISTS errors */
 static int __init acpi_serialize_setup(char *str)
@@ -1530,7 +1571,7 @@ acpi_status __init acpi_os_initialize(void)
        return AE_OK;
 }
 
-acpi_status acpi_os_initialize1(void)
+acpi_status __init acpi_os_initialize1(void)
 {
        kacpid_wq = create_workqueue("kacpid");
        kacpi_notify_wq = create_workqueue("kacpi_notify");
index 67dedeed144cf82c8e13859e7222b976d0eebb2e..4c9c2fb5d98f9a14a67e8618b44dc6f2c642887b 100644 (file)
@@ -213,11 +213,13 @@ static int acpi_power_on(acpi_handle handle)
                                  resource->name));
        } else {
                result = __acpi_power_on(resource);
+               if (result)
+                       resource->ref_count--;
        }
 
        mutex_unlock(&resource->resource_lock);
 
-       return 0;
+       return result;
 }
 
 static int acpi_power_off_device(acpi_handle handle)
@@ -465,10 +467,12 @@ int acpi_power_transition(struct acpi_device *device, int state)
        struct acpi_handle_list *tl = NULL;     /* Target Resources */
        int i = 0;
 
-
        if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3))
                return -EINVAL;
 
+       if (device->power.state == state)
+               return 0;
+
        if ((device->power.state < ACPI_STATE_D0)
            || (device->power.state > ACPI_STATE_D3))
                return -ENODEV;
@@ -488,10 +492,6 @@ int acpi_power_transition(struct acpi_device *device, int state)
                        goto end;
        }
 
-       if (device->power.state == state) {
-               goto end;
-       }
-
        /*
         * Then we dereference all power resources used in the current list.
         */
index fde49b9b1d99ed04eaf4192473ff7ce3bb913fd6..79cb6533289456c4f43b92dda5d7059a27345afa 100644 (file)
@@ -156,15 +156,6 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state)
        return 0;
 }
 
-static int acpi_thermal_cpufreq_increase(unsigned int cpu)
-{
-       return -ENODEV;
-}
-static int acpi_thermal_cpufreq_decrease(unsigned int cpu)
-{
-       return -ENODEV;
-}
-
 #endif
 
 int acpi_processor_get_limit_info(struct acpi_processor *pr)
index 721d93b3ceee78c3b271f5f84ffe4fc795e435e1..febb153b5a68cf216fdd1b528ac44159e73abcba 100644 (file)
@@ -27,8 +27,6 @@
 
 static u8 sleep_states[ACPI_S_STATE_COUNT];
 
-static u32 acpi_target_sleep_state = ACPI_STATE_S0;
-
 static void acpi_sleep_tts_switch(u32 acpi_state)
 {
        union acpi_object in_arg = { ACPI_TYPE_INTEGER };
@@ -81,6 +79,8 @@ static int acpi_sleep_prepare(u32 acpi_state)
 }
 
 #ifdef CONFIG_ACPI_SLEEP
+static u32 acpi_target_sleep_state = ACPI_STATE_S0;
+
 /*
  * The ACPI specification wants us to save NVS memory regions during hibernation
  * and to restore them during the subsequent resume.  Windows does that also for
@@ -427,6 +427,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1Z1E"),
                },
        },
+       {
+       .callback = init_nvs_nosave,
+       .ident = "Sony Vaio VGN-NW130D",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NW130D"),
+               },
+       },
        {},
 };
 #endif /* CONFIG_SUSPEND */
index 19835d39289dd7497f689f7c6a57681e84f6e637..66aa4bee80a659712b75e8b3949678d56e8bd5a3 100644 (file)
@@ -3166,8 +3166,8 @@ static inline int __ata_scsi_queuecmd(struct scsi_cmnd *scmd,
 
 /**
  *     ata_scsi_queuecmd - Issue SCSI cdb to libata-managed device
+ *     @shost: SCSI host of command to be sent
  *     @cmd: SCSI command to be sent
- *     @done: Completion function, called when command is complete
  *
  *     In some cases, this function translates SCSI commands into
  *     ATA taskfiles, and queues the taskfiles to be sent to
@@ -3177,42 +3177,39 @@ static inline int __ata_scsi_queuecmd(struct scsi_cmnd *scmd,
  *     ATA and ATAPI devices appearing as SCSI devices.
  *
  *     LOCKING:
- *     Releases scsi-layer-held lock, and obtains host lock.
+ *     ATA host lock
  *
  *     RETURNS:
  *     Return value from __ata_scsi_queuecmd() if @cmd can be queued,
  *     0 otherwise.
  */
-static int ata_scsi_queuecmd_lck(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
+int ata_scsi_queuecmd(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
 {
        struct ata_port *ap;
        struct ata_device *dev;
        struct scsi_device *scsidev = cmd->device;
-       struct Scsi_Host *shost = scsidev->host;
        int rc = 0;
+       unsigned long irq_flags;
 
        ap = ata_shost_to_port(shost);
 
-       spin_unlock(shost->host_lock);
-       spin_lock(ap->lock);
+       spin_lock_irqsave(ap->lock, irq_flags);
 
        ata_scsi_dump_cdb(ap, cmd);
 
        dev = ata_scsi_find_dev(ap, scsidev);
        if (likely(dev))
-               rc = __ata_scsi_queuecmd(cmd, done, dev);
+               rc = __ata_scsi_queuecmd(cmd, cmd->scsi_done, dev);
        else {
                cmd->result = (DID_BAD_TARGET << 16);
-               done(cmd);
+               cmd->scsi_done(cmd);
        }
 
-       spin_unlock(ap->lock);
-       spin_lock(shost->host_lock);
+       spin_unlock_irqrestore(ap->lock, irq_flags);
+
        return rc;
 }
 
-DEF_SCSI_QCMD(ata_scsi_queuecmd)
-
 /**
  *     ata_scsi_simulate - simulate SCSI command on ATA device
  *     @dev: the target device
index c21589986c695f38756d1ced8a13422acfa3cac9..8b677bbf2d37be97d37e89c57441e26807a55e87 100644 (file)
@@ -538,7 +538,7 @@ static int vt8251_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
        return 0;
 }
 
-static void svia_configure(struct pci_dev *pdev)
+static void svia_configure(struct pci_dev *pdev, int board_id)
 {
        u8 tmp8;
 
@@ -577,7 +577,7 @@ static void svia_configure(struct pci_dev *pdev)
        }
 
        /*
-        * vt6421 has problems talking to some drives.  The following
+        * vt6420/1 has problems talking to some drives.  The following
         * is the fix from Joseph Chan <JosephChan@via.com.tw>.
         *
         * When host issues HOLD, device may send up to 20DW of data
@@ -596,8 +596,9 @@ static void svia_configure(struct pci_dev *pdev)
         *
         * https://bugzilla.kernel.org/show_bug.cgi?id=15173
         * http://article.gmane.org/gmane.linux.ide/46352
+        * http://thread.gmane.org/gmane.linux.kernel/1062139
         */
-       if (pdev->device == 0x3249) {
+       if (board_id == vt6420 || board_id == vt6421) {
                pci_read_config_byte(pdev, 0x52, &tmp8);
                tmp8 |= 1 << 2;
                pci_write_config_byte(pdev, 0x52, tmp8);
@@ -652,7 +653,7 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (rc)
                return rc;
 
-       svia_configure(pdev);
+       svia_configure(pdev, board_id);
 
        pci_set_master(pdev);
        return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
index 46b94762125b0b179792948cbd47be8a9bc8448f..f9b983ae68777544f5cc986f3e0e4e3b1f074179 100644 (file)
@@ -154,7 +154,7 @@ static int __init adummy_init(void)
                err = -ENOMEM;
                goto out;
        }
-       atm_dev = atm_dev_register(DEV_LABEL, &adummy_ops, -1, NULL);
+       atm_dev = atm_dev_register(DEV_LABEL, NULL, &adummy_ops, -1, NULL);
        if (!atm_dev) {
                printk(KERN_ERR DEV_LABEL ": atm_dev_register() failed\n");
                err = -ENODEV;
index a33896a482e6eb0e0dd964649b5b6d7d90e64858..ffe9b655292e148e929365fe5bd8cd1b86443411 100644 (file)
@@ -2244,7 +2244,8 @@ static int __devinit amb_probe(struct pci_dev *pci_dev, const struct pci_device_
                goto out_reset;
        }
 
-       dev->atm_dev = atm_dev_register (DEV_LABEL, &amb_ops, -1, NULL);
+       dev->atm_dev = atm_dev_register (DEV_LABEL, &pci_dev->dev, &amb_ops, -1,
+                                        NULL);
        if (!dev->atm_dev) {
                PRINTD (DBG_ERR, "failed to register Madge ATM adapter");
                err = -EINVAL;
index b9101818b47b4012d9c5589d7b8ffd672cb26fc7..2b464b631f22697ac5f177d371b94d5646683d8f 100644 (file)
@@ -366,7 +366,7 @@ static int atmtcp_create(int itf,int persist,struct atm_dev **result)
        if (!dev_data)
                return -ENOMEM;
 
-       dev = atm_dev_register(DEV_LABEL,&atmtcp_v_dev_ops,itf,NULL);
+       dev = atm_dev_register(DEV_LABEL,NULL,&atmtcp_v_dev_ops,itf,NULL);
        if (!dev) {
                kfree(dev_data);
                return itf == -1 ? -ENOMEM : -EBUSY;
index 97c5898cd76e894350dfcc3a444de9ce2d202e35..c495fae742008c6569da47d5c3ca91c7f5ad48b4 100644 (file)
@@ -2244,7 +2244,7 @@ static int __devinit eni_init_one(struct pci_dev *pci_dev,
                    &zeroes);
                if (!cpu_zeroes) goto out1;
        }
-       dev = atm_dev_register(DEV_LABEL,&ops,-1,NULL);
+       dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &ops, -1, NULL);
        if (!dev) goto out2;
        pci_set_drvdata(pci_dev, dev);
        eni_dev->pci_dev = pci_dev;
index 5d86bb803e9493443659f49180b68c147066a166..7d912baf01d444c6adaaa943f87e107ead7441b6 100644 (file)
@@ -1911,7 +1911,7 @@ static int __devinit firestream_init_one (struct pci_dev *pci_dev,
                    fs_dev, sizeof (struct fs_dev));
        if (!fs_dev)
                goto err_out;
-       atm_dev = atm_dev_register("fs", &ops, -1, NULL);
+       atm_dev = atm_dev_register("fs", &pci_dev->dev, &ops, -1, NULL);
        if (!atm_dev)
                goto err_out_free_fs_dev;
   
index c8fc69c85a062f81029495e827ae615547f964e9..962c309b40c035bea03e751fd9531de6eb7df1e9 100644 (file)
@@ -2567,14 +2567,14 @@ release:
 
 
 static int __devinit
-fore200e_register(struct fore200e* fore200e)
+fore200e_register(struct fore200e* fore200e, struct device *parent)
 {
     struct atm_dev* atm_dev;
 
     DPRINTK(2, "device %s being registered\n", fore200e->name);
 
-    atm_dev = atm_dev_register(fore200e->bus->proc_name, &fore200e_ops, -1,
-      NULL); 
+    atm_dev = atm_dev_register(fore200e->bus->proc_name, parent, &fore200e_ops,
+                               -1, NULL);
     if (atm_dev == NULL) {
        printk(FORE200E "unable to register device %s\n", fore200e->name);
        return -ENODEV;
@@ -2594,9 +2594,9 @@ fore200e_register(struct fore200e* fore200e)
 
 
 static int __devinit
-fore200e_init(struct fore200e* fore200e)
+fore200e_init(struct fore200e* fore200e, struct device *parent)
 {
-    if (fore200e_register(fore200e) < 0)
+    if (fore200e_register(fore200e, parent) < 0)
        return -ENODEV;
     
     if (fore200e->bus->configure(fore200e) < 0)
@@ -2662,7 +2662,7 @@ static int __devinit fore200e_sba_probe(struct platform_device *op,
 
        sprintf(fore200e->name, "%s-%d", bus->model_name, index);
 
-       err = fore200e_init(fore200e);
+       err = fore200e_init(fore200e, &op->dev);
        if (err < 0) {
                fore200e_shutdown(fore200e);
                kfree(fore200e);
@@ -2740,7 +2740,7 @@ fore200e_pca_detect(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent
 
     sprintf(fore200e->name, "%s-%d", bus->model_name, index);
 
-    err = fore200e_init(fore200e);
+    err = fore200e_init(fore200e, &pci_dev->dev);
     if (err < 0) {
        fore200e_shutdown(fore200e);
        goto out_free;
index 801e8b6e9d1fee08dd1b3d091ff3739193ee98cc..6cf59bf281dc1b601884586b7d8651ea0ecbeaa7 100644 (file)
@@ -366,7 +366,7 @@ he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
                goto init_one_failure;
        }
 
-       atm_dev = atm_dev_register(DEV_LABEL, &he_ops, -1, NULL);
+       atm_dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &he_ops, -1, NULL);
        if (!atm_dev) {
                err = -ENODEV;
                goto init_one_failure;
index a95790452a685f3325ed64af5db2f2596f911236..24761e1d6642d7c6a2c7dcb6e8d4073c89f76c64 100644 (file)
@@ -2733,7 +2733,8 @@ static int __devinit hrz_probe(struct pci_dev *pci_dev, const struct pci_device_
        PRINTD(DBG_INFO, "found Madge ATM adapter (hrz) at: IO %x, IRQ %u, MEM %p",
               iobase, irq, membase);
 
-       dev->atm_dev = atm_dev_register(DEV_LABEL, &hrz_ops, -1, NULL);
+       dev->atm_dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &hrz_ops, -1,
+                                       NULL);
        if (!(dev->atm_dev)) {
                PRINTD(DBG_ERR, "failed to register Madge ATM adapter");
                err = -EINVAL;
index bce57328ddde9addf376fe550a768194c4173c9b..bfb7feee0400df5c8f9a13adc0cde06a053c2ac7 100644 (file)
@@ -3698,7 +3698,8 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
                goto err_out_iounmap;
        }
 
-       dev = atm_dev_register("idt77252", &idt77252_ops, -1, NULL);
+       dev = atm_dev_register("idt77252", &pcidev->dev, &idt77252_ops, -1,
+                              NULL);
        if (!dev) {
                printk("%s: can't register atm device\n", card->name);
                err = -EIO;
index 9309d4724e1322effe4010042dc0a3136a432ebb..729254053758f0d3680ad67f52a32a07865f86b0 100644 (file)
@@ -3172,7 +3172,7 @@ static int __devinit ia_init_one(struct pci_dev *pdev,
                ret = -ENODEV;
                goto err_out_free_iadev;
        }
-       dev = atm_dev_register(DEV_LABEL, &ops, -1, NULL);
+       dev = atm_dev_register(DEV_LABEL, &pdev->dev, &ops, -1, NULL);
        if (!dev) {
                ret = -ENOMEM;
                goto err_out_disable_dev;
index cbe15a86c6698b2044b45469fa57f8d199aca15e..a395c9aab146ec4f78d0b05767c81b04889c16ef 100644 (file)
@@ -2591,7 +2591,7 @@ static int __devinit lanai_init_one(struct pci_dev *pci,
                return -ENOMEM;
        }
 
-       atmdev = atm_dev_register(DEV_LABEL, &ops, -1, NULL);
+       atmdev = atm_dev_register(DEV_LABEL, &pci->dev, &ops, -1, NULL);
        if (atmdev == NULL) {
                printk(KERN_ERR DEV_LABEL
                    ": couldn't register atm device!\n");
index 2f3516b7f118cd59e7b9156ba1b004a6caee6c86..6b313ee9231baa2cd37893ba26c5e4877462ba0a 100644 (file)
@@ -771,7 +771,8 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
        }
 
        /* Register device */
-       card->atmdev = atm_dev_register("nicstar", &atm_ops, -1, NULL);
+       card->atmdev = atm_dev_register("nicstar", &card->pcidev->dev, &atm_ops,
+                                       -1, NULL);
        if (card->atmdev == NULL) {
                printk("nicstar%d: can't register device.\n", i);
                error = 17;
index 2e08c996fd30a6156e8a0a19e46966824d3d89df..73fb1c4f4cd4e99f0b57df7977c22216a781e1e6 100644 (file)
@@ -166,7 +166,7 @@ static irqreturn_t solos_irq(int irq, void *dev_id);
 static struct atm_vcc* find_vcc(struct atm_dev *dev, short vpi, int vci);
 static int list_vccs(int vci);
 static void release_vccs(struct atm_dev *dev);
-static int atm_init(struct solos_card *);
+static int atm_init(struct solos_card *, struct device *);
 static void atm_remove(struct solos_card *);
 static int send_command(struct solos_card *card, int dev, const char *buf, size_t size);
 static void solos_bh(unsigned long);
@@ -1210,7 +1210,7 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
        if (db_firmware_upgrade)
                flash_upgrade(card, 3);
 
-       err = atm_init(card);
+       err = atm_init(card, &dev->dev);
        if (err)
                goto out_free_irq;
 
@@ -1233,7 +1233,7 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
        return err;
 }
 
-static int atm_init(struct solos_card *card)
+static int atm_init(struct solos_card *card, struct device *parent)
 {
        int i;
 
@@ -1244,7 +1244,7 @@ static int atm_init(struct solos_card *card)
                skb_queue_head_init(&card->tx_queue[i]);
                skb_queue_head_init(&card->cli_queue[i]);
 
-               card->atmdev[i] = atm_dev_register("solos-pci", &fpga_ops, -1, NULL);
+               card->atmdev[i] = atm_dev_register("solos-pci", parent, &fpga_ops, -1, NULL);
                if (!card->atmdev[i]) {
                        dev_err(&card->dev->dev, "Could not register ATM device %d\n", i);
                        atm_remove(card);
index 4e885d2da49c6f0b5899b9eb3d8d1a874e700ca3..624917902b656f249fd06b057090f0f9d7b97961 100644 (file)
@@ -1597,7 +1597,7 @@ static int __devinit zatm_init_one(struct pci_dev *pci_dev,
                goto out;
        }
 
-       dev = atm_dev_register(DEV_LABEL, &ops, -1, NULL);
+       dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &ops, -1, NULL);
        if (!dev)
                goto out_free;
 
index a1725e6488d3081628aa2923e1da77195c4d914a..7888501ad9ee1af078b47695a00c8074011797c3 100644 (file)
@@ -1341,7 +1341,7 @@ static struct request *set_next_request(void)
 {
        struct request_queue *q;
        int cnt = FD_MAX_UNITS;
-       struct request *rq;
+       struct request *rq = NULL;
 
        /* Find next queue we can dispatch from */
        fdc_queue = fdc_queue + 1;
index 4e4cc6c828cb71359ebb6f8aa5ab06335444c6bf..605a67e40bbfc902609233ebc52d22f8bc008e23 100644 (file)
@@ -1399,7 +1399,7 @@ static struct request *set_next_request(void)
 {
        struct request_queue *q;
        int old_pos = fdc_queue;
-       struct request *rq;
+       struct request *rq = NULL;
 
        do {
                q = unit[fdc_queue].disk->queue;
index a67d0a611a8ac1d53ee16a00963ef19ade3487c8..8e0f9256eb5829102b47977ea489e6e03b205fde 100644 (file)
@@ -66,6 +66,7 @@ MODULE_VERSION("3.6.26");
 MODULE_LICENSE("GPL");
 
 static DEFINE_MUTEX(cciss_mutex);
+static struct proc_dir_entry *proc_cciss;
 
 #include "cciss_cmd.h"
 #include "cciss.h"
@@ -363,8 +364,6 @@ static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG",
 #define ENG_GIG_FACTOR (ENG_GIG/512)
 #define ENGAGE_SCSI    "engage scsi"
 
-static struct proc_dir_entry *proc_cciss;
-
 static void cciss_seq_show_header(struct seq_file *seq)
 {
        ctlr_info_t *h = seq->private;
@@ -2835,6 +2834,8 @@ static int cciss_revalidate(struct gendisk *disk)
        InquiryData_struct *inq_buff = NULL;
 
        for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) {
+               if (!h->drv[logvol])
+                       continue;
                if (memcmp(h->drv[logvol]->LunID, drv->LunID,
                        sizeof(drv->LunID)) == 0) {
                        FOUND = 1;
index 89d8a7cc4054ba627b670a8786e05b1824f5a8b3..24487d4fb20297e6676a91e60c9525f26092e315 100644 (file)
@@ -3627,17 +3627,19 @@ static void drbdd(struct drbd_conf *mdev)
                }
 
                shs = drbd_cmd_handler[cmd].pkt_size - sizeof(union p_header);
-               rv = drbd_recv(mdev, &header->h80.payload, shs);
-               if (unlikely(rv != shs)) {
-                       dev_err(DEV, "short read while reading sub header: rv=%d\n", rv);
-                       goto err_out;
-               }
-
                if (packet_size - shs > 0 && !drbd_cmd_handler[cmd].expect_payload) {
                        dev_err(DEV, "No payload expected %s l:%d\n", cmdname(cmd), packet_size);
                        goto err_out;
                }
 
+               if (shs) {
+                       rv = drbd_recv(mdev, &header->h80.payload, shs);
+                       if (unlikely(rv != shs)) {
+                               dev_err(DEV, "short read while reading sub header: rv=%d\n", rv);
+                               goto err_out;
+                       }
+               }
+
                rv = drbd_cmd_handler[cmd].function(mdev, cmd, packet_size - shs);
 
                if (unlikely(!rv)) {
index 181ea0364822d4f6d559ff1101d95d7d675eff7f..ab2bd09d54b4bfc9fbf7bf74c2e46dbbeb389db5 100644 (file)
@@ -339,7 +339,8 @@ static inline int _req_mod(struct drbd_request *req, enum drbd_req_event what)
 }
 
 /* completion of master bio is outside of spinlock.
- * If you need it irqsave, do it your self! */
+ * If you need it irqsave, do it your self!
+ * Which means: don't use from bio endio callback. */
 static inline int req_mod(struct drbd_request *req,
                enum drbd_req_event what)
 {
index 47d223c2409c8cebbd233103d8ff1790dfae833c..34f224b018b37b1e1781134fedf67179799ab20e 100644 (file)
@@ -193,8 +193,10 @@ void drbd_endio_sec(struct bio *bio, int error)
  */
 void drbd_endio_pri(struct bio *bio, int error)
 {
+       unsigned long flags;
        struct drbd_request *req = bio->bi_private;
        struct drbd_conf *mdev = req->mdev;
+       struct bio_and_error m;
        enum drbd_req_event what;
        int uptodate = bio_flagged(bio, BIO_UPTODATE);
 
@@ -220,7 +222,13 @@ void drbd_endio_pri(struct bio *bio, int error)
        bio_put(req->private_bio);
        req->private_bio = ERR_PTR(error);
 
-       req_mod(req, what);
+       /* not req_mod(), we need irqsave here! */
+       spin_lock_irqsave(&mdev->req_lock, flags);
+       __req_mod(req, what, &m);
+       spin_unlock_irqrestore(&mdev->req_lock, flags);
+
+       if (m.bio)
+               complete_master_bio(mdev, &m);
 }
 
 int w_read_retry_remote(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
index 6ec9d53806c5e791b5d56fa0ae27dae0e903db02..008d4a00b50df57f529528b1b2eefec9b379a544 100644 (file)
 
 
 
-   Instructions for use
-   --------------------
+   For usage instructions, please refer to:
 
-   1) Map a Linux block device to an existing rbd image.
-
-      Usage: <mon ip addr> <options> <pool name> <rbd image name> [snap name]
-
-      $ echo "192.168.0.1 name=admin rbd foo" > /sys/class/rbd/add
-
-      The snapshot name can be "-" or omitted to map the image read/write.
-
-   2) List all active blkdev<->object mappings.
-
-      In this example, we have performed step #1 twice, creating two blkdevs,
-      mapped to two separate rados objects in the rados rbd pool
-
-      $ cat /sys/class/rbd/list
-      #id     major   client_name     pool    name    snap    KB
-      0       254     client4143      rbd     foo     -      1024000
-
-      The columns, in order, are:
-      - blkdev unique id
-      - blkdev assigned major
-      - rados client id
-      - rados pool name
-      - rados block device name
-      - mapped snapshot ("-" if none)
-      - device size in KB
-
-
-   3) Create a snapshot.
-
-      Usage: <blkdev id> <snapname>
-
-      $ echo "0 mysnap" > /sys/class/rbd/snap_create
-
-
-   4) Listing a snapshot.
-
-      $ cat /sys/class/rbd/snaps_list
-      #id     snap    KB
-      0       -       1024000 (*)
-      0       foo     1024000
-
-      The columns, in order, are:
-      - blkdev unique id
-      - snapshot name, '-' means none (active read/write version)
-      - size of device at time of snapshot
-      - the (*) indicates this is the active version
-
-   5) Rollback to snapshot.
-
-      Usage: <blkdev id> <snapname>
-
-      $ echo "0 mysnap" > /sys/class/rbd/snap_rollback
-
-
-   6) Mapping an image using snapshot.
-
-      A snapshot mapping is read-only. This is being done by passing
-      snap=<snapname> to the options when adding a device.
-
-      $ echo "192.168.0.1 name=admin,snap=mysnap rbd foo" > /sys/class/rbd/add
-
-
-   7) Remove an active blkdev<->rbd image mapping.
-
-      In this example, we remove the mapping with blkdev unique id 1.
-
-      $ echo 1 > /sys/class/rbd/remove
-
-
-   NOTE:  The actual creation and deletion of rados objects is outside the scope
-   of this driver.
+                 Documentation/ABI/testing/sysfs-bus-rbd
 
  */
 
@@ -163,6 +92,14 @@ struct rbd_request {
        u64                     len;
 };
 
+struct rbd_snap {
+       struct  device          dev;
+       const char              *name;
+       size_t                  size;
+       struct list_head        node;
+       u64                     id;
+};
+
 /*
  * a single device
  */
@@ -193,21 +130,60 @@ struct rbd_device {
        int read_only;
 
        struct list_head        node;
+
+       /* list of snapshots */
+       struct list_head        snaps;
+
+       /* sysfs related */
+       struct device           dev;
+};
+
+static struct bus_type rbd_bus_type = {
+       .name           = "rbd",
 };
 
 static spinlock_t node_lock;      /* protects client get/put */
 
-static struct class *class_rbd;          /* /sys/class/rbd */
 static DEFINE_MUTEX(ctl_mutex);          /* Serialize open/close/setup/teardown */
 static LIST_HEAD(rbd_dev_list);    /* devices */
 static LIST_HEAD(rbd_client_list);      /* clients */
 
+static int __rbd_init_snaps_header(struct rbd_device *rbd_dev);
+static void rbd_dev_release(struct device *dev);
+static ssize_t rbd_snap_rollback(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf,
+                                size_t size);
+static ssize_t rbd_snap_add(struct device *dev,
+                           struct device_attribute *attr,
+                           const char *buf,
+                           size_t count);
+static void __rbd_remove_snap_dev(struct rbd_device *rbd_dev,
+                                 struct rbd_snap *snap);;
+
+
+static struct rbd_device *dev_to_rbd(struct device *dev)
+{
+       return container_of(dev, struct rbd_device, dev);
+}
+
+static struct device *rbd_get_dev(struct rbd_device *rbd_dev)
+{
+       return get_device(&rbd_dev->dev);
+}
+
+static void rbd_put_dev(struct rbd_device *rbd_dev)
+{
+       put_device(&rbd_dev->dev);
+}
 
 static int rbd_open(struct block_device *bdev, fmode_t mode)
 {
        struct gendisk *disk = bdev->bd_disk;
        struct rbd_device *rbd_dev = disk->private_data;
 
+       rbd_get_dev(rbd_dev);
+
        set_device_ro(bdev, rbd_dev->read_only);
 
        if ((mode & FMODE_WRITE) && rbd_dev->read_only)
@@ -216,9 +192,19 @@ static int rbd_open(struct block_device *bdev, fmode_t mode)
        return 0;
 }
 
+static int rbd_release(struct gendisk *disk, fmode_t mode)
+{
+       struct rbd_device *rbd_dev = disk->private_data;
+
+       rbd_put_dev(rbd_dev);
+
+       return 0;
+}
+
 static const struct block_device_operations rbd_bd_ops = {
        .owner                  = THIS_MODULE,
        .open                   = rbd_open,
+       .release                = rbd_release,
 };
 
 /*
@@ -361,7 +347,6 @@ static int rbd_header_from_disk(struct rbd_image_header *header,
        int ret = -ENOMEM;
 
        init_rwsem(&header->snap_rwsem);
-
        header->snap_names_len = le64_to_cpu(ondisk->snap_names_len);
        header->snapc = kmalloc(sizeof(struct ceph_snap_context) +
                                snap_count *
@@ -1256,10 +1241,20 @@ bad:
        return -ERANGE;
 }
 
+static void __rbd_remove_all_snaps(struct rbd_device *rbd_dev)
+{
+       struct rbd_snap *snap;
+
+       while (!list_empty(&rbd_dev->snaps)) {
+               snap = list_first_entry(&rbd_dev->snaps, struct rbd_snap, node);
+               __rbd_remove_snap_dev(rbd_dev, snap);
+       }
+}
+
 /*
  * only read the first part of the ondisk header, without the snaps info
  */
-static int rbd_update_snaps(struct rbd_device *rbd_dev)
+static int __rbd_update_snaps(struct rbd_device *rbd_dev)
 {
        int ret;
        struct rbd_image_header h;
@@ -1280,12 +1275,15 @@ static int rbd_update_snaps(struct rbd_device *rbd_dev)
        rbd_dev->header.total_snaps = h.total_snaps;
        rbd_dev->header.snapc = h.snapc;
        rbd_dev->header.snap_names = h.snap_names;
+       rbd_dev->header.snap_names_len = h.snap_names_len;
        rbd_dev->header.snap_sizes = h.snap_sizes;
        rbd_dev->header.snapc->seq = snap_seq;
 
+       ret = __rbd_init_snaps_header(rbd_dev);
+
        up_write(&rbd_dev->header.snap_rwsem);
 
-       return 0;
+       return ret;
 }
 
 static int rbd_init_disk(struct rbd_device *rbd_dev)
@@ -1300,6 +1298,11 @@ static int rbd_init_disk(struct rbd_device *rbd_dev)
        if (rc)
                return rc;
 
+       /* no need to lock here, as rbd_dev is not registered yet */
+       rc = __rbd_init_snaps_header(rbd_dev);
+       if (rc)
+               return rc;
+
        rc = rbd_header_set_snap(rbd_dev, rbd_dev->snap_name, &total_size);
        if (rc)
                return rc;
@@ -1343,54 +1346,360 @@ out:
        return rc;
 }
 
-/********************************************************************
- * /sys/class/rbd/
- *                   add       map rados objects to blkdev
- *                   remove    unmap rados objects
- *                   list      show mappings
- *******************************************************************/
+/*
+  sysfs
+*/
+
+static ssize_t rbd_size_show(struct device *dev,
+                            struct device_attribute *attr, char *buf)
+{
+       struct rbd_device *rbd_dev = dev_to_rbd(dev);
+
+       return sprintf(buf, "%llu\n", (unsigned long long)rbd_dev->header.image_size);
+}
+
+static ssize_t rbd_major_show(struct device *dev,
+                             struct device_attribute *attr, char *buf)
+{
+       struct rbd_device *rbd_dev = dev_to_rbd(dev);
 
-static void class_rbd_release(struct class *cls)
+       return sprintf(buf, "%d\n", rbd_dev->major);
+}
+
+static ssize_t rbd_client_id_show(struct device *dev,
+                                 struct device_attribute *attr, char *buf)
 {
-       kfree(cls);
+       struct rbd_device *rbd_dev = dev_to_rbd(dev);
+
+       return sprintf(buf, "client%lld\n", ceph_client_id(rbd_dev->client));
 }
 
-static ssize_t class_rbd_list(struct class *c,
-                             struct class_attribute *attr,
-                             char *data)
+static ssize_t rbd_pool_show(struct device *dev,
+                            struct device_attribute *attr, char *buf)
 {
-       int n = 0;
-       struct list_head *tmp;
-       int max = PAGE_SIZE;
+       struct rbd_device *rbd_dev = dev_to_rbd(dev);
+
+       return sprintf(buf, "%s\n", rbd_dev->pool_name);
+}
+
+static ssize_t rbd_name_show(struct device *dev,
+                            struct device_attribute *attr, char *buf)
+{
+       struct rbd_device *rbd_dev = dev_to_rbd(dev);
+
+       return sprintf(buf, "%s\n", rbd_dev->obj);
+}
+
+static ssize_t rbd_snap_show(struct device *dev,
+                            struct device_attribute *attr,
+                            char *buf)
+{
+       struct rbd_device *rbd_dev = dev_to_rbd(dev);
+
+       return sprintf(buf, "%s\n", rbd_dev->snap_name);
+}
+
+static ssize_t rbd_image_refresh(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf,
+                                size_t size)
+{
+       struct rbd_device *rbd_dev = dev_to_rbd(dev);
+       int rc;
+       int ret = size;
 
        mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
 
-       n += snprintf(data, max,
-                     "#id\tmajor\tclient_name\tpool\tname\tsnap\tKB\n");
+       rc = __rbd_update_snaps(rbd_dev);
+       if (rc < 0)
+               ret = rc;
 
-       list_for_each(tmp, &rbd_dev_list) {
-               struct rbd_device *rbd_dev;
+       mutex_unlock(&ctl_mutex);
+       return ret;
+}
 
-               rbd_dev = list_entry(tmp, struct rbd_device, node);
-               n += snprintf(data+n, max-n,
-                             "%d\t%d\tclient%lld\t%s\t%s\t%s\t%lld\n",
-                             rbd_dev->id,
-                             rbd_dev->major,
-                             ceph_client_id(rbd_dev->client),
-                             rbd_dev->pool_name,
-                             rbd_dev->obj, rbd_dev->snap_name,
-                             rbd_dev->header.image_size >> 10);
-               if (n == max)
+static DEVICE_ATTR(size, S_IRUGO, rbd_size_show, NULL);
+static DEVICE_ATTR(major, S_IRUGO, rbd_major_show, NULL);
+static DEVICE_ATTR(client_id, S_IRUGO, rbd_client_id_show, NULL);
+static DEVICE_ATTR(pool, S_IRUGO, rbd_pool_show, NULL);
+static DEVICE_ATTR(name, S_IRUGO, rbd_name_show, NULL);
+static DEVICE_ATTR(refresh, S_IWUSR, NULL, rbd_image_refresh);
+static DEVICE_ATTR(current_snap, S_IRUGO, rbd_snap_show, NULL);
+static DEVICE_ATTR(create_snap, S_IWUSR, NULL, rbd_snap_add);
+static DEVICE_ATTR(rollback_snap, S_IWUSR, NULL, rbd_snap_rollback);
+
+static struct attribute *rbd_attrs[] = {
+       &dev_attr_size.attr,
+       &dev_attr_major.attr,
+       &dev_attr_client_id.attr,
+       &dev_attr_pool.attr,
+       &dev_attr_name.attr,
+       &dev_attr_current_snap.attr,
+       &dev_attr_refresh.attr,
+       &dev_attr_create_snap.attr,
+       &dev_attr_rollback_snap.attr,
+       NULL
+};
+
+static struct attribute_group rbd_attr_group = {
+       .attrs = rbd_attrs,
+};
+
+static const struct attribute_group *rbd_attr_groups[] = {
+       &rbd_attr_group,
+       NULL
+};
+
+static void rbd_sysfs_dev_release(struct device *dev)
+{
+}
+
+static struct device_type rbd_device_type = {
+       .name           = "rbd",
+       .groups         = rbd_attr_groups,
+       .release        = rbd_sysfs_dev_release,
+};
+
+
+/*
+  sysfs - snapshots
+*/
+
+static ssize_t rbd_snap_size_show(struct device *dev,
+                                 struct device_attribute *attr,
+                                 char *buf)
+{
+       struct rbd_snap *snap = container_of(dev, struct rbd_snap, dev);
+
+       return sprintf(buf, "%lld\n", (long long)snap->size);
+}
+
+static ssize_t rbd_snap_id_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct rbd_snap *snap = container_of(dev, struct rbd_snap, dev);
+
+       return sprintf(buf, "%lld\n", (long long)snap->id);
+}
+
+static DEVICE_ATTR(snap_size, S_IRUGO, rbd_snap_size_show, NULL);
+static DEVICE_ATTR(snap_id, S_IRUGO, rbd_snap_id_show, NULL);
+
+static struct attribute *rbd_snap_attrs[] = {
+       &dev_attr_snap_size.attr,
+       &dev_attr_snap_id.attr,
+       NULL,
+};
+
+static struct attribute_group rbd_snap_attr_group = {
+       .attrs = rbd_snap_attrs,
+};
+
+static void rbd_snap_dev_release(struct device *dev)
+{
+       struct rbd_snap *snap = container_of(dev, struct rbd_snap, dev);
+       kfree(snap->name);
+       kfree(snap);
+}
+
+static const struct attribute_group *rbd_snap_attr_groups[] = {
+       &rbd_snap_attr_group,
+       NULL
+};
+
+static struct device_type rbd_snap_device_type = {
+       .groups         = rbd_snap_attr_groups,
+       .release        = rbd_snap_dev_release,
+};
+
+static void __rbd_remove_snap_dev(struct rbd_device *rbd_dev,
+                                 struct rbd_snap *snap)
+{
+       list_del(&snap->node);
+       device_unregister(&snap->dev);
+}
+
+static int rbd_register_snap_dev(struct rbd_device *rbd_dev,
+                                 struct rbd_snap *snap,
+                                 struct device *parent)
+{
+       struct device *dev = &snap->dev;
+       int ret;
+
+       dev->type = &rbd_snap_device_type;
+       dev->parent = parent;
+       dev->release = rbd_snap_dev_release;
+       dev_set_name(dev, "snap_%s", snap->name);
+       ret = device_register(dev);
+
+       return ret;
+}
+
+static int __rbd_add_snap_dev(struct rbd_device *rbd_dev,
+                             int i, const char *name,
+                             struct rbd_snap **snapp)
+{
+       int ret;
+       struct rbd_snap *snap = kzalloc(sizeof(*snap), GFP_KERNEL);
+       if (!snap)
+               return -ENOMEM;
+       snap->name = kstrdup(name, GFP_KERNEL);
+       snap->size = rbd_dev->header.snap_sizes[i];
+       snap->id = rbd_dev->header.snapc->snaps[i];
+       if (device_is_registered(&rbd_dev->dev)) {
+               ret = rbd_register_snap_dev(rbd_dev, snap,
+                                            &rbd_dev->dev);
+               if (ret < 0)
+                       goto err;
+       }
+       *snapp = snap;
+       return 0;
+err:
+       kfree(snap->name);
+       kfree(snap);
+       return ret;
+}
+
+/*
+ * search for the previous snap in a null delimited string list
+ */
+const char *rbd_prev_snap_name(const char *name, const char *start)
+{
+       if (name < start + 2)
+               return NULL;
+
+       name -= 2;
+       while (*name) {
+               if (name == start)
+                       return start;
+               name--;
+       }
+       return name + 1;
+}
+
+/*
+ * compare the old list of snapshots that we have to what's in the header
+ * and update it accordingly. Note that the header holds the snapshots
+ * in a reverse order (from newest to oldest) and we need to go from
+ * older to new so that we don't get a duplicate snap name when
+ * doing the process (e.g., removed snapshot and recreated a new
+ * one with the same name.
+ */
+static int __rbd_init_snaps_header(struct rbd_device *rbd_dev)
+{
+       const char *name, *first_name;
+       int i = rbd_dev->header.total_snaps;
+       struct rbd_snap *snap, *old_snap = NULL;
+       int ret;
+       struct list_head *p, *n;
+
+       first_name = rbd_dev->header.snap_names;
+       name = first_name + rbd_dev->header.snap_names_len;
+
+       list_for_each_prev_safe(p, n, &rbd_dev->snaps) {
+               u64 cur_id;
+
+               old_snap = list_entry(p, struct rbd_snap, node);
+
+               if (i)
+                       cur_id = rbd_dev->header.snapc->snaps[i - 1];
+
+               if (!i || old_snap->id < cur_id) {
+                       /* old_snap->id was skipped, thus was removed */
+                       __rbd_remove_snap_dev(rbd_dev, old_snap);
+                       continue;
+               }
+               if (old_snap->id == cur_id) {
+                       /* we have this snapshot already */
+                       i--;
+                       name = rbd_prev_snap_name(name, first_name);
+                       continue;
+               }
+               for (; i > 0;
+                    i--, name = rbd_prev_snap_name(name, first_name)) {
+                       if (!name) {
+                               WARN_ON(1);
+                               return -EINVAL;
+                       }
+                       cur_id = rbd_dev->header.snapc->snaps[i];
+                       /* snapshot removal? handle it above */
+                       if (cur_id >= old_snap->id)
+                               break;
+                       /* a new snapshot */
+                       ret = __rbd_add_snap_dev(rbd_dev, i - 1, name, &snap);
+                       if (ret < 0)
+                               return ret;
+
+                       /* note that we add it backward so using n and not p */
+                       list_add(&snap->node, n);
+                       p = &snap->node;
+               }
+       }
+       /* we're done going over the old snap list, just add what's left */
+       for (; i > 0; i--) {
+               name = rbd_prev_snap_name(name, first_name);
+               if (!name) {
+                       WARN_ON(1);
+                       return -EINVAL;
+               }
+               ret = __rbd_add_snap_dev(rbd_dev, i - 1, name, &snap);
+               if (ret < 0)
+                       return ret;
+               list_add(&snap->node, &rbd_dev->snaps);
+       }
+
+       return 0;
+}
+
+
+static void rbd_root_dev_release(struct device *dev)
+{
+}
+
+static struct device rbd_root_dev = {
+       .init_name =    "rbd",
+       .release =      rbd_root_dev_release,
+};
+
+static int rbd_bus_add_dev(struct rbd_device *rbd_dev)
+{
+       int ret = -ENOMEM;
+       struct device *dev;
+       struct rbd_snap *snap;
+
+       mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+       dev = &rbd_dev->dev;
+
+       dev->bus = &rbd_bus_type;
+       dev->type = &rbd_device_type;
+       dev->parent = &rbd_root_dev;
+       dev->release = rbd_dev_release;
+       dev_set_name(dev, "%d", rbd_dev->id);
+       ret = device_register(dev);
+       if (ret < 0)
+               goto done_free;
+
+       list_for_each_entry(snap, &rbd_dev->snaps, node) {
+               ret = rbd_register_snap_dev(rbd_dev, snap,
+                                            &rbd_dev->dev);
+               if (ret < 0)
                        break;
        }
 
        mutex_unlock(&ctl_mutex);
-       return n;
+       return 0;
+done_free:
+       mutex_unlock(&ctl_mutex);
+       return ret;
 }
 
-static ssize_t class_rbd_add(struct class *c,
-                            struct class_attribute *attr,
-                            const char *buf, size_t count)
+static void rbd_bus_del_dev(struct rbd_device *rbd_dev)
+{
+       device_unregister(&rbd_dev->dev);
+}
+
+static ssize_t rbd_add(struct bus_type *bus, const char *buf, size_t count)
 {
        struct ceph_osd_client *osdc;
        struct rbd_device *rbd_dev;
@@ -1419,6 +1728,7 @@ static ssize_t class_rbd_add(struct class *c,
        /* static rbd_device initialization */
        spin_lock_init(&rbd_dev->lock);
        INIT_LIST_HEAD(&rbd_dev->node);
+       INIT_LIST_HEAD(&rbd_dev->snaps);
 
        /* generate unique id: find highest unique id, add one */
        mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
@@ -1478,6 +1788,9 @@ static ssize_t class_rbd_add(struct class *c,
        }
        rbd_dev->major = irc;
 
+       rc = rbd_bus_add_dev(rbd_dev);
+       if (rc)
+               goto err_out_disk;
        /* set up and announce blkdev mapping */
        rc = rbd_init_disk(rbd_dev);
        if (rc)
@@ -1487,6 +1800,8 @@ static ssize_t class_rbd_add(struct class *c,
 
 err_out_blkdev:
        unregister_blkdev(rbd_dev->major, rbd_dev->name);
+err_out_disk:
+       rbd_free_disk(rbd_dev);
 err_out_client:
        rbd_put_client(rbd_dev);
        mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
@@ -1518,35 +1833,10 @@ static struct rbd_device *__rbd_get_dev(unsigned long id)
        return NULL;
 }
 
-static ssize_t class_rbd_remove(struct class *c,
-                               struct class_attribute *attr,
-                               const char *buf,
-                               size_t count)
+static void rbd_dev_release(struct device *dev)
 {
-       struct rbd_device *rbd_dev = NULL;
-       int target_id, rc;
-       unsigned long ul;
-
-       rc = strict_strtoul(buf, 10, &ul);
-       if (rc)
-               return rc;
-
-       /* convert to int; abort if we lost anything in the conversion */
-       target_id = (int) ul;
-       if (target_id != ul)
-               return -EINVAL;
-
-       /* remove object from list immediately */
-       mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
-
-       rbd_dev = __rbd_get_dev(target_id);
-       if (rbd_dev)
-               list_del_init(&rbd_dev->node);
-
-       mutex_unlock(&ctl_mutex);
-
-       if (!rbd_dev)
-               return -ENOENT;
+       struct rbd_device *rbd_dev =
+                       container_of(dev, struct rbd_device, dev);
 
        rbd_put_client(rbd_dev);
 
@@ -1557,67 +1847,11 @@ static ssize_t class_rbd_remove(struct class *c,
 
        /* release module ref */
        module_put(THIS_MODULE);
-
-       return count;
 }
 
-static ssize_t class_rbd_snaps_list(struct class *c,
-                             struct class_attribute *attr,
-                             char *data)
-{
-       struct rbd_device *rbd_dev = NULL;
-       struct list_head *tmp;
-       struct rbd_image_header *header;
-       int i, n = 0, max = PAGE_SIZE;
-       int ret;
-
-       mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
-
-       n += snprintf(data, max, "#id\tsnap\tKB\n");
-
-       list_for_each(tmp, &rbd_dev_list) {
-               char *names, *p;
-               struct ceph_snap_context *snapc;
-
-               rbd_dev = list_entry(tmp, struct rbd_device, node);
-               header = &rbd_dev->header;
-
-               down_read(&header->snap_rwsem);
-
-               names = header->snap_names;
-               snapc = header->snapc;
-
-               n += snprintf(data + n, max - n, "%d\t%s\t%lld%s\n",
-                             rbd_dev->id, RBD_SNAP_HEAD_NAME,
-                             header->image_size >> 10,
-                             (!rbd_dev->cur_snap ? " (*)" : ""));
-               if (n == max)
-                       break;
-
-               p = names;
-               for (i = 0; i < header->total_snaps; i++, p += strlen(p) + 1) {
-                       n += snprintf(data + n, max - n, "%d\t%s\t%lld%s\n",
-                             rbd_dev->id, p, header->snap_sizes[i] >> 10,
-                             (rbd_dev->cur_snap &&
-                              (snap_index(header, i) == rbd_dev->cur_snap) ?
-                              " (*)" : ""));
-                       if (n == max)
-                               break;
-               }
-
-               up_read(&header->snap_rwsem);
-       }
-
-
-       ret = n;
-       mutex_unlock(&ctl_mutex);
-       return ret;
-}
-
-static ssize_t class_rbd_snaps_refresh(struct class *c,
-                               struct class_attribute *attr,
-                               const char *buf,
-                               size_t count)
+static ssize_t rbd_remove(struct bus_type *bus,
+                         const char *buf,
+                         size_t count)
 {
        struct rbd_device *rbd_dev = NULL;
        int target_id, rc;
@@ -1641,95 +1875,70 @@ static ssize_t class_rbd_snaps_refresh(struct class *c,
                goto done;
        }
 
-       rc = rbd_update_snaps(rbd_dev);
-       if (rc < 0)
-               ret = rc;
+       list_del_init(&rbd_dev->node);
+
+       __rbd_remove_all_snaps(rbd_dev);
+       rbd_bus_del_dev(rbd_dev);
 
 done:
        mutex_unlock(&ctl_mutex);
        return ret;
 }
 
-static ssize_t class_rbd_snap_create(struct class *c,
-                               struct class_attribute *attr,
-                               const char *buf,
-                               size_t count)
+static ssize_t rbd_snap_add(struct device *dev,
+                           struct device_attribute *attr,
+                           const char *buf,
+                           size_t count)
 {
-       struct rbd_device *rbd_dev = NULL;
-       int target_id, ret;
-       char *name;
-
-       name = kmalloc(RBD_MAX_SNAP_NAME_LEN + 1, GFP_KERNEL);
+       struct rbd_device *rbd_dev = dev_to_rbd(dev);
+       int ret;
+       char *name = kmalloc(count + 1, GFP_KERNEL);
        if (!name)
                return -ENOMEM;
 
-       /* parse snaps add command */
-       if (sscanf(buf, "%d "
-                  "%" __stringify(RBD_MAX_SNAP_NAME_LEN) "s",
-                  &target_id,
-                  name) != 2) {
-               ret = -EINVAL;
-               goto done;
-       }
+       snprintf(name, count, "%s", buf);
 
        mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
 
-       rbd_dev = __rbd_get_dev(target_id);
-       if (!rbd_dev) {
-               ret = -ENOENT;
-               goto done_unlock;
-       }
-
        ret = rbd_header_add_snap(rbd_dev,
                                  name, GFP_KERNEL);
        if (ret < 0)
                goto done_unlock;
 
-       ret = rbd_update_snaps(rbd_dev);
+       ret = __rbd_update_snaps(rbd_dev);
        if (ret < 0)
                goto done_unlock;
 
        ret = count;
 done_unlock:
        mutex_unlock(&ctl_mutex);
-done:
        kfree(name);
        return ret;
 }
 
-static ssize_t class_rbd_rollback(struct class *c,
-                               struct class_attribute *attr,
-                               const char *buf,
-                               size_t count)
+static ssize_t rbd_snap_rollback(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf,
+                                size_t count)
 {
-       struct rbd_device *rbd_dev = NULL;
-       int target_id, ret;
+       struct rbd_device *rbd_dev = dev_to_rbd(dev);
+       int ret;
        u64 snapid;
-       char snap_name[RBD_MAX_SNAP_NAME_LEN];
        u64 cur_ofs;
-       char *seg_name;
+       char *seg_name = NULL;
+       char *snap_name = kmalloc(count + 1, GFP_KERNEL);
+       ret = -ENOMEM;
+       if (!snap_name)
+               return ret;
 
        /* parse snaps add command */
-       if (sscanf(buf, "%d "
-                  "%" __stringify(RBD_MAX_SNAP_NAME_LEN) "s",
-                  &target_id,
-                  snap_name) != 2) {
-               return -EINVAL;
-       }
-
-       ret = -ENOMEM;
+       snprintf(snap_name, count, "%s", buf);
        seg_name = kmalloc(RBD_MAX_SEG_NAME_LEN + 1, GFP_NOIO);
        if (!seg_name)
-               return ret;
+               goto done;
 
        mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
 
-       rbd_dev = __rbd_get_dev(target_id);
-       if (!rbd_dev) {
-               ret = -ENOENT;
-               goto done_unlock;
-       }
-
        ret = snap_by_name(&rbd_dev->header, snap_name, &snapid, NULL);
        if (ret < 0)
                goto done_unlock;
@@ -1750,7 +1959,7 @@ static ssize_t class_rbd_rollback(struct class *c,
                                   seg_name, ret);
        }
 
-       ret = rbd_update_snaps(rbd_dev);
+       ret = __rbd_update_snaps(rbd_dev);
        if (ret < 0)
                goto done_unlock;
 
@@ -1758,57 +1967,42 @@ static ssize_t class_rbd_rollback(struct class *c,
 
 done_unlock:
        mutex_unlock(&ctl_mutex);
+done:
        kfree(seg_name);
+       kfree(snap_name);
 
        return ret;
 }
 
-static struct class_attribute class_rbd_attrs[] = {
-       __ATTR(add,             0200, NULL, class_rbd_add),
-       __ATTR(remove,          0200, NULL, class_rbd_remove),
-       __ATTR(list,            0444, class_rbd_list, NULL),
-       __ATTR(snaps_refresh,   0200, NULL, class_rbd_snaps_refresh),
-       __ATTR(snap_create,     0200, NULL, class_rbd_snap_create),
-       __ATTR(snaps_list,      0444, class_rbd_snaps_list, NULL),
-       __ATTR(snap_rollback,   0200, NULL, class_rbd_rollback),
+static struct bus_attribute rbd_bus_attrs[] = {
+       __ATTR(add, S_IWUSR, NULL, rbd_add),
+       __ATTR(remove, S_IWUSR, NULL, rbd_remove),
        __ATTR_NULL
 };
 
 /*
  * create control files in sysfs
- * /sys/class/rbd/...
+ * /sys/bus/rbd/...
  */
 static int rbd_sysfs_init(void)
 {
-       int ret = -ENOMEM;
+       int ret;
 
-       class_rbd = kzalloc(sizeof(*class_rbd), GFP_KERNEL);
-       if (!class_rbd)
-               goto out;
+       rbd_bus_type.bus_attrs = rbd_bus_attrs;
 
-       class_rbd->name = DRV_NAME;
-       class_rbd->owner = THIS_MODULE;
-       class_rbd->class_release = class_rbd_release;
-       class_rbd->class_attrs = class_rbd_attrs;
+       ret = bus_register(&rbd_bus_type);
+        if (ret < 0)
+               return ret;
 
-       ret = class_register(class_rbd);
-       if (ret)
-               goto out_class;
-       return 0;
+       ret = device_register(&rbd_root_dev);
 
-out_class:
-       kfree(class_rbd);
-       class_rbd = NULL;
-       pr_err(DRV_NAME ": failed to create class rbd\n");
-out:
        return ret;
 }
 
 static void rbd_sysfs_cleanup(void)
 {
-       if (class_rbd)
-               class_destroy(class_rbd);
-       class_rbd = NULL;
+       device_unregister(&rbd_root_dev);
+       bus_unregister(&rbd_bus_type);
 }
 
 int __init rbd_init(void)
index 255035cfc88ab8ff3a279578487facd6d17a113f..657873e4328dbf05421b80e8d1231f27c5d3b369 100644 (file)
@@ -65,14 +65,14 @@ enum blkif_state {
 
 struct blk_shadow {
        struct blkif_request req;
-       unsigned long request;
+       struct request *request;
        unsigned long frame[BLKIF_MAX_SEGMENTS_PER_REQUEST];
 };
 
 static DEFINE_MUTEX(blkfront_mutex);
 static const struct block_device_operations xlvbd_block_fops;
 
-#define BLK_RING_SIZE __RING_SIZE((struct blkif_sring *)0, PAGE_SIZE)
+#define BLK_RING_SIZE __CONST_RING_SIZE(blkif, PAGE_SIZE)
 
 /*
  * We have one of these per vbd, whether ide, scsi or 'other'.  They
@@ -136,7 +136,7 @@ static void add_id_to_freelist(struct blkfront_info *info,
                               unsigned long id)
 {
        info->shadow[id].req.id  = info->shadow_free;
-       info->shadow[id].request = 0;
+       info->shadow[id].request = NULL;
        info->shadow_free = id;
 }
 
@@ -245,14 +245,11 @@ static int blkif_ioctl(struct block_device *bdev, fmode_t mode,
 }
 
 /*
- * blkif_queue_request
+ * Generate a Xen blkfront IO request from a blk layer request.  Reads
+ * and writes are handled as expected.  Since we lack a loose flush
+ * request, we map flushes into a full ordered barrier.
  *
- * request block io
- *
- * id: for guest use only.
- * operation: BLKIF_OP_{READ,WRITE,PROBE}
- * buffer: buffer to read/write into. this should be a
- *   virtual address in the guest os.
+ * @req: a request struct
  */
 static int blkif_queue_request(struct request *req)
 {
@@ -281,7 +278,7 @@ static int blkif_queue_request(struct request *req)
        /* Fill out a communications ring structure. */
        ring_req = RING_GET_REQUEST(&info->ring, info->ring.req_prod_pvt);
        id = get_id_from_freelist(info);
-       info->shadow[id].request = (unsigned long)req;
+       info->shadow[id].request = req;
 
        ring_req->id = id;
        ring_req->sector_number = (blkif_sector_t)blk_rq_pos(req);
@@ -290,6 +287,18 @@ static int blkif_queue_request(struct request *req)
        ring_req->operation = rq_data_dir(req) ?
                BLKIF_OP_WRITE : BLKIF_OP_READ;
 
+       if (req->cmd_flags & (REQ_FLUSH | REQ_FUA)) {
+               /*
+                * Ideally we could just do an unordered
+                * flush-to-disk, but all we have is a full write
+                * barrier at the moment.  However, a barrier write is
+                * a superset of FUA, so we can implement it the same
+                * way.  (It's also a FLUSH+FUA, since it is
+                * guaranteed ordered WRT previous writes.)
+                */
+               ring_req->operation = BLKIF_OP_WRITE_BARRIER;
+       }
+
        ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg);
        BUG_ON(ring_req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST);
 
@@ -634,7 +643,7 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
 
                bret = RING_GET_RESPONSE(&info->ring, i);
                id   = bret->id;
-               req  = (struct request *)info->shadow[id].request;
+               req  = info->shadow[id].request;
 
                blkif_completion(&info->shadow[id]);
 
@@ -647,6 +656,16 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
                                printk(KERN_WARNING "blkfront: %s: write barrier op failed\n",
                                       info->gd->disk_name);
                                error = -EOPNOTSUPP;
+                       }
+                       if (unlikely(bret->status == BLKIF_RSP_ERROR &&
+                                    info->shadow[id].req.nr_segments == 0)) {
+                               printk(KERN_WARNING "blkfront: %s: empty write barrier op failed\n",
+                                      info->gd->disk_name);
+                               error = -EOPNOTSUPP;
+                       }
+                       if (unlikely(error)) {
+                               if (error == -EOPNOTSUPP)
+                                       error = 0;
                                info->feature_flush = 0;
                                xlvbd_flush(info);
                        }
@@ -899,7 +918,7 @@ static int blkif_recover(struct blkfront_info *info)
        /* Stage 3: Find pending requests and requeue them. */
        for (i = 0; i < BLK_RING_SIZE; i++) {
                /* Not in use? */
-               if (copy[i].request == 0)
+               if (!copy[i].request)
                        continue;
 
                /* Grab a request slot and copy shadow state into it. */
@@ -916,9 +935,7 @@ static int blkif_recover(struct blkfront_info *info)
                                req->seg[j].gref,
                                info->xbdev->otherend_id,
                                pfn_to_mfn(info->shadow[req->id].frame[j]),
-                               rq_data_dir(
-                                       (struct request *)
-                                       info->shadow[req->id].request));
+                               rq_data_dir(info->shadow[req->id].request));
                info->shadow[req->id].req = *req;
 
                info->ring.req_prod_pvt++;
@@ -1067,14 +1084,8 @@ static void blkfront_connect(struct blkfront_info *info)
         */
        info->feature_flush = 0;
 
-       /*
-        * The driver doesn't properly handled empty flushes, so
-        * lets disable barrier support for now.
-        */
-#if 0
        if (!err && barrier)
-               info->feature_flush = REQ_FLUSH;
-#endif
+               info->feature_flush = REQ_FLUSH | REQ_FUA;
 
        err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size);
        if (err) {
index 128cae4e8629465429cf271209f587b8e192b3ad..949ed09c6361130c30c3ebda1bc4db02b00fa4c2 100644 (file)
 static struct usb_device_id ath3k_table[] = {
        /* Atheros AR3011 */
        { USB_DEVICE(0x0CF3, 0x3000) },
+
+       /* Atheros AR3011 with sflash firmware*/
+       { USB_DEVICE(0x0CF3, 0x3002) },
+
        { }     /* Terminating entry */
 };
 
index ab3894f742c3002a90a98b89f116ab30c75cdb28..1da773f899a2708f1c151b892098ed3ddbaf79cf 100644 (file)
@@ -99,6 +99,9 @@ static struct usb_device_id blacklist_table[] = {
        /* Broadcom BCM2033 without firmware */
        { USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE },
 
+       /* Atheros 3011 with sflash firmware */
+       { USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
+
        /* Broadcom BCM2035 */
        { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
        { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
@@ -239,7 +242,8 @@ static void btusb_intr_complete(struct urb *urb)
 
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (err < 0) {
-               BT_ERR("%s urb %p failed to resubmit (%d)",
+               if (err != -EPERM)
+                       BT_ERR("%s urb %p failed to resubmit (%d)",
                                                hdev->name, urb, -err);
                usb_unanchor_urb(urb);
        }
@@ -323,7 +327,8 @@ static void btusb_bulk_complete(struct urb *urb)
 
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (err < 0) {
-               BT_ERR("%s urb %p failed to resubmit (%d)",
+               if (err != -EPERM)
+                       BT_ERR("%s urb %p failed to resubmit (%d)",
                                                hdev->name, urb, -err);
                usb_unanchor_urb(urb);
        }
@@ -412,7 +417,8 @@ static void btusb_isoc_complete(struct urb *urb)
 
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (err < 0) {
-               BT_ERR("%s urb %p failed to resubmit (%d)",
+               if (err != -EPERM)
+                       BT_ERR("%s urb %p failed to resubmit (%d)",
                                                hdev->name, urb, -err);
                usb_unanchor_urb(urb);
        }
index 9272c38dd3c6ce8a66e9e0d2b0a5085ddd2973a7..16a2847b7cdbfeee43c9dcd212915a2f6b500711 100644 (file)
@@ -812,8 +812,10 @@ static int intel_fake_agp_fetch_size(void)
 
 static void i830_cleanup(void)
 {
-       kunmap(intel_private.i8xx_page);
-       intel_private.i8xx_flush_page = NULL;
+       if (intel_private.i8xx_flush_page) {
+               kunmap(intel_private.i8xx_flush_page);
+               intel_private.i8xx_flush_page = NULL;
+       }
 
        __free_page(intel_private.i8xx_page);
        intel_private.i8xx_page = NULL;
index 1030f8420137adb8ff7363eb259f9578026fe178..c17a305ecb2806256c2f7c4f1e9e0e4c3f878734 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/wait.h>
+#include <linux/acpi.h>
 #include "tpm.h"
 
 #define TPM_HEADER_SIZE 10
@@ -78,6 +79,26 @@ enum tis_defaults {
 static LIST_HEAD(tis_chips);
 static DEFINE_SPINLOCK(tis_lock);
 
+#ifdef CONFIG_ACPI
+static int is_itpm(struct pnp_dev *dev)
+{
+       struct acpi_device *acpi = pnp_acpi_device(dev);
+       struct acpi_hardware_id *id;
+
+       list_for_each_entry(id, &acpi->pnp.ids, list) {
+               if (!strcmp("INTC0102", id->id))
+                       return 1;
+       }
+
+       return 0;
+}
+#else
+static int is_itpm(struct pnp_dev *dev)
+{
+       return 0;
+}
+#endif
+
 static int check_locality(struct tpm_chip *chip, int l)
 {
        if ((ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
@@ -472,6 +493,9 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
                 "1.2 TPM (device-id 0x%X, rev-id %d)\n",
                 vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
 
+       if (is_itpm(to_pnp_dev(dev)))
+               itpm = 1;
+
        if (itpm)
                dev_info(dev, "Intel iTPM workaround enabled\n");
 
index 6c1b676643a9ef43fe3984bb8495996960cf4337..896a2ced1d27952d9288a48911ee406ccabe1ee7 100644 (file)
@@ -1547,31 +1547,16 @@ static int init_vqs(struct ports_device *portdev)
        nr_queues = use_multiport(portdev) ? (nr_ports + 1) * 2 : 2;
 
        vqs = kmalloc(nr_queues * sizeof(struct virtqueue *), GFP_KERNEL);
-       if (!vqs) {
-               err = -ENOMEM;
-               goto fail;
-       }
        io_callbacks = kmalloc(nr_queues * sizeof(vq_callback_t *), GFP_KERNEL);
-       if (!io_callbacks) {
-               err = -ENOMEM;
-               goto free_vqs;
-       }
        io_names = kmalloc(nr_queues * sizeof(char *), GFP_KERNEL);
-       if (!io_names) {
-               err = -ENOMEM;
-               goto free_callbacks;
-       }
        portdev->in_vqs = kmalloc(nr_ports * sizeof(struct virtqueue *),
                                  GFP_KERNEL);
-       if (!portdev->in_vqs) {
-               err = -ENOMEM;
-               goto free_names;
-       }
        portdev->out_vqs = kmalloc(nr_ports * sizeof(struct virtqueue *),
                                   GFP_KERNEL);
-       if (!portdev->out_vqs) {
+       if (!vqs || !io_callbacks || !io_names || !portdev->in_vqs ||
+                       !portdev->out_vqs) {
                err = -ENOMEM;
-               goto free_invqs;
+               goto free;
        }
 
        /*
@@ -1605,7 +1590,7 @@ static int init_vqs(struct ports_device *portdev)
                                              io_callbacks,
                                              (const char **)io_names);
        if (err)
-               goto free_outvqs;
+               goto free;
 
        j = 0;
        portdev->in_vqs[0] = vqs[0];
@@ -1621,23 +1606,19 @@ static int init_vqs(struct ports_device *portdev)
                        portdev->out_vqs[i] = vqs[j + 1];
                }
        }
-       kfree(io_callbacks);
        kfree(io_names);
+       kfree(io_callbacks);
        kfree(vqs);
 
        return 0;
 
-free_names:
-       kfree(io_names);
-free_callbacks:
-       kfree(io_callbacks);
-free_outvqs:
+free:
        kfree(portdev->out_vqs);
-free_invqs:
        kfree(portdev->in_vqs);
-free_vqs:
+       kfree(io_names);
+       kfree(io_callbacks);
        kfree(vqs);
-fail:
+
        return err;
 }
 
index d68d3aa1814b4ac635017e98cebd9625b0e7b40a..f975d24890fada4fd5db9c920fbc0a5c393d6511 100644 (file)
@@ -283,16 +283,21 @@ static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p,
        } while (delay);
 }
 
-static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta)
+static void __sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta)
 {
-       unsigned long flags;
-
        if (delta > p->max_match_value)
                dev_warn(&p->pdev->dev, "delta out of range\n");
 
-       spin_lock_irqsave(&p->lock, flags);
        p->next_match_value = delta;
        sh_cmt_clock_event_program_verify(p, 0);
+}
+
+static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&p->lock, flags);
+       __sh_cmt_set_next(p, delta);
        spin_unlock_irqrestore(&p->lock, flags);
 }
 
@@ -359,7 +364,7 @@ static int sh_cmt_start(struct sh_cmt_priv *p, unsigned long flag)
 
        /* setup timeout if no clockevent */
        if ((flag == FLAG_CLOCKSOURCE) && (!(p->flags & FLAG_CLOCKEVENT)))
-               sh_cmt_set_next(p, p->max_match_value);
+               __sh_cmt_set_next(p, p->max_match_value);
  out:
        spin_unlock_irqrestore(&p->lock, flags);
 
@@ -381,7 +386,7 @@ static void sh_cmt_stop(struct sh_cmt_priv *p, unsigned long flag)
 
        /* adjust the timeout to maximum if only clocksource left */
        if ((flag == FLAG_CLOCKEVENT) && (p->flags & FLAG_CLOCKSOURCE))
-               sh_cmt_set_next(p, p->max_match_value);
+               __sh_cmt_set_next(p, p->max_match_value);
 
        spin_unlock_irqrestore(&p->lock, flags);
 }
index e16c3fa8d2e3e3649a6cab79fb34db9323aae711..05117f1ad8674839331ddb7c473b4cfc739bbddd 100644 (file)
@@ -36,6 +36,7 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
 MODULE_DESCRIPTION("Generic userspace <-> kernelspace connector.");
+MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_CONNECTOR);
 
 static struct cn_dev cdev;
 
index a8a84f4587f20d7437af9ce12932dbf8e92a4e1b..64b21f5cd740fc5dfa1d5f09b1a944ed1f661440 100644 (file)
@@ -1,8 +1,8 @@
 ifeq ($(CONFIG_DMADEVICES_DEBUG),y)
-       EXTRA_CFLAGS    += -DDEBUG
+       ccflags-y       += -DDEBUG
 endif
 ifeq ($(CONFIG_DMADEVICES_VDEBUG),y)
-       EXTRA_CFLAGS    += -DVERBOSE_DEBUG
+       ccflags-y       += -DVERBOSE_DEBUG
 endif
 
 obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
index a0f3e6a06e06532b3701ade73b110d823eec591f..ea0ee81cff53e266643140eb752ef3ba26289c6a 100644 (file)
@@ -722,7 +722,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                        desc->lli.daddr = mem;
                        desc->lli.ctrla = ctrla
                                        | ATC_DST_WIDTH(mem_width)
-                                       | len >> mem_width;
+                                       | len >> reg_width;
                        desc->lli.ctrlb = ctrlb;
 
                        if (!first) {
index 286c3ac6bdcc236d020229ce0397ee9e78e07100..e5e172d21692d60a81fce6a9ed06e5807c57b370 100644 (file)
@@ -50,9 +50,11 @@ static void dma_init(struct fsldma_chan *chan)
                 * EIE - Error interrupt enable
                 * EOSIE - End of segments interrupt enable (basic mode)
                 * EOLNIE - End of links interrupt enable
+                * BWC - Bandwidth sharing among channels
                 */
-               DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_EIE
-                               | FSL_DMA_MR_EOLNIE | FSL_DMA_MR_EOSIE, 32);
+               DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_BWC
+                               | FSL_DMA_MR_EIE | FSL_DMA_MR_EOLNIE
+                               | FSL_DMA_MR_EOSIE, 32);
                break;
        case FSL_DMA_IP_83XX:
                /* Set the channel to below modes:
index cb4d6ff5159766baf7dce594dca6fb57e3d28dd2..ba9f403c0fbe9127441e7b92bf70c59c71cbde28 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright (C) 2007-2010 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Author:
  *   Zhang Wei <wei.zhang@freescale.com>, Jul 2007
 #define FSL_DMA_MR_DAHE                0x00002000
 #define FSL_DMA_MR_SAHE                0x00001000
 
+/*
+ * Bandwidth/pause control determines how many bytes a given
+ * channel is allowed to transfer before the DMA engine pauses
+ * the current channel and switches to the next channel
+ */
+#define FSL_DMA_MR_BWC         0x08000000
+
 /* Special MR definition for MPC8349 */
 #define FSL_DMA_MR_EOTIE       0x00000080
 #define FSL_DMA_MR_PRC_RM      0x00000800
index f629e4961af593f0ab5d3697fce77b306ab1ed9b..e53d438142bb8747cb8f288e64d75b0ba2e18a97 100644 (file)
@@ -379,7 +379,7 @@ static int __init imxdma_probe(struct platform_device *pdev)
        return 0;
 
 err_init:
-       while (i-- >= 0) {
+       while (--i >= 0) {
                struct imxdma_channel *imxdmac = &imxdma->channel[i];
                imx_dma_free(imxdmac->imxdma_channel);
        }
index 0834323a0599595b5a7fa8db1224a85125305031..d0602dd5d1b238eedf2500cd240ef0dc092800a8 100644 (file)
@@ -951,7 +951,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
                struct sdma_buffer_descriptor *bd = &sdmac->bd[i];
                int param;
 
-               bd->buffer_addr = sgl->dma_address;
+               bd->buffer_addr = sg->dma_address;
 
                count = sg->length;
 
@@ -1385,7 +1385,7 @@ static int __init sdma_module_init(void)
 {
        return platform_driver_probe(&sdma_driver, sdma_probe);
 }
-subsys_initcall(sdma_module_init);
+module_init(sdma_module_init);
 
 MODULE_AUTHOR("Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>");
 MODULE_DESCRIPTION("i.MX SDMA driver");
index 338bc4eed1f3f55b4de66c623a135289862c783f..3109bd94bc4f403c5aba44e8ff7cb092aa23b4cd 100644 (file)
@@ -1075,7 +1075,6 @@ static int mid_setup_dma(struct pci_dev *pdev)
        if (NULL == dma->dma_pool) {
                pr_err("ERR_MDMA:pci_pool_create failed\n");
                err = -ENOMEM;
-               kfree(dma);
                goto err_dma_pool;
        }
 
@@ -1186,7 +1185,6 @@ err_engine:
        free_irq(pdev->irq, dma);
 err_irq:
        pci_pool_destroy(dma->dma_pool);
-       kfree(dma);
 err_dma_pool:
        pr_err("ERR_MDMA:setup_dma failed: %d\n", err);
        return err;
@@ -1413,7 +1411,7 @@ static const struct dev_pm_ops intel_mid_dma_pm = {
        .runtime_idle = dma_runtime_idle,
 };
 
-static struct pci_driver intel_mid_dma_pci = {
+static struct pci_driver intel_mid_dma_pci_driver = {
        .name           =       "Intel MID DMA",
        .id_table       =       intel_mid_dma_ids,
        .probe          =       intel_mid_dma_probe,
@@ -1431,13 +1429,13 @@ static int __init intel_mid_dma_init(void)
 {
        pr_debug("INFO_MDMA: LNW DMA Driver Version %s\n",
                        INTEL_MID_DMA_DRIVER_VERSION);
-       return pci_register_driver(&intel_mid_dma_pci);
+       return pci_register_driver(&intel_mid_dma_pci_driver);
 }
 fs_initcall(intel_mid_dma_init);
 
 static void __exit intel_mid_dma_exit(void)
 {
-       pci_unregister_driver(&intel_mid_dma_pci);
+       pci_unregister_driver(&intel_mid_dma_pci_driver);
 }
 module_exit(intel_mid_dma_exit);
 
index 8997d3fb9051db0020bbeb721cc5a562d780bf47..0ff7270af25b97800d64fcc6f62c350f3115f322 100644 (file)
@@ -1,2 +1,2 @@
 obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o
-ioatdma-objs := pci.o dma.o dma_v2.o dma_v3.o dca.o
+ioatdma-y := pci.o dma.o dma_v2.o dma_v3.o dca.o
index 92b679024fedd9e033e9cbae311f7f8d7f221142..c064c89420d06080a737ea48356501aeeae869cd 100644 (file)
@@ -259,11 +259,6 @@ static void pdc_dostart(struct pch_dma_chan *pd_chan, struct pch_dma_desc* desc)
                return;
        }
 
-       channel_writel(pd_chan, DEV_ADDR, desc->regs.dev_addr);
-       channel_writel(pd_chan, MEM_ADDR, desc->regs.mem_addr);
-       channel_writel(pd_chan, SIZE, desc->regs.size);
-       channel_writel(pd_chan, NEXT, desc->regs.next);
-
        dev_dbg(chan2dev(&pd_chan->chan), "chan %d -> dev_addr: %x\n",
                pd_chan->chan.chan_id, desc->regs.dev_addr);
        dev_dbg(chan2dev(&pd_chan->chan), "chan %d -> mem_addr: %x\n",
@@ -273,10 +268,16 @@ static void pdc_dostart(struct pch_dma_chan *pd_chan, struct pch_dma_desc* desc)
        dev_dbg(chan2dev(&pd_chan->chan), "chan %d -> next: %x\n",
                pd_chan->chan.chan_id, desc->regs.next);
 
-       if (list_empty(&desc->tx_list))
+       if (list_empty(&desc->tx_list)) {
+               channel_writel(pd_chan, DEV_ADDR, desc->regs.dev_addr);
+               channel_writel(pd_chan, MEM_ADDR, desc->regs.mem_addr);
+               channel_writel(pd_chan, SIZE, desc->regs.size);
+               channel_writel(pd_chan, NEXT, desc->regs.next);
                pdc_set_mode(&pd_chan->chan, DMA_CTL0_ONESHOT);
-       else
+       } else {
+               channel_writel(pd_chan, NEXT, desc->txd.phys);
                pdc_set_mode(&pd_chan->chan, DMA_CTL0_SG);
+       }
 
        val = dma_readl(pd, CTL2);
        val |= 1 << (DMA_CTL2_START_SHIFT_BITS + pd_chan->chan.chan_id);
index 0d58a4a4487fbbaefc167182a627c6b0b0f222b3..cef584533ee8a9ca5628b874b5d6c644a4ad05f4 100644 (file)
@@ -4449,9 +4449,8 @@ static int __devinit ppc440spe_adma_probe(struct platform_device *ofdev,
 
        if (!request_mem_region(res.start, resource_size(&res),
                                dev_driver_string(&ofdev->dev))) {
-               dev_err(&ofdev->dev, "failed to request memory region "
-                       "(0x%016llx-0x%016llx)\n",
-                       (u64)res.start, (u64)res.end);
+               dev_err(&ofdev->dev, "failed to request memory region %pR\n",
+                       &res);
                initcode = PPC_ADMA_INIT_MEMREG;
                ret = -EBUSY;
                goto out;
index eb6b54dbb8064a9a5d2e71eb3261132195ff6f8d..85ffd5e38c5031690ea125cf5341fa70591bfa58 100644 (file)
@@ -1213,3 +1213,4 @@ module_exit(sh_dmae_exit);
 MODULE_AUTHOR("Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>");
 MODULE_DESCRIPTION("Renesas SH DMA Engine driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:sh-dma-engine");
index b3781399b38abf7997d00ae6ee7da7b023d9cd26..ba2898b3639bd0d26c489c3ac1ee228193ca51ab 100644 (file)
@@ -10,16 +10,16 @@ obj-$(CONFIG_EDAC)                  := edac_stub.o
 obj-$(CONFIG_EDAC_MM_EDAC)             += edac_core.o
 obj-$(CONFIG_EDAC_MCE)                 += edac_mce.o
 
-edac_core-objs := edac_mc.o edac_device.o edac_mc_sysfs.o edac_pci_sysfs.o
-edac_core-objs += edac_module.o edac_device_sysfs.o
+edac_core-y    := edac_mc.o edac_device.o edac_mc_sysfs.o edac_pci_sysfs.o
+edac_core-y    += edac_module.o edac_device_sysfs.o
 
 ifdef CONFIG_PCI
-edac_core-objs += edac_pci.o edac_pci_sysfs.o
+edac_core-y    += edac_pci.o edac_pci_sysfs.o
 endif
 
 obj-$(CONFIG_EDAC_MCE_INJ)             += mce_amd_inj.o
 
-edac_mce_amd-objs                      := mce_amd.o
+edac_mce_amd-y                         := mce_amd.o
 obj-$(CONFIG_EDAC_DECODE_MCE)          += edac_mce_amd.o
 
 obj-$(CONFIG_EDAC_AMD76X)              += amd76x_edac.o
index 8521401bbd751406e6f2752e10868f63c7e3b48a..eca9ba193e94a914aa64740f0b4262b8f7c99b81 100644 (file)
@@ -1572,7 +1572,7 @@ static int f10_match_to_this_node(struct amd64_pvt *pvt, int dram_range,
        debugf1("   HoleOffset=0x%x  HoleValid=0x%x IntlvSel=0x%x\n",
                        hole_off, hole_valid, intlv_sel);
 
-       if (intlv_en ||
+       if (intlv_en &&
            (intlv_sel != ((sys_addr >> 12) & intlv_en)))
                return -EINVAL;
 
index d7ca43a828bd3fe57b3de1341d7e75d1bed84f0a..251440cd50a3b41ea47f4511365909b707ebf0e8 100644 (file)
 #define MC_PROC_NAME_MAX_LEN   7
 
 #if PAGE_SHIFT < 20
-#define PAGES_TO_MiB( pages )  ( ( pages ) >> ( 20 - PAGE_SHIFT ) )
-#define MiB_TO_PAGES(mb)       ((mb) >> (20 - PAGE_SHIFT))
+#define PAGES_TO_MiB(pages)    ((pages) >> (20 - PAGE_SHIFT))
+#define MiB_TO_PAGES(mb)       ((mb) << (20 - PAGE_SHIFT))
 #else                          /* PAGE_SHIFT > 20 */
-#define PAGES_TO_MiB( pages )  ( ( pages ) << ( PAGE_SHIFT - 20 ) )
+#define PAGES_TO_MiB(pages)    ((pages) << (PAGE_SHIFT - 20))
 #define MiB_TO_PAGES(mb)       ((mb) >> (PAGE_SHIFT - 20))
 #endif
 
index ba6586a69ccce3b000fb22ee21512ab4673b44ac..795ea69c4d8f5fb6149c62fba8e085bd83363309 100644 (file)
@@ -586,14 +586,16 @@ struct mem_ctl_info *edac_mc_del_mc(struct device *dev)
                return NULL;
        }
 
-       /* marking MCI offline */
-       mci->op_state = OP_OFFLINE;
-
        del_mc_from_global_list(mci);
        mutex_unlock(&mem_ctls_mutex);
 
-       /* flush workq processes and remove sysfs */
+       /* flush workq processes */
        edac_mc_workq_teardown(mci);
+
+       /* marking MCI offline */
+       mci->op_state = OP_OFFLINE;
+
+       /* remove from sysfs */
        edac_remove_sysfs_mci_device(mci);
 
        edac_printk(KERN_INFO, EDAC_MC,
index 8d0688f36d4cee2331c84fddb2848325badd849e..39faded3cadd6c753a9aecd5d4257a2bf12fa1c7 100644 (file)
@@ -139,7 +139,7 @@ static int __init edac_init_mce_inject(void)
        return 0;
 
 err_sysfs_create:
-       while (i-- >= 0)
+       while (--i >= 0)
                sysfs_remove_file(mce_kobj, &sysfs_attrs[i]->attr);
 
        kobject_del(mce_kobj);
index 18fdd9703b483fbdaadbaec83cbbb956ffa669dd..1a467a91fb0b2c8ee4c7ac577f02c497d249e1dc 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/bug.h>
+#include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/firewire.h>
 #include <linux/firewire-constants.h>
 #include <asm/unaligned.h>
 #include <net/arp.h>
 
-#define FWNET_MAX_FRAGMENTS    25      /* arbitrary limit */
-#define FWNET_ISO_PAGE_COUNT   (PAGE_SIZE < 16 * 1024 ? 4 : 2)
+/* rx limits */
+#define FWNET_MAX_FRAGMENTS            30 /* arbitrary, > TX queue depth */
+#define FWNET_ISO_PAGE_COUNT           (PAGE_SIZE < 16*1024 ? 4 : 2)
+
+/* tx limits */
+#define FWNET_MAX_QUEUED_DATAGRAMS     20 /* < 64 = number of tlabels */
+#define FWNET_MIN_QUEUED_DATAGRAMS     10 /* should keep AT DMA busy enough */
+#define FWNET_TX_QUEUE_LEN             FWNET_MAX_QUEUED_DATAGRAMS /* ? */
 
 #define IEEE1394_BROADCAST_CHANNEL     31
 #define IEEE1394_ALL_NODES             (0xffc0 | 0x003f)
@@ -169,15 +176,8 @@ struct fwnet_device {
        struct fw_address_handler handler;
        u64 local_fifo;
 
-       /* List of packets to be sent */
-       struct list_head packet_list;
-       /*
-        * List of packets that were broadcasted.  When we get an ISO interrupt
-        * one of them has been sent
-        */
-       struct list_head broadcasted_list;
-       /* List of packets that have been sent but not yet acked */
-       struct list_head sent_list;
+       /* Number of tx datagrams that have been queued but not yet acked */
+       int queued_datagrams;
 
        struct list_head peer_list;
        struct fw_card *card;
@@ -195,7 +195,7 @@ struct fwnet_peer {
        unsigned pdg_size;        /* pd_list size */
 
        u16 datagram_label;       /* outgoing datagram label */
-       unsigned max_payload;     /* includes RFC2374_FRAG_HDR_SIZE overhead */
+       u16 max_payload;          /* includes RFC2374_FRAG_HDR_SIZE overhead */
        int node_id;
        int generation;
        unsigned speed;
@@ -203,22 +203,18 @@ struct fwnet_peer {
 
 /* This is our task struct. It's used for the packet complete callback.  */
 struct fwnet_packet_task {
-       /*
-        * ptask can actually be on dev->packet_list, dev->broadcasted_list,
-        * or dev->sent_list depending on its current state.
-        */
-       struct list_head pt_link;
        struct fw_transaction transaction;
        struct rfc2734_header hdr;
        struct sk_buff *skb;
        struct fwnet_device *dev;
 
        int outstanding_pkts;
-       unsigned max_payload;
        u64 fifo_addr;
        u16 dest_node;
+       u16 max_payload;
        u8 generation;
        u8 speed;
+       u8 enqueued;
 };
 
 /*
@@ -650,8 +646,6 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
                net->stats.rx_packets++;
                net->stats.rx_bytes += skb->len;
        }
-       if (netif_queue_stopped(net))
-               netif_wake_queue(net);
 
        return 0;
 
@@ -660,8 +654,6 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
        net->stats.rx_dropped++;
 
        dev_kfree_skb_any(skb);
-       if (netif_queue_stopped(net))
-               netif_wake_queue(net);
 
        return -ENOENT;
 }
@@ -793,15 +785,10 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
         * Datagram is not complete, we're done for the
         * moment.
         */
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       return 0;
+       retval = 0;
  fail:
        spin_unlock_irqrestore(&dev->lock, flags);
 
-       if (netif_queue_stopped(net))
-               netif_wake_queue(net);
-
        return retval;
 }
 
@@ -901,11 +888,19 @@ static void fwnet_free_ptask(struct fwnet_packet_task *ptask)
        kmem_cache_free(fwnet_packet_task_cache, ptask);
 }
 
+/* Caller must hold dev->lock. */
+static void dec_queued_datagrams(struct fwnet_device *dev)
+{
+       if (--dev->queued_datagrams == FWNET_MIN_QUEUED_DATAGRAMS)
+               netif_wake_queue(dev->netdev);
+}
+
 static int fwnet_send_packet(struct fwnet_packet_task *ptask);
 
 static void fwnet_transmit_packet_done(struct fwnet_packet_task *ptask)
 {
        struct fwnet_device *dev = ptask->dev;
+       struct sk_buff *skb = ptask->skb;
        unsigned long flags;
        bool free;
 
@@ -914,10 +909,14 @@ static void fwnet_transmit_packet_done(struct fwnet_packet_task *ptask)
        ptask->outstanding_pkts--;
 
        /* Check whether we or the networking TX soft-IRQ is last user. */
-       free = (ptask->outstanding_pkts == 0 && !list_empty(&ptask->pt_link));
+       free = (ptask->outstanding_pkts == 0 && ptask->enqueued);
+       if (free)
+               dec_queued_datagrams(dev);
 
-       if (ptask->outstanding_pkts == 0)
-               list_del(&ptask->pt_link);
+       if (ptask->outstanding_pkts == 0) {
+               dev->netdev->stats.tx_packets++;
+               dev->netdev->stats.tx_bytes += skb->len;
+       }
 
        spin_unlock_irqrestore(&dev->lock, flags);
 
@@ -926,7 +925,6 @@ static void fwnet_transmit_packet_done(struct fwnet_packet_task *ptask)
                u16 fg_off;
                u16 datagram_label;
                u16 lf;
-               struct sk_buff *skb;
 
                /* Update the ptask to point to the next fragment and send it */
                lf = fwnet_get_hdr_lf(&ptask->hdr);
@@ -953,7 +951,7 @@ static void fwnet_transmit_packet_done(struct fwnet_packet_task *ptask)
                        datagram_label = fwnet_get_hdr_dgl(&ptask->hdr);
                        break;
                }
-               skb = ptask->skb;
+
                skb_pull(skb, ptask->max_payload);
                if (ptask->outstanding_pkts > 1) {
                        fwnet_make_sf_hdr(&ptask->hdr, RFC2374_HDR_INTFRAG,
@@ -970,6 +968,31 @@ static void fwnet_transmit_packet_done(struct fwnet_packet_task *ptask)
                fwnet_free_ptask(ptask);
 }
 
+static void fwnet_transmit_packet_failed(struct fwnet_packet_task *ptask)
+{
+       struct fwnet_device *dev = ptask->dev;
+       unsigned long flags;
+       bool free;
+
+       spin_lock_irqsave(&dev->lock, flags);
+
+       /* One fragment failed; don't try to send remaining fragments. */
+       ptask->outstanding_pkts = 0;
+
+       /* Check whether we or the networking TX soft-IRQ is last user. */
+       free = ptask->enqueued;
+       if (free)
+               dec_queued_datagrams(dev);
+
+       dev->netdev->stats.tx_dropped++;
+       dev->netdev->stats.tx_errors++;
+
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       if (free)
+               fwnet_free_ptask(ptask);
+}
+
 static void fwnet_write_complete(struct fw_card *card, int rcode,
                                 void *payload, size_t length, void *data)
 {
@@ -977,11 +1000,12 @@ static void fwnet_write_complete(struct fw_card *card, int rcode,
 
        ptask = data;
 
-       if (rcode == RCODE_COMPLETE)
+       if (rcode == RCODE_COMPLETE) {
                fwnet_transmit_packet_done(ptask);
-       else
+       } else {
                fw_error("fwnet_write_complete: failed: %x\n", rcode);
-               /* ??? error recovery */
+               fwnet_transmit_packet_failed(ptask);
+       }
 }
 
 static int fwnet_send_packet(struct fwnet_packet_task *ptask)
@@ -1039,9 +1063,11 @@ static int fwnet_send_packet(struct fwnet_packet_task *ptask)
                spin_lock_irqsave(&dev->lock, flags);
 
                /* If the AT tasklet already ran, we may be last user. */
-               free = (ptask->outstanding_pkts == 0 && list_empty(&ptask->pt_link));
+               free = (ptask->outstanding_pkts == 0 && !ptask->enqueued);
                if (!free)
-                       list_add_tail(&ptask->pt_link, &dev->broadcasted_list);
+                       ptask->enqueued = true;
+               else
+                       dec_queued_datagrams(dev);
 
                spin_unlock_irqrestore(&dev->lock, flags);
 
@@ -1056,9 +1082,11 @@ static int fwnet_send_packet(struct fwnet_packet_task *ptask)
        spin_lock_irqsave(&dev->lock, flags);
 
        /* If the AT tasklet already ran, we may be last user. */
-       free = (ptask->outstanding_pkts == 0 && list_empty(&ptask->pt_link));
+       free = (ptask->outstanding_pkts == 0 && !ptask->enqueued);
        if (!free)
-               list_add_tail(&ptask->pt_link, &dev->sent_list);
+               ptask->enqueued = true;
+       else
+               dec_queued_datagrams(dev);
 
        spin_unlock_irqrestore(&dev->lock, flags);
 
@@ -1224,6 +1252,15 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
        struct fwnet_peer *peer;
        unsigned long flags;
 
+       spin_lock_irqsave(&dev->lock, flags);
+
+       /* Can this happen? */
+       if (netif_queue_stopped(dev->netdev)) {
+               spin_unlock_irqrestore(&dev->lock, flags);
+
+               return NETDEV_TX_BUSY;
+       }
+
        ptask = kmem_cache_alloc(fwnet_packet_task_cache, GFP_ATOMIC);
        if (ptask == NULL)
                goto fail;
@@ -1242,9 +1279,6 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
        proto = hdr_buf.h_proto;
        dg_size = skb->len;
 
-       /* serialize access to peer, including peer->datagram_label */
-       spin_lock_irqsave(&dev->lock, flags);
-
        /*
         * Set the transmission type for the packet.  ARP packets and IP
         * broadcast packets are sent via GASP.
@@ -1266,7 +1300,7 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
 
                peer = fwnet_peer_find_by_guid(dev, be64_to_cpu(guid));
                if (!peer || peer->fifo == FWNET_NO_FIFO_ADDR)
-                       goto fail_unlock;
+                       goto fail;
 
                generation         = peer->generation;
                dest_node          = peer->node_id;
@@ -1320,18 +1354,21 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
                max_payload += RFC2374_FRAG_HDR_SIZE;
        }
 
+       if (++dev->queued_datagrams == FWNET_MAX_QUEUED_DATAGRAMS)
+               netif_stop_queue(dev->netdev);
+
        spin_unlock_irqrestore(&dev->lock, flags);
 
        ptask->max_payload = max_payload;
-       INIT_LIST_HEAD(&ptask->pt_link);
+       ptask->enqueued    = 0;
 
        fwnet_send_packet(ptask);
 
        return NETDEV_TX_OK;
 
- fail_unlock:
-       spin_unlock_irqrestore(&dev->lock, flags);
  fail:
+       spin_unlock_irqrestore(&dev->lock, flags);
+
        if (ptask)
                kmem_cache_free(fwnet_packet_task_cache, ptask);
 
@@ -1377,7 +1414,7 @@ static void fwnet_init_dev(struct net_device *net)
        net->addr_len           = FWNET_ALEN;
        net->hard_header_len    = FWNET_HLEN;
        net->type               = ARPHRD_IEEE1394;
-       net->tx_queue_len       = 10;
+       net->tx_queue_len       = FWNET_TX_QUEUE_LEN;
 }
 
 /* caller must hold fwnet_device_mutex */
@@ -1457,14 +1494,9 @@ static int fwnet_probe(struct device *_dev)
        dev->broadcast_rcv_context = NULL;
        dev->broadcast_xmt_max_payload = 0;
        dev->broadcast_xmt_datagramlabel = 0;
-
        dev->local_fifo = FWNET_NO_FIFO_ADDR;
-
-       INIT_LIST_HEAD(&dev->packet_list);
-       INIT_LIST_HEAD(&dev->broadcasted_list);
-       INIT_LIST_HEAD(&dev->sent_list);
+       dev->queued_datagrams = 0;
        INIT_LIST_HEAD(&dev->peer_list);
-
        dev->card = card;
        dev->netdev = net;
 
@@ -1522,7 +1554,7 @@ static int fwnet_remove(struct device *_dev)
        struct fwnet_peer *peer = dev_get_drvdata(_dev);
        struct fwnet_device *dev = peer->dev;
        struct net_device *net;
-       struct fwnet_packet_task *ptask, *pt_next;
+       int i;
 
        mutex_lock(&fwnet_device_mutex);
 
@@ -1540,21 +1572,9 @@ static int fwnet_remove(struct device *_dev)
                                              dev->card);
                        fw_iso_context_destroy(dev->broadcast_rcv_context);
                }
-               list_for_each_entry_safe(ptask, pt_next,
-                                        &dev->packet_list, pt_link) {
-                       dev_kfree_skb_any(ptask->skb);
-                       kmem_cache_free(fwnet_packet_task_cache, ptask);
-               }
-               list_for_each_entry_safe(ptask, pt_next,
-                                        &dev->broadcasted_list, pt_link) {
-                       dev_kfree_skb_any(ptask->skb);
-                       kmem_cache_free(fwnet_packet_task_cache, ptask);
-               }
-               list_for_each_entry_safe(ptask, pt_next,
-                                        &dev->sent_list, pt_link) {
-                       dev_kfree_skb_any(ptask->skb);
-                       kmem_cache_free(fwnet_packet_task_cache, ptask);
-               }
+               for (i = 0; dev->queued_datagrams && i < 5; i++)
+                       ssleep(1);
+               WARN_ON(dev->queued_datagrams);
                list_del(&dev->dev_link);
 
                free_netdev(net);
index 84eb607d6c031b4275e834604d4c0c0729fa8502..e3c8b60bd86be8873e781bef053f466898be16c2 100644 (file)
@@ -242,6 +242,7 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card)
 
 static char ohci_driver_name[] = KBUILD_MODNAME;
 
+#define PCI_DEVICE_ID_AGERE_FW643      0x5901
 #define PCI_DEVICE_ID_JMICRON_JMB38X_FW        0x2380
 #define PCI_DEVICE_ID_TI_TSB12LV22     0x8009
 
@@ -253,18 +254,34 @@ static char ohci_driver_name[] = KBUILD_MODNAME;
 
 /* In case of multiple matches in ohci_quirks[], only the first one is used. */
 static const struct {
-       unsigned short vendor, device, flags;
+       unsigned short vendor, device, revision, flags;
 } ohci_quirks[] = {
-       {PCI_VENDOR_ID_TI,      PCI_DEVICE_ID_TI_TSB12LV22, QUIRK_CYCLE_TIMER |
-                                                           QUIRK_RESET_PACKET |
-                                                           QUIRK_NO_1394A},
-       {PCI_VENDOR_ID_TI,      PCI_ANY_ID,     QUIRK_RESET_PACKET},
-       {PCI_VENDOR_ID_AL,      PCI_ANY_ID,     QUIRK_CYCLE_TIMER},
-       {PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, QUIRK_NO_MSI},
-       {PCI_VENDOR_ID_NEC,     PCI_ANY_ID,     QUIRK_CYCLE_TIMER},
-       {PCI_VENDOR_ID_VIA,     PCI_ANY_ID,     QUIRK_CYCLE_TIMER},
-       {PCI_VENDOR_ID_RICOH,   PCI_ANY_ID,     QUIRK_CYCLE_TIMER},
-       {PCI_VENDOR_ID_APPLE,   PCI_DEVICE_ID_APPLE_UNI_N_FW, QUIRK_BE_HEADERS},
+       {PCI_VENDOR_ID_AL, PCI_ANY_ID, PCI_ANY_ID,
+               QUIRK_CYCLE_TIMER},
+
+       {PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_FW, PCI_ANY_ID,
+               QUIRK_BE_HEADERS},
+
+       {PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_AGERE_FW643, 6,
+               QUIRK_NO_MSI},
+
+       {PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, PCI_ANY_ID,
+               QUIRK_NO_MSI},
+
+       {PCI_VENDOR_ID_NEC, PCI_ANY_ID, PCI_ANY_ID,
+               QUIRK_CYCLE_TIMER},
+
+       {PCI_VENDOR_ID_RICOH, PCI_ANY_ID, PCI_ANY_ID,
+               QUIRK_CYCLE_TIMER},
+
+       {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, PCI_ANY_ID,
+               QUIRK_CYCLE_TIMER | QUIRK_RESET_PACKET | QUIRK_NO_1394A},
+
+       {PCI_VENDOR_ID_TI, PCI_ANY_ID, PCI_ANY_ID,
+               QUIRK_RESET_PACKET},
+
+       {PCI_VENDOR_ID_VIA, PCI_ANY_ID, PCI_ANY_ID,
+               QUIRK_CYCLE_TIMER | QUIRK_NO_MSI},
 };
 
 /* This overrides anything that was found in ohci_quirks[]. */
@@ -2927,9 +2944,11 @@ static int __devinit pci_probe(struct pci_dev *dev,
        }
 
        for (i = 0; i < ARRAY_SIZE(ohci_quirks); i++)
-               if (ohci_quirks[i].vendor == dev->vendor &&
-                   (ohci_quirks[i].device == dev->device ||
-                    ohci_quirks[i].device == (unsigned short)PCI_ANY_ID)) {
+               if ((ohci_quirks[i].vendor == dev->vendor) &&
+                   (ohci_quirks[i].device == (unsigned short)PCI_ANY_ID ||
+                    ohci_quirks[i].device == dev->device) &&
+                   (ohci_quirks[i].revision == (unsigned short)PCI_ANY_ID ||
+                    ohci_quirks[i].revision >= dev->revision)) {
                        ohci->quirks = ohci_quirks[i].flags;
                        break;
                }
index e23c06893d19f62195247220075aafce1cfa75c0..599f6c9e0fbf18661d7607407d11b73cd3cda7ff 100644 (file)
@@ -56,6 +56,18 @@ static struct cs5535_gpio_chip {
  * registers, see include/linux/cs5535.h.
  */
 
+static void errata_outl(u32 val, unsigned long addr)
+{
+       /*
+        * According to the CS5536 errata (#36), after suspend
+        * a write to the high bank GPIO register will clear all
+        * non-selected bits; the recommended workaround is a
+        * read-modify-write operation.
+        */
+       val |= inl(addr);
+       outl(val, addr);
+}
+
 static void __cs5535_gpio_set(struct cs5535_gpio_chip *chip, unsigned offset,
                unsigned int reg)
 {
@@ -64,7 +76,7 @@ static void __cs5535_gpio_set(struct cs5535_gpio_chip *chip, unsigned offset,
                outl(1 << offset, chip->base + reg);
        else
                /* high bank register */
-               outl(1 << (offset - 16), chip->base + 0x80 + reg);
+               errata_outl(1 << (offset - 16), chip->base + 0x80 + reg);
 }
 
 void cs5535_gpio_set(unsigned offset, unsigned int reg)
@@ -86,7 +98,7 @@ static void __cs5535_gpio_clear(struct cs5535_gpio_chip *chip, unsigned offset,
                outl(1 << (offset + 16), chip->base + reg);
        else
                /* high bank register */
-               outl(1 << offset, chip->base + 0x80 + reg);
+               errata_outl(1 << offset, chip->base + 0x80 + reg);
 }
 
 void cs5535_gpio_clear(unsigned offset, unsigned int reg)
index 6985cb1da72cbc232919ab2bb93a52f26304a345..2baa6708e44cd835704ea832c861b7d5fe4b6e33 100644 (file)
@@ -156,12 +156,12 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] =
        { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO", 0 },
        { DRM_MODE_CONNECTOR_LVDS, "LVDS", 0 },
        { DRM_MODE_CONNECTOR_Component, "Component", 0 },
-       { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN", 0 },
-       { DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort", 0 },
-       { DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A", 0 },
-       { DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B", 0 },
+       { DRM_MODE_CONNECTOR_9PinDIN, "DIN", 0 },
+       { DRM_MODE_CONNECTOR_DisplayPort, "DP", 0 },
+       { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A", 0 },
+       { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B", 0 },
        { DRM_MODE_CONNECTOR_TV, "TV", 0 },
-       { DRM_MODE_CONNECTOR_eDP, "Embedded DisplayPort", 0 },
+       { DRM_MODE_CONNECTOR_eDP, "eDP", 0 },
 };
 
 static struct drm_prop_enum_list drm_encoder_enum_list[] =
index f7af91cb273d58232d41c68b712b2d6d4404671c..bede10a0340700b69717caf1da8e81ee0546ab00 100644 (file)
@@ -241,7 +241,7 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)
        }
 
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-               if (!drm_helper_encoder_in_use(encoder)) {
+               if (encoder->crtc && !drm_helper_encoder_in_use(encoder)) {
                        drm_encoder_disable(encoder);
                        /* disconnector encoder from any connector */
                        encoder->crtc = NULL;
@@ -471,6 +471,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
        int count = 0, ro, fail = 0;
        struct drm_crtc_helper_funcs *crtc_funcs;
        int ret = 0;
+       int i;
 
        DRM_DEBUG_KMS("\n");
 
@@ -666,6 +667,12 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                if (ret != 0)
                        goto fail;
        }
+       DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
+       for (i = 0; i < set->num_connectors; i++) {
+               DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
+                             drm_get_connector_name(set->connectors[i]));
+               set->connectors[i]->dpms = DRM_MODE_DPMS_ON;
+       }
 
        kfree(save_connectors);
        kfree(save_encoders);
@@ -841,7 +848,7 @@ static void output_poll_execute(struct work_struct *work)
        struct delayed_work *delayed_work = to_delayed_work(work);
        struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work);
        struct drm_connector *connector;
-       enum drm_connector_status old_status, status;
+       enum drm_connector_status old_status;
        bool repoll = false, changed = false;
 
        if (!drm_kms_helper_poll)
@@ -866,8 +873,9 @@ static void output_poll_execute(struct work_struct *work)
                    !(connector->polled & DRM_CONNECTOR_POLL_HPD))
                        continue;
 
-               status = connector->funcs->detect(connector, false);
-               if (old_status != status)
+               connector->status = connector->funcs->detect(connector, false);
+               DRM_DEBUG_KMS("connector status updated to %d\n", connector->status);
+               if (old_status != connector->status)
                        changed = true;
        }
 
index 9d3a5030b6e1dfcfbf522a783d24f14816c7b813..16d5155edad14fd63dea3b10243a71c6bd3d0ea1 100644 (file)
@@ -585,10 +585,13 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
        struct timeval now;
        unsigned long flags;
        unsigned int seq;
+       int ret;
 
        e = kzalloc(sizeof *e, GFP_KERNEL);
-       if (e == NULL)
-               return -ENOMEM;
+       if (e == NULL) {
+               ret = -ENOMEM;
+               goto err_put;
+       }
 
        e->pipe = pipe;
        e->base.pid = current->pid;
@@ -603,9 +606,8 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
        spin_lock_irqsave(&dev->event_lock, flags);
 
        if (file_priv->event_space < sizeof e->event) {
-               spin_unlock_irqrestore(&dev->event_lock, flags);
-               kfree(e);
-               return -ENOMEM;
+               ret = -EBUSY;
+               goto err_unlock;
        }
 
        file_priv->event_space -= sizeof e->event;
@@ -626,7 +628,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
        if ((seq - vblwait->request.sequence) <= (1 << 23)) {
                e->event.tv_sec = now.tv_sec;
                e->event.tv_usec = now.tv_usec;
-               drm_vblank_put(dev, e->pipe);
+               drm_vblank_put(dev, pipe);
                list_add_tail(&e->base.link, &e->base.file_priv->event_list);
                wake_up_interruptible(&e->base.file_priv->event_wait);
                trace_drm_vblank_event_delivered(current->pid, pipe,
@@ -638,6 +640,13 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
        spin_unlock_irqrestore(&dev->event_lock, flags);
 
        return 0;
+
+err_unlock:
+       spin_unlock_irqrestore(&dev->event_lock, flags);
+       kfree(e);
+err_put:
+       drm_vblank_put(dev, pipe);
+       return ret;
 }
 
 /**
index 7a26f4dd21ae0a055036f78ce588ea4def08d73a..e6800819bca846f6a3fd102ef37e2632858247f8 100644 (file)
@@ -767,6 +767,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
        case I915_PARAM_HAS_BLT:
                value = HAS_BLT(dev);
                break;
+       case I915_PARAM_HAS_COHERENT_RINGS:
+               value = 1;
+               break;
        default:
                DRM_DEBUG_DRIVER("Unknown parameter %d\n",
                                 param->param);
index 80745f85902cf73fe17bf2ec41863dcb36a38550..f737960712e607c448eabc83d57e6d0557269f16 100644 (file)
@@ -150,7 +150,8 @@ static const struct intel_device_info intel_ironlake_d_info = {
 
 static const struct intel_device_info intel_ironlake_m_info = {
        .gen = 5, .is_mobile = 1,
-       .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1,
+       .need_gfx_hws = 1, .has_rc6 = 1, .has_hotplug = 1,
+       .has_fbc = 0, /* disabled due to buggy hardware */
        .has_bsd_ring = 1,
 };
 
index 90414ae86afcd0758d49b2c70dfb39f613ab22f5..409826da3099dcb594473685bdf4b5f2e78183c9 100644 (file)
@@ -1045,6 +1045,8 @@ void i915_gem_clflush_object(struct drm_gem_object *obj);
 int i915_gem_object_set_domain(struct drm_gem_object *obj,
                               uint32_t read_domains,
                               uint32_t write_domain);
+int i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj,
+                             bool interruptible);
 int i915_gem_init_ringbuffer(struct drm_device *dev);
 void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
 int i915_gem_do_init(struct drm_device *dev, unsigned long start,
index ef188e391406a1b3a2763e92d578c8f9e03b28b3..275ec6ed43ae7dcc4f396322909296e00305c617 100644 (file)
@@ -38,8 +38,7 @@
 
 static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj);
 
-static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj,
-                                                 bool pipelined);
+static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj);
 static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj);
 static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj);
 static int i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj,
@@ -547,6 +546,19 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
        struct drm_i915_gem_object *obj_priv;
        int ret = 0;
 
+       if (args->size == 0)
+               return 0;
+
+       if (!access_ok(VERIFY_WRITE,
+                      (char __user *)(uintptr_t)args->data_ptr,
+                      args->size))
+               return -EFAULT;
+
+       ret = fault_in_pages_writeable((char __user *)(uintptr_t)args->data_ptr,
+                                      args->size);
+       if (ret)
+               return -EFAULT;
+
        ret = i915_mutex_lock_interruptible(dev);
        if (ret)
                return ret;
@@ -564,23 +576,6 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
                goto out;
        }
 
-       if (args->size == 0)
-               goto out;
-
-       if (!access_ok(VERIFY_WRITE,
-                      (char __user *)(uintptr_t)args->data_ptr,
-                      args->size)) {
-               ret = -EFAULT;
-               goto out;
-       }
-
-       ret = fault_in_pages_writeable((char __user *)(uintptr_t)args->data_ptr,
-                                      args->size);
-       if (ret) {
-               ret = -EFAULT;
-               goto out;
-       }
-
        ret = i915_gem_object_get_pages_or_evict(obj);
        if (ret)
                goto out;
@@ -981,7 +976,20 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
        struct drm_i915_gem_pwrite *args = data;
        struct drm_gem_object *obj;
        struct drm_i915_gem_object *obj_priv;
-       int ret = 0;
+       int ret;
+
+       if (args->size == 0)
+               return 0;
+
+       if (!access_ok(VERIFY_READ,
+                      (char __user *)(uintptr_t)args->data_ptr,
+                      args->size))
+               return -EFAULT;
+
+       ret = fault_in_pages_readable((char __user *)(uintptr_t)args->data_ptr,
+                                     args->size);
+       if (ret)
+               return -EFAULT;
 
        ret = i915_mutex_lock_interruptible(dev);
        if (ret)
@@ -994,30 +1002,12 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
        }
        obj_priv = to_intel_bo(obj);
 
-
        /* Bounds check destination. */
        if (args->offset > obj->size || args->size > obj->size - args->offset) {
                ret = -EINVAL;
                goto out;
        }
 
-       if (args->size == 0)
-               goto out;
-
-       if (!access_ok(VERIFY_READ,
-                      (char __user *)(uintptr_t)args->data_ptr,
-                      args->size)) {
-               ret = -EFAULT;
-               goto out;
-       }
-
-       ret = fault_in_pages_readable((char __user *)(uintptr_t)args->data_ptr,
-                                     args->size);
-       if (ret) {
-               ret = -EFAULT;
-               goto out;
-       }
-
        /* We can only do the GTT pwrite on untiled buffers, as otherwise
         * it would end up going through the fenced access, and we'll get
         * different detiling behavior between reading and writing.
@@ -2603,7 +2593,7 @@ i915_gem_object_put_fence_reg(struct drm_gem_object *obj,
        if (reg->gpu) {
                int ret;
 
-               ret = i915_gem_object_flush_gpu_write_domain(obj, true);
+               ret = i915_gem_object_flush_gpu_write_domain(obj);
                if (ret)
                        return ret;
 
@@ -2751,8 +2741,7 @@ i915_gem_clflush_object(struct drm_gem_object *obj)
 
 /** Flushes any GPU write domain for the object if it's dirty. */
 static int
-i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj,
-                                      bool pipelined)
+i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj)
 {
        struct drm_device *dev = obj->dev;
        uint32_t old_write_domain;
@@ -2771,10 +2760,7 @@ i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj,
                                            obj->read_domains,
                                            old_write_domain);
 
-       if (pipelined)
-               return 0;
-
-       return i915_gem_object_wait_rendering(obj, true);
+       return 0;
 }
 
 /** Flushes the GTT write domain for the object if it's dirty. */
@@ -2835,18 +2821,15 @@ i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write)
        if (obj_priv->gtt_space == NULL)
                return -EINVAL;
 
-       ret = i915_gem_object_flush_gpu_write_domain(obj, false);
+       ret = i915_gem_object_flush_gpu_write_domain(obj);
        if (ret != 0)
                return ret;
+       ret = i915_gem_object_wait_rendering(obj, true);
+       if (ret)
+               return ret;
 
        i915_gem_object_flush_cpu_write_domain(obj);
 
-       if (write) {
-               ret = i915_gem_object_wait_rendering(obj, true);
-               if (ret)
-                       return ret;
-       }
-
        old_write_domain = obj->write_domain;
        old_read_domains = obj->read_domains;
 
@@ -2884,7 +2867,7 @@ i915_gem_object_set_to_display_plane(struct drm_gem_object *obj,
        if (obj_priv->gtt_space == NULL)
                return -EINVAL;
 
-       ret = i915_gem_object_flush_gpu_write_domain(obj, true);
+       ret = i915_gem_object_flush_gpu_write_domain(obj);
        if (ret)
                return ret;
 
@@ -2907,6 +2890,20 @@ i915_gem_object_set_to_display_plane(struct drm_gem_object *obj,
        return 0;
 }
 
+int
+i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj,
+                         bool interruptible)
+{
+       if (!obj->active)
+               return 0;
+
+       if (obj->base.write_domain & I915_GEM_GPU_DOMAINS)
+               i915_gem_flush_ring(obj->base.dev, NULL, obj->ring,
+                                   0, obj->base.write_domain);
+
+       return i915_gem_object_wait_rendering(&obj->base, interruptible);
+}
+
 /**
  * Moves a single object to the CPU read, and possibly write domain.
  *
@@ -2919,9 +2916,12 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write)
        uint32_t old_write_domain, old_read_domains;
        int ret;
 
-       ret = i915_gem_object_flush_gpu_write_domain(obj, false);
+       ret = i915_gem_object_flush_gpu_write_domain(obj);
        if (ret != 0)
                return ret;
+       ret = i915_gem_object_wait_rendering(obj, true);
+       if (ret)
+               return ret;
 
        i915_gem_object_flush_gtt_write_domain(obj);
 
@@ -2930,12 +2930,6 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write)
         */
        i915_gem_object_set_to_full_cpu_read_domain(obj);
 
-       if (write) {
-               ret = i915_gem_object_wait_rendering(obj, true);
-               if (ret)
-                       return ret;
-       }
-
        old_write_domain = obj->write_domain;
        old_read_domains = obj->read_domains;
 
@@ -3200,9 +3194,13 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj,
        if (offset == 0 && size == obj->size)
                return i915_gem_object_set_to_cpu_domain(obj, 0);
 
-       ret = i915_gem_object_flush_gpu_write_domain(obj, false);
+       ret = i915_gem_object_flush_gpu_write_domain(obj);
        if (ret != 0)
                return ret;
+       ret = i915_gem_object_wait_rendering(obj, true);
+       if (ret)
+               return ret;
+
        i915_gem_object_flush_gtt_write_domain(obj);
 
        /* If we're already fully in the CPU read domain, we're done. */
@@ -3249,192 +3247,230 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj,
        return 0;
 }
 
-/**
- * Pin an object to the GTT and evaluate the relocations landing in it.
- */
 static int
-i915_gem_execbuffer_relocate(struct drm_i915_gem_object *obj,
-                            struct drm_file *file_priv,
-                            struct drm_i915_gem_exec_object2 *entry)
+i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
+                                  struct drm_file *file_priv,
+                                  struct drm_i915_gem_exec_object2 *entry,
+                                  struct drm_i915_gem_relocation_entry *reloc)
 {
        struct drm_device *dev = obj->base.dev;
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_i915_gem_relocation_entry __user *user_relocs;
-       struct drm_gem_object *target_obj = NULL;
-       uint32_t target_handle = 0;
-       int i, ret = 0;
+       struct drm_gem_object *target_obj;
+       uint32_t target_offset;
+       int ret = -EINVAL;
 
-       user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr;
-       for (i = 0; i < entry->relocation_count; i++) {
-               struct drm_i915_gem_relocation_entry reloc;
-               uint32_t target_offset;
+       target_obj = drm_gem_object_lookup(dev, file_priv,
+                                          reloc->target_handle);
+       if (target_obj == NULL)
+               return -ENOENT;
 
-               if (__copy_from_user_inatomic(&reloc,
-                                             user_relocs+i,
-                                             sizeof(reloc))) {
-                       ret = -EFAULT;
-                       break;
-               }
+       target_offset = to_intel_bo(target_obj)->gtt_offset;
 
-               if (reloc.target_handle != target_handle) {
-                       drm_gem_object_unreference(target_obj);
+#if WATCH_RELOC
+       DRM_INFO("%s: obj %p offset %08x target %d "
+                "read %08x write %08x gtt %08x "
+                "presumed %08x delta %08x\n",
+                __func__,
+                obj,
+                (int) reloc->offset,
+                (int) reloc->target_handle,
+                (int) reloc->read_domains,
+                (int) reloc->write_domain,
+                (int) target_offset,
+                (int) reloc->presumed_offset,
+                reloc->delta);
+#endif
 
-                       target_obj = drm_gem_object_lookup(dev, file_priv,
-                                                          reloc.target_handle);
-                       if (target_obj == NULL) {
-                               ret = -ENOENT;
-                               break;
-                       }
+       /* The target buffer should have appeared before us in the
+        * exec_object list, so it should have a GTT space bound by now.
+        */
+       if (target_offset == 0) {
+               DRM_ERROR("No GTT space found for object %d\n",
+                         reloc->target_handle);
+               goto err;
+       }
 
-                       target_handle = reloc.target_handle;
-               }
-               target_offset = to_intel_bo(target_obj)->gtt_offset;
+       /* Validate that the target is in a valid r/w GPU domain */
+       if (reloc->write_domain & (reloc->write_domain - 1)) {
+               DRM_ERROR("reloc with multiple write domains: "
+                         "obj %p target %d offset %d "
+                         "read %08x write %08x",
+                         obj, reloc->target_handle,
+                         (int) reloc->offset,
+                         reloc->read_domains,
+                         reloc->write_domain);
+               goto err;
+       }
+       if (reloc->write_domain & I915_GEM_DOMAIN_CPU ||
+           reloc->read_domains & I915_GEM_DOMAIN_CPU) {
+               DRM_ERROR("reloc with read/write CPU domains: "
+                         "obj %p target %d offset %d "
+                         "read %08x write %08x",
+                         obj, reloc->target_handle,
+                         (int) reloc->offset,
+                         reloc->read_domains,
+                         reloc->write_domain);
+               goto err;
+       }
+       if (reloc->write_domain && target_obj->pending_write_domain &&
+           reloc->write_domain != target_obj->pending_write_domain) {
+               DRM_ERROR("Write domain conflict: "
+                         "obj %p target %d offset %d "
+                         "new %08x old %08x\n",
+                         obj, reloc->target_handle,
+                         (int) reloc->offset,
+                         reloc->write_domain,
+                         target_obj->pending_write_domain);
+               goto err;
+       }
 
-#if WATCH_RELOC
-               DRM_INFO("%s: obj %p offset %08x target %d "
-                        "read %08x write %08x gtt %08x "
-                        "presumed %08x delta %08x\n",
-                        __func__,
-                        obj,
-                        (int) reloc.offset,
-                        (int) reloc.target_handle,
-                        (int) reloc.read_domains,
-                        (int) reloc.write_domain,
-                        (int) target_offset,
-                        (int) reloc.presumed_offset,
-                        reloc.delta);
-#endif
+       target_obj->pending_read_domains |= reloc->read_domains;
+       target_obj->pending_write_domain |= reloc->write_domain;
 
-               /* The target buffer should have appeared before us in the
-                * exec_object list, so it should have a GTT space bound by now.
-                */
-               if (target_offset == 0) {
-                       DRM_ERROR("No GTT space found for object %d\n",
-                                 reloc.target_handle);
-                       ret = -EINVAL;
-                       break;
-               }
+       /* If the relocation already has the right value in it, no
+        * more work needs to be done.
+        */
+       if (target_offset == reloc->presumed_offset)
+               goto out;
 
-               /* Validate that the target is in a valid r/w GPU domain */
-               if (reloc.write_domain & (reloc.write_domain - 1)) {
-                       DRM_ERROR("reloc with multiple write domains: "
-                                 "obj %p target %d offset %d "
-                                 "read %08x write %08x",
-                                 obj, reloc.target_handle,
-                                 (int) reloc.offset,
-                                 reloc.read_domains,
-                                 reloc.write_domain);
-                       ret = -EINVAL;
-                       break;
-               }
-               if (reloc.write_domain & I915_GEM_DOMAIN_CPU ||
-                   reloc.read_domains & I915_GEM_DOMAIN_CPU) {
-                       DRM_ERROR("reloc with read/write CPU domains: "
-                                 "obj %p target %d offset %d "
-                                 "read %08x write %08x",
-                                 obj, reloc.target_handle,
-                                 (int) reloc.offset,
-                                 reloc.read_domains,
-                                 reloc.write_domain);
-                       ret = -EINVAL;
-                       break;
-               }
-               if (reloc.write_domain && target_obj->pending_write_domain &&
-                   reloc.write_domain != target_obj->pending_write_domain) {
-                       DRM_ERROR("Write domain conflict: "
-                                 "obj %p target %d offset %d "
-                                 "new %08x old %08x\n",
-                                 obj, reloc.target_handle,
-                                 (int) reloc.offset,
-                                 reloc.write_domain,
-                                 target_obj->pending_write_domain);
-                       ret = -EINVAL;
-                       break;
-               }
+       /* Check that the relocation address is valid... */
+       if (reloc->offset > obj->base.size - 4) {
+               DRM_ERROR("Relocation beyond object bounds: "
+                         "obj %p target %d offset %d size %d.\n",
+                         obj, reloc->target_handle,
+                         (int) reloc->offset,
+                         (int) obj->base.size);
+               goto err;
+       }
+       if (reloc->offset & 3) {
+               DRM_ERROR("Relocation not 4-byte aligned: "
+                         "obj %p target %d offset %d.\n",
+                         obj, reloc->target_handle,
+                         (int) reloc->offset);
+               goto err;
+       }
 
-               target_obj->pending_read_domains |= reloc.read_domains;
-               target_obj->pending_write_domain |= reloc.write_domain;
+       /* and points to somewhere within the target object. */
+       if (reloc->delta >= target_obj->size) {
+               DRM_ERROR("Relocation beyond target object bounds: "
+                         "obj %p target %d delta %d size %d.\n",
+                         obj, reloc->target_handle,
+                         (int) reloc->delta,
+                         (int) target_obj->size);
+               goto err;
+       }
 
-               /* If the relocation already has the right value in it, no
-                * more work needs to be done.
-                */
-               if (target_offset == reloc.presumed_offset)
-                       continue;
+       reloc->delta += target_offset;
+       if (obj->base.write_domain == I915_GEM_DOMAIN_CPU) {
+               uint32_t page_offset = reloc->offset & ~PAGE_MASK;
+               char *vaddr;
 
-               /* Check that the relocation address is valid... */
-               if (reloc.offset > obj->base.size - 4) {
-                       DRM_ERROR("Relocation beyond object bounds: "
-                                 "obj %p target %d offset %d size %d.\n",
-                                 obj, reloc.target_handle,
-                                 (int) reloc.offset, (int) obj->base.size);
-                       ret = -EINVAL;
-                       break;
-               }
-               if (reloc.offset & 3) {
-                       DRM_ERROR("Relocation not 4-byte aligned: "
-                                 "obj %p target %d offset %d.\n",
-                                 obj, reloc.target_handle,
-                                 (int) reloc.offset);
-                       ret = -EINVAL;
-                       break;
-               }
+               vaddr = kmap_atomic(obj->pages[reloc->offset >> PAGE_SHIFT]);
+               *(uint32_t *)(vaddr + page_offset) = reloc->delta;
+               kunmap_atomic(vaddr);
+       } else {
+               struct drm_i915_private *dev_priv = dev->dev_private;
+               uint32_t __iomem *reloc_entry;
+               void __iomem *reloc_page;
 
-               /* and points to somewhere within the target object. */
-               if (reloc.delta >= target_obj->size) {
-                       DRM_ERROR("Relocation beyond target object bounds: "
-                                 "obj %p target %d delta %d size %d.\n",
-                                 obj, reloc.target_handle,
-                                 (int) reloc.delta, (int) target_obj->size);
-                       ret = -EINVAL;
-                       break;
-               }
+               ret = i915_gem_object_set_to_gtt_domain(&obj->base, 1);
+               if (ret)
+                       goto err;
 
-               reloc.delta += target_offset;
-               if (obj->base.write_domain == I915_GEM_DOMAIN_CPU) {
-                       uint32_t page_offset = reloc.offset & ~PAGE_MASK;
-                       char *vaddr;
+               /* Map the page containing the relocation we're going to perform.  */
+               reloc->offset += obj->gtt_offset;
+               reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
+                                                     reloc->offset & PAGE_MASK);
+               reloc_entry = (uint32_t __iomem *)
+                       (reloc_page + (reloc->offset & ~PAGE_MASK));
+               iowrite32(reloc->delta, reloc_entry);
+               io_mapping_unmap_atomic(reloc_page);
+       }
 
-                       vaddr = kmap_atomic(obj->pages[reloc.offset >> PAGE_SHIFT]);
-                       *(uint32_t *)(vaddr + page_offset) = reloc.delta;
-                       kunmap_atomic(vaddr);
-               } else {
-                       uint32_t __iomem *reloc_entry;
-                       void __iomem *reloc_page;
+       /* and update the user's relocation entry */
+       reloc->presumed_offset = target_offset;
 
-                       ret = i915_gem_object_set_to_gtt_domain(&obj->base, 1);
-                       if (ret)
-                               break;
+out:
+       ret = 0;
+err:
+       drm_gem_object_unreference(target_obj);
+       return ret;
+}
 
-                       /* Map the page containing the relocation we're going to perform.  */
-                       reloc.offset += obj->gtt_offset;
-                       reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
-                                                             reloc.offset & PAGE_MASK);
-                       reloc_entry = (uint32_t __iomem *)
-                               (reloc_page + (reloc.offset & ~PAGE_MASK));
-                       iowrite32(reloc.delta, reloc_entry);
-                       io_mapping_unmap_atomic(reloc_page);
-               }
+static int
+i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj,
+                                   struct drm_file *file_priv,
+                                   struct drm_i915_gem_exec_object2 *entry)
+{
+       struct drm_i915_gem_relocation_entry __user *user_relocs;
+       int i, ret;
+
+       user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr;
+       for (i = 0; i < entry->relocation_count; i++) {
+               struct drm_i915_gem_relocation_entry reloc;
+
+               if (__copy_from_user_inatomic(&reloc,
+                                             user_relocs+i,
+                                             sizeof(reloc)))
+                       return -EFAULT;
+
+               ret = i915_gem_execbuffer_relocate_entry(obj, file_priv, entry, &reloc);
+               if (ret)
+                       return ret;
 
-               /* and update the user's relocation entry */
-               reloc.presumed_offset = target_offset;
                if (__copy_to_user_inatomic(&user_relocs[i].presumed_offset,
-                                             &reloc.presumed_offset,
-                                             sizeof(reloc.presumed_offset))) {
-                   ret = -EFAULT;
-                   break;
-               }
+                                           &reloc.presumed_offset,
+                                           sizeof(reloc.presumed_offset)))
+                       return -EFAULT;
        }
 
-       drm_gem_object_unreference(target_obj);
-       return ret;
+       return 0;
 }
 
 static int
-i915_gem_execbuffer_pin(struct drm_device *dev,
-                       struct drm_file *file,
-                       struct drm_gem_object **object_list,
-                       struct drm_i915_gem_exec_object2 *exec_list,
-                       int count)
+i915_gem_execbuffer_relocate_object_slow(struct drm_i915_gem_object *obj,
+                                        struct drm_file *file_priv,
+                                        struct drm_i915_gem_exec_object2 *entry,
+                                        struct drm_i915_gem_relocation_entry *relocs)
+{
+       int i, ret;
+
+       for (i = 0; i < entry->relocation_count; i++) {
+               ret = i915_gem_execbuffer_relocate_entry(obj, file_priv, entry, &relocs[i]);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int
+i915_gem_execbuffer_relocate(struct drm_device *dev,
+                            struct drm_file *file,
+                            struct drm_gem_object **object_list,
+                            struct drm_i915_gem_exec_object2 *exec_list,
+                            int count)
+{
+       int i, ret;
+
+       for (i = 0; i < count; i++) {
+               struct drm_i915_gem_object *obj = to_intel_bo(object_list[i]);
+               obj->base.pending_read_domains = 0;
+               obj->base.pending_write_domain = 0;
+               ret = i915_gem_execbuffer_relocate_object(obj, file,
+                                                         &exec_list[i]);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int
+i915_gem_execbuffer_reserve(struct drm_device *dev,
+                           struct drm_file *file,
+                           struct drm_gem_object **object_list,
+                           struct drm_i915_gem_exec_object2 *exec_list,
+                           int count)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret, i, retry;
@@ -3496,6 +3532,87 @@ i915_gem_execbuffer_pin(struct drm_device *dev,
        return 0;
 }
 
+static int
+i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
+                                 struct drm_file *file,
+                                 struct drm_gem_object **object_list,
+                                 struct drm_i915_gem_exec_object2 *exec_list,
+                                 int count)
+{
+       struct drm_i915_gem_relocation_entry *reloc;
+       int i, total, ret;
+
+       for (i = 0; i < count; i++) {
+               struct drm_i915_gem_object *obj = to_intel_bo(object_list[i]);
+               obj->in_execbuffer = false;
+       }
+
+       mutex_unlock(&dev->struct_mutex);
+
+       total = 0;
+       for (i = 0; i < count; i++)
+               total += exec_list[i].relocation_count;
+
+       reloc = drm_malloc_ab(total, sizeof(*reloc));
+       if (reloc == NULL) {
+               mutex_lock(&dev->struct_mutex);
+               return -ENOMEM;
+       }
+
+       total = 0;
+       for (i = 0; i < count; i++) {
+               struct drm_i915_gem_relocation_entry __user *user_relocs;
+
+               user_relocs = (void __user *)(uintptr_t)exec_list[i].relocs_ptr;
+
+               if (copy_from_user(reloc+total, user_relocs,
+                                  exec_list[i].relocation_count *
+                                  sizeof(*reloc))) {
+                       ret = -EFAULT;
+                       mutex_lock(&dev->struct_mutex);
+                       goto err;
+               }
+
+               total += exec_list[i].relocation_count;
+       }
+
+       ret = i915_mutex_lock_interruptible(dev);
+       if (ret) {
+               mutex_lock(&dev->struct_mutex);
+               goto err;
+       }
+
+       ret = i915_gem_execbuffer_reserve(dev, file,
+                                         object_list, exec_list,
+                                         count);
+       if (ret)
+               goto err;
+
+       total = 0;
+       for (i = 0; i < count; i++) {
+               struct drm_i915_gem_object *obj = to_intel_bo(object_list[i]);
+               obj->base.pending_read_domains = 0;
+               obj->base.pending_write_domain = 0;
+               ret = i915_gem_execbuffer_relocate_object_slow(obj, file,
+                                                              &exec_list[i],
+                                                              reloc + total);
+               if (ret)
+                       goto err;
+
+               total += exec_list[i].relocation_count;
+       }
+
+       /* Leave the user relocations as are, this is the painfully slow path,
+        * and we want to avoid the complication of dropping the lock whilst
+        * having buffers reserved in the aperture and so causing spurious
+        * ENOSPC for random operations.
+        */
+
+err:
+       drm_free_large(reloc);
+       return ret;
+}
+
 static int
 i915_gem_execbuffer_move_to_gpu(struct drm_device *dev,
                                struct drm_file *file,
@@ -3625,8 +3742,15 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
 
        for (i = 0; i < count; i++) {
                char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr;
-               size_t length = exec[i].relocation_count * sizeof(struct drm_i915_gem_relocation_entry);
+               int length; /* limited by fault_in_pages_readable() */
+
+               /* First check for malicious input causing overflow */
+               if (exec[i].relocation_count >
+                   INT_MAX / sizeof(struct drm_i915_gem_relocation_entry))
+                       return -EINVAL;
 
+               length = exec[i].relocation_count *
+                       sizeof(struct drm_i915_gem_relocation_entry);
                if (!access_ok(VERIFY_READ, ptr, length))
                        return -EFAULT;
 
@@ -3769,18 +3893,24 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
        }
 
        /* Move the objects en-masse into the GTT, evicting if necessary. */
-       ret = i915_gem_execbuffer_pin(dev, file,
-                                     object_list, exec_list,
-                                     args->buffer_count);
+       ret = i915_gem_execbuffer_reserve(dev, file,
+                                         object_list, exec_list,
+                                         args->buffer_count);
        if (ret)
                goto err;
 
        /* The objects are in their final locations, apply the relocations. */
-       for (i = 0; i < args->buffer_count; i++) {
-               struct drm_i915_gem_object *obj = to_intel_bo(object_list[i]);
-               obj->base.pending_read_domains = 0;
-               obj->base.pending_write_domain = 0;
-               ret = i915_gem_execbuffer_relocate(obj, file, &exec_list[i]);
+       ret = i915_gem_execbuffer_relocate(dev, file,
+                                          object_list, exec_list,
+                                          args->buffer_count);
+       if (ret) {
+               if (ret == -EFAULT) {
+                       ret = i915_gem_execbuffer_relocate_slow(dev, file,
+                                                               object_list,
+                                                               exec_list,
+                                                               args->buffer_count);
+                       BUG_ON(!mutex_is_locked(&dev->struct_mutex));
+               }
                if (ret)
                        goto err;
        }
@@ -4244,10 +4374,20 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
                 * use this buffer rather sooner than later, so issuing the required
                 * flush earlier is beneficial.
                 */
-               if (obj->write_domain & I915_GEM_GPU_DOMAINS)
+               if (obj->write_domain & I915_GEM_GPU_DOMAINS) {
                        i915_gem_flush_ring(dev, file_priv,
                                            obj_priv->ring,
                                            0, obj->write_domain);
+               } else if (obj_priv->ring->outstanding_lazy_request) {
+                       /* This ring is not being cleared by active usage,
+                        * so emit a request to do so.
+                        */
+                       u32 seqno = i915_add_request(dev,
+                                                    NULL, NULL,
+                                                    obj_priv->ring);
+                       if (seqno == 0)
+                               ret = -ENOMEM;
+               }
 
                /* Update the active list for the hardware's current position.
                 * Otherwise this only updates on a delayed timer or when irqs
index 25ed911a31127256b753970d2b2fca22d67f755d..878fc766a12cc05f6b30c90d53d65a52c6023727 100644 (file)
 #define  TRANS_DP_10BPC                (1<<9)
 #define  TRANS_DP_6BPC         (2<<9)
 #define  TRANS_DP_12BPC                (3<<9)
+#define  TRANS_DP_BPC_MASK     (3<<9)
 #define  TRANS_DP_VSYNC_ACTIVE_HIGH    (1<<4)
 #define  TRANS_DP_VSYNC_ACTIVE_LOW     0
 #define  TRANS_DP_HSYNC_ACTIVE_HIGH    (1<<3)
index 454c064f8ef7f8d0daffe0ed40394354b152ee55..42729d25da58a5ecfb98317330ed1a62dcd3a745 100644 (file)
@@ -239,6 +239,16 @@ static void i915_save_modeset_reg(struct drm_device *dev)
        if (drm_core_check_feature(dev, DRIVER_MODESET))
                return;
 
+       /* Cursor state */
+       dev_priv->saveCURACNTR = I915_READ(CURACNTR);
+       dev_priv->saveCURAPOS = I915_READ(CURAPOS);
+       dev_priv->saveCURABASE = I915_READ(CURABASE);
+       dev_priv->saveCURBCNTR = I915_READ(CURBCNTR);
+       dev_priv->saveCURBPOS = I915_READ(CURBPOS);
+       dev_priv->saveCURBBASE = I915_READ(CURBBASE);
+       if (IS_GEN2(dev))
+               dev_priv->saveCURSIZE = I915_READ(CURSIZE);
+
        if (HAS_PCH_SPLIT(dev)) {
                dev_priv->savePCH_DREF_CONTROL = I915_READ(PCH_DREF_CONTROL);
                dev_priv->saveDISP_ARB_CTL = I915_READ(DISP_ARB_CTL);
@@ -529,6 +539,16 @@ static void i915_restore_modeset_reg(struct drm_device *dev)
        I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
        I915_WRITE(DSPBADDR, I915_READ(DSPBADDR));
 
+       /* Cursor state */
+       I915_WRITE(CURAPOS, dev_priv->saveCURAPOS);
+       I915_WRITE(CURACNTR, dev_priv->saveCURACNTR);
+       I915_WRITE(CURABASE, dev_priv->saveCURABASE);
+       I915_WRITE(CURBPOS, dev_priv->saveCURBPOS);
+       I915_WRITE(CURBCNTR, dev_priv->saveCURBCNTR);
+       I915_WRITE(CURBBASE, dev_priv->saveCURBBASE);
+       if (IS_GEN2(dev))
+               I915_WRITE(CURSIZE, dev_priv->saveCURSIZE);
+
        return;
 }
 
@@ -543,16 +563,6 @@ void i915_save_display(struct drm_device *dev)
        /* Don't save them in KMS mode */
        i915_save_modeset_reg(dev);
 
-       /* Cursor state */
-       dev_priv->saveCURACNTR = I915_READ(CURACNTR);
-       dev_priv->saveCURAPOS = I915_READ(CURAPOS);
-       dev_priv->saveCURABASE = I915_READ(CURABASE);
-       dev_priv->saveCURBCNTR = I915_READ(CURBCNTR);
-       dev_priv->saveCURBPOS = I915_READ(CURBPOS);
-       dev_priv->saveCURBBASE = I915_READ(CURBBASE);
-       if (IS_GEN2(dev))
-               dev_priv->saveCURSIZE = I915_READ(CURSIZE);
-
        /* CRT state */
        if (HAS_PCH_SPLIT(dev)) {
                dev_priv->saveADPA = I915_READ(PCH_ADPA);
@@ -657,16 +667,6 @@ void i915_restore_display(struct drm_device *dev)
        /* Don't restore them in KMS mode */
        i915_restore_modeset_reg(dev);
 
-       /* Cursor state */
-       I915_WRITE(CURAPOS, dev_priv->saveCURAPOS);
-       I915_WRITE(CURACNTR, dev_priv->saveCURACNTR);
-       I915_WRITE(CURABASE, dev_priv->saveCURABASE);
-       I915_WRITE(CURBPOS, dev_priv->saveCURBPOS);
-       I915_WRITE(CURBCNTR, dev_priv->saveCURBCNTR);
-       I915_WRITE(CURBBASE, dev_priv->saveCURBBASE);
-       if (IS_GEN2(dev))
-               I915_WRITE(CURSIZE, dev_priv->saveCURSIZE);
-
        /* CRT state */
        if (HAS_PCH_SPLIT(dev))
                I915_WRITE(PCH_ADPA, dev_priv->saveADPA);
index 65c88f9ba12c825cad46592938f390e0eabf4ee6..2cb8e0b9f1ee4f9975fd3b8e863673d359bafdfe 100644 (file)
@@ -190,37 +190,6 @@ out:
        kfree(output.pointer);
 }
 
-static int intel_dsm_switchto(enum vga_switcheroo_client_id id)
-{
-       return 0;
-}
-
-static int intel_dsm_power_state(enum vga_switcheroo_client_id id,
-                                enum vga_switcheroo_state state)
-{
-       return 0;
-}
-
-static int intel_dsm_init(void)
-{
-       return 0;
-}
-
-static int intel_dsm_get_client_id(struct pci_dev *pdev)
-{
-       if (intel_dsm_priv.dhandle == DEVICE_ACPI_HANDLE(&pdev->dev))
-               return VGA_SWITCHEROO_IGD;
-       else
-               return VGA_SWITCHEROO_DIS;
-}
-
-static struct vga_switcheroo_handler intel_dsm_handler = {
-       .switchto = intel_dsm_switchto,
-       .power_state = intel_dsm_power_state,
-       .init = intel_dsm_init,
-       .get_client_id = intel_dsm_get_client_id,
-};
-
 static bool intel_dsm_pci_probe(struct pci_dev *pdev)
 {
        acpi_handle dhandle, intel_handle;
@@ -276,11 +245,8 @@ void intel_register_dsm_handler(void)
 {
        if (!intel_dsm_detect())
                return;
-
-       vga_switcheroo_register_handler(&intel_dsm_handler);
 }
 
 void intel_unregister_dsm_handler(void)
 {
-       vga_switcheroo_unregister_handler();
 }
index c55c77043357cb0243a4b368a1e6d63b7a4af398..8df574316063fb751d683b4b9d5c0d59b82f42f1 100644 (file)
 #include "i915_drm.h"
 #include "i915_drv.h"
 
+/* Here's the desired hotplug mode */
+#define ADPA_HOTPLUG_BITS (ADPA_CRT_HOTPLUG_PERIOD_128 |               \
+                          ADPA_CRT_HOTPLUG_WARMUP_10MS |               \
+                          ADPA_CRT_HOTPLUG_SAMPLE_4S |                 \
+                          ADPA_CRT_HOTPLUG_VOLTAGE_50 |                \
+                          ADPA_CRT_HOTPLUG_VOLREF_325MV |              \
+                          ADPA_CRT_HOTPLUG_ENABLE)
+
+struct intel_crt {
+       struct intel_encoder base;
+       bool force_hotplug_required;
+};
+
+static struct intel_crt *intel_attached_crt(struct drm_connector *connector)
+{
+       return container_of(intel_attached_encoder(connector),
+                           struct intel_crt, base);
+}
+
 static void intel_crt_dpms(struct drm_encoder *encoder, int mode)
 {
        struct drm_device *dev = encoder->dev;
@@ -129,7 +148,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
                           dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
        }
 
-       adpa = 0;
+       adpa = ADPA_HOTPLUG_BITS;
        if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
                adpa |= ADPA_HSYNC_ACTIVE_HIGH;
        if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
@@ -157,53 +176,44 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
 static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
+       struct intel_crt *crt = intel_attached_crt(connector);
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 adpa, temp;
+       u32 adpa;
        bool ret;
-       bool turn_off_dac = false;
 
-       temp = adpa = I915_READ(PCH_ADPA);
+       /* The first time through, trigger an explicit detection cycle */
+       if (crt->force_hotplug_required) {
+               bool turn_off_dac = HAS_PCH_SPLIT(dev);
+               u32 save_adpa;
 
-       if (HAS_PCH_SPLIT(dev))
-               turn_off_dac = true;
-
-       adpa &= ~ADPA_CRT_HOTPLUG_MASK;
-       if (turn_off_dac)
-               adpa &= ~ADPA_DAC_ENABLE;
-
-       /* disable HPD first */
-       I915_WRITE(PCH_ADPA, adpa);
-       (void)I915_READ(PCH_ADPA);
-
-       adpa |= (ADPA_CRT_HOTPLUG_PERIOD_128 |
-                       ADPA_CRT_HOTPLUG_WARMUP_10MS |
-                       ADPA_CRT_HOTPLUG_SAMPLE_4S |
-                       ADPA_CRT_HOTPLUG_VOLTAGE_50 | /* default */
-                       ADPA_CRT_HOTPLUG_VOLREF_325MV |
-                       ADPA_CRT_HOTPLUG_ENABLE |
-                       ADPA_CRT_HOTPLUG_FORCE_TRIGGER);
-
-       DRM_DEBUG_KMS("pch crt adpa 0x%x", adpa);
-       I915_WRITE(PCH_ADPA, adpa);
-
-       if (wait_for((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0,
-                    1000))
-               DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER");
-
-       if (turn_off_dac) {
-               /* Make sure hotplug is enabled */
-               I915_WRITE(PCH_ADPA, temp | ADPA_CRT_HOTPLUG_ENABLE);
-               (void)I915_READ(PCH_ADPA);
+               crt->force_hotplug_required = 0;
+
+               save_adpa = adpa = I915_READ(PCH_ADPA);
+               DRM_DEBUG_KMS("trigger hotplug detect cycle: adpa=0x%x\n", adpa);
+
+               adpa |= ADPA_CRT_HOTPLUG_FORCE_TRIGGER;
+               if (turn_off_dac)
+                       adpa &= ~ADPA_DAC_ENABLE;
+
+               I915_WRITE(PCH_ADPA, adpa);
+
+               if (wait_for((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0,
+                            1000))
+                       DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER");
+
+               if (turn_off_dac) {
+                       I915_WRITE(PCH_ADPA, save_adpa);
+                       POSTING_READ(PCH_ADPA);
+               }
        }
 
        /* Check the status to see if both blue and green are on now */
        adpa = I915_READ(PCH_ADPA);
-       adpa &= ADPA_CRT_HOTPLUG_MONITOR_MASK;
-       if ((adpa == ADPA_CRT_HOTPLUG_MONITOR_COLOR) ||
-               (adpa == ADPA_CRT_HOTPLUG_MONITOR_MONO))
+       if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) != 0)
                ret = true;
        else
                ret = false;
+       DRM_DEBUG_KMS("ironlake hotplug adpa=0x%x, result %d\n", adpa, ret);
 
        return ret;
 }
@@ -277,13 +287,12 @@ static bool intel_crt_ddc_probe(struct drm_i915_private *dev_priv, int ddc_bus)
        return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 1) == 1;
 }
 
-static bool intel_crt_detect_ddc(struct drm_encoder *encoder)
+static bool intel_crt_detect_ddc(struct intel_crt *crt)
 {
-       struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
-       struct drm_i915_private *dev_priv = encoder->dev->dev_private;
+       struct drm_i915_private *dev_priv = crt->base.base.dev->dev_private;
 
        /* CRT should always be at 0, but check anyway */
-       if (intel_encoder->type != INTEL_OUTPUT_ANALOG)
+       if (crt->base.type != INTEL_OUTPUT_ANALOG)
                return false;
 
        if (intel_crt_ddc_probe(dev_priv, dev_priv->crt_ddc_pin)) {
@@ -291,7 +300,7 @@ static bool intel_crt_detect_ddc(struct drm_encoder *encoder)
                return true;
        }
 
-       if (intel_ddc_probe(intel_encoder, dev_priv->crt_ddc_pin)) {
+       if (intel_ddc_probe(&crt->base, dev_priv->crt_ddc_pin)) {
                DRM_DEBUG_KMS("CRT detected via DDC:0x50 [EDID]\n");
                return true;
        }
@@ -300,9 +309,9 @@ static bool intel_crt_detect_ddc(struct drm_encoder *encoder)
 }
 
 static enum drm_connector_status
-intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder)
+intel_crt_load_detect(struct drm_crtc *crtc, struct intel_crt *crt)
 {
-       struct drm_encoder *encoder = &intel_encoder->base;
+       struct drm_encoder *encoder = &crt->base.base;
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -434,7 +443,7 @@ static enum drm_connector_status
 intel_crt_detect(struct drm_connector *connector, bool force)
 {
        struct drm_device *dev = connector->dev;
-       struct intel_encoder *encoder = intel_attached_encoder(connector);
+       struct intel_crt *crt = intel_attached_crt(connector);
        struct drm_crtc *crtc;
        int dpms_mode;
        enum drm_connector_status status;
@@ -443,28 +452,31 @@ intel_crt_detect(struct drm_connector *connector, bool force)
                if (intel_crt_detect_hotplug(connector)) {
                        DRM_DEBUG_KMS("CRT detected via hotplug\n");
                        return connector_status_connected;
-               } else
+               } else {
+                       DRM_DEBUG_KMS("CRT not detected via hotplug\n");
                        return connector_status_disconnected;
+               }
        }
 
-       if (intel_crt_detect_ddc(&encoder->base))
+       if (intel_crt_detect_ddc(crt))
                return connector_status_connected;
 
        if (!force)
                return connector->status;
 
        /* for pre-945g platforms use load detect */
-       if (encoder->base.crtc && encoder->base.crtc->enabled) {
-               status = intel_crt_load_detect(encoder->base.crtc, encoder);
+       crtc = crt->base.base.crtc;
+       if (crtc && crtc->enabled) {
+               status = intel_crt_load_detect(crtc, crt);
        } else {
-               crtc = intel_get_load_detect_pipe(encoder, connector,
+               crtc = intel_get_load_detect_pipe(&crt->base, connector,
                                                  NULL, &dpms_mode);
                if (crtc) {
-                       if (intel_crt_detect_ddc(&encoder->base))
+                       if (intel_crt_detect_ddc(crt))
                                status = connector_status_connected;
                        else
-                               status = intel_crt_load_detect(crtc, encoder);
-                       intel_release_load_detect_pipe(encoder,
+                               status = intel_crt_load_detect(crtc, crt);
+                       intel_release_load_detect_pipe(&crt->base,
                                                       connector, dpms_mode);
                } else
                        status = connector_status_unknown;
@@ -536,17 +548,17 @@ static const struct drm_encoder_funcs intel_crt_enc_funcs = {
 void intel_crt_init(struct drm_device *dev)
 {
        struct drm_connector *connector;
-       struct intel_encoder *intel_encoder;
+       struct intel_crt *crt;
        struct intel_connector *intel_connector;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       intel_encoder = kzalloc(sizeof(struct intel_encoder), GFP_KERNEL);
-       if (!intel_encoder)
+       crt = kzalloc(sizeof(struct intel_crt), GFP_KERNEL);
+       if (!crt)
                return;
 
        intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
        if (!intel_connector) {
-               kfree(intel_encoder);
+               kfree(crt);
                return;
        }
 
@@ -554,20 +566,20 @@ void intel_crt_init(struct drm_device *dev)
        drm_connector_init(dev, &intel_connector->base,
                           &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
 
-       drm_encoder_init(dev, &intel_encoder->base, &intel_crt_enc_funcs,
+       drm_encoder_init(dev, &crt->base.base, &intel_crt_enc_funcs,
                         DRM_MODE_ENCODER_DAC);
 
-       intel_connector_attach_encoder(intel_connector, intel_encoder);
+       intel_connector_attach_encoder(intel_connector, &crt->base);
 
-       intel_encoder->type = INTEL_OUTPUT_ANALOG;
-       intel_encoder->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
-                                  (1 << INTEL_ANALOG_CLONE_BIT) |
-                                  (1 << INTEL_SDVO_LVDS_CLONE_BIT);
-       intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
+       crt->base.type = INTEL_OUTPUT_ANALOG;
+       crt->base.clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT |
+                               1 << INTEL_ANALOG_CLONE_BIT |
+                               1 << INTEL_SDVO_LVDS_CLONE_BIT);
+       crt->base.crtc_mask = (1 << 0) | (1 << 1);
        connector->interlace_allowed = 1;
        connector->doublescan_allowed = 0;
 
-       drm_encoder_helper_add(&intel_encoder->base, &intel_crt_helper_funcs);
+       drm_encoder_helper_add(&crt->base.base, &intel_crt_helper_funcs);
        drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
 
        drm_sysfs_connector_add(connector);
@@ -577,5 +589,22 @@ void intel_crt_init(struct drm_device *dev)
        else
                connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 
+       /*
+        * Configure the automatic hotplug detection stuff
+        */
+       crt->force_hotplug_required = 0;
+       if (HAS_PCH_SPLIT(dev)) {
+               u32 adpa;
+
+               adpa = I915_READ(PCH_ADPA);
+               adpa &= ~ADPA_CRT_HOTPLUG_MASK;
+               adpa |= ADPA_HOTPLUG_BITS;
+               I915_WRITE(PCH_ADPA, adpa);
+               POSTING_READ(PCH_ADPA);
+
+               DRM_DEBUG_KMS("pch crt adpa set to 0x%x\n", adpa);
+               crt->force_hotplug_required = 1;
+       }
+
        dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS;
 }
index 48d8fd686ea91d9fb3ba307036ecd0f5388174e9..d9b7092439ef59ab19acc9546a039ff60f0bb43c 100644 (file)
@@ -1611,6 +1611,18 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 
                wait_event(dev_priv->pending_flip_queue,
                           atomic_read(&obj_priv->pending_flip) == 0);
+
+               /* Big Hammer, we also need to ensure that any pending
+                * MI_WAIT_FOR_EVENT inside a user batch buffer on the
+                * current scanout is retired before unpinning the old
+                * framebuffer.
+                */
+               ret = i915_gem_object_flush_gpu(obj_priv, false);
+               if (ret) {
+                       i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj);
+                       mutex_unlock(&dev->struct_mutex);
+                       return ret;
+               }
        }
 
        ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y,
@@ -2108,9 +2120,11 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
                reg = TRANS_DP_CTL(pipe);
                temp = I915_READ(reg);
                temp &= ~(TRANS_DP_PORT_SEL_MASK |
-                         TRANS_DP_SYNC_MASK);
+                         TRANS_DP_SYNC_MASK |
+                         TRANS_DP_BPC_MASK);
                temp |= (TRANS_DP_OUTPUT_ENABLE |
                         TRANS_DP_ENH_FRAMING);
+               temp |= TRANS_DP_8BPC;
 
                if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC)
                        temp |= TRANS_DP_HSYNC_ACTIVE_HIGH;
@@ -2700,27 +2714,19 @@ fdi_reduce_ratio(u32 *num, u32 *den)
        }
 }
 
-#define DATA_N 0x800000
-#define LINK_N 0x80000
-
 static void
 ironlake_compute_m_n(int bits_per_pixel, int nlanes, int pixel_clock,
                     int link_clock, struct fdi_m_n *m_n)
 {
-       u64 temp;
-
        m_n->tu = 64; /* default size */
 
-       temp = (u64) DATA_N * pixel_clock;
-       temp = div_u64(temp, link_clock);
-       m_n->gmch_m = div_u64(temp * bits_per_pixel, nlanes);
-       m_n->gmch_m >>= 3; /* convert to bytes_per_pixel */
-       m_n->gmch_n = DATA_N;
+       /* BUG_ON(pixel_clock > INT_MAX / 36); */
+       m_n->gmch_m = bits_per_pixel * pixel_clock;
+       m_n->gmch_n = link_clock * nlanes * 8;
        fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
 
-       temp = (u64) LINK_N * pixel_clock;
-       m_n->link_m = div_u64(temp, link_clock);
-       m_n->link_n = LINK_N;
+       m_n->link_m = pixel_clock;
+       m_n->link_n = link_clock;
        fdi_reduce_ratio(&m_n->link_m, &m_n->link_n);
 }
 
@@ -3704,6 +3710,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 
        /* FDI link */
        if (HAS_PCH_SPLIT(dev)) {
+               int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
                int lane = 0, link_bw, bpp;
                /* CPU eDP doesn't require FDI link, so just set DP M/N
                   according to current link config */
@@ -3787,6 +3794,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 
                intel_crtc->fdi_lanes = lane;
 
+               if (pixel_multiplier > 1)
+                       link_bw *= pixel_multiplier;
                ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n);
        }
 
@@ -5224,6 +5233,55 @@ static const struct drm_crtc_funcs intel_crtc_funcs = {
        .page_flip = intel_crtc_page_flip,
 };
 
+static void intel_sanitize_modesetting(struct drm_device *dev,
+                                      int pipe, int plane)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 reg, val;
+
+       if (HAS_PCH_SPLIT(dev))
+               return;
+
+       /* Who knows what state these registers were left in by the BIOS or
+        * grub?
+        *
+        * If we leave the registers in a conflicting state (e.g. with the
+        * display plane reading from the other pipe than the one we intend
+        * to use) then when we attempt to teardown the active mode, we will
+        * not disable the pipes and planes in the correct order -- leaving
+        * a plane reading from a disabled pipe and possibly leading to
+        * undefined behaviour.
+        */
+
+       reg = DSPCNTR(plane);
+       val = I915_READ(reg);
+
+       if ((val & DISPLAY_PLANE_ENABLE) == 0)
+               return;
+       if (!!(val & DISPPLANE_SEL_PIPE_MASK) == pipe)
+               return;
+
+       /* This display plane is active and attached to the other CPU pipe. */
+       pipe = !pipe;
+
+       /* Disable the plane and wait for it to stop reading from the pipe. */
+       I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE);
+       intel_flush_display_plane(dev, plane);
+
+       if (IS_GEN2(dev))
+               intel_wait_for_vblank(dev, pipe);
+
+       if (pipe == 0 && (dev_priv->quirks & QUIRK_PIPEA_FORCE))
+               return;
+
+       /* Switch off the pipe. */
+       reg = PIPECONF(pipe);
+       val = I915_READ(reg);
+       if (val & PIPECONF_ENABLE) {
+               I915_WRITE(reg, val & ~PIPECONF_ENABLE);
+               intel_wait_for_pipe_off(dev, pipe);
+       }
+}
 
 static void intel_crtc_init(struct drm_device *dev, int pipe)
 {
@@ -5275,6 +5333,8 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 
        setup_timer(&intel_crtc->idle_timer, intel_crtc_idle_timer,
                    (unsigned long)intel_crtc);
+
+       intel_sanitize_modesetting(dev, intel_crtc->pipe, intel_crtc->plane);
 }
 
 int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
@@ -5324,9 +5384,14 @@ static void intel_setup_outputs(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_encoder *encoder;
        bool dpd_is_edp = false;
+       bool has_lvds = false;
 
        if (IS_MOBILE(dev) && !IS_I830(dev))
-               intel_lvds_init(dev);
+               has_lvds = intel_lvds_init(dev);
+       if (!has_lvds && !HAS_PCH_SPLIT(dev)) {
+               /* disable the panel fitter on everything but LVDS */
+               I915_WRITE(PFIT_CONTROL, 0);
+       }
 
        if (HAS_PCH_SPLIT(dev)) {
                dpd_is_edp = intel_dpd_is_edp(dev);
index c8e005553310a5eaeae98e4cb8ed349b4b204164..df648cb4c29641cec581307b1c40a46d812fd58b 100644 (file)
@@ -584,17 +584,6 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
                mode->clock = dev_priv->panel_fixed_mode->clock;
        }
 
-       /* Just use VBT values for eDP */
-       if (is_edp(intel_dp)) {
-               intel_dp->lane_count = dev_priv->edp.lanes;
-               intel_dp->link_bw = dev_priv->edp.rate;
-               adjusted_mode->clock = intel_dp_link_clock(intel_dp->link_bw);
-               DRM_DEBUG_KMS("eDP link bw %02x lane count %d clock %d\n",
-                             intel_dp->link_bw, intel_dp->lane_count,
-                             adjusted_mode->clock);
-               return true;
-       }
-
        for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
                for (clock = 0; clock <= max_clock; clock++) {
                        int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
@@ -613,6 +602,19 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
                }
        }
 
+       if (is_edp(intel_dp)) {
+               /* okay we failed just pick the highest */
+               intel_dp->lane_count = max_lane_count;
+               intel_dp->link_bw = bws[max_clock];
+               adjusted_mode->clock = intel_dp_link_clock(intel_dp->link_bw);
+               DRM_DEBUG_KMS("Force picking display port link bw %02x lane "
+                             "count %d clock %d\n",
+                             intel_dp->link_bw, intel_dp->lane_count,
+                             adjusted_mode->clock);
+
+               return true;
+       }
+
        return false;
 }
 
@@ -1087,21 +1089,11 @@ intel_get_adjust_train(struct intel_dp *intel_dp)
 }
 
 static uint32_t
-intel_dp_signal_levels(struct intel_dp *intel_dp)
+intel_dp_signal_levels(uint8_t train_set, int lane_count)
 {
-       struct drm_device *dev = intel_dp->base.base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       uint32_t signal_levels = 0;
-       u8 train_set = intel_dp->train_set[0];
-       u32 vswing = train_set & DP_TRAIN_VOLTAGE_SWING_MASK;
-       u32 preemphasis = train_set & DP_TRAIN_PRE_EMPHASIS_MASK;
+       uint32_t        signal_levels = 0;
 
-       if (is_edp(intel_dp)) {
-               vswing = dev_priv->edp.vswing;
-               preemphasis = dev_priv->edp.preemphasis;
-       }
-
-       switch (vswing) {
+       switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
        case DP_TRAIN_VOLTAGE_SWING_400:
        default:
                signal_levels |= DP_VOLTAGE_0_4;
@@ -1116,7 +1108,7 @@ intel_dp_signal_levels(struct intel_dp *intel_dp)
                signal_levels |= DP_VOLTAGE_1_2;
                break;
        }
-       switch (preemphasis) {
+       switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) {
        case DP_TRAIN_PRE_EMPHASIS_0:
        default:
                signal_levels |= DP_PRE_EMPHASIS_0;
@@ -1202,18 +1194,6 @@ intel_channel_eq_ok(struct intel_dp *intel_dp)
        return true;
 }
 
-static bool
-intel_dp_aux_handshake_required(struct intel_dp *intel_dp)
-{
-       struct drm_device *dev = intel_dp->base.base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       if (is_edp(intel_dp) && dev_priv->no_aux_handshake)
-               return false;
-
-       return true;
-}
-
 static bool
 intel_dp_set_link_train(struct intel_dp *intel_dp,
                        uint32_t dp_reg_value,
@@ -1226,9 +1206,6 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
        I915_WRITE(intel_dp->output_reg, dp_reg_value);
        POSTING_READ(intel_dp->output_reg);
 
-       if (!intel_dp_aux_handshake_required(intel_dp))
-               return true;
-
        intel_dp_aux_native_write_1(intel_dp,
                                    DP_TRAINING_PATTERN_SET,
                                    dp_train_pat);
@@ -1261,11 +1238,10 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
        POSTING_READ(intel_dp->output_reg);
        intel_wait_for_vblank(dev, intel_crtc->pipe);
 
-       if (intel_dp_aux_handshake_required(intel_dp))
-               /* Write the link configuration data */
-               intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET,
-                                         intel_dp->link_configuration,
-                                         DP_LINK_CONFIGURATION_SIZE);
+       /* Write the link configuration data */
+       intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET,
+                                 intel_dp->link_configuration,
+                                 DP_LINK_CONFIGURATION_SIZE);
 
        DP |= DP_PORT_EN;
        if (HAS_PCH_CPT(dev) && !is_edp(intel_dp))
@@ -1283,7 +1259,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
                        signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]);
                        DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
                } else {
-                       signal_levels = intel_dp_signal_levels(intel_dp);
+                       signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count);
                        DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
                }
 
@@ -1297,37 +1273,33 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
                        break;
                /* Set training pattern 1 */
 
-               udelay(500);
-               if (intel_dp_aux_handshake_required(intel_dp)) {
+               udelay(100);
+               if (!intel_dp_get_link_status(intel_dp))
+                       break;
+
+               if (intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) {
+                       clock_recovery = true;
                        break;
-               } else {
-                       if (!intel_dp_get_link_status(intel_dp))
-                               break;
+               }
 
-                       if (intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) {
-                               clock_recovery = true;
+               /* Check to see if we've tried the max voltage */
+               for (i = 0; i < intel_dp->lane_count; i++)
+                       if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
                                break;
-                       }
+               if (i == intel_dp->lane_count)
+                       break;
 
-                       /* Check to see if we've tried the max voltage */
-                       for (i = 0; i < intel_dp->lane_count; i++)
-                               if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
-                                       break;
-                       if (i == intel_dp->lane_count)
+               /* Check to see if we've tried the same voltage 5 times */
+               if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
+                       ++tries;
+                       if (tries == 5)
                                break;
+               } else
+                       tries = 0;
+               voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
 
-                       /* Check to see if we've tried the same voltage 5 times */
-                       if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
-                               ++tries;
-                               if (tries == 5)
-                                       break;
-                       } else
-                               tries = 0;
-                       voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
-
-                       /* Compute new intel_dp->train_set as requested by target */
-                       intel_get_adjust_train(intel_dp);
-               }
+               /* Compute new intel_dp->train_set as requested by target */
+               intel_get_adjust_train(intel_dp);
        }
 
        intel_dp->DP = DP;
@@ -1354,7 +1326,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
                        signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]);
                        DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
                } else {
-                       signal_levels = intel_dp_signal_levels(intel_dp);
+                       signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count);
                        DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
                }
 
@@ -1368,28 +1340,24 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
                                             DP_TRAINING_PATTERN_2))
                        break;
 
-               udelay(500);
-
-               if (!intel_dp_aux_handshake_required(intel_dp)) {
+               udelay(400);
+               if (!intel_dp_get_link_status(intel_dp))
                        break;
-               } else {
-                       if (!intel_dp_get_link_status(intel_dp))
-                               break;
 
-                       if (intel_channel_eq_ok(intel_dp)) {
-                               channel_eq = true;
-                               break;
-                       }
+               if (intel_channel_eq_ok(intel_dp)) {
+                       channel_eq = true;
+                       break;
+               }
 
-                       /* Try 5 times */
-                       if (tries > 5)
-                               break;
+               /* Try 5 times */
+               if (tries > 5)
+                       break;
 
-                       /* Compute new intel_dp->train_set as requested by target */
-                       intel_get_adjust_train(intel_dp);
-                       ++tries;
-               }
+               /* Compute new intel_dp->train_set as requested by target */
+               intel_get_adjust_train(intel_dp);
+               ++tries;
        }
+
        if (HAS_PCH_CPT(dev) && !is_edp(intel_dp))
                reg = DP | DP_LINK_TRAIN_OFF_CPT;
        else
@@ -1408,6 +1376,9 @@ intel_dp_link_down(struct intel_dp *intel_dp)
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t DP = intel_dp->DP;
 
+       if ((I915_READ(intel_dp->output_reg) & DP_PORT_EN) == 0)
+               return;
+
        DRM_DEBUG_KMS("\n");
 
        if (is_edp(intel_dp)) {
@@ -1430,6 +1401,28 @@ intel_dp_link_down(struct intel_dp *intel_dp)
 
        if (is_edp(intel_dp))
                DP |= DP_LINK_TRAIN_OFF;
+
+       if (!HAS_PCH_CPT(dev) &&
+           I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) {
+               struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc);
+               /* Hardware workaround: leaving our transcoder select
+                * set to transcoder B while it's off will prevent the
+                * corresponding HDMI output on transcoder A.
+                *
+                * Combine this with another hardware workaround:
+                * transcoder select bit can only be cleared while the
+                * port is enabled.
+                */
+               DP &= ~DP_PIPEB_SELECT;
+               I915_WRITE(intel_dp->output_reg, DP);
+
+               /* Changes to enable or select take place the vblank
+                * after being written.
+                */
+               intel_wait_for_vblank(intel_dp->base.base.dev,
+                                     intel_crtc->pipe);
+       }
+
        I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
        POSTING_READ(intel_dp->output_reg);
 }
index 21551fe745416abb4597341b18d647f2529e85ce..e52c6125bb1f05636e59f52420d055fc4e919e9f 100644 (file)
@@ -237,7 +237,7 @@ extern bool intel_sdvo_init(struct drm_device *dev, int output_device);
 extern void intel_dvo_init(struct drm_device *dev);
 extern void intel_tv_init(struct drm_device *dev);
 extern void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj);
-extern void intel_lvds_init(struct drm_device *dev);
+extern bool intel_lvds_init(struct drm_device *dev);
 extern void intel_dp_init(struct drm_device *dev, int dp_reg);
 void
 intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
index 2be4f728ed0c7b250550613cc93259462db9735a..3dba086e7eea012947c410738e208a9ef39bfa9e 100644 (file)
@@ -160,7 +160,7 @@ intel_gpio_create(struct drm_i915_private *dev_priv, u32 pin)
        };
        struct intel_gpio *gpio;
 
-       if (pin < 1 || pin > 7)
+       if (pin >= ARRAY_SIZE(map_pin_to_reg) || !map_pin_to_reg[pin])
                return NULL;
 
        gpio = kzalloc(sizeof(struct intel_gpio), GFP_KERNEL);
@@ -172,7 +172,8 @@ intel_gpio_create(struct drm_i915_private *dev_priv, u32 pin)
                gpio->reg += PCH_GPIOA - GPIOA;
        gpio->dev_priv = dev_priv;
 
-       snprintf(gpio->adapter.name, I2C_NAME_SIZE, "GPIO%c", "?BACDEF?"[pin]);
+       snprintf(gpio->adapter.name, sizeof(gpio->adapter.name),
+                "i915 GPIO%c", "?BACDE?F"[pin]);
        gpio->adapter.owner = THIS_MODULE;
        gpio->adapter.algo_data = &gpio->algo;
        gpio->adapter.dev.parent = &dev_priv->dev->pdev->dev;
@@ -349,7 +350,7 @@ int intel_setup_gmbus(struct drm_device *dev)
                "panel",
                "dpc",
                "dpb",
-               "reserved"
+               "reserved",
                "dpd",
        };
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -366,8 +367,8 @@ int intel_setup_gmbus(struct drm_device *dev)
                bus->adapter.owner = THIS_MODULE;
                bus->adapter.class = I2C_CLASS_DDC;
                snprintf(bus->adapter.name,
-                        I2C_NAME_SIZE,
-                        "gmbus %s",
+                        sizeof(bus->adapter.name),
+                        "i915 gmbus %s",
                         names[i]);
 
                bus->adapter.dev.parent = &dev->pdev->dev;
index 4324a326f98ee28f4d67936b7a4789556344c4fb..25bcedf386fd5e07f93b2c2f77d78dd8dc905170 100644 (file)
@@ -68,7 +68,7 @@ static struct intel_lvds *intel_attached_lvds(struct drm_connector *connector)
 /**
  * Sets the power state for the panel.
  */
-static void intel_lvds_set_power(struct intel_lvds *intel_lvds, bool on)
+static void intel_lvds_enable(struct intel_lvds *intel_lvds)
 {
        struct drm_device *dev = intel_lvds->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -82,26 +82,61 @@ static void intel_lvds_set_power(struct intel_lvds *intel_lvds, bool on)
                lvds_reg = LVDS;
        }
 
-       if (on) {
-               I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN);
-               I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON);
-               intel_panel_set_backlight(dev, dev_priv->backlight_level);
-       } else {
-               dev_priv->backlight_level = intel_panel_get_backlight(dev);
-
-               intel_panel_set_backlight(dev, 0);
-               I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON);
+       I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN);
 
-               if (intel_lvds->pfit_control) {
-                       if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000))
-                               DRM_ERROR("timed out waiting for panel to power off\n");
-                       I915_WRITE(PFIT_CONTROL, 0);
-                       intel_lvds->pfit_control = 0;
+       if (intel_lvds->pfit_dirty) {
+               /*
+                * Enable automatic panel scaling so that non-native modes
+                * fill the screen.  The panel fitter should only be
+                * adjusted whilst the pipe is disabled, according to
+                * register description and PRM.
+                */
+               DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n",
+                             intel_lvds->pfit_control,
+                             intel_lvds->pfit_pgm_ratios);
+               if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000)) {
+                       DRM_ERROR("timed out waiting for panel to power off\n");
+               } else {
+                       I915_WRITE(PFIT_PGM_RATIOS, intel_lvds->pfit_pgm_ratios);
+                       I915_WRITE(PFIT_CONTROL, intel_lvds->pfit_control);
                        intel_lvds->pfit_dirty = false;
                }
+       }
+
+       I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON);
+       POSTING_READ(lvds_reg);
+
+       intel_panel_set_backlight(dev, dev_priv->backlight_level);
+}
+
+static void intel_lvds_disable(struct intel_lvds *intel_lvds)
+{
+       struct drm_device *dev = intel_lvds->base.base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 ctl_reg, lvds_reg;
+
+       if (HAS_PCH_SPLIT(dev)) {
+               ctl_reg = PCH_PP_CONTROL;
+               lvds_reg = PCH_LVDS;
+       } else {
+               ctl_reg = PP_CONTROL;
+               lvds_reg = LVDS;
+       }
+
+       dev_priv->backlight_level = intel_panel_get_backlight(dev);
+       intel_panel_set_backlight(dev, 0);
+
+       I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON);
+
+       if (intel_lvds->pfit_control) {
+               if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000))
+                       DRM_ERROR("timed out waiting for panel to power off\n");
 
-               I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN);
+               I915_WRITE(PFIT_CONTROL, 0);
+               intel_lvds->pfit_dirty = true;
        }
+
+       I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN);
        POSTING_READ(lvds_reg);
 }
 
@@ -110,9 +145,9 @@ static void intel_lvds_dpms(struct drm_encoder *encoder, int mode)
        struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
 
        if (mode == DRM_MODE_DPMS_ON)
-               intel_lvds_set_power(intel_lvds, true);
+               intel_lvds_enable(intel_lvds);
        else
-               intel_lvds_set_power(intel_lvds, false);
+               intel_lvds_disable(intel_lvds);
 
        /* XXX: We never power down the LVDS pairs. */
 }
@@ -411,43 +446,18 @@ static void intel_lvds_commit(struct drm_encoder *encoder)
        /* Always do a full power on as we do not know what state
         * we were left in.
         */
-       intel_lvds_set_power(intel_lvds, true);
+       intel_lvds_enable(intel_lvds);
 }
 
 static void intel_lvds_mode_set(struct drm_encoder *encoder,
                                struct drm_display_mode *mode,
                                struct drm_display_mode *adjusted_mode)
 {
-       struct drm_device *dev = encoder->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
-
        /*
         * The LVDS pin pair will already have been turned on in the
         * intel_crtc_mode_set since it has a large impact on the DPLL
         * settings.
         */
-
-       if (HAS_PCH_SPLIT(dev))
-               return;
-
-       if (!intel_lvds->pfit_dirty)
-               return;
-
-       /*
-        * Enable automatic panel scaling so that non-native modes fill the
-        * screen.  Should be enabled before the pipe is enabled, according to
-        * register description and PRM.
-        */
-       DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n",
-                     intel_lvds->pfit_control,
-                     intel_lvds->pfit_pgm_ratios);
-       if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000))
-               DRM_ERROR("timed out waiting for panel to power off\n");
-
-       I915_WRITE(PFIT_PGM_RATIOS, intel_lvds->pfit_pgm_ratios);
-       I915_WRITE(PFIT_CONTROL, intel_lvds->pfit_control);
-       intel_lvds->pfit_dirty = false;
 }
 
 /**
@@ -837,7 +847,7 @@ static bool intel_lvds_ddc_probe(struct drm_device *dev, u8 pin)
  * Create the connector, register the LVDS DDC bus, and try to figure out what
  * modes we can display on the LVDS panel (if present).
  */
-void intel_lvds_init(struct drm_device *dev)
+bool intel_lvds_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_lvds *intel_lvds;
@@ -853,37 +863,37 @@ void intel_lvds_init(struct drm_device *dev)
 
        /* Skip init on machines we know falsely report LVDS */
        if (dmi_check_system(intel_no_lvds))
-               return;
+               return false;
 
        pin = GMBUS_PORT_PANEL;
        if (!lvds_is_present_in_vbt(dev, &pin)) {
                DRM_DEBUG_KMS("LVDS is not present in VBT\n");
-               return;
+               return false;
        }
 
        if (HAS_PCH_SPLIT(dev)) {
                if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0)
-                       return;
+                       return false;
                if (dev_priv->edp.support) {
                        DRM_DEBUG_KMS("disable LVDS for eDP support\n");
-                       return;
+                       return false;
                }
        }
 
        if (!intel_lvds_ddc_probe(dev, pin)) {
                DRM_DEBUG_KMS("LVDS did not respond to DDC probe\n");
-               return;
+               return false;
        }
 
        intel_lvds = kzalloc(sizeof(struct intel_lvds), GFP_KERNEL);
        if (!intel_lvds) {
-               return;
+               return false;
        }
 
        intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
        if (!intel_connector) {
                kfree(intel_lvds);
-               return;
+               return false;
        }
 
        if (!HAS_PCH_SPLIT(dev)) {
@@ -1026,7 +1036,7 @@ out:
        /* keep the LVDS connector */
        dev_priv->int_lvds_connector = connector;
        drm_sysfs_connector_add(connector);
-       return;
+       return true;
 
 failed:
        DRM_DEBUG_KMS("No LVDS modes found, disabling.\n");
@@ -1034,4 +1044,5 @@ failed:
        drm_encoder_cleanup(encoder);
        kfree(intel_lvds);
        kfree(intel_connector);
+       return false;
 }
index b83306f9244b6c887d84976b4f1801449445941a..89a65be8a3f364359edaf6add71b6259affa3cbd 100644 (file)
@@ -156,23 +156,25 @@ static int init_ring_common(struct drm_device *dev,
 
        /* G45 ring initialization fails to reset head to zero */
        if (head != 0) {
-               DRM_ERROR("%s head not reset to zero "
-                               "ctl %08x head %08x tail %08x start %08x\n",
-                               ring->name,
-                               I915_READ_CTL(ring),
-                               I915_READ_HEAD(ring),
-                               I915_READ_TAIL(ring),
-                               I915_READ_START(ring));
+               DRM_DEBUG_KMS("%s head not reset to zero "
+                             "ctl %08x head %08x tail %08x start %08x\n",
+                             ring->name,
+                             I915_READ_CTL(ring),
+                             I915_READ_HEAD(ring),
+                             I915_READ_TAIL(ring),
+                             I915_READ_START(ring));
 
                I915_WRITE_HEAD(ring, 0);
 
-               DRM_ERROR("%s head forced to zero "
-                               "ctl %08x head %08x tail %08x start %08x\n",
-                               ring->name,
-                               I915_READ_CTL(ring),
-                               I915_READ_HEAD(ring),
-                               I915_READ_TAIL(ring),
-                               I915_READ_START(ring));
+               if (I915_READ_HEAD(ring) & HEAD_ADDR) {
+                       DRM_ERROR("failed to set %s head to zero "
+                                 "ctl %08x head %08x tail %08x start %08x\n",
+                                 ring->name,
+                                 I915_READ_CTL(ring),
+                                 I915_READ_HEAD(ring),
+                                 I915_READ_TAIL(ring),
+                                 I915_READ_START(ring));
+               }
        }
 
        I915_WRITE_CTL(ring,
index de158b76bcd572da1e261713c66d43fa4428f72c..d97e6cb52d34a102705d9ab59f030cb551333e16 100644 (file)
@@ -107,7 +107,8 @@ struct intel_sdvo {
         * This is set if we treat the device as HDMI, instead of DVI.
         */
        bool is_hdmi;
-       bool has_audio;
+       bool has_hdmi_monitor;
+       bool has_hdmi_audio;
 
        /**
         * This is set if we detect output of sdvo device as LVDS and
@@ -1023,7 +1024,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
        if (!intel_sdvo_set_target_input(intel_sdvo))
                return;
 
-       if (intel_sdvo->is_hdmi &&
+       if (intel_sdvo->has_hdmi_monitor &&
            !intel_sdvo_set_avi_infoframe(intel_sdvo))
                return;
 
@@ -1063,7 +1064,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
        }
        if (intel_crtc->pipe == 1)
                sdvox |= SDVO_PIPE_B_SELECT;
-       if (intel_sdvo->has_audio)
+       if (intel_sdvo->has_hdmi_audio)
                sdvox |= SDVO_AUDIO_ENABLE;
 
        if (INTEL_INFO(dev)->gen >= 4) {
@@ -1295,55 +1296,14 @@ intel_sdvo_get_edid(struct drm_connector *connector)
        return drm_get_edid(connector, &sdvo->ddc);
 }
 
-static struct drm_connector *
-intel_find_analog_connector(struct drm_device *dev)
-{
-       struct drm_connector *connector;
-       struct intel_sdvo *encoder;
-
-       list_for_each_entry(encoder,
-                           &dev->mode_config.encoder_list,
-                           base.base.head) {
-               if (encoder->base.type == INTEL_OUTPUT_ANALOG) {
-                       list_for_each_entry(connector,
-                                           &dev->mode_config.connector_list,
-                                           head) {
-                               if (&encoder->base ==
-                                   intel_attached_encoder(connector))
-                                       return connector;
-                       }
-               }
-       }
-
-       return NULL;
-}
-
-static int
-intel_analog_is_connected(struct drm_device *dev)
-{
-       struct drm_connector *analog_connector;
-
-       analog_connector = intel_find_analog_connector(dev);
-       if (!analog_connector)
-               return false;
-
-       if (analog_connector->funcs->detect(analog_connector, false) ==
-                       connector_status_disconnected)
-               return false;
-
-       return true;
-}
-
 /* Mac mini hack -- use the same DDC as the analog connector */
 static struct edid *
 intel_sdvo_get_analog_edid(struct drm_connector *connector)
 {
        struct drm_i915_private *dev_priv = connector->dev->dev_private;
 
-       if (!intel_analog_is_connected(connector->dev))
-               return NULL;
-
-       return drm_get_edid(connector, &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter);
+       return drm_get_edid(connector,
+                           &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter);
 }
 
 enum drm_connector_status
@@ -1388,8 +1348,10 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
                /* DDC bus is shared, match EDID to connector type */
                if (edid->input & DRM_EDID_INPUT_DIGITAL) {
                        status = connector_status_connected;
-                       intel_sdvo->is_hdmi = drm_detect_hdmi_monitor(edid);
-                       intel_sdvo->has_audio = drm_detect_monitor_audio(edid);
+                       if (intel_sdvo->is_hdmi) {
+                               intel_sdvo->has_hdmi_monitor = drm_detect_hdmi_monitor(edid);
+                               intel_sdvo->has_hdmi_audio = drm_detect_monitor_audio(edid);
+                       }
                }
                connector->display_info.raw_edid = NULL;
                kfree(edid);
@@ -1398,7 +1360,7 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
        if (status == connector_status_connected) {
                struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector);
                if (intel_sdvo_connector->force_audio)
-                       intel_sdvo->has_audio = intel_sdvo_connector->force_audio > 0;
+                       intel_sdvo->has_hdmi_audio = intel_sdvo_connector->force_audio > 0;
        }
 
        return status;
@@ -1415,10 +1377,12 @@ intel_sdvo_detect(struct drm_connector *connector, bool force)
        if (!intel_sdvo_write_cmd(intel_sdvo,
                                  SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0))
                return connector_status_unknown;
-       if (intel_sdvo->is_tv) {
-               /* add 30ms delay when the output type is SDVO-TV */
+
+       /* add 30ms delay when the output type might be TV */
+       if (intel_sdvo->caps.output_flags &
+           (SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_CVBS0))
                mdelay(30);
-       }
+
        if (!intel_sdvo_read_response(intel_sdvo, &response, 2))
                return connector_status_unknown;
 
@@ -1472,8 +1436,10 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
                edid = intel_sdvo_get_analog_edid(connector);
 
        if (edid != NULL) {
-               drm_mode_connector_update_edid_property(connector, edid);
-               drm_add_edid_modes(connector, edid);
+               if (edid->input & DRM_EDID_INPUT_DIGITAL) {
+                       drm_mode_connector_update_edid_property(connector, edid);
+                       drm_add_edid_modes(connector, edid);
+               }
                connector->display_info.raw_edid = NULL;
                kfree(edid);
        }
@@ -1713,12 +1679,12 @@ intel_sdvo_set_property(struct drm_connector *connector,
 
                intel_sdvo_connector->force_audio = val;
 
-               if (val > 0 && intel_sdvo->has_audio)
+               if (val > 0 && intel_sdvo->has_hdmi_audio)
                        return 0;
-               if (val < 0 && !intel_sdvo->has_audio)
+               if (val < 0 && !intel_sdvo->has_hdmi_audio)
                        return 0;
 
-               intel_sdvo->has_audio = val > 0;
+               intel_sdvo->has_hdmi_audio = val > 0;
                goto done;
        }
 
@@ -2070,6 +2036,8 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
                intel_sdvo_set_colorimetry(intel_sdvo,
                                           SDVO_COLORIMETRY_RGB256);
                connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
+
+               intel_sdvo_add_hdmi_properties(intel_sdvo_connector);
                intel_sdvo->is_hdmi = true;
        }
        intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
@@ -2077,8 +2045,6 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
 
        intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
 
-       intel_sdvo_add_hdmi_properties(intel_sdvo_connector);
-
        return true;
 }
 
index 406228f4a2a05e549090f8a4e4fca09253546833..b14c811105756706103fe770bc140f24e0a604a7 100644 (file)
@@ -31,6 +31,7 @@
  */
 
 #include <linux/backlight.h>
+#include <linux/acpi.h>
 
 #include "drmP.h"
 #include "nouveau_drv.h"
@@ -136,6 +137,14 @@ int nouveau_backlight_init(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
 
+#ifdef CONFIG_ACPI
+       if (acpi_video_backlight_support()) {
+               NV_INFO(dev, "ACPI backlight interface available, "
+                            "not registering our own\n");
+               return 0;
+       }
+#endif
+
        switch (dev_priv->card_type) {
        case NV_40:
                return nouveau_nv40_backlight_init(dev);
index 5f21030a293bbc3f373a76631a5e092a0075ea3f..b2293576f27895f3b67e41e563675ab52519b3ad 100644 (file)
@@ -6829,7 +6829,7 @@ nouveau_bios_posted(struct drm_device *dev)
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        unsigned htotal;
 
-       if (dev_priv->chipset >= NV_50) {
+       if (dev_priv->card_type >= NV_50) {
                if (NVReadVgaCrtc(dev, 0, 0x00) == 0 &&
                    NVReadVgaCrtc(dev, 0, 0x1a) == 0)
                        return false;
index 80353e2b8409fdfe34b620b54ce8fdc119af5acd..c41e1c200ef5f2143ea670b45eb3f1d0633864e2 100644 (file)
@@ -143,8 +143,10 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
        nvbo->no_vm = no_vm;
        nvbo->tile_mode = tile_mode;
        nvbo->tile_flags = tile_flags;
+       nvbo->bo.bdev = &dev_priv->ttm.bdev;
 
-       nouveau_bo_fixup_align(dev, tile_mode, tile_flags, &align, &size);
+       nouveau_bo_fixup_align(dev, tile_mode, nouveau_bo_tile_layout(nvbo),
+                              &align, &size);
        align >>= PAGE_SHIFT;
 
        nouveau_bo_placement_set(nvbo, flags, 0);
@@ -176,6 +178,31 @@ set_placement_list(uint32_t *pl, unsigned *n, uint32_t type, uint32_t flags)
                pl[(*n)++] = TTM_PL_FLAG_SYSTEM | flags;
 }
 
+static void
+set_placement_range(struct nouveau_bo *nvbo, uint32_t type)
+{
+       struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev);
+
+       if (dev_priv->card_type == NV_10 &&
+           nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM)) {
+               /*
+                * Make sure that the color and depth buffers are handled
+                * by independent memory controller units. Up to a 9x
+                * speed up when alpha-blending and depth-test are enabled
+                * at the same time.
+                */
+               int vram_pages = dev_priv->vram_size >> PAGE_SHIFT;
+
+               if (nvbo->tile_flags & NOUVEAU_GEM_TILE_ZETA) {
+                       nvbo->placement.fpfn = vram_pages / 2;
+                       nvbo->placement.lpfn = ~0;
+               } else {
+                       nvbo->placement.fpfn = 0;
+                       nvbo->placement.lpfn = vram_pages / 2;
+               }
+       }
+}
+
 void
 nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t type, uint32_t busy)
 {
@@ -190,6 +217,8 @@ nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t type, uint32_t busy)
        pl->busy_placement = nvbo->busy_placements;
        set_placement_list(nvbo->busy_placements, &pl->num_busy_placement,
                           type | busy, flags);
+
+       set_placement_range(nvbo, type);
 }
 
 int
@@ -525,7 +554,8 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
                stride  = 16 * 4;
                height  = amount / stride;
 
-               if (new_mem->mem_type == TTM_PL_VRAM && nvbo->tile_flags) {
+               if (new_mem->mem_type == TTM_PL_VRAM &&
+                   nouveau_bo_tile_layout(nvbo)) {
                        ret = RING_SPACE(chan, 8);
                        if (ret)
                                return ret;
@@ -546,7 +576,8 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
                        BEGIN_RING(chan, NvSubM2MF, 0x0200, 1);
                        OUT_RING  (chan, 1);
                }
-               if (old_mem->mem_type == TTM_PL_VRAM && nvbo->tile_flags) {
+               if (old_mem->mem_type == TTM_PL_VRAM &&
+                   nouveau_bo_tile_layout(nvbo)) {
                        ret = RING_SPACE(chan, 8);
                        if (ret)
                                return ret;
@@ -753,7 +784,8 @@ nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem,
        if (dev_priv->card_type == NV_50) {
                ret = nv50_mem_vm_bind_linear(dev,
                                              offset + dev_priv->vm_vram_base,
-                                             new_mem->size, nvbo->tile_flags,
+                                             new_mem->size,
+                                             nouveau_bo_tile_layout(nvbo),
                                              offset);
                if (ret)
                        return ret;
@@ -894,7 +926,8 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
         * nothing to do here.
         */
        if (bo->mem.mem_type != TTM_PL_VRAM) {
-               if (dev_priv->card_type < NV_50 || !nvbo->tile_flags)
+               if (dev_priv->card_type < NV_50 ||
+                   !nouveau_bo_tile_layout(nvbo))
                        return 0;
        }
 
index 0871495096fa86f1278f825c8420f8e14f1e6b38..52c356e9a3d177b92ed5013e8f55247a56468f5d 100644 (file)
@@ -281,7 +281,7 @@ detect_analog:
        nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG);
        if (!nv_encoder && !nouveau_tv_disable)
                nv_encoder = find_encoder_by_type(connector, OUTPUT_TV);
-       if (nv_encoder) {
+       if (nv_encoder && force) {
                struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
                struct drm_encoder_helper_funcs *helper =
                                                encoder->helper_private;
@@ -641,11 +641,28 @@ nouveau_connector_get_modes(struct drm_connector *connector)
        return ret;
 }
 
+static unsigned
+get_tmds_link_bandwidth(struct drm_connector *connector)
+{
+       struct nouveau_connector *nv_connector = nouveau_connector(connector);
+       struct drm_nouveau_private *dev_priv = connector->dev->dev_private;
+       struct dcb_entry *dcb = nv_connector->detected_encoder->dcb;
+
+       if (dcb->location != DCB_LOC_ON_CHIP ||
+           dev_priv->chipset >= 0x46)
+               return 165000;
+       else if (dev_priv->chipset >= 0x40)
+               return 155000;
+       else if (dev_priv->chipset >= 0x18)
+               return 135000;
+       else
+               return 112000;
+}
+
 static int
 nouveau_connector_mode_valid(struct drm_connector *connector,
                             struct drm_display_mode *mode)
 {
-       struct drm_nouveau_private *dev_priv = connector->dev->dev_private;
        struct nouveau_connector *nv_connector = nouveau_connector(connector);
        struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
        struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
@@ -663,11 +680,9 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
                max_clock = 400000;
                break;
        case OUTPUT_TMDS:
-               if ((dev_priv->card_type >= NV_50 && !nouveau_duallink) ||
-                   !nv_encoder->dcb->duallink_possible)
-                       max_clock = 165000;
-               else
-                       max_clock = 330000;
+               max_clock = get_tmds_link_bandwidth(connector);
+               if (nouveau_duallink && nv_encoder->dcb->duallink_possible)
+                       max_clock *= 2;
                break;
        case OUTPUT_ANALOG:
                max_clock = nv_encoder->dcb->crtconf.maxfreq;
@@ -709,44 +724,6 @@ nouveau_connector_best_encoder(struct drm_connector *connector)
        return NULL;
 }
 
-void
-nouveau_connector_set_polling(struct drm_connector *connector)
-{
-       struct drm_device *dev = connector->dev;
-       struct drm_nouveau_private *dev_priv = dev->dev_private;
-       struct drm_crtc *crtc;
-       bool spare_crtc = false;
-
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
-               spare_crtc |= !crtc->enabled;
-
-       connector->polled = 0;
-
-       switch (connector->connector_type) {
-       case DRM_MODE_CONNECTOR_VGA:
-       case DRM_MODE_CONNECTOR_TV:
-               if (dev_priv->card_type >= NV_50 ||
-                   (nv_gf4_disp_arch(dev) && spare_crtc))
-                       connector->polled = DRM_CONNECTOR_POLL_CONNECT;
-               break;
-
-       case DRM_MODE_CONNECTOR_DVII:
-       case DRM_MODE_CONNECTOR_DVID:
-       case DRM_MODE_CONNECTOR_HDMIA:
-       case DRM_MODE_CONNECTOR_DisplayPort:
-       case DRM_MODE_CONNECTOR_eDP:
-               if (dev_priv->card_type >= NV_50)
-                       connector->polled = DRM_CONNECTOR_POLL_HPD;
-               else if (connector->connector_type == DRM_MODE_CONNECTOR_DVID ||
-                        spare_crtc)
-                       connector->polled = DRM_CONNECTOR_POLL_CONNECT;
-               break;
-
-       default:
-               break;
-       }
-}
-
 static const struct drm_connector_helper_funcs
 nouveau_connector_helper_funcs = {
        .get_modes = nouveau_connector_get_modes,
@@ -872,6 +849,7 @@ nouveau_connector_create(struct drm_device *dev, int index)
                                        dev->mode_config.scaling_mode_property,
                                        nv_connector->scaling_mode);
                }
+               connector->polled = DRM_CONNECTOR_POLL_CONNECT;
                /* fall-through */
        case DCB_CONNECTOR_TV_0:
        case DCB_CONNECTOR_TV_1:
@@ -888,11 +866,16 @@ nouveau_connector_create(struct drm_device *dev, int index)
                                dev->mode_config.dithering_mode_property,
                                nv_connector->use_dithering ?
                                DRM_MODE_DITHERING_ON : DRM_MODE_DITHERING_OFF);
+
+               if (dcb->type != DCB_CONNECTOR_LVDS) {
+                       if (dev_priv->card_type >= NV_50)
+                               connector->polled = DRM_CONNECTOR_POLL_HPD;
+                       else
+                               connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+               }
                break;
        }
 
-       nouveau_connector_set_polling(connector);
-
        drm_sysfs_connector_add(connector);
        dcb->drm = connector;
        return dcb->drm;
index c21ed6b16f88d41aebdee888997c12a7249fdd03..711b1e9203aff075c16757fd41394a5ea06d33e7 100644 (file)
@@ -52,9 +52,6 @@ static inline struct nouveau_connector *nouveau_connector(
 struct drm_connector *
 nouveau_connector_create(struct drm_device *, int index);
 
-void
-nouveau_connector_set_polling(struct drm_connector *);
-
 int
 nouveau_connector_bpp(struct drm_connector *);
 
index 3a07e580d27af548fe2fd247b4e7df4c67994956..1c7db64c03bf03b45070939f16bc5a0092820ba0 100644 (file)
@@ -100,6 +100,9 @@ struct nouveau_bo {
        int pin_refcnt;
 };
 
+#define nouveau_bo_tile_layout(nvbo)                           \
+       ((nvbo)->tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK)
+
 static inline struct nouveau_bo *
 nouveau_bo(struct ttm_buffer_object *bo)
 {
@@ -304,6 +307,7 @@ struct nouveau_fifo_engine {
        void (*destroy_context)(struct nouveau_channel *);
        int  (*load_context)(struct nouveau_channel *);
        int  (*unload_context)(struct drm_device *);
+       void (*tlb_flush)(struct drm_device *dev);
 };
 
 struct nouveau_pgraph_object_method {
@@ -336,6 +340,7 @@ struct nouveau_pgraph_engine {
        void (*destroy_context)(struct nouveau_channel *);
        int  (*load_context)(struct nouveau_channel *);
        int  (*unload_context)(struct drm_device *);
+       void (*tlb_flush)(struct drm_device *dev);
 
        void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr,
                                  uint32_t size, uint32_t pitch);
@@ -485,13 +490,13 @@ enum nv04_fp_display_regs {
 };
 
 struct nv04_crtc_reg {
-       unsigned char MiscOutReg;     /* */
+       unsigned char MiscOutReg;
        uint8_t CRTC[0xa0];
        uint8_t CR58[0x10];
        uint8_t Sequencer[5];
        uint8_t Graphics[9];
        uint8_t Attribute[21];
-       unsigned char DAC[768];       /* Internal Colorlookuptable */
+       unsigned char DAC[768];
 
        /* PCRTC regs */
        uint32_t fb_start;
@@ -539,43 +544,9 @@ struct nv04_output_reg {
 };
 
 struct nv04_mode_state {
-       uint32_t bpp;
-       uint32_t width;
-       uint32_t height;
-       uint32_t interlace;
-       uint32_t repaint0;
-       uint32_t repaint1;
-       uint32_t screen;
-       uint32_t scale;
-       uint32_t dither;
-       uint32_t extra;
-       uint32_t fifo;
-       uint32_t pixel;
-       uint32_t horiz;
-       int arbitration0;
-       int arbitration1;
-       uint32_t pll;
-       uint32_t pllB;
-       uint32_t vpll;
-       uint32_t vpll2;
-       uint32_t vpllB;
-       uint32_t vpll2B;
+       struct nv04_crtc_reg crtc_reg[2];
        uint32_t pllsel;
        uint32_t sel_clk;
-       uint32_t general;
-       uint32_t crtcOwner;
-       uint32_t head;
-       uint32_t head2;
-       uint32_t cursorConfig;
-       uint32_t cursor0;
-       uint32_t cursor1;
-       uint32_t cursor2;
-       uint32_t timingH;
-       uint32_t timingV;
-       uint32_t displayV;
-       uint32_t crtcSync;
-
-       struct nv04_crtc_reg crtc_reg[2];
 };
 
 enum nouveau_card_type {
@@ -613,6 +584,12 @@ struct drm_nouveau_private {
        struct work_struct irq_work;
        struct work_struct hpd_work;
 
+       struct {
+               spinlock_t lock;
+               uint32_t hpd0_bits;
+               uint32_t hpd1_bits;
+       } hpd_state;
+
        struct list_head vbl_waiting;
 
        struct {
@@ -1045,6 +1022,7 @@ extern int  nv50_fifo_create_context(struct nouveau_channel *);
 extern void nv50_fifo_destroy_context(struct nouveau_channel *);
 extern int  nv50_fifo_load_context(struct nouveau_channel *);
 extern int  nv50_fifo_unload_context(struct drm_device *);
+extern void nv50_fifo_tlb_flush(struct drm_device *dev);
 
 /* nvc0_fifo.c */
 extern int  nvc0_fifo_init(struct drm_device *);
@@ -1122,6 +1100,8 @@ extern int  nv50_graph_load_context(struct nouveau_channel *);
 extern int  nv50_graph_unload_context(struct drm_device *);
 extern void nv50_graph_context_switch(struct drm_device *);
 extern int  nv50_grctx_init(struct nouveau_grctx *);
+extern void nv50_graph_tlb_flush(struct drm_device *dev);
+extern void nv86_graph_tlb_flush(struct drm_device *dev);
 
 /* nvc0_graph.c */
 extern int  nvc0_graph_init(struct drm_device *);
@@ -1239,7 +1219,6 @@ extern u16 nouveau_bo_rd16(struct nouveau_bo *nvbo, unsigned index);
 extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val);
 extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index);
 extern void nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val);
-extern int nouveau_bo_sync_gpu(struct nouveau_bo *, struct nouveau_channel *);
 
 /* nouveau_fence.c */
 struct nouveau_fence;
index 441b12420bb1b713fb56b98edad389d31fe367ea..ab1bbfbf266e6a63755264ad461484f3608a10c1 100644 (file)
@@ -249,6 +249,7 @@ alloc_semaphore(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_semaphore *sema;
+       int ret;
 
        if (!USE_SEMA(dev))
                return NULL;
@@ -257,10 +258,14 @@ alloc_semaphore(struct drm_device *dev)
        if (!sema)
                goto fail;
 
+       ret = drm_mm_pre_get(&dev_priv->fence.heap);
+       if (ret)
+               goto fail;
+
        spin_lock(&dev_priv->fence.lock);
        sema->mem = drm_mm_search_free(&dev_priv->fence.heap, 4, 0, 0);
        if (sema->mem)
-               sema->mem = drm_mm_get_block(sema->mem, 4, 0);
+               sema->mem = drm_mm_get_block_atomic(sema->mem, 4, 0);
        spin_unlock(&dev_priv->fence.lock);
 
        if (!sema->mem)
index 5c4c929d7f744d6911c1a16b67924ab770b6de5c..9a1fdcf400c2fea235544f062fe8b33cd1b01fd4 100644 (file)
@@ -107,23 +107,29 @@ nouveau_gem_info(struct drm_gem_object *gem, struct drm_nouveau_gem_info *rep)
 }
 
 static bool
-nouveau_gem_tile_flags_valid(struct drm_device *dev, uint32_t tile_flags) {
-       switch (tile_flags) {
-       case 0x0000:
-       case 0x1800:
-       case 0x2800:
-       case 0x4800:
-       case 0x7000:
-       case 0x7400:
-       case 0x7a00:
-       case 0xe000:
-               break;
-       default:
-               NV_ERROR(dev, "bad page flags: 0x%08x\n", tile_flags);
-               return false;
+nouveau_gem_tile_flags_valid(struct drm_device *dev, uint32_t tile_flags)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       if (dev_priv->card_type >= NV_50) {
+               switch (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) {
+               case 0x0000:
+               case 0x1800:
+               case 0x2800:
+               case 0x4800:
+               case 0x7000:
+               case 0x7400:
+               case 0x7a00:
+               case 0xe000:
+                       return true;
+               }
+       } else {
+               if (!(tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK))
+                       return true;
        }
 
-       return true;
+       NV_ERROR(dev, "bad page flags: 0x%08x\n", tile_flags);
+       return false;
 }
 
 int
index bed669a54a2da0692af9a9a1cd4a89064f4d0fd0..b9672a05c411f12866035884acf8778a4742eb9c 100644 (file)
@@ -519,11 +519,11 @@ nouveau_hw_fix_bad_vpll(struct drm_device *dev, int head)
 
        struct pll_lims pll_lim;
        struct nouveau_pll_vals pv;
-       uint32_t pllreg = head ? NV_RAMDAC_VPLL2 : NV_PRAMDAC_VPLL_COEFF;
+       enum pll_types pll = head ? PLL_VPLL1 : PLL_VPLL0;
 
-       if (get_pll_limits(dev, pllreg, &pll_lim))
+       if (get_pll_limits(dev, pll, &pll_lim))
                return;
-       nouveau_hw_get_pllvals(dev, pllreg, &pv);
+       nouveau_hw_get_pllvals(dev, pll, &pv);
 
        if (pv.M1 >= pll_lim.vco1.min_m && pv.M1 <= pll_lim.vco1.max_m &&
            pv.N1 >= pll_lim.vco1.min_n && pv.N1 <= pll_lim.vco1.max_n &&
@@ -536,7 +536,7 @@ nouveau_hw_fix_bad_vpll(struct drm_device *dev, int head)
        pv.M1 = pll_lim.vco1.max_m;
        pv.N1 = pll_lim.vco1.min_n;
        pv.log2P = pll_lim.max_usable_log2p;
-       nouveau_hw_setpll(dev, pllreg, &pv);
+       nouveau_hw_setpll(dev, pll_lim.reg, &pv);
 }
 
 /*
index 869130f83602f6cf027a2329eb7be49eafb88ccc..2989090b94349abdcd05096f89735f641a748c3b 100644 (file)
@@ -415,6 +415,25 @@ nv_fix_nv40_hw_cursor(struct drm_device *dev, int head)
        NVWriteRAMDAC(dev, head, NV_PRAMDAC_CU_START_POS, curpos);
 }
 
+static inline void
+nv_set_crtc_base(struct drm_device *dev, int head, uint32_t offset)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       NVWriteCRTC(dev, head, NV_PCRTC_START, offset);
+
+       if (dev_priv->card_type == NV_04) {
+               /*
+                * Hilarious, the 24th bit doesn't want to stick to
+                * PCRTC_START...
+                */
+               int cre_heb = NVReadVgaCrtc(dev, head, NV_CIO_CRE_HEB__INDEX);
+
+               NVWriteVgaCrtc(dev, head, NV_CIO_CRE_HEB__INDEX,
+                              (cre_heb & ~0x40) | ((offset >> 18) & 0x40));
+       }
+}
+
 static inline void
 nv_show_cursor(struct drm_device *dev, int head, bool show)
 {
index fdd7e3de79c895138c93706bc023048772f93026..cb389d014326ae4c89b78724f3438a023e0f06b7 100644 (file)
@@ -256,7 +256,7 @@ nouveau_i2c_find(struct drm_device *dev, int index)
        if (index >= DCB_MAX_NUM_I2C_ENTRIES)
                return NULL;
 
-       if (dev_priv->chipset >= NV_50 && (i2c->entry & 0x00000100)) {
+       if (dev_priv->card_type >= NV_50 && (i2c->entry & 0x00000100)) {
                uint32_t reg = 0xe500, val;
 
                if (i2c->port_type == 6) {
index 6fd51a51c60861e697f43755593f4ad2a1830c9c..7bfd9e6c9d67194b298047d7670a54a996c16750 100644 (file)
 #include "nouveau_connector.h"
 #include "nv50_display.h"
 
+static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20);
+
+static int nouveau_ratelimit(void)
+{
+       return __ratelimit(&nouveau_ratelimit_state);
+}
+
 void
 nouveau_irq_preinstall(struct drm_device *dev)
 {
@@ -53,6 +60,7 @@ nouveau_irq_preinstall(struct drm_device *dev)
        if (dev_priv->card_type >= NV_50) {
                INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh);
                INIT_WORK(&dev_priv->hpd_work, nv50_display_irq_hotplug_bh);
+               spin_lock_init(&dev_priv->hpd_state.lock);
                INIT_LIST_HEAD(&dev_priv->vbl_waiting);
        }
 }
@@ -202,8 +210,8 @@ nouveau_fifo_irq_handler(struct drm_device *dev)
                }
 
                if (status & NV_PFIFO_INTR_DMA_PUSHER) {
-                       u32 get = nv_rd32(dev, 0x003244);
-                       u32 put = nv_rd32(dev, 0x003240);
+                       u32 dma_get = nv_rd32(dev, 0x003244);
+                       u32 dma_put = nv_rd32(dev, 0x003240);
                        u32 push = nv_rd32(dev, 0x003220);
                        u32 state = nv_rd32(dev, 0x003228);
 
@@ -213,16 +221,18 @@ nouveau_fifo_irq_handler(struct drm_device *dev)
                                u32 ib_get = nv_rd32(dev, 0x003334);
                                u32 ib_put = nv_rd32(dev, 0x003330);
 
-                               NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%02x%08x "
+                               if (nouveau_ratelimit())
+                                       NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%02x%08x "
                                             "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x "
                                             "State 0x%08x Push 0x%08x\n",
-                                       chid, ho_get, get, ho_put, put, ib_get, ib_put,
-                                       state, push);
+                                               chid, ho_get, dma_get, ho_put,
+                                               dma_put, ib_get, ib_put, state,
+                                               push);
 
                                /* METHOD_COUNT, in DMA_STATE on earlier chipsets */
                                nv_wr32(dev, 0x003364, 0x00000000);
-                               if (get != put || ho_get != ho_put) {
-                                       nv_wr32(dev, 0x003244, put);
+                               if (dma_get != dma_put || ho_get != ho_put) {
+                                       nv_wr32(dev, 0x003244, dma_put);
                                        nv_wr32(dev, 0x003328, ho_put);
                                } else
                                if (ib_get != ib_put) {
@@ -231,10 +241,10 @@ nouveau_fifo_irq_handler(struct drm_device *dev)
                        } else {
                                NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%08x "
                                             "Put 0x%08x State 0x%08x Push 0x%08x\n",
-                                       chid, get, put, state, push);
+                                       chid, dma_get, dma_put, state, push);
 
-                               if (get != put)
-                                       nv_wr32(dev, 0x003244, put);
+                               if (dma_get != dma_put)
+                                       nv_wr32(dev, 0x003244, dma_put);
                        }
 
                        nv_wr32(dev, 0x003228, 0x00000000);
@@ -266,8 +276,9 @@ nouveau_fifo_irq_handler(struct drm_device *dev)
                }
 
                if (status) {
-                       NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n",
-                               status, chid);
+                       if (nouveau_ratelimit())
+                               NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n",
+                                       status, chid);
                        nv_wr32(dev, NV03_PFIFO_INTR_0, status);
                        status = 0;
                }
@@ -544,13 +555,6 @@ nouveau_pgraph_intr_notify(struct drm_device *dev, uint32_t nsource)
                nouveau_graph_dump_trap_info(dev, "PGRAPH_NOTIFY", &trap);
 }
 
-static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20);
-
-static int nouveau_ratelimit(void)
-{
-       return __ratelimit(&nouveau_ratelimit_state);
-}
-
 
 static inline void
 nouveau_pgraph_intr_error(struct drm_device *dev, uint32_t nsource)
index a163c7c612e78eb6b6718620ee75773cd49a26f7..fe4a30dc4b42e929f283d35e1094b26a422f4f2e 100644 (file)
@@ -33,9 +33,9 @@
 #include "drmP.h"
 #include "drm.h"
 #include "drm_sarea.h"
-#include "nouveau_drv.h"
 
-#define MIN(a,b) a < b ? a : b
+#include "nouveau_drv.h"
+#include "nouveau_pm.h"
 
 /*
  * NV10-NV40 tiling helpers
@@ -175,11 +175,10 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size,
                        }
                }
        }
-       dev_priv->engine.instmem.flush(dev);
 
-       nv50_vm_flush(dev, 5);
-       nv50_vm_flush(dev, 0);
-       nv50_vm_flush(dev, 4);
+       dev_priv->engine.instmem.flush(dev);
+       dev_priv->engine.fifo.tlb_flush(dev);
+       dev_priv->engine.graph.tlb_flush(dev);
        nv50_vm_flush(dev, 6);
        return 0;
 }
@@ -209,11 +208,10 @@ nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size)
                        pte++;
                }
        }
-       dev_priv->engine.instmem.flush(dev);
 
-       nv50_vm_flush(dev, 5);
-       nv50_vm_flush(dev, 0);
-       nv50_vm_flush(dev, 4);
+       dev_priv->engine.instmem.flush(dev);
+       dev_priv->engine.fifo.tlb_flush(dev);
+       dev_priv->engine.graph.tlb_flush(dev);
        nv50_vm_flush(dev, 6);
 }
 
@@ -653,6 +651,7 @@ nouveau_mem_gart_init(struct drm_device *dev)
 void
 nouveau_mem_timing_init(struct drm_device *dev)
 {
+       /* cards < NVC0 only */
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
        struct nouveau_pm_memtimings *memtimings = &pm->memtimings;
@@ -719,14 +718,14 @@ nouveau_mem_timing_init(struct drm_device *dev)
                tUNK_19 = 1;
                tUNK_20 = 0;
                tUNK_21 = 0;
-               switch (MIN(recordlen,21)) {
-               case 21:
+               switch (min(recordlen, 22)) {
+               case 22:
                        tUNK_21 = entry[21];
-               case 20:
+               case 21:
                        tUNK_20 = entry[20];
-               case 19:
+               case 20:
                        tUNK_19 = entry[19];
-               case 18:
+               case 19:
                        tUNK_18 = entry[18];
                default:
                        tUNK_0  = entry[0];
@@ -756,24 +755,30 @@ nouveau_mem_timing_init(struct drm_device *dev)
                timing->reg_100228 = (tUNK_12 << 16 | tUNK_11 << 8 | tUNK_10);
                if(recordlen > 19) {
                        timing->reg_100228 += (tUNK_19 - 1) << 24;
-               } else {
+               }/* I cannot back-up this else-statement right now
+                        else {
                        timing->reg_100228 += tUNK_12 << 24;
-               }
+               }*/
 
                /* XXX: reg_10022c */
+               timing->reg_10022c = tUNK_2 - 1;
 
                timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 |
                                      tUNK_13 << 8  | tUNK_13);
 
                /* XXX: +6? */
                timing->reg_100234 = (tRAS << 24 | (tUNK_19 + 6) << 8 | tRC);
-               if(tUNK_10 > tUNK_11) {
-                       timing->reg_100234 += tUNK_10 << 16;
-               } else {
-                       timing->reg_100234 += tUNK_11 << 16;
+               timing->reg_100234 += max(tUNK_10,tUNK_11) << 16;
+
+               /* XXX; reg_100238, reg_10023c
+                * reg: 0x00??????
+                * reg_10023c:
+                *      0 for pre-NV50 cards
+                *      0x????0202 for NV50+ cards (empirical evidence) */
+               if(dev_priv->card_type >= NV_50) {
+                       timing->reg_10023c = 0x202;
                }
 
-               /* XXX; reg_100238, reg_10023c */
                NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i,
                         timing->reg_100220, timing->reg_100224,
                         timing->reg_100228, timing->reg_10022c);
index 896cf8634144a2b5cf7f69fdd006c848b4b2eb79..dd572adca02ad0232df35715257ccc597adf86f3 100644 (file)
@@ -129,7 +129,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
                        if (ramin == NULL) {
                                spin_unlock(&dev_priv->ramin_lock);
                                nouveau_gpuobj_ref(NULL, &gpuobj);
-                               return ret;
+                               return -ENOMEM;
                        }
 
                        ramin = drm_mm_get_block_atomic(ramin, size, align);
index 1c99c55d6d468a91fb09cda39d5660d3bf712aa5..9f7b158f5825c7dfd97b5f112afef7a9858e7b23 100644 (file)
@@ -284,6 +284,7 @@ nouveau_sysfs_fini(struct drm_device *dev)
        }
 }
 
+#ifdef CONFIG_HWMON
 static ssize_t
 nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf)
 {
@@ -395,10 +396,12 @@ static struct attribute *hwmon_attributes[] = {
 static const struct attribute_group hwmon_attrgroup = {
        .attrs = hwmon_attributes,
 };
+#endif
 
 static int
 nouveau_hwmon_init(struct drm_device *dev)
 {
+#ifdef CONFIG_HWMON
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
        struct device *hwmon_dev;
@@ -425,13 +428,14 @@ nouveau_hwmon_init(struct drm_device *dev)
        }
 
        pm->hwmon = hwmon_dev;
-
+#endif
        return 0;
 }
 
 static void
 nouveau_hwmon_fini(struct drm_device *dev)
 {
+#ifdef CONFIG_HWMON
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
 
@@ -439,6 +443,7 @@ nouveau_hwmon_fini(struct drm_device *dev)
                sysfs_remove_group(&pm->hwmon->kobj, &hwmon_attrgroup);
                hwmon_device_unregister(pm->hwmon);
        }
+#endif
 }
 
 int
index 7f16697cc96ce6438896414735b5fa4d12a84a34..2d8580927ca4579075cd870e5cfdf6459c44d9c6 100644 (file)
@@ -153,26 +153,42 @@ nouveau_ramht_insert(struct nouveau_channel *chan, u32 handle,
        return -ENOMEM;
 }
 
+static struct nouveau_ramht_entry *
+nouveau_ramht_remove_entry(struct nouveau_channel *chan, u32 handle)
+{
+       struct nouveau_ramht *ramht = chan ? chan->ramht : NULL;
+       struct nouveau_ramht_entry *entry;
+       unsigned long flags;
+
+       if (!ramht)
+               return NULL;
+
+       spin_lock_irqsave(&ramht->lock, flags);
+       list_for_each_entry(entry, &ramht->entries, head) {
+               if (entry->channel == chan &&
+                   (!handle || entry->handle == handle)) {
+                       list_del(&entry->head);
+                       spin_unlock_irqrestore(&ramht->lock, flags);
+
+                       return entry;
+               }
+       }
+       spin_unlock_irqrestore(&ramht->lock, flags);
+
+       return NULL;
+}
+
 static void
-nouveau_ramht_remove_locked(struct nouveau_channel *chan, u32 handle)
+nouveau_ramht_remove_hash(struct nouveau_channel *chan, u32 handle)
 {
        struct drm_device *dev = chan->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
        struct nouveau_gpuobj *ramht = chan->ramht->gpuobj;
-       struct nouveau_ramht_entry *entry, *tmp;
+       unsigned long flags;
        u32 co, ho;
 
-       list_for_each_entry_safe(entry, tmp, &chan->ramht->entries, head) {
-               if (entry->channel != chan || entry->handle != handle)
-                       continue;
-
-               nouveau_gpuobj_ref(NULL, &entry->gpuobj);
-               list_del(&entry->head);
-               kfree(entry);
-               break;
-       }
-
+       spin_lock_irqsave(&chan->ramht->lock, flags);
        co = ho = nouveau_ramht_hash_handle(chan, handle);
        do {
                if (nouveau_ramht_entry_valid(dev, ramht, co) &&
@@ -184,7 +200,7 @@ nouveau_ramht_remove_locked(struct nouveau_channel *chan, u32 handle)
                        nv_wo32(ramht, co + 0, 0x00000000);
                        nv_wo32(ramht, co + 4, 0x00000000);
                        instmem->flush(dev);
-                       return;
+                       goto out;
                }
 
                co += 8;
@@ -194,17 +210,22 @@ nouveau_ramht_remove_locked(struct nouveau_channel *chan, u32 handle)
 
        NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n",
                 chan->id, handle);
+out:
+       spin_unlock_irqrestore(&chan->ramht->lock, flags);
 }
 
 void
 nouveau_ramht_remove(struct nouveau_channel *chan, u32 handle)
 {
-       struct nouveau_ramht *ramht = chan->ramht;
-       unsigned long flags;
+       struct nouveau_ramht_entry *entry;
 
-       spin_lock_irqsave(&ramht->lock, flags);
-       nouveau_ramht_remove_locked(chan, handle);
-       spin_unlock_irqrestore(&ramht->lock, flags);
+       entry = nouveau_ramht_remove_entry(chan, handle);
+       if (!entry)
+               return;
+
+       nouveau_ramht_remove_hash(chan, entry->handle);
+       nouveau_gpuobj_ref(NULL, &entry->gpuobj);
+       kfree(entry);
 }
 
 struct nouveau_gpuobj *
@@ -265,23 +286,19 @@ void
 nouveau_ramht_ref(struct nouveau_ramht *ref, struct nouveau_ramht **ptr,
                  struct nouveau_channel *chan)
 {
-       struct nouveau_ramht_entry *entry, *tmp;
+       struct nouveau_ramht_entry *entry;
        struct nouveau_ramht *ramht;
-       unsigned long flags;
 
        if (ref)
                kref_get(&ref->refcount);
 
        ramht = *ptr;
        if (ramht) {
-               spin_lock_irqsave(&ramht->lock, flags);
-               list_for_each_entry_safe(entry, tmp, &ramht->entries, head) {
-                       if (entry->channel != chan)
-                               continue;
-
-                       nouveau_ramht_remove_locked(chan, entry->handle);
+               while ((entry = nouveau_ramht_remove_entry(chan, 0))) {
+                       nouveau_ramht_remove_hash(chan, entry->handle);
+                       nouveau_gpuobj_ref(NULL, &entry->gpuobj);
+                       kfree(entry);
                }
-               spin_unlock_irqrestore(&ramht->lock, flags);
 
                kref_put(&ramht->refcount, nouveau_ramht_del);
        }
index 288bacac7e5aefc2f3c6c9b4f461a7e48d6e9ce7..d4ac970070386cea340283ba459194eb8b1de50a 100644 (file)
@@ -120,8 +120,8 @@ nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
        dev_priv->engine.instmem.flush(nvbe->dev);
 
        if (dev_priv->card_type == NV_50) {
-               nv50_vm_flush(dev, 5); /* PGRAPH */
-               nv50_vm_flush(dev, 0); /* PFIFO */
+               dev_priv->engine.fifo.tlb_flush(dev);
+               dev_priv->engine.graph.tlb_flush(dev);
        }
 
        nvbe->bound = true;
@@ -162,8 +162,8 @@ nouveau_sgdma_unbind(struct ttm_backend *be)
        dev_priv->engine.instmem.flush(nvbe->dev);
 
        if (dev_priv->card_type == NV_50) {
-               nv50_vm_flush(dev, 5);
-               nv50_vm_flush(dev, 0);
+               dev_priv->engine.fifo.tlb_flush(dev);
+               dev_priv->engine.graph.tlb_flush(dev);
        }
 
        nvbe->bound = false;
@@ -224,7 +224,11 @@ nouveau_sgdma_init(struct drm_device *dev)
        int i, ret;
 
        if (dev_priv->card_type < NV_50) {
-               aper_size = (64 * 1024 * 1024);
+               if(dev_priv->ramin_rsvd_vram < 2 * 1024 * 1024)
+                       aper_size = 64 * 1024 * 1024;
+               else
+                       aper_size = 512 * 1024 * 1024;
+
                obj_size  = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 4;
                obj_size += 8; /* ctxdma header */
        } else {
index ed7757f14083a17e3122250ca83aa8ee2959ddec..049f755567e5c83b047298f74ff1c24b6ceea5fe 100644 (file)
@@ -354,6 +354,15 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->graph.destroy_context   = nv50_graph_destroy_context;
                engine->graph.load_context      = nv50_graph_load_context;
                engine->graph.unload_context    = nv50_graph_unload_context;
+               if (dev_priv->chipset != 0x86)
+                       engine->graph.tlb_flush = nv50_graph_tlb_flush;
+               else {
+                       /* from what i can see nvidia do this on every
+                        * pre-NVA3 board except NVAC, but, we've only
+                        * ever seen problems on NV86
+                        */
+                       engine->graph.tlb_flush = nv86_graph_tlb_flush;
+               }
                engine->fifo.channels           = 128;
                engine->fifo.init               = nv50_fifo_init;
                engine->fifo.takedown           = nv50_fifo_takedown;
@@ -365,6 +374,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->fifo.destroy_context    = nv50_fifo_destroy_context;
                engine->fifo.load_context       = nv50_fifo_load_context;
                engine->fifo.unload_context     = nv50_fifo_unload_context;
+               engine->fifo.tlb_flush          = nv50_fifo_tlb_flush;
                engine->display.early_init      = nv50_display_early_init;
                engine->display.late_takedown   = nv50_display_late_takedown;
                engine->display.create          = nv50_display_create;
@@ -1041,6 +1051,9 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data,
        case NOUVEAU_GETPARAM_PTIMER_TIME:
                getparam->value = dev_priv->engine.timer.read(dev);
                break;
+       case NOUVEAU_GETPARAM_HAS_BO_USAGE:
+               getparam->value = 1;
+               break;
        case NOUVEAU_GETPARAM_GRAPH_UNITS:
                /* NV40 and NV50 versions are quite different, but register
                 * address is the same. User is supposed to know the card
@@ -1051,7 +1064,7 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data,
                }
                /* FALLTHRU */
        default:
-               NV_ERROR(dev, "unknown parameter %lld\n", getparam->param);
+               NV_DEBUG(dev, "unknown parameter %lld\n", getparam->param);
                return -EINVAL;
        }
 
@@ -1066,7 +1079,7 @@ nouveau_ioctl_setparam(struct drm_device *dev, void *data,
 
        switch (setparam->param) {
        default:
-               NV_ERROR(dev, "unknown parameter %lld\n", setparam->param);
+               NV_DEBUG(dev, "unknown parameter %lld\n", setparam->param);
                return -EINVAL;
        }
 
index 16bbbf1eff63bc5ef37038e37d85fccc7f407a8d..7ecc4adc1e4575aca6ef2791752c25300ff7668b 100644 (file)
@@ -191,7 +191,7 @@ nv40_temp_get(struct drm_device *dev)
        int offset = sensor->offset_mult / sensor->offset_div;
        int core_temp;
 
-       if (dev_priv->chipset >= 0x50) {
+       if (dev_priv->card_type >= NV_50) {
                core_temp = nv_rd32(dev, 0x20008);
        } else {
                core_temp = nv_rd32(dev, 0x0015b4) & 0x1fff;
index c71abc2a34d5d9cf22a01d3c3bf455a29c5d1dbf..40e180741629e056f72445ffab06104760bd70ec 100644 (file)
@@ -158,7 +158,6 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
        struct drm_device *dev = crtc->dev;
-       struct drm_connector *connector;
        unsigned char seq1 = 0, crtc17 = 0;
        unsigned char crtc1A;
 
@@ -213,10 +212,6 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode)
        NVVgaSeqReset(dev, nv_crtc->index, false);
 
        NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RPC1_INDEX, crtc1A);
-
-       /* Update connector polling modes */
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head)
-               nouveau_connector_set_polling(connector);
 }
 
 static bool
@@ -831,7 +826,7 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
        /* Update the framebuffer location. */
        regp->fb_start = nv_crtc->fb.offset & ~3;
        regp->fb_start += (y * drm_fb->pitch) + (x * drm_fb->bits_per_pixel / 8);
-       NVWriteCRTC(dev, nv_crtc->index, NV_PCRTC_START, regp->fb_start);
+       nv_set_crtc_base(dev, nv_crtc->index, regp->fb_start);
 
        /* Update the arbitration parameters. */
        nouveau_calc_arb(dev, crtc->mode.clock, drm_fb->bits_per_pixel,
index c936403b26e22f7b4bcc1b4fee4fa6809498689b..ef23550407b5d7da95c0a4a5a6c35b82670ad4e5 100644 (file)
@@ -185,14 +185,15 @@ static bool nv04_dfp_mode_fixup(struct drm_encoder *encoder,
        struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
        struct nouveau_connector *nv_connector = nouveau_encoder_connector_get(nv_encoder);
 
-       /* For internal panels and gpu scaling on DVI we need the native mode */
-       if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) {
-               if (!nv_connector->native_mode)
-                       return false;
+       if (!nv_connector->native_mode ||
+           nv_connector->scaling_mode == DRM_MODE_SCALE_NONE ||
+           mode->hdisplay > nv_connector->native_mode->hdisplay ||
+           mode->vdisplay > nv_connector->native_mode->vdisplay) {
+               nv_encoder->mode = *adjusted_mode;
+
+       } else {
                nv_encoder->mode = *nv_connector->native_mode;
                adjusted_mode->clock = nv_connector->native_mode->clock;
-       } else {
-               nv_encoder->mode = *adjusted_mode;
        }
 
        return true;
index 6a6eb697d38e0b387941b05b38dadc8a5bd371f1..eb1c70dd82ed41540629792dc7264452f511e6f3 100644 (file)
@@ -76,6 +76,15 @@ nv04_pm_clock_set(struct drm_device *dev, void *pre_state)
                reg += 4;
 
        nouveau_hw_setpll(dev, reg, &state->calc);
+
+       if (dev_priv->card_type < NV_30 && reg == NV_PRAMDAC_MPLL_COEFF) {
+               if (dev_priv->card_type == NV_20)
+                       nv_mask(dev, 0x1002c4, 0, 1 << 20);
+
+               /* Reset the DLLs */
+               nv_mask(dev, 0x1002c0, 0, 1 << 8);
+       }
+
        kfree(state);
 }
 
index 2cdc2bfe717924bf4f8e29237c11efcc0865408b..de81151648f831c5a7c97b9491d3670c356276f5 100644 (file)
@@ -51,24 +51,28 @@ nv50_calc_pll2(struct drm_device *dev, struct pll_lims *pll, int clk,
               int *N, int *fN, int *M, int *P)
 {
        fixed20_12 fb_div, a, b;
+       u32 refclk = pll->refclk / 10;
+       u32 max_vco_freq = pll->vco1.maxfreq / 10;
+       u32 max_vco_inputfreq = pll->vco1.max_inputfreq / 10;
+       clk /= 10;
 
-       *P = pll->vco1.maxfreq / clk;
+       *P = max_vco_freq / clk;
        if (*P > pll->max_p)
                *P = pll->max_p;
        if (*P < pll->min_p)
                *P = pll->min_p;
 
-       /* *M = ceil(refclk / pll->vco.max_inputfreq); */
-       a.full = dfixed_const(pll->refclk);
-       b.full = dfixed_const(pll->vco1.max_inputfreq);
+       /* *M = floor((refclk + max_vco_inputfreq) / max_vco_inputfreq); */
+       a.full = dfixed_const(refclk + max_vco_inputfreq);
+       b.full = dfixed_const(max_vco_inputfreq);
        a.full = dfixed_div(a, b);
-       a.full = dfixed_ceil(a);
+       a.full = dfixed_floor(a);
        *M = dfixed_trunc(a);
 
        /* fb_div = (vco * *M) / refclk; */
        fb_div.full = dfixed_const(clk * *P);
        fb_div.full = dfixed_mul(fb_div, a);
-       a.full = dfixed_const(pll->refclk);
+       a.full = dfixed_const(refclk);
        fb_div.full = dfixed_div(fb_div, a);
 
        /* *N = floor(fb_div); */
index 16380d52cd885599f349219c903f12cf7b9c6159..56476d0c6de8ee5255ff6c8916070a5c5ed86aec 100644 (file)
@@ -546,7 +546,7 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
        }
 
        nv_crtc->fb.offset = fb->nvbo->bo.offset - dev_priv->vm_vram_base;
-       nv_crtc->fb.tile_flags = fb->nvbo->tile_flags;
+       nv_crtc->fb.tile_flags = nouveau_bo_tile_layout(fb->nvbo);
        nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8;
        if (!nv_crtc->fb.blanked && dev_priv->chipset != 0x50) {
                ret = RING_SPACE(evo, 2);
@@ -578,7 +578,7 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
                                  fb->nvbo->tile_mode);
        }
        if (dev_priv->chipset == 0x50)
-               OUT_RING(evo, (fb->nvbo->tile_flags << 8) | format);
+               OUT_RING(evo, (nv_crtc->fb.tile_flags << 8) | format);
        else
                OUT_RING(evo, format);
 
index 55c9663ef2bf8ddd4df2cf15b452daed66abc583..f624c611ddeaf39cb1c46010d7da30e4461c35ad 100644 (file)
@@ -1032,11 +1032,18 @@ nv50_display_irq_hotplug_bh(struct work_struct *work)
        struct drm_connector *connector;
        const uint32_t gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 };
        uint32_t unplug_mask, plug_mask, change_mask;
-       uint32_t hpd0, hpd1 = 0;
+       uint32_t hpd0, hpd1;
 
-       hpd0 = nv_rd32(dev, 0xe054) & nv_rd32(dev, 0xe050);
+       spin_lock_irq(&dev_priv->hpd_state.lock);
+       hpd0 = dev_priv->hpd_state.hpd0_bits;
+       dev_priv->hpd_state.hpd0_bits = 0;
+       hpd1 = dev_priv->hpd_state.hpd1_bits;
+       dev_priv->hpd_state.hpd1_bits = 0;
+       spin_unlock_irq(&dev_priv->hpd_state.lock);
+
+       hpd0 &= nv_rd32(dev, 0xe050);
        if (dev_priv->chipset >= 0x90)
-               hpd1 = nv_rd32(dev, 0xe074) & nv_rd32(dev, 0xe070);
+               hpd1 &= nv_rd32(dev, 0xe070);
 
        plug_mask   = (hpd0 & 0x0000ffff) | (hpd1 << 16);
        unplug_mask = (hpd0 >> 16) | (hpd1 & 0xffff0000);
@@ -1078,10 +1085,6 @@ nv50_display_irq_hotplug_bh(struct work_struct *work)
                        helper->dpms(connector->encoder, DRM_MODE_DPMS_OFF);
        }
 
-       nv_wr32(dev, 0xe054, nv_rd32(dev, 0xe054));
-       if (dev_priv->chipset >= 0x90)
-               nv_wr32(dev, 0xe074, nv_rd32(dev, 0xe074));
-
        drm_helper_hpd_irq_event(dev);
 }
 
@@ -1092,8 +1095,22 @@ nv50_display_irq_handler(struct drm_device *dev)
        uint32_t delayed = 0;
 
        if (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_HOTPLUG) {
-               if (!work_pending(&dev_priv->hpd_work))
-                       queue_work(dev_priv->wq, &dev_priv->hpd_work);
+               uint32_t hpd0_bits, hpd1_bits = 0;
+
+               hpd0_bits = nv_rd32(dev, 0xe054);
+               nv_wr32(dev, 0xe054, hpd0_bits);
+
+               if (dev_priv->chipset >= 0x90) {
+                       hpd1_bits = nv_rd32(dev, 0xe074);
+                       nv_wr32(dev, 0xe074, hpd1_bits);
+               }
+
+               spin_lock(&dev_priv->hpd_state.lock);
+               dev_priv->hpd_state.hpd0_bits |= hpd0_bits;
+               dev_priv->hpd_state.hpd1_bits |= hpd1_bits;
+               spin_unlock(&dev_priv->hpd_state.lock);
+
+               queue_work(dev_priv->wq, &dev_priv->hpd_work);
        }
 
        while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) {
index a46a961102f39052832856cac762e3cfe8ae1f88..1da65bd60c109f89ea44e20a8eb561ec35a0f237 100644 (file)
@@ -464,3 +464,8 @@ nv50_fifo_unload_context(struct drm_device *dev)
        return 0;
 }
 
+void
+nv50_fifo_tlb_flush(struct drm_device *dev)
+{
+       nv50_vm_flush(dev, 5);
+}
index cbf5ae2f67d4a110de1bb9d9c129224fbcdd6c3c..8b669d0af6105fb934c3485457e7db18fb43e0ad 100644 (file)
@@ -402,3 +402,55 @@ struct nouveau_pgraph_object_class nv50_graph_grclass[] = {
        { 0x8597, false, NULL }, /* tesla (nva3, nva5, nva8) */
        {}
 };
+
+void
+nv50_graph_tlb_flush(struct drm_device *dev)
+{
+       nv50_vm_flush(dev, 0);
+}
+
+void
+nv86_graph_tlb_flush(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
+       bool idle, timeout = false;
+       unsigned long flags;
+       u64 start;
+       u32 tmp;
+
+       spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+       nv_mask(dev, 0x400500, 0x00000001, 0x00000000);
+
+       start = ptimer->read(dev);
+       do {
+               idle = true;
+
+               for (tmp = nv_rd32(dev, 0x400380); tmp && idle; tmp >>= 3) {
+                       if ((tmp & 7) == 1)
+                               idle = false;
+               }
+
+               for (tmp = nv_rd32(dev, 0x400384); tmp && idle; tmp >>= 3) {
+                       if ((tmp & 7) == 1)
+                               idle = false;
+               }
+
+               for (tmp = nv_rd32(dev, 0x400388); tmp && idle; tmp >>= 3) {
+                       if ((tmp & 7) == 1)
+                               idle = false;
+               }
+       } while (!idle && !(timeout = ptimer->read(dev) - start > 2000000000));
+
+       if (timeout) {
+               NV_ERROR(dev, "PGRAPH TLB flush idle timeout fail: "
+                             "0x%08x 0x%08x 0x%08x 0x%08x\n",
+                        nv_rd32(dev, 0x400700), nv_rd32(dev, 0x400380),
+                        nv_rd32(dev, 0x400384), nv_rd32(dev, 0x400388));
+       }
+
+       nv50_vm_flush(dev, 0);
+
+       nv_mask(dev, 0x400500, 0x00000001, 0x00000001);
+       spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
+}
index a53fc974332b38ec659513e91a8421017e43c411..b773229b764793c1ee974462431ab5d9a4e57385 100644 (file)
@@ -402,7 +402,6 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
        }
        dev_priv->engine.instmem.flush(dev);
 
-       nv50_vm_flush(dev, 4);
        nv50_vm_flush(dev, 6);
 
        gpuobj->im_bound = 1;
index 8e421f644a5435d44b6a0bc26f0edf3039b78c21..05efb5b9f13e841d265e3219d33e279e781de22f 100644 (file)
@@ -112,6 +112,7 @@ static uint32_t atom_iio_execute(struct atom_context *ctx, int base,
                        base += 3;
                        break;
                case ATOM_IIO_WRITE:
+                       (void)ctx->card->ioreg_read(ctx->card, CU16(base + 1));
                        ctx->card->ioreg_write(ctx->card, CU16(base + 1), temp);
                        base += 3;
                        break;
index 488c36c8f5e6069ebbb6cf5f9b830747a61c062e..4dc5b4714c5a6ae1919246ac55ed32d3bacc44ac 100644 (file)
@@ -1650,7 +1650,36 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
                }
        }
 
-       rdev->config.evergreen.tile_config = gb_addr_config;
+       /* setup tiling info dword.  gb_addr_config is not adequate since it does
+        * not have bank info, so create a custom tiling dword.
+        * bits 3:0   num_pipes
+        * bits 7:4   num_banks
+        * bits 11:8  group_size
+        * bits 15:12 row_size
+        */
+       rdev->config.evergreen.tile_config = 0;
+       switch (rdev->config.evergreen.max_tile_pipes) {
+       case 1:
+       default:
+               rdev->config.evergreen.tile_config |= (0 << 0);
+               break;
+       case 2:
+               rdev->config.evergreen.tile_config |= (1 << 0);
+               break;
+       case 4:
+               rdev->config.evergreen.tile_config |= (2 << 0);
+               break;
+       case 8:
+               rdev->config.evergreen.tile_config |= (3 << 0);
+               break;
+       }
+       rdev->config.evergreen.tile_config |=
+               ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4;
+       rdev->config.evergreen.tile_config |=
+               ((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) << 8;
+       rdev->config.evergreen.tile_config |=
+               ((gb_addr_config & 0x30000000) >> 28) << 12;
+
        WREG32(GB_BACKEND_MAP, gb_backend_map);
        WREG32(GB_ADDR_CONFIG, gb_addr_config);
        WREG32(DMIF_ADDR_CONFIG, gb_addr_config);
index ac3b6dde23db7ca1fd5f80083436cb49fcce0312..e0e590110dd47ffb06b2161ed1058e731620c826 100644 (file)
@@ -459,7 +459,7 @@ int evergreen_blit_init(struct radeon_device *rdev)
        obj_size += evergreen_ps_size * 4;
        obj_size = ALIGN(obj_size, 256);
 
-       r = radeon_bo_create(rdev, NULL, obj_size, true, RADEON_GEM_DOMAIN_VRAM,
+       r = radeon_bo_create(rdev, NULL, obj_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
                                &rdev->r600_blit.shader_obj);
        if (r) {
                DRM_ERROR("evergreen failed to allocate shader\n");
index 0f806cc7dc75f02f5bb00f98fc0d65b662aad688..4d7a2e1bdb90e498138eea542e22884c9e36eb0d 100644 (file)
@@ -878,12 +878,15 @@ void r600_pcie_gart_tlb_flush(struct radeon_device *rdev)
        u32 tmp;
 
        /* flush hdp cache so updates hit vram */
-       if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740)) {
+       if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) &&
+           !(rdev->flags & RADEON_IS_AGP)) {
                void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
                u32 tmp;
 
                /* r7xx hw bug.  write to HDP_DEBUG1 followed by fb read
                 * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL
+                * This seems to cause problems on some AGP cards. Just use the old
+                * method for them.
                 */
                WREG32(HDP_DEBUG1, 0);
                tmp = readl((void __iomem *)ptr);
@@ -1195,8 +1198,10 @@ void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
                                mc->vram_end, mc->real_vram_size >> 20);
        } else {
                u64 base = 0;
-               if (rdev->flags & RADEON_IS_IGP)
-                       base = (RREG32(MC_VM_FB_LOCATION) & 0xFFFF) << 24;
+               if (rdev->flags & RADEON_IS_IGP) {
+                       base = RREG32(MC_VM_FB_LOCATION) & 0xFFFF;
+                       base <<= 24;
+               }
                radeon_vram_location(rdev, &rdev->mc, base);
                rdev->mc.gtt_base_align = 0;
                radeon_gtt_location(rdev, mc);
@@ -2718,7 +2723,7 @@ static int r600_ih_ring_alloc(struct radeon_device *rdev)
        /* Allocate ring buffer */
        if (rdev->ih.ring_obj == NULL) {
                r = radeon_bo_create(rdev, NULL, rdev->ih.ring_size,
-                                    true,
+                                    PAGE_SIZE, true,
                                     RADEON_GEM_DOMAIN_GTT,
                                     &rdev->ih.ring_obj);
                if (r) {
@@ -3483,10 +3488,12 @@ int r600_debugfs_mc_info_init(struct radeon_device *rdev)
 void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo)
 {
        /* r7xx hw bug.  write to HDP_DEBUG1 followed by fb read
-        * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL
+        * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL.
+        * This seems to cause problems on some AGP cards. Just use the old
+        * method for them.
         */
        if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) &&
-           rdev->vram_scratch.ptr) {
+           rdev->vram_scratch.ptr && !(rdev->flags & RADEON_IS_AGP)) {
                void __iomem *ptr = (void *)rdev->vram_scratch.ptr;
                u32 tmp;
 
index 8362974ef41ac9eac713f1e66377661aa7106c0b..86e5aa07f0db32ffe410f1c2dea0330fefd89d9d 100644 (file)
@@ -501,7 +501,7 @@ int r600_blit_init(struct radeon_device *rdev)
        obj_size += r6xx_ps_size * 4;
        obj_size = ALIGN(obj_size, 256);
 
-       r = radeon_bo_create(rdev, NULL, obj_size, true, RADEON_GEM_DOMAIN_VRAM,
+       r = radeon_bo_create(rdev, NULL, obj_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
                                &rdev->r600_blit.shader_obj);
        if (r) {
                DRM_ERROR("r600 failed to allocate shader\n");
index 37cc2aa9f923cbace55e151d33870d1ac910a6a2..0f90fc3482ce205df9991bcd1d7c1170abd912ca 100644 (file)
@@ -50,6 +50,7 @@ struct r600_cs_track {
        u32                     nsamples;
        u32                     cb_color_base_last[8];
        struct radeon_bo        *cb_color_bo[8];
+       u64                     cb_color_bo_mc[8];
        u32                     cb_color_bo_offset[8];
        struct radeon_bo        *cb_color_frag_bo[8];
        struct radeon_bo        *cb_color_tile_bo[8];
@@ -67,6 +68,7 @@ struct r600_cs_track {
        u32                     db_depth_size;
        u32                     db_offset;
        struct radeon_bo        *db_bo;
+       u64                     db_bo_mc;
 };
 
 static inline int r600_bpe_from_format(u32 *bpe, u32 format)
@@ -140,6 +142,68 @@ static inline int r600_bpe_from_format(u32 *bpe, u32 format)
        return 0;
 }
 
+struct array_mode_checker {
+       int array_mode;
+       u32 group_size;
+       u32 nbanks;
+       u32 npipes;
+       u32 nsamples;
+       u32 bpe;
+};
+
+/* returns alignment in pixels for pitch/height/depth and bytes for base */
+static inline int r600_get_array_mode_alignment(struct array_mode_checker *values,
+                                               u32 *pitch_align,
+                                               u32 *height_align,
+                                               u32 *depth_align,
+                                               u64 *base_align)
+{
+       u32 tile_width = 8;
+       u32 tile_height = 8;
+       u32 macro_tile_width = values->nbanks;
+       u32 macro_tile_height = values->npipes;
+       u32 tile_bytes = tile_width * tile_height * values->bpe * values->nsamples;
+       u32 macro_tile_bytes = macro_tile_width * macro_tile_height * tile_bytes;
+
+       switch (values->array_mode) {
+       case ARRAY_LINEAR_GENERAL:
+               /* technically tile_width/_height for pitch/height */
+               *pitch_align = 1; /* tile_width */
+               *height_align = 1; /* tile_height */
+               *depth_align = 1;
+               *base_align = 1;
+               break;
+       case ARRAY_LINEAR_ALIGNED:
+               *pitch_align = max((u32)64, (u32)(values->group_size / values->bpe));
+               *height_align = tile_height;
+               *depth_align = 1;
+               *base_align = values->group_size;
+               break;
+       case ARRAY_1D_TILED_THIN1:
+               *pitch_align = max((u32)tile_width,
+                                  (u32)(values->group_size /
+                                        (tile_height * values->bpe * values->nsamples)));
+               *height_align = tile_height;
+               *depth_align = 1;
+               *base_align = values->group_size;
+               break;
+       case ARRAY_2D_TILED_THIN1:
+               *pitch_align = max((u32)macro_tile_width,
+                                 (u32)(((values->group_size / tile_height) /
+                                        (values->bpe * values->nsamples)) *
+                                       values->nbanks)) * tile_width;
+               *height_align = macro_tile_height * tile_height;
+               *depth_align = 1;
+               *base_align = max(macro_tile_bytes,
+                                 (*pitch_align) * values->bpe * (*height_align) * values->nsamples);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static void r600_cs_track_init(struct r600_cs_track *track)
 {
        int i;
@@ -153,10 +217,12 @@ static void r600_cs_track_init(struct r600_cs_track *track)
                track->cb_color_info[i] = 0;
                track->cb_color_bo[i] = NULL;
                track->cb_color_bo_offset[i] = 0xFFFFFFFF;
+               track->cb_color_bo_mc[i] = 0xFFFFFFFF;
        }
        track->cb_target_mask = 0xFFFFFFFF;
        track->cb_shader_mask = 0xFFFFFFFF;
        track->db_bo = NULL;
+       track->db_bo_mc = 0xFFFFFFFF;
        /* assume the biggest format and that htile is enabled */
        track->db_depth_info = 7 | (1 << 25);
        track->db_depth_view = 0xFFFFC000;
@@ -168,7 +234,10 @@ static void r600_cs_track_init(struct r600_cs_track *track)
 static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
 {
        struct r600_cs_track *track = p->track;
-       u32 bpe = 0, pitch, slice_tile_max, size, tmp, height, pitch_align;
+       u32 bpe = 0, slice_tile_max, size, tmp;
+       u32 height, height_align, pitch, pitch_align, depth_align;
+       u64 base_offset, base_align;
+       struct array_mode_checker array_check;
        volatile u32 *ib = p->ib->ptr;
        unsigned array_mode;
 
@@ -183,60 +252,40 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
                        i, track->cb_color_info[i]);
                return -EINVAL;
        }
-       /* pitch is the number of 8x8 tiles per row */
-       pitch = G_028060_PITCH_TILE_MAX(track->cb_color_size[i]) + 1;
+       /* pitch in pixels */
+       pitch = (G_028060_PITCH_TILE_MAX(track->cb_color_size[i]) + 1) * 8;
        slice_tile_max = G_028060_SLICE_TILE_MAX(track->cb_color_size[i]) + 1;
        slice_tile_max *= 64;
-       height = slice_tile_max / (pitch * 8);
+       height = slice_tile_max / pitch;
        if (height > 8192)
                height = 8192;
        array_mode = G_0280A0_ARRAY_MODE(track->cb_color_info[i]);
+
+       base_offset = track->cb_color_bo_mc[i] + track->cb_color_bo_offset[i];
+       array_check.array_mode = array_mode;
+       array_check.group_size = track->group_size;
+       array_check.nbanks = track->nbanks;
+       array_check.npipes = track->npipes;
+       array_check.nsamples = track->nsamples;
+       array_check.bpe = bpe;
+       if (r600_get_array_mode_alignment(&array_check,
+                                         &pitch_align, &height_align, &depth_align, &base_align)) {
+               dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__,
+                        G_0280A0_ARRAY_MODE(track->cb_color_info[i]), i,
+                        track->cb_color_info[i]);
+               return -EINVAL;
+       }
        switch (array_mode) {
        case V_0280A0_ARRAY_LINEAR_GENERAL:
-               /* technically height & 0x7 */
                break;
        case V_0280A0_ARRAY_LINEAR_ALIGNED:
-               pitch_align = max((u32)64, (u32)(track->group_size / bpe)) / 8;
-               if (!IS_ALIGNED(pitch, pitch_align)) {
-                       dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
-                                __func__, __LINE__, pitch);
-                       return -EINVAL;
-               }
-               if (!IS_ALIGNED(height, 8)) {
-                       dev_warn(p->dev, "%s:%d cb height (%d) invalid\n",
-                                __func__, __LINE__, height);
-                       return -EINVAL;
-               }
                break;
        case V_0280A0_ARRAY_1D_TILED_THIN1:
-               pitch_align = max((u32)8, (u32)(track->group_size / (8 * bpe * track->nsamples))) / 8;
-               if (!IS_ALIGNED(pitch, pitch_align)) {
-                       dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
-                                __func__, __LINE__, pitch);
-                       return -EINVAL;
-               }
                /* avoid breaking userspace */
                if (height > 7)
                        height &= ~0x7;
-               if (!IS_ALIGNED(height, 8)) {
-                       dev_warn(p->dev, "%s:%d cb height (%d) invalid\n",
-                                __func__, __LINE__, height);
-                       return -EINVAL;
-               }
                break;
        case V_0280A0_ARRAY_2D_TILED_THIN1:
-               pitch_align = max((u32)track->nbanks,
-                                 (u32)(((track->group_size / 8) / (bpe * track->nsamples)) * track->nbanks)) / 8;
-               if (!IS_ALIGNED(pitch, pitch_align)) {
-                       dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
-                               __func__, __LINE__, pitch);
-                       return -EINVAL;
-               }
-               if (!IS_ALIGNED((height / 8), track->npipes)) {
-                       dev_warn(p->dev, "%s:%d cb height (%d) invalid\n",
-                                __func__, __LINE__, height);
-                       return -EINVAL;
-               }
                break;
        default:
                dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__,
@@ -244,8 +293,24 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
                        track->cb_color_info[i]);
                return -EINVAL;
        }
+
+       if (!IS_ALIGNED(pitch, pitch_align)) {
+               dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
+                        __func__, __LINE__, pitch);
+               return -EINVAL;
+       }
+       if (!IS_ALIGNED(height, height_align)) {
+               dev_warn(p->dev, "%s:%d cb height (%d) invalid\n",
+                        __func__, __LINE__, height);
+               return -EINVAL;
+       }
+       if (!IS_ALIGNED(base_offset, base_align)) {
+               dev_warn(p->dev, "%s offset[%d] 0x%llx not aligned\n", __func__, i, base_offset);
+               return -EINVAL;
+       }
+
        /* check offset */
-       tmp = height * pitch * 8 * bpe;
+       tmp = height * pitch * bpe;
        if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) {
                if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) {
                        /* the initial DDX does bad things with the CB size occasionally */
@@ -260,15 +325,11 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
                        return -EINVAL;
                }
        }
-       if (!IS_ALIGNED(track->cb_color_bo_offset[i], track->group_size)) {
-               dev_warn(p->dev, "%s offset[%d] %d not aligned\n", __func__, i, track->cb_color_bo_offset[i]);
-               return -EINVAL;
-       }
        /* limit max tile */
-       tmp = (height * pitch * 8) >> 6;
+       tmp = (height * pitch) >> 6;
        if (tmp < slice_tile_max)
                slice_tile_max = tmp;
-       tmp = S_028060_PITCH_TILE_MAX(pitch - 1) |
+       tmp = S_028060_PITCH_TILE_MAX((pitch / 8) - 1) |
                S_028060_SLICE_TILE_MAX(slice_tile_max - 1);
        ib[track->cb_color_size_idx[i]] = tmp;
        return 0;
@@ -310,7 +371,12 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)
        /* Check depth buffer */
        if (G_028800_STENCIL_ENABLE(track->db_depth_control) ||
                G_028800_Z_ENABLE(track->db_depth_control)) {
-               u32 nviews, bpe, ntiles, pitch, pitch_align, height, size, slice_tile_max;
+               u32 nviews, bpe, ntiles, size, slice_tile_max;
+               u32 height, height_align, pitch, pitch_align, depth_align;
+               u64 base_offset, base_align;
+               struct array_mode_checker array_check;
+               int array_mode;
+
                if (track->db_bo == NULL) {
                        dev_warn(p->dev, "z/stencil with no depth buffer\n");
                        return -EINVAL;
@@ -353,41 +419,34 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)
                        ib[track->db_depth_size_idx] = S_028000_SLICE_TILE_MAX(tmp - 1) | (track->db_depth_size & 0x3FF);
                } else {
                        size = radeon_bo_size(track->db_bo);
-                       pitch = G_028000_PITCH_TILE_MAX(track->db_depth_size) + 1;
+                       /* pitch in pixels */
+                       pitch = (G_028000_PITCH_TILE_MAX(track->db_depth_size) + 1) * 8;
                        slice_tile_max = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
                        slice_tile_max *= 64;
-                       height = slice_tile_max / (pitch * 8);
+                       height = slice_tile_max / pitch;
                        if (height > 8192)
                                height = 8192;
-                       switch (G_028010_ARRAY_MODE(track->db_depth_info)) {
+                       base_offset = track->db_bo_mc + track->db_offset;
+                       array_mode = G_028010_ARRAY_MODE(track->db_depth_info);
+                       array_check.array_mode = array_mode;
+                       array_check.group_size = track->group_size;
+                       array_check.nbanks = track->nbanks;
+                       array_check.npipes = track->npipes;
+                       array_check.nsamples = track->nsamples;
+                       array_check.bpe = bpe;
+                       if (r600_get_array_mode_alignment(&array_check,
+                                                         &pitch_align, &height_align, &depth_align, &base_align)) {
+                               dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
+                                        G_028010_ARRAY_MODE(track->db_depth_info),
+                                        track->db_depth_info);
+                               return -EINVAL;
+                       }
+                       switch (array_mode) {
                        case V_028010_ARRAY_1D_TILED_THIN1:
-                               pitch_align = (max((u32)8, (u32)(track->group_size / (8 * bpe))) / 8);
-                               if (!IS_ALIGNED(pitch, pitch_align)) {
-                                       dev_warn(p->dev, "%s:%d db pitch (%d) invalid\n",
-                                                __func__, __LINE__, pitch);
-                                       return -EINVAL;
-                               }
                                /* don't break userspace */
                                height &= ~0x7;
-                               if (!IS_ALIGNED(height, 8)) {
-                                       dev_warn(p->dev, "%s:%d db height (%d) invalid\n",
-                                                __func__, __LINE__, height);
-                                       return -EINVAL;
-                               }
                                break;
                        case V_028010_ARRAY_2D_TILED_THIN1:
-                               pitch_align = max((u32)track->nbanks,
-                                                 (u32)(((track->group_size / 8) / bpe) * track->nbanks)) / 8;
-                               if (!IS_ALIGNED(pitch, pitch_align)) {
-                                       dev_warn(p->dev, "%s:%d db pitch (%d) invalid\n",
-                                                __func__, __LINE__, pitch);
-                                       return -EINVAL;
-                               }
-                               if (!IS_ALIGNED((height / 8), track->npipes)) {
-                                       dev_warn(p->dev, "%s:%d db height (%d) invalid\n",
-                                                __func__, __LINE__, height);
-                                       return -EINVAL;
-                               }
                                break;
                        default:
                                dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
@@ -395,15 +454,27 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)
                                         track->db_depth_info);
                                return -EINVAL;
                        }
-                       if (!IS_ALIGNED(track->db_offset, track->group_size)) {
-                               dev_warn(p->dev, "%s offset[%d] %d not aligned\n", __func__, i, track->db_offset);
+
+                       if (!IS_ALIGNED(pitch, pitch_align)) {
+                               dev_warn(p->dev, "%s:%d db pitch (%d) invalid\n",
+                                        __func__, __LINE__, pitch);
+                               return -EINVAL;
+                       }
+                       if (!IS_ALIGNED(height, height_align)) {
+                               dev_warn(p->dev, "%s:%d db height (%d) invalid\n",
+                                        __func__, __LINE__, height);
                                return -EINVAL;
                        }
+                       if (!IS_ALIGNED(base_offset, base_align)) {
+                               dev_warn(p->dev, "%s offset[%d] 0x%llx not aligned\n", __func__, i, base_offset);
+                               return -EINVAL;
+                       }
+
                        ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
                        nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1;
                        tmp = ntiles * bpe * 64 * nviews;
                        if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) {
-                               dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %d -> %d have %ld)\n",
+                               dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %d -> %u have %lu)\n",
                                                track->db_depth_size, ntiles, nviews, bpe, tmp + track->db_offset,
                                                radeon_bo_size(track->db_bo));
                                return -EINVAL;
@@ -954,6 +1025,7 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx
                ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
                track->cb_color_base_last[tmp] = ib[idx];
                track->cb_color_bo[tmp] = reloc->robj;
+               track->cb_color_bo_mc[tmp] = reloc->lobj.gpu_offset;
                break;
        case DB_DEPTH_BASE:
                r = r600_cs_packet_next_reloc(p, &reloc);
@@ -965,6 +1037,7 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx
                track->db_offset = radeon_get_ib_value(p, idx) << 8;
                ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
                track->db_bo = reloc->robj;
+               track->db_bo_mc = reloc->lobj.gpu_offset;
                break;
        case DB_HTILE_DATA_BASE:
        case SQ_PGM_START_FS:
@@ -1086,16 +1159,25 @@ static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned nlevels
 static inline int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,
                                              struct radeon_bo *texture,
                                              struct radeon_bo *mipmap,
+                                             u64 base_offset,
+                                             u64 mip_offset,
                                              u32 tiling_flags)
 {
        struct r600_cs_track *track = p->track;
        u32 nfaces, nlevels, blevel, w0, h0, d0, bpe = 0;
-       u32 word0, word1, l0_size, mipmap_size, pitch, pitch_align;
+       u32 word0, word1, l0_size, mipmap_size;
+       u32 height_align, pitch, pitch_align, depth_align;
+       u64 base_align;
+       struct array_mode_checker array_check;
 
        /* on legacy kernel we don't perform advanced check */
        if (p->rdev == NULL)
                return 0;
 
+       /* convert to bytes */
+       base_offset <<= 8;
+       mip_offset <<= 8;
+
        word0 = radeon_get_ib_value(p, idx + 0);
        if (tiling_flags & RADEON_TILING_MACRO)
                word0 |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
@@ -1128,46 +1210,38 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 i
                return -EINVAL;
        }
 
-       pitch = G_038000_PITCH(word0) + 1;
-       switch (G_038000_TILE_MODE(word0)) {
-       case V_038000_ARRAY_LINEAR_GENERAL:
-               pitch_align = 1;
-               /* XXX check height align */
-               break;
-       case V_038000_ARRAY_LINEAR_ALIGNED:
-               pitch_align = max((u32)64, (u32)(track->group_size / bpe)) / 8;
-               if (!IS_ALIGNED(pitch, pitch_align)) {
-                       dev_warn(p->dev, "%s:%d tex pitch (%d) invalid\n",
-                                __func__, __LINE__, pitch);
-                       return -EINVAL;
-               }
-               /* XXX check height align */
-               break;
-       case V_038000_ARRAY_1D_TILED_THIN1:
-               pitch_align = max((u32)8, (u32)(track->group_size / (8 * bpe))) / 8;
-               if (!IS_ALIGNED(pitch, pitch_align)) {
-                       dev_warn(p->dev, "%s:%d tex pitch (%d) invalid\n",
-                                __func__, __LINE__, pitch);
-                       return -EINVAL;
-               }
-               /* XXX check height align */
-               break;
-       case V_038000_ARRAY_2D_TILED_THIN1:
-               pitch_align = max((u32)track->nbanks,
-                                 (u32)(((track->group_size / 8) / bpe) * track->nbanks)) / 8;
-               if (!IS_ALIGNED(pitch, pitch_align)) {
-                       dev_warn(p->dev, "%s:%d tex pitch (%d) invalid\n",
-                               __func__, __LINE__, pitch);
-                       return -EINVAL;
-               }
-               /* XXX check height align */
-               break;
-       default:
-               dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
-                        G_038000_TILE_MODE(word0), word0);
+       /* pitch in texels */
+       pitch = (G_038000_PITCH(word0) + 1) * 8;
+       array_check.array_mode = G_038000_TILE_MODE(word0);
+       array_check.group_size = track->group_size;
+       array_check.nbanks = track->nbanks;
+       array_check.npipes = track->npipes;
+       array_check.nsamples = 1;
+       array_check.bpe = bpe;
+       if (r600_get_array_mode_alignment(&array_check,
+                                         &pitch_align, &height_align, &depth_align, &base_align)) {
+               dev_warn(p->dev, "%s:%d tex array mode (%d) invalid\n",
+                        __func__, __LINE__, G_038000_TILE_MODE(word0));
+               return -EINVAL;
+       }
+
+       /* XXX check height as well... */
+
+       if (!IS_ALIGNED(pitch, pitch_align)) {
+               dev_warn(p->dev, "%s:%d tex pitch (%d) invalid\n",
+                        __func__, __LINE__, pitch);
+               return -EINVAL;
+       }
+       if (!IS_ALIGNED(base_offset, base_align)) {
+               dev_warn(p->dev, "%s:%d tex base offset (0x%llx) invalid\n",
+                        __func__, __LINE__, base_offset);
+               return -EINVAL;
+       }
+       if (!IS_ALIGNED(mip_offset, base_align)) {
+               dev_warn(p->dev, "%s:%d tex mip offset (0x%llx) invalid\n",
+                        __func__, __LINE__, mip_offset);
                return -EINVAL;
        }
-       /* XXX check offset align */
 
        word0 = radeon_get_ib_value(p, idx + 4);
        word1 = radeon_get_ib_value(p, idx + 5);
@@ -1402,7 +1476,10 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                                mip_offset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
                                mipmap = reloc->robj;
                                r = r600_check_texture_resource(p,  idx+(i*7)+1,
-                                                               texture, mipmap, reloc->lobj.tiling_flags);
+                                                               texture, mipmap,
+                                                               base_offset + radeon_get_ib_value(p, idx+1+(i*7)+2),
+                                                               mip_offset + radeon_get_ib_value(p, idx+1+(i*7)+3),
+                                                               reloc->lobj.tiling_flags);
                                if (r)
                                        return r;
                                ib[idx+1+(i*7)+2] += base_offset;
index d84612ae47e0786228f7d80a4a311aadbdde88ce..33cda016b083be82ca99f6a382da813d28e777a2 100644 (file)
@@ -86,6 +86,7 @@
 #define R600_HDP_NONSURFACE_BASE                                0x2c04
 
 #define R600_BUS_CNTL                                           0x5420
+#       define R600_BIOS_ROM_DIS                                (1 << 1)
 #define R600_CONFIG_CNTL                                        0x5424
 #define R600_CONFIG_MEMSIZE                                     0x5428
 #define R600_CONFIG_F0_BASE                                     0x542C
index 966a793e225b79a5bfdf3f8bf4c1f413ee2b3dc5..bff4dc4f410f8d5b514539c8ffecd914436a7f90 100644 (file)
 #define PTE_READABLE                           (1 << 5)
 #define PTE_WRITEABLE                          (1 << 6)
 
+/* tiling bits */
+#define     ARRAY_LINEAR_GENERAL              0x00000000
+#define     ARRAY_LINEAR_ALIGNED              0x00000001
+#define     ARRAY_1D_TILED_THIN1              0x00000002
+#define     ARRAY_2D_TILED_THIN1              0x00000004
+
 /* Registers */
 #define        ARB_POP                                         0x2418
 #define        ENABLE_TC128                                    (1 << 30)
index 73f600d39ad4bb79c4dfdeddee97972a8caeaec0..3a7095743d441b1bf71da544bd0f19007408362c 100644 (file)
@@ -1262,6 +1262,10 @@ void r100_pll_errata_after_index(struct radeon_device *rdev);
                (rdev->family == CHIP_RS400) ||                 \
                (rdev->family == CHIP_RS480))
 #define ASIC_IS_AVIVO(rdev) ((rdev->family >= CHIP_RS600))
+#define ASIC_IS_DCE2(rdev) ((rdev->family == CHIP_RS600)  ||   \
+                           (rdev->family == CHIP_RS690)  ||    \
+                           (rdev->family == CHIP_RS740)  ||    \
+                           (rdev->family >= CHIP_R600))
 #define ASIC_IS_DCE3(rdev) ((rdev->family >= CHIP_RV620))
 #define ASIC_IS_DCE32(rdev) ((rdev->family >= CHIP_RV730))
 #define ASIC_IS_DCE4(rdev) ((rdev->family >= CHIP_CEDAR))
index 87ead090c7d5a5195af6cf8d15be5a5809ff9678..bc5a2c3382d92fbd10efca3f29f69a927e381fc0 100644 (file)
@@ -98,6 +98,14 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev
                                }
                        }
 
+                       /* some DCE3 boards have bad data for this entry */
+                       if (ASIC_IS_DCE3(rdev)) {
+                               if ((i == 4) &&
+                                   (gpio->usClkMaskRegisterIndex == 0x1fda) &&
+                                   (gpio->sucI2cId.ucAccess == 0x94))
+                                       gpio->sucI2cId.ucAccess = 0x14;
+                       }
+
                        if (gpio->sucI2cId.ucAccess == id) {
                                i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
                                i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
@@ -174,6 +182,14 @@ void radeon_atombios_i2c_init(struct radeon_device *rdev)
                                }
                        }
 
+                       /* some DCE3 boards have bad data for this entry */
+                       if (ASIC_IS_DCE3(rdev)) {
+                               if ((i == 4) &&
+                                   (gpio->usClkMaskRegisterIndex == 0x1fda) &&
+                                   (gpio->sucI2cId.ucAccess == 0x94))
+                                       gpio->sucI2cId.ucAccess = 0x14;
+                       }
+
                        i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
                        i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
                        i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
index 7932dc4d6b90bde396e258108247402ec90ce8ca..c558685cc637698a83fb7ceed220df897f988b44 100644 (file)
@@ -41,7 +41,7 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize,
 
        size = bsize;
        n = 1024;
-       r = radeon_bo_create(rdev, NULL, size, true, sdomain, &sobj);
+       r = radeon_bo_create(rdev, NULL, size, PAGE_SIZE, true, sdomain, &sobj);
        if (r) {
                goto out_cleanup;
        }
@@ -53,7 +53,7 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize,
        if (r) {
                goto out_cleanup;
        }
-       r = radeon_bo_create(rdev, NULL, size, true, ddomain, &dobj);
+       r = radeon_bo_create(rdev, NULL, size, PAGE_SIZE, true, ddomain, &dobj);
        if (r) {
                goto out_cleanup;
        }
index 654787ec43f4d33687f2c7dd0e0318c17be92dd6..8f2c7b50dcf57df6267be12ef349479597dd0f62 100644 (file)
@@ -130,6 +130,7 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev)
        }
        return true;
 }
+
 static bool r700_read_disabled_bios(struct radeon_device *rdev)
 {
        uint32_t viph_control;
@@ -143,7 +144,7 @@ static bool r700_read_disabled_bios(struct radeon_device *rdev)
        bool r;
 
        viph_control = RREG32(RADEON_VIPH_CONTROL);
-       bus_cntl = RREG32(RADEON_BUS_CNTL);
+       bus_cntl = RREG32(R600_BUS_CNTL);
        d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);
        d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);
        vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL);
@@ -152,7 +153,7 @@ static bool r700_read_disabled_bios(struct radeon_device *rdev)
        /* disable VIP */
        WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));
        /* enable the rom */
-       WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM));
+       WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS));
        /* Disable VGA mode */
        WREG32(AVIVO_D1VGA_CONTROL,
               (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
@@ -191,7 +192,7 @@ static bool r700_read_disabled_bios(struct radeon_device *rdev)
                        cg_spll_status = RREG32(R600_CG_SPLL_STATUS);
        }
        WREG32(RADEON_VIPH_CONTROL, viph_control);
-       WREG32(RADEON_BUS_CNTL, bus_cntl);
+       WREG32(R600_BUS_CNTL, bus_cntl);
        WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
        WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
        WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
@@ -216,7 +217,7 @@ static bool r600_read_disabled_bios(struct radeon_device *rdev)
        bool r;
 
        viph_control = RREG32(RADEON_VIPH_CONTROL);
-       bus_cntl = RREG32(RADEON_BUS_CNTL);
+       bus_cntl = RREG32(R600_BUS_CNTL);
        d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);
        d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);
        vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL);
@@ -231,7 +232,7 @@ static bool r600_read_disabled_bios(struct radeon_device *rdev)
        /* disable VIP */
        WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));
        /* enable the rom */
-       WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM));
+       WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS));
        /* Disable VGA mode */
        WREG32(AVIVO_D1VGA_CONTROL,
               (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
@@ -262,7 +263,7 @@ static bool r600_read_disabled_bios(struct radeon_device *rdev)
 
        /* restore regs */
        WREG32(RADEON_VIPH_CONTROL, viph_control);
-       WREG32(RADEON_BUS_CNTL, bus_cntl);
+       WREG32(R600_BUS_CNTL, bus_cntl);
        WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
        WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
        WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
index 7b7ea269549ccef95c1e6c343083071774e7e9de..137b8075f6e7c434fc02b5e328c19d06127f8e05 100644 (file)
@@ -571,6 +571,7 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde
        }
 
        if (clk_mask && data_mask) {
+               /* system specific masks */
                i2c.mask_clk_mask = clk_mask;
                i2c.mask_data_mask = data_mask;
                i2c.a_clk_mask = clk_mask;
@@ -579,7 +580,19 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde
                i2c.en_data_mask = data_mask;
                i2c.y_clk_mask = clk_mask;
                i2c.y_data_mask = data_mask;
+       } else if ((ddc_line == RADEON_GPIOPAD_MASK) ||
+                  (ddc_line == RADEON_MDGPIO_MASK)) {
+               /* default gpiopad masks */
+               i2c.mask_clk_mask = (0x20 << 8);
+               i2c.mask_data_mask = 0x80;
+               i2c.a_clk_mask = (0x20 << 8);
+               i2c.a_data_mask = 0x80;
+               i2c.en_clk_mask = (0x20 << 8);
+               i2c.en_data_mask = 0x80;
+               i2c.y_clk_mask = (0x20 << 8);
+               i2c.y_data_mask = 0x80;
        } else {
+               /* default masks for ddc pads */
                i2c.mask_clk_mask = RADEON_GPIO_EN_1;
                i2c.mask_data_mask = RADEON_GPIO_EN_0;
                i2c.a_clk_mask = RADEON_GPIO_A_1;
@@ -716,7 +729,7 @@ void radeon_combios_i2c_init(struct radeon_device *rdev)
                                        clk = RBIOS8(offset + 3 + (i * 5) + 3);
                                        data = RBIOS8(offset + 3 + (i * 5) + 4);
                                        i2c = combios_setup_i2c_bus(rdev, DDC_MONID,
-                                                                   clk, data);
+                                                                   (1 << clk), (1 << data));
                                        rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "GPIOPAD_MASK");
                                        break;
                                }
index fe6c74780f18e67bb55ea5fdeefdbb038ffadbf1..8afaf7a7459e1c27ece79fee57d384d1bcaf67d9 100644 (file)
@@ -1008,9 +1008,21 @@ static void radeon_dp_connector_destroy(struct drm_connector *connector)
 static int radeon_dp_get_modes(struct drm_connector *connector)
 {
        struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+       struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
        int ret;
 
+       if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+               if (!radeon_dig_connector->edp_on)
+                       atombios_set_edp_panel_power(connector,
+                                                    ATOM_TRANSMITTER_ACTION_POWER_ON);
+       }
        ret = radeon_ddc_get_modes(radeon_connector);
+       if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+               if (!radeon_dig_connector->edp_on)
+                       atombios_set_edp_panel_power(connector,
+                                                    ATOM_TRANSMITTER_ACTION_POWER_OFF);
+       }
+
        return ret;
 }
 
@@ -1029,8 +1041,14 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
        if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
                /* eDP is always DP */
                radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DISPLAYPORT;
+               if (!radeon_dig_connector->edp_on)
+                       atombios_set_edp_panel_power(connector,
+                                                    ATOM_TRANSMITTER_ACTION_POWER_ON);
                if (radeon_dp_getdpcd(radeon_connector))
                        ret = connector_status_connected;
+               if (!radeon_dig_connector->edp_on)
+                       atombios_set_edp_panel_power(connector,
+                                                    ATOM_TRANSMITTER_ACTION_POWER_OFF);
        } else {
                radeon_dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector);
                if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) {
@@ -1157,6 +1175,8 @@ radeon_add_atom_connector(struct drm_device *dev,
                /* no HPD on analog connectors */
                radeon_connector->hpd.hpd = RADEON_HPD_NONE;
                connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+               connector->interlace_allowed = true;
+               connector->doublescan_allowed = true;
                break;
        case DRM_MODE_CONNECTOR_DVIA:
                drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
@@ -1172,6 +1192,8 @@ radeon_add_atom_connector(struct drm_device *dev,
                                              1);
                /* no HPD on analog connectors */
                radeon_connector->hpd.hpd = RADEON_HPD_NONE;
+               connector->interlace_allowed = true;
+               connector->doublescan_allowed = true;
                break;
        case DRM_MODE_CONNECTOR_DVII:
        case DRM_MODE_CONNECTOR_DVID:
@@ -1208,6 +1230,11 @@ radeon_add_atom_connector(struct drm_device *dev,
                                                      rdev->mode_info.load_detect_property,
                                                      1);
                }
+               connector->interlace_allowed = true;
+               if (connector_type == DRM_MODE_CONNECTOR_DVII)
+                       connector->doublescan_allowed = true;
+               else
+                       connector->doublescan_allowed = false;
                break;
        case DRM_MODE_CONNECTOR_HDMIA:
        case DRM_MODE_CONNECTOR_HDMIB:
@@ -1238,6 +1265,11 @@ radeon_add_atom_connector(struct drm_device *dev,
                                                      0);
                }
                subpixel_order = SubPixelHorizontalRGB;
+               connector->interlace_allowed = true;
+               if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
+                       connector->doublescan_allowed = true;
+               else
+                       connector->doublescan_allowed = false;
                break;
        case DRM_MODE_CONNECTOR_DisplayPort:
        case DRM_MODE_CONNECTOR_eDP:
@@ -1275,6 +1307,9 @@ radeon_add_atom_connector(struct drm_device *dev,
                                                      rdev->mode_info.underscan_vborder_property,
                                                      0);
                }
+               connector->interlace_allowed = true;
+               /* in theory with a DP to VGA converter... */
+               connector->doublescan_allowed = false;
                break;
        case DRM_MODE_CONNECTOR_SVIDEO:
        case DRM_MODE_CONNECTOR_Composite:
@@ -1290,6 +1325,8 @@ radeon_add_atom_connector(struct drm_device *dev,
                                              radeon_atombios_get_tv_info(rdev));
                /* no HPD on analog connectors */
                radeon_connector->hpd.hpd = RADEON_HPD_NONE;
+               connector->interlace_allowed = false;
+               connector->doublescan_allowed = false;
                break;
        case DRM_MODE_CONNECTOR_LVDS:
                radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
@@ -1308,6 +1345,8 @@ radeon_add_atom_connector(struct drm_device *dev,
                                              dev->mode_config.scaling_mode_property,
                                              DRM_MODE_SCALE_FULLSCREEN);
                subpixel_order = SubPixelHorizontalRGB;
+               connector->interlace_allowed = false;
+               connector->doublescan_allowed = false;
                break;
        }
 
@@ -1385,6 +1424,8 @@ radeon_add_legacy_connector(struct drm_device *dev,
                /* no HPD on analog connectors */
                radeon_connector->hpd.hpd = RADEON_HPD_NONE;
                connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+               connector->interlace_allowed = true;
+               connector->doublescan_allowed = true;
                break;
        case DRM_MODE_CONNECTOR_DVIA:
                drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
@@ -1400,6 +1441,8 @@ radeon_add_legacy_connector(struct drm_device *dev,
                                              1);
                /* no HPD on analog connectors */
                radeon_connector->hpd.hpd = RADEON_HPD_NONE;
+               connector->interlace_allowed = true;
+               connector->doublescan_allowed = true;
                break;
        case DRM_MODE_CONNECTOR_DVII:
        case DRM_MODE_CONNECTOR_DVID:
@@ -1417,6 +1460,11 @@ radeon_add_legacy_connector(struct drm_device *dev,
                                                      1);
                }
                subpixel_order = SubPixelHorizontalRGB;
+               connector->interlace_allowed = true;
+               if (connector_type == DRM_MODE_CONNECTOR_DVII)
+                       connector->doublescan_allowed = true;
+               else
+                       connector->doublescan_allowed = false;
                break;
        case DRM_MODE_CONNECTOR_SVIDEO:
        case DRM_MODE_CONNECTOR_Composite:
@@ -1439,6 +1487,8 @@ radeon_add_legacy_connector(struct drm_device *dev,
                                              radeon_combios_get_tv_info(rdev));
                /* no HPD on analog connectors */
                radeon_connector->hpd.hpd = RADEON_HPD_NONE;
+               connector->interlace_allowed = false;
+               connector->doublescan_allowed = false;
                break;
        case DRM_MODE_CONNECTOR_LVDS:
                drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type);
@@ -1452,6 +1502,8 @@ radeon_add_legacy_connector(struct drm_device *dev,
                                              dev->mode_config.scaling_mode_property,
                                              DRM_MODE_SCALE_FULLSCREEN);
                subpixel_order = SubPixelHorizontalRGB;
+               connector->interlace_allowed = false;
+               connector->doublescan_allowed = false;
                break;
        }
 
index 8adfedfe547f6b6455676deaa26dada2592ff6a5..e12e79326cb115a490ed5d94e0eda2a84ee400db 100644 (file)
@@ -180,7 +180,7 @@ int radeon_wb_init(struct radeon_device *rdev)
        int r;
 
        if (rdev->wb.wb_obj == NULL) {
-               r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, true,
+               r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true,
                                RADEON_GEM_DOMAIN_GTT, &rdev->wb.wb_obj);
                if (r) {
                        dev_warn(rdev->dev, "(%d) create WB bo failed\n", r);
@@ -286,7 +286,7 @@ void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64
                mc->mc_vram_size = mc->aper_size;
        }
        mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
-       dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n",
+       dev_info(rdev->dev, "VRAM: %lluM 0x%016llX - 0x%016llX (%lluM used)\n",
                        mc->mc_vram_size >> 20, mc->vram_start,
                        mc->vram_end, mc->real_vram_size >> 20);
 }
@@ -323,7 +323,7 @@ void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
                mc->gtt_start = (mc->vram_end + 1 + mc->gtt_base_align) & ~mc->gtt_base_align;
        }
        mc->gtt_end = mc->gtt_start + mc->gtt_size - 1;
-       dev_info(rdev->dev, "GTT: %lluM 0x%08llX - 0x%08llX\n",
+       dev_info(rdev->dev, "GTT: %lluM 0x%016llX - 0x%016llX\n",
                        mc->gtt_size >> 20, mc->gtt_start, mc->gtt_end);
 }
 
index f678257c42e6ab54f668951b93e685cf04d287d5..041943df966be15803ebedc2e5291fa00953745e 100644 (file)
@@ -176,6 +176,7 @@ static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder)
                return false;
        }
 }
+
 void
 radeon_link_encoder_connector(struct drm_device *dev)
 {
@@ -228,6 +229,27 @@ radeon_get_connector_for_encoder(struct drm_encoder *encoder)
        return NULL;
 }
 
+struct drm_encoder *radeon_atom_get_external_encoder(struct drm_encoder *encoder)
+{
+       struct drm_device *dev = encoder->dev;
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct drm_encoder *other_encoder;
+       struct radeon_encoder *other_radeon_encoder;
+
+       if (radeon_encoder->is_ext_encoder)
+               return NULL;
+
+       list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) {
+               if (other_encoder == encoder)
+                       continue;
+               other_radeon_encoder = to_radeon_encoder(other_encoder);
+               if (other_radeon_encoder->is_ext_encoder &&
+                   (radeon_encoder->devices & other_radeon_encoder->devices))
+                       return other_encoder;
+       }
+       return NULL;
+}
+
 void radeon_panel_mode_fixup(struct drm_encoder *encoder,
                             struct drm_display_mode *adjusted_mode)
 {
@@ -426,52 +448,49 @@ atombios_tv_setup(struct drm_encoder *encoder, int action)
 
 }
 
-void
-atombios_external_tmds_setup(struct drm_encoder *encoder, int action)
-{
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION args;
-       int index = 0;
-
-       memset(&args, 0, sizeof(args));
-
-       index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
-
-       args.sXTmdsEncoder.ucEnable = action;
-
-       if (radeon_encoder->pixel_clock > 165000)
-               args.sXTmdsEncoder.ucMisc = PANEL_ENCODER_MISC_DUAL;
-
-       /*if (pScrn->rgbBits == 8)*/
-       args.sXTmdsEncoder.ucMisc |= (1 << 1);
-
-       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
-}
+union dvo_encoder_control {
+       ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION ext_tmds;
+       DVO_ENCODER_CONTROL_PS_ALLOCATION dvo;
+       DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 dvo_v3;
+};
 
-static void
-atombios_ddia_setup(struct drm_encoder *encoder, int action)
+void
+atombios_dvo_setup(struct drm_encoder *encoder, int action)
 {
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       DVO_ENCODER_CONTROL_PS_ALLOCATION args;
-       int index = 0;
+       union dvo_encoder_control args;
+       int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
 
        memset(&args, 0, sizeof(args));
 
-       index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
+       if (ASIC_IS_DCE3(rdev)) {
+               /* DCE3+ */
+               args.dvo_v3.ucAction = action;
+               args.dvo_v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+               args.dvo_v3.ucDVOConfig = 0; /* XXX */
+       } else if (ASIC_IS_DCE2(rdev)) {
+               /* DCE2 (pre-DCE3 R6xx, RS600/690/740 */
+               args.dvo.sDVOEncoder.ucAction = action;
+               args.dvo.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+               /* DFP1, CRT1, TV1 depending on the type of port */
+               args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX;
+
+               if (radeon_encoder->pixel_clock > 165000)
+                       args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL;
+       } else {
+               /* R4xx, R5xx */
+               args.ext_tmds.sXTmdsEncoder.ucEnable = action;
 
-       args.sDVOEncoder.ucAction = action;
-       args.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+               if (radeon_encoder->pixel_clock > 165000)
+                       args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL;
 
-       if (radeon_encoder->pixel_clock > 165000)
-               args.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute = PANEL_ENCODER_MISC_DUAL;
+               /*if (pScrn->rgbBits == 8)*/
+               args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB;
+       }
 
        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
 }
 
 union lvds_encoder_control {
@@ -532,14 +551,14 @@ atombios_digital_setup(struct drm_encoder *encoder, int action)
                                if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
                                        args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
                                if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
-                                       args.v1.ucMisc |= (1 << 1);
+                                       args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
                        } else {
                                if (dig->linkb)
                                        args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
                                if (radeon_encoder->pixel_clock > 165000)
                                        args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
                                /*if (pScrn->rgbBits == 8) */
-                               args.v1.ucMisc |= (1 << 1);
+                               args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
                        }
                        break;
                case 2:
@@ -595,6 +614,7 @@ atombios_digital_setup(struct drm_encoder *encoder, int action)
 int
 atombios_get_encoder_mode(struct drm_encoder *encoder)
 {
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
        struct drm_connector *connector;
@@ -602,9 +622,20 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
        struct radeon_connector_atom_dig *dig_connector;
 
        connector = radeon_get_connector_for_encoder(encoder);
-       if (!connector)
-               return 0;
-
+       if (!connector) {
+               switch (radeon_encoder->encoder_id) {
+               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+               case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+               case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+                       return ATOM_ENCODER_MODE_DVI;
+               case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+               case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+               default:
+                       return ATOM_ENCODER_MODE_CRT;
+               }
+       }
        radeon_connector = to_radeon_connector(connector);
 
        switch (connector->connector_type) {
@@ -834,6 +865,9 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
        memset(&args, 0, sizeof(args));
 
        switch (radeon_encoder->encoder_id) {
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+               index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
+               break;
        case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
        case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
        case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
@@ -978,6 +1012,105 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
+void
+atombios_set_edp_panel_power(struct drm_connector *connector, int action)
+{
+       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+       struct drm_device *dev = radeon_connector->base.dev;
+       struct radeon_device *rdev = dev->dev_private;
+       union dig_transmitter_control args;
+       int index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
+       uint8_t frev, crev;
+
+       if (connector->connector_type != DRM_MODE_CONNECTOR_eDP)
+               return;
+
+       if (!ASIC_IS_DCE4(rdev))
+               return;
+
+       if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) ||
+           (action != ATOM_TRANSMITTER_ACTION_POWER_OFF))
+               return;
+
+       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+               return;
+
+       memset(&args, 0, sizeof(args));
+
+       args.v1.ucAction = action;
+
+       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+union external_encoder_control {
+       EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1;
+};
+
+static void
+atombios_external_encoder_setup(struct drm_encoder *encoder,
+                               struct drm_encoder *ext_encoder,
+                               int action)
+{
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       union external_encoder_control args;
+       struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+       int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl);
+       u8 frev, crev;
+       int dp_clock = 0;
+       int dp_lane_count = 0;
+       int connector_object_id = 0;
+
+       if (connector) {
+               struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+               struct radeon_connector_atom_dig *dig_connector =
+                       radeon_connector->con_priv;
+
+               dp_clock = dig_connector->dp_clock;
+               dp_lane_count = dig_connector->dp_lane_count;
+               connector_object_id =
+                       (radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
+       }
+
+       memset(&args, 0, sizeof(args));
+
+       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+               return;
+
+       switch (frev) {
+       case 1:
+               /* no params on frev 1 */
+               break;
+       case 2:
+               switch (crev) {
+               case 1:
+               case 2:
+                       args.v1.sDigEncoder.ucAction = action;
+                       args.v1.sDigEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+                       args.v1.sDigEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
+
+                       if (args.v1.sDigEncoder.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
+                               if (dp_clock == 270000)
+                                       args.v1.sDigEncoder.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
+                               args.v1.sDigEncoder.ucLaneNum = dp_lane_count;
+                       } else if (radeon_encoder->pixel_clock > 165000)
+                               args.v1.sDigEncoder.ucLaneNum = 8;
+                       else
+                               args.v1.sDigEncoder.ucLaneNum = 4;
+                       break;
+               default:
+                       DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
+                       return;
+               }
+               break;
+       default:
+               DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
+               return;
+       }
+       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
 static void
 atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
 {
@@ -1021,6 +1154,7 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
        DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
        int index = 0;
        bool is_dig = false;
@@ -1043,9 +1177,14 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
                break;
        case ENCODER_OBJECT_ID_INTERNAL_DVO1:
        case ENCODER_OBJECT_ID_INTERNAL_DDI:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
                index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
                break;
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+               if (ASIC_IS_DCE3(rdev))
+                       is_dig = true;
+               else
+                       index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
+               break;
        case ENCODER_OBJECT_ID_INTERNAL_LVDS:
                index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
                break;
@@ -1082,34 +1221,85 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
                        if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
                                struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
 
+                               if (connector &&
+                                   (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
+                                       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+                                       struct radeon_connector_atom_dig *radeon_dig_connector =
+                                               radeon_connector->con_priv;
+                                       atombios_set_edp_panel_power(connector,
+                                                                    ATOM_TRANSMITTER_ACTION_POWER_ON);
+                                       radeon_dig_connector->edp_on = true;
+                               }
                                dp_link_train(encoder, connector);
                                if (ASIC_IS_DCE4(rdev))
                                        atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON);
                        }
+                       if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+                               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
                        break;
                case DRM_MODE_DPMS_STANDBY:
                case DRM_MODE_DPMS_SUSPEND:
                case DRM_MODE_DPMS_OFF:
                        atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
                        if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
+                               struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+
                                if (ASIC_IS_DCE4(rdev))
                                        atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF);
+                               if (connector &&
+                                   (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
+                                       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+                                       struct radeon_connector_atom_dig *radeon_dig_connector =
+                                               radeon_connector->con_priv;
+                                       atombios_set_edp_panel_power(connector,
+                                                                    ATOM_TRANSMITTER_ACTION_POWER_OFF);
+                                       radeon_dig_connector->edp_on = false;
+                               }
                        }
+                       if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+                               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
                        break;
                }
        } else {
                switch (mode) {
                case DRM_MODE_DPMS_ON:
                        args.ucAction = ATOM_ENABLE;
+                       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+                       if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+                               args.ucAction = ATOM_LCD_BLON;
+                               atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+                       }
                        break;
                case DRM_MODE_DPMS_STANDBY:
                case DRM_MODE_DPMS_SUSPEND:
                case DRM_MODE_DPMS_OFF:
                        args.ucAction = ATOM_DISABLE;
+                       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+                       if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+                               args.ucAction = ATOM_LCD_BLOFF;
+                               atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+                       }
                        break;
                }
-               atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
        }
+
+       if (ext_encoder) {
+               int action;
+
+               switch (mode) {
+               case DRM_MODE_DPMS_ON:
+               default:
+                       action = ATOM_ENABLE;
+                       break;
+               case DRM_MODE_DPMS_STANDBY:
+               case DRM_MODE_DPMS_SUSPEND:
+               case DRM_MODE_DPMS_OFF:
+                       action = ATOM_DISABLE;
+                       break;
+               }
+               atombios_external_encoder_setup(encoder, ext_encoder, action);
+       }
+
        radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
 
 }
@@ -1242,7 +1432,7 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
                break;
        default:
                DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
-               break;
+               return;
        }
 
        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
@@ -1357,6 +1547,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
 
        radeon_encoder->pixel_clock = adjusted_mode->clock;
 
@@ -1400,11 +1591,9 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
                }
                break;
        case ENCODER_OBJECT_ID_INTERNAL_DDI:
-               atombios_ddia_setup(encoder, ATOM_ENABLE);
-               break;
        case ENCODER_OBJECT_ID_INTERNAL_DVO1:
        case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-               atombios_external_tmds_setup(encoder, ATOM_ENABLE);
+               atombios_dvo_setup(encoder, ATOM_ENABLE);
                break;
        case ENCODER_OBJECT_ID_INTERNAL_DAC1:
        case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
@@ -1419,6 +1608,11 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
                }
                break;
        }
+
+       if (ext_encoder) {
+               atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
+       }
+
        atombios_apply_encoder_quirks(encoder, adjusted_mode);
 
        if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
@@ -1595,11 +1789,9 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
                }
                break;
        case ENCODER_OBJECT_ID_INTERNAL_DDI:
-               atombios_ddia_setup(encoder, ATOM_DISABLE);
-               break;
        case ENCODER_OBJECT_ID_INTERNAL_DVO1:
        case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-               atombios_external_tmds_setup(encoder, ATOM_DISABLE);
+               atombios_dvo_setup(encoder, ATOM_DISABLE);
                break;
        case ENCODER_OBJECT_ID_INTERNAL_DAC1:
        case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
@@ -1621,6 +1813,53 @@ disable_done:
        radeon_encoder->active_device = 0;
 }
 
+/* these are handled by the primary encoders */
+static void radeon_atom_ext_prepare(struct drm_encoder *encoder)
+{
+
+}
+
+static void radeon_atom_ext_commit(struct drm_encoder *encoder)
+{
+
+}
+
+static void
+radeon_atom_ext_mode_set(struct drm_encoder *encoder,
+                        struct drm_display_mode *mode,
+                        struct drm_display_mode *adjusted_mode)
+{
+
+}
+
+static void radeon_atom_ext_disable(struct drm_encoder *encoder)
+{
+
+}
+
+static void
+radeon_atom_ext_dpms(struct drm_encoder *encoder, int mode)
+{
+
+}
+
+static bool radeon_atom_ext_mode_fixup(struct drm_encoder *encoder,
+                                      struct drm_display_mode *mode,
+                                      struct drm_display_mode *adjusted_mode)
+{
+       return true;
+}
+
+static const struct drm_encoder_helper_funcs radeon_atom_ext_helper_funcs = {
+       .dpms = radeon_atom_ext_dpms,
+       .mode_fixup = radeon_atom_ext_mode_fixup,
+       .prepare = radeon_atom_ext_prepare,
+       .mode_set = radeon_atom_ext_mode_set,
+       .commit = radeon_atom_ext_commit,
+       .disable = radeon_atom_ext_disable,
+       /* no detect for TMDS/LVDS yet */
+};
+
 static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
        .dpms = radeon_atom_encoder_dpms,
        .mode_fixup = radeon_atom_mode_fixup,
@@ -1730,6 +1969,7 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_t
        radeon_encoder->devices = supported_device;
        radeon_encoder->rmx_type = RMX_OFF;
        radeon_encoder->underscan_type = UNDERSCAN_OFF;
+       radeon_encoder->is_ext_encoder = false;
 
        switch (radeon_encoder->encoder_id) {
        case ENCODER_OBJECT_ID_INTERNAL_LVDS:
@@ -1771,6 +2011,9 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_t
                        radeon_encoder->rmx_type = RMX_FULL;
                        drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
                        radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
+               } else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) {
+                       drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
+                       radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
                } else {
                        drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
                        radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
@@ -1779,5 +2022,22 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_t
                }
                drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
                break;
+       case ENCODER_OBJECT_ID_SI170B:
+       case ENCODER_OBJECT_ID_CH7303:
+       case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
+       case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
+       case ENCODER_OBJECT_ID_TITFP513:
+       case ENCODER_OBJECT_ID_VT1623:
+       case ENCODER_OBJECT_ID_HDMI_SI1930:
+               /* these are handled by the primary encoders */
+               radeon_encoder->is_ext_encoder = true;
+               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+                       drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
+               else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT))
+                       drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
+               else
+                       drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
+               drm_encoder_helper_add(encoder, &radeon_atom_ext_helper_funcs);
+               break;
        }
 }
index e65b90317fab282df8b97b6b11b277ea867a2647..65016117d95f2f4e332bc6bdd0d9de63e8dbeafe 100644 (file)
@@ -79,8 +79,8 @@ int radeon_gart_table_vram_alloc(struct radeon_device *rdev)
 
        if (rdev->gart.table.vram.robj == NULL) {
                r = radeon_bo_create(rdev, NULL, rdev->gart.table_size,
-                                       true, RADEON_GEM_DOMAIN_VRAM,
-                                       &rdev->gart.table.vram.robj);
+                                    PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
+                                    &rdev->gart.table.vram.robj);
                if (r) {
                        return r;
                }
index d1e595d9172396b8104d19c7a1d0a87d3b14b772..df95eb83dac6d52e4cad7f6570d6cca9e2807b1f 100644 (file)
@@ -67,7 +67,7 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size,
        if (alignment < PAGE_SIZE) {
                alignment = PAGE_SIZE;
        }
-       r = radeon_bo_create(rdev, gobj, size, kernel, initial_domain, &robj);
+       r = radeon_bo_create(rdev, gobj, size, alignment, kernel, initial_domain, &robj);
        if (r) {
                if (r != -ERESTARTSYS)
                        DRM_ERROR("Failed to allocate GEM object (%d, %d, %u, %d)\n",
index 0cfbba02c4d03773df29eb07efe74010a989002b..ded2a45bc95cd5f2845b9d32009d98dc00105c5f 100644 (file)
@@ -896,7 +896,8 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
             ((rdev->family <= CHIP_RS480) ||
              ((rdev->family >= CHIP_RV515) && (rdev->family <= CHIP_R580))))) {
                /* set the radeon hw i2c adapter */
-               sprintf(i2c->adapter.name, "Radeon i2c hw bus %s", name);
+               snprintf(i2c->adapter.name, sizeof(i2c->adapter.name),
+                        "Radeon i2c hw bus %s", name);
                i2c->adapter.algo = &radeon_i2c_algo;
                ret = i2c_add_adapter(&i2c->adapter);
                if (ret) {
@@ -905,7 +906,8 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
                }
        } else {
                /* set the radeon bit adapter */
-               sprintf(i2c->adapter.name, "Radeon i2c bit bus %s", name);
+               snprintf(i2c->adapter.name, sizeof(i2c->adapter.name),
+                        "Radeon i2c bit bus %s", name);
                i2c->adapter.algo_data = &i2c->algo.bit;
                i2c->algo.bit.pre_xfer = pre_xfer;
                i2c->algo.bit.post_xfer = post_xfer;
@@ -946,6 +948,8 @@ struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev,
        i2c->rec = *rec;
        i2c->adapter.owner = THIS_MODULE;
        i2c->dev = dev;
+       snprintf(i2c->adapter.name, sizeof(i2c->adapter.name),
+                "Radeon aux bus %s", name);
        i2c_set_adapdata(&i2c->adapter, i2c);
        i2c->adapter.algo_data = &i2c->algo.dp;
        i2c->algo.dp.aux_ch = radeon_dp_i2c_aux_ch;
index 2f349a300195992c9450c9ddd1d6e091eed23ef8..465746bd51b76e4b88cbb1812f7729be430a6da7 100644 (file)
@@ -76,7 +76,7 @@ int radeon_enable_vblank(struct drm_device *dev, int crtc)
                default:
                        DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
                                  crtc);
-                       return EINVAL;
+                       return -EINVAL;
                }
        } else {
                switch (crtc) {
@@ -89,7 +89,7 @@ int radeon_enable_vblank(struct drm_device *dev, int crtc)
                default:
                        DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
                                  crtc);
-                       return EINVAL;
+                       return -EINVAL;
                }
        }
 
index 0b8397000f4c68ae98e80df717a652cb2ddf6253..59f834ba283dd3fa15dde00b373c6a330d62decc 100644 (file)
@@ -670,7 +670,7 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder,
 
        if (rdev->is_atom_bios) {
                radeon_encoder->pixel_clock = adjusted_mode->clock;
-               atombios_external_tmds_setup(encoder, ATOM_ENABLE);
+               atombios_dvo_setup(encoder, ATOM_ENABLE);
                fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
        } else {
                fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
index 680f57644e865ce2a5e4fdc97b5154a7dffb11a5..e301c6f9e0595889a28a4ab99a10e530d41f2112 100644 (file)
@@ -375,6 +375,7 @@ struct radeon_encoder {
        int hdmi_config_offset;
        int hdmi_audio_workaround;
        int hdmi_buffer_status;
+       bool is_ext_encoder;
 };
 
 struct radeon_connector_atom_dig {
@@ -385,6 +386,7 @@ struct radeon_connector_atom_dig {
        u8 dp_sink_type;
        int dp_clock;
        int dp_lane_count;
+       bool edp_on;
 };
 
 struct radeon_gpio_rec {
@@ -523,9 +525,10 @@ struct drm_encoder *radeon_encoder_legacy_primary_dac_add(struct drm_device *dev
 struct drm_encoder *radeon_encoder_legacy_tv_dac_add(struct drm_device *dev, int bios_index, int with_tv);
 struct drm_encoder *radeon_encoder_legacy_tmds_int_add(struct drm_device *dev, int bios_index);
 struct drm_encoder *radeon_encoder_legacy_tmds_ext_add(struct drm_device *dev, int bios_index);
-extern void atombios_external_tmds_setup(struct drm_encoder *encoder, int action);
+extern void atombios_dvo_setup(struct drm_encoder *encoder, int action);
 extern void atombios_digital_setup(struct drm_encoder *encoder, int action);
 extern int atombios_get_encoder_mode(struct drm_encoder *encoder);
+extern void atombios_set_edp_panel_power(struct drm_connector *connector, int action);
 extern void radeon_encoder_set_active_device(struct drm_encoder *encoder);
 
 extern void radeon_crtc_load_lut(struct drm_crtc *crtc);
index 8eb183466015326f7ca93b2647e85a610fe91f6f..a598d0049aa5938900a84c656c3cd9677010ee20 100644 (file)
@@ -69,7 +69,7 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
        u32 c = 0;
 
        rbo->placement.fpfn = 0;
-       rbo->placement.lpfn = rbo->rdev->mc.active_vram_size >> PAGE_SHIFT;
+       rbo->placement.lpfn = 0;
        rbo->placement.placement = rbo->placements;
        rbo->placement.busy_placement = rbo->placements;
        if (domain & RADEON_GEM_DOMAIN_VRAM)
@@ -86,11 +86,13 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
 }
 
 int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj,
-                       unsigned long size, bool kernel, u32 domain,
-                       struct radeon_bo **bo_ptr)
+                    unsigned long size, int byte_align, bool kernel, u32 domain,
+                    struct radeon_bo **bo_ptr)
 {
        struct radeon_bo *bo;
        enum ttm_bo_type type;
+       unsigned long page_align = roundup(byte_align, PAGE_SIZE) >> PAGE_SHIFT;
+       unsigned long max_size = 0;
        int r;
 
        if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) {
@@ -103,6 +105,14 @@ int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj,
        }
        *bo_ptr = NULL;
 
+       /* maximun bo size is the minimun btw visible vram and gtt size */
+       max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size);
+       if ((page_align << PAGE_SHIFT) >= max_size) {
+               printk(KERN_WARNING "%s:%d alloc size %ldM bigger than %ldMb limit\n",
+                       __func__, __LINE__, page_align  >> (20 - PAGE_SHIFT), max_size >> 20);
+               return -ENOMEM;
+       }
+
 retry:
        bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL);
        if (bo == NULL)
@@ -115,7 +125,7 @@ retry:
        /* Kernel allocation are uninterruptible */
        mutex_lock(&rdev->vram_mutex);
        r = ttm_bo_init(&rdev->mman.bdev, &bo->tbo, size, type,
-                       &bo->placement, 0, 0, !kernel, NULL, size,
+                       &bo->placement, page_align, 0, !kernel, NULL, size,
                        &radeon_ttm_bo_destroy);
        mutex_unlock(&rdev->vram_mutex);
        if (unlikely(r != 0)) {
index 3481bc7f6f582b08a0c2a9ff079fa9787defb6cd..d143702b244a4febdd51aa69ca7023e19d692a62 100644 (file)
@@ -137,9 +137,10 @@ static inline int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type,
 }
 
 extern int radeon_bo_create(struct radeon_device *rdev,
-                               struct drm_gem_object *gobj, unsigned long size,
-                               bool kernel, u32 domain,
-                               struct radeon_bo **bo_ptr);
+                           struct drm_gem_object *gobj, unsigned long size,
+                           int byte_align,
+                           bool kernel, u32 domain,
+                           struct radeon_bo **bo_ptr);
 extern int radeon_bo_kmap(struct radeon_bo *bo, void **ptr);
 extern void radeon_bo_kunmap(struct radeon_bo *bo);
 extern void radeon_bo_unref(struct radeon_bo **bo);
index 6ea798ce821896dd4b2704461b260578a63a2516..06e79822a2bff74b68fb74793c9ec906ad0834a1 100644 (file)
@@ -176,8 +176,8 @@ int radeon_ib_pool_init(struct radeon_device *rdev)
        INIT_LIST_HEAD(&rdev->ib_pool.bogus_ib);
        /* Allocate 1M object buffer */
        r = radeon_bo_create(rdev, NULL,  RADEON_IB_POOL_SIZE*64*1024,
-                               true, RADEON_GEM_DOMAIN_GTT,
-                               &rdev->ib_pool.robj);
+                            PAGE_SIZE, true, RADEON_GEM_DOMAIN_GTT,
+                            &rdev->ib_pool.robj);
        if (r) {
                DRM_ERROR("radeon: failed to ib pool (%d).\n", r);
                return r;
@@ -332,7 +332,7 @@ int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size)
        rdev->cp.ring_size = ring_size;
        /* Allocate ring buffer */
        if (rdev->cp.ring_obj == NULL) {
-               r = radeon_bo_create(rdev, NULL, rdev->cp.ring_size, true,
+               r = radeon_bo_create(rdev, NULL, rdev->cp.ring_size, PAGE_SIZE, true,
                                        RADEON_GEM_DOMAIN_GTT,
                                        &rdev->cp.ring_obj);
                if (r) {
index 313c96bc09da1dcfcb0703ed3aa82a2038af0731..5b44f652145c45cb5b1b588fa263fb318739a168 100644 (file)
@@ -52,7 +52,7 @@ void radeon_test_moves(struct radeon_device *rdev)
                goto out_cleanup;
        }
 
-       r = radeon_bo_create(rdev, NULL, size, true, RADEON_GEM_DOMAIN_VRAM,
+       r = radeon_bo_create(rdev, NULL, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
                                &vram_obj);
        if (r) {
                DRM_ERROR("Failed to create VRAM object\n");
@@ -71,7 +71,7 @@ void radeon_test_moves(struct radeon_device *rdev)
                void **gtt_start, **gtt_end;
                void **vram_start, **vram_end;
 
-               r = radeon_bo_create(rdev, NULL, size, true,
+               r = radeon_bo_create(rdev, NULL, size, PAGE_SIZE, true,
                                         RADEON_GEM_DOMAIN_GTT, gtt_obj + i);
                if (r) {
                        DRM_ERROR("Failed to create GTT object %d\n", i);
index 01c2c736a1daff116284db0f84f3896977e6eecb..1272e4b6a1d45469add57610a397c213704d5446 100644 (file)
@@ -529,7 +529,7 @@ int radeon_ttm_init(struct radeon_device *rdev)
                DRM_ERROR("Failed initializing VRAM heap.\n");
                return r;
        }
-       r = radeon_bo_create(rdev, NULL, 256 * 1024, true,
+       r = radeon_bo_create(rdev, NULL, 256 * 1024, PAGE_SIZE, true,
                                RADEON_GEM_DOMAIN_VRAM,
                                &rdev->stollen_vga_memory);
        if (r) {
index 245374e2b778b7706e9bf828c8a65876c1e11a00..4dfead8cee33907ae025c9c58adede92c12db4f6 100644 (file)
@@ -915,8 +915,8 @@ static int rv770_vram_scratch_init(struct radeon_device *rdev)
 
        if (rdev->vram_scratch.robj == NULL) {
                r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE,
-                                       true, RADEON_GEM_DOMAIN_VRAM,
-                                       &rdev->vram_scratch.robj);
+                                    PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
+                                    &rdev->vram_scratch.robj);
                if (r) {
                        return r;
                }
index 3ca77dc03915017e78d0e7f7e8e479d9f279fc56..148a322d8f5d7c45d0487351635f89eb9a9a0949 100644 (file)
@@ -224,6 +224,9 @@ int ttm_bo_reserve_locked(struct ttm_buffer_object *bo,
        int ret;
 
        while (unlikely(atomic_cmpxchg(&bo->reserved, 0, 1) != 0)) {
+               /**
+                * Deadlock avoidance for multi-bo reserving.
+                */
                if (use_sequence && bo->seq_valid &&
                        (sequence - bo->val_seq < (1 << 31))) {
                        return -EAGAIN;
@@ -241,6 +244,14 @@ int ttm_bo_reserve_locked(struct ttm_buffer_object *bo,
        }
 
        if (use_sequence) {
+               /**
+                * Wake up waiters that may need to recheck for deadlock,
+                * if we decreased the sequence number.
+                */
+               if (unlikely((bo->val_seq - sequence < (1 << 31))
+                            || !bo->seq_valid))
+                       wake_up_all(&bo->event_queue);
+
                bo->val_seq = sequence;
                bo->seq_valid = true;
        } else {
index 36e129f0023ffc3d6407b9c0251376aa3fc9f5c0..5408b1b7996f054dee95b9ed5aac4e9d63ee99a1 100644 (file)
@@ -862,7 +862,7 @@ int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
                              &vmw_vram_sys_placement, true,
                              &vmw_user_dmabuf_destroy);
        if (unlikely(ret != 0))
-               return ret;
+               goto out_no_dmabuf;
 
        tmp = ttm_bo_reference(&vmw_user_bo->dma.base);
        ret = ttm_base_object_init(vmw_fpriv(file_priv)->tfile,
@@ -870,19 +870,21 @@ int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
                                   false,
                                   ttm_buffer_type,
                                   &vmw_user_dmabuf_release, NULL);
-       if (unlikely(ret != 0)) {
-               ttm_bo_unref(&tmp);
-       else {
+       if (unlikely(ret != 0))
+               goto out_no_base_object;
+       else {
                rep->handle = vmw_user_bo->base.hash.key;
                rep->map_handle = vmw_user_bo->dma.base.addr_space_offset;
                rep->cur_gmr_id = vmw_user_bo->base.hash.key;
                rep->cur_gmr_offset = 0;
        }
-       ttm_bo_unref(&tmp);
 
+out_no_base_object:
+       ttm_bo_unref(&tmp);
+out_no_dmabuf:
        ttm_read_unlock(&vmaster->lock);
 
-       return 0;
+       return ret;
 }
 
 int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data,
index 515345b11ac95b380942638ce25f8ea8afccd472..88cb04e7962bad32e0410b90826ff3b4a55c25a9 100644 (file)
@@ -1386,6 +1386,7 @@ static const struct hid_device_id hid_blacklist[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb653) },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb65a) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) },
index 54b017ad258d29cf5e726ad04ee3297235a22366..5a1b52e0eb85f1ecfd7035f317c3b6577bf5d7cb 100644 (file)
@@ -221,7 +221,7 @@ static int egalax_probe(struct hid_device *hdev, const struct hid_device_id *id)
        struct egalax_data *td;
        struct hid_report *report;
 
-       td = kmalloc(sizeof(struct egalax_data), GFP_KERNEL);
+       td = kzalloc(sizeof(struct egalax_data), GFP_KERNEL);
        if (!td) {
                dev_err(&hdev->dev, "cannot allocate eGalax data\n");
                return -ENOMEM;
index bb0b3659437b1a98302f159f2e1773db21a0e2ee..d8d372bae3cc16d3d5f43dda55ee89214d05d2d4 100644 (file)
@@ -174,7 +174,7 @@ static int hidinput_setkeycode(struct input_dev *dev,
 
                clear_bit(*old_keycode, dev->keybit);
                set_bit(usage->code, dev->keybit);
-               dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n",
+               dbg_hid("Assigned keycode %d to HID usage code %x\n",
                        usage->code, usage->hid);
 
                /*
@@ -203,8 +203,8 @@ static int hidinput_setkeycode(struct input_dev *dev,
  *
  * as seen in the HID specification v1.11 6.2.2.7 Global Items.
  *
- * Only exponent 1 length units are processed. Centimeters are converted to
- * inches. Degrees are converted to radians.
+ * Only exponent 1 length units are processed. Centimeters and inches are
+ * converted to millimeters. Degrees are converted to radians.
  */
 static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
 {
@@ -225,13 +225,16 @@ static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
         */
        if (code == ABS_X || code == ABS_Y || code == ABS_Z) {
                if (field->unit == 0x11) {              /* If centimeters */
-                       /* Convert to inches */
-                       prev = logical_extents;
-                       logical_extents *= 254;
-                       if (logical_extents < prev)
+                       /* Convert to millimeters */
+                       unit_exponent += 1;
+               } else if (field->unit == 0x13) {       /* If inches */
+                       /* Convert to millimeters */
+                       prev = physical_extents;
+                       physical_extents *= 254;
+                       if (physical_extents < prev)
                                return 0;
-                       unit_exponent += 2;
-               } else if (field->unit != 0x13) {       /* If not inches */
+                       unit_exponent -= 1;
+               } else {
                        return 0;
                }
        } else if (code == ABS_RX || code == ABS_RY || code == ABS_RZ) {
index 15434c814793409bd7d00a2e0a4ee20ea8302456..25be4e1461bde288497ab2ed5363842934a18df4 100644 (file)
@@ -256,6 +256,8 @@ static const struct hid_device_id tm_devices[] = {
                .driver_data = (unsigned long)ff_joystick },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654),   /* FGT Force Feedback Wheel */
                .driver_data = (unsigned long)ff_joystick },
+       { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb65a),   /* F430 Force Feedback Wheel */
+               .driver_data = (unsigned long)ff_joystick },
        { }
 };
 MODULE_DEVICE_TABLE(hid, tm_devices);
index 4bf969c0a32b5ee9cb667a4341759e651f58d569..be0fdd58aa29301fbe15f9186580d724ba769544 100644 (file)
@@ -916,27 +916,27 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
        int nr = sensor_attr->index;
        struct i2c_client *client = to_i2c_client(dev);
        struct adm1026_data *data = i2c_get_clientdata(client);
-       int val, orig_div, new_div, shift;
+       int val, orig_div, new_div;
 
        val = simple_strtol(buf, NULL, 10);
        new_div = DIV_TO_REG(val);
-       if (new_div == 0) {
-               return -EINVAL;
-       }
+
        mutex_lock(&data->update_lock);
        orig_div = data->fan_div[nr];
        data->fan_div[nr] = DIV_FROM_REG(new_div);
 
        if (nr < 4) { /* 0 <= nr < 4 */
-               shift = 2 * nr;
                adm1026_write_value(client, ADM1026_REG_FAN_DIV_0_3,
-                       ((DIV_TO_REG(orig_div) & (~(0x03 << shift))) |
-                       (new_div << shift)));
+                                   (DIV_TO_REG(data->fan_div[0]) << 0) |
+                                   (DIV_TO_REG(data->fan_div[1]) << 2) |
+                                   (DIV_TO_REG(data->fan_div[2]) << 4) |
+                                   (DIV_TO_REG(data->fan_div[3]) << 6));
        } else { /* 3 < nr < 8 */
-               shift = 2 * (nr - 4);
                adm1026_write_value(client, ADM1026_REG_FAN_DIV_4_7,
-                       ((DIV_TO_REG(orig_div) & (~(0x03 << (2 * shift)))) |
-                       (new_div << shift)));
+                                   (DIV_TO_REG(data->fan_div[4]) << 0) |
+                                   (DIV_TO_REG(data->fan_div[5]) << 2) |
+                                   (DIV_TO_REG(data->fan_div[6]) << 4) |
+                                   (DIV_TO_REG(data->fan_div[7]) << 6));
        }
 
        if (data->fan_div[nr] != orig_div) {
index 937983407e2a47b12569d9ca4305af174e78f405..c4c40be0edbfd6afb00a7e6dbf6a0b20a5544b3f 100644 (file)
@@ -497,12 +497,14 @@ static unsigned long chipset_ids[] = {
        0
 };
 
+#ifdef MODULE
 static struct pci_device_id i5k_amb_ids[] __devinitdata = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5000_ERR) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_ERR) },
        { 0, }
 };
 MODULE_DEVICE_TABLE(pci, i5k_amb_ids);
+#endif
 
 static int __devinit i5k_amb_probe(struct platform_device *pdev)
 {
index 14a5d981be7d07030a264352dbc8d8af1e158c2d..a428a92641954a640dd783f051fc9c5565c13d9b 100644 (file)
@@ -187,6 +187,7 @@ static const u8 IT87_REG_FANX_MIN[] = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 };
 #define IT87_REG_FAN_MAIN_CTRL 0x13
 #define IT87_REG_FAN_CTL       0x14
 #define IT87_REG_PWM(nr)       (0x15 + (nr))
+#define IT87_REG_PWM_DUTY(nr)  (0x63 + (nr) * 8)
 
 #define IT87_REG_VIN(nr)       (0x20 + (nr))
 #define IT87_REG_TEMP(nr)      (0x29 + (nr))
@@ -251,12 +252,16 @@ struct it87_data {
        u8 fan_main_ctrl;       /* Register value */
        u8 fan_ctl;             /* Register value */
 
-       /* The following 3 arrays correspond to the same registers. The
-        * meaning of bits 6-0 depends on the value of bit 7, and we want
-        * to preserve settings on mode changes, so we have to track all
-        * values separately. */
+       /* The following 3 arrays correspond to the same registers up to
+        * the IT8720F. The meaning of bits 6-0 depends on the value of bit
+        * 7, and we want to preserve settings on mode changes, so we have
+        * to track all values separately.
+        * Starting with the IT8721F, the manual PWM duty cycles are stored
+        * in separate registers (8-bit values), so the separate tracking
+        * is no longer needed, but it is still done to keep the driver
+        * simple. */
        u8 pwm_ctrl[3];         /* Register value */
-       u8 pwm_duty[3];         /* Manual PWM value set by user (bit 6-0) */
+       u8 pwm_duty[3];         /* Manual PWM value set by user */
        u8 pwm_temp_map[3];     /* PWM to temp. chan. mapping (bits 1-0) */
 
        /* Automatic fan speed control registers */
@@ -832,7 +837,9 @@ static ssize_t set_pwm_enable(struct device *dev,
                                 data->fan_main_ctrl);
        } else {
                if (val == 1)                           /* Manual mode */
-                       data->pwm_ctrl[nr] = data->pwm_duty[nr];
+                       data->pwm_ctrl[nr] = data->type == it8721 ?
+                                            data->pwm_temp_map[nr] :
+                                            data->pwm_duty[nr];
                else                                    /* Automatic mode */
                        data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr];
                it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
@@ -858,12 +865,25 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
                return -EINVAL;
 
        mutex_lock(&data->update_lock);
-       data->pwm_duty[nr] = pwm_to_reg(data, val);
-       /* If we are in manual mode, write the duty cycle immediately;
-        * otherwise, just store it for later use. */
-       if (!(data->pwm_ctrl[nr] & 0x80)) {
-               data->pwm_ctrl[nr] = data->pwm_duty[nr];
-               it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
+       if (data->type == it8721) {
+               /* If we are in automatic mode, the PWM duty cycle register
+                * is read-only so we can't write the value */
+               if (data->pwm_ctrl[nr] & 0x80) {
+                       mutex_unlock(&data->update_lock);
+                       return -EBUSY;
+               }
+               data->pwm_duty[nr] = pwm_to_reg(data, val);
+               it87_write_value(data, IT87_REG_PWM_DUTY(nr),
+                                data->pwm_duty[nr]);
+       } else {
+               data->pwm_duty[nr] = pwm_to_reg(data, val);
+               /* If we are in manual mode, write the duty cycle immediately;
+                * otherwise, just store it for later use. */
+               if (!(data->pwm_ctrl[nr] & 0x80)) {
+                       data->pwm_ctrl[nr] = data->pwm_duty[nr];
+                       it87_write_value(data, IT87_REG_PWM(nr),
+                                        data->pwm_ctrl[nr]);
+               }
        }
        mutex_unlock(&data->update_lock);
        return count;
@@ -1958,7 +1978,10 @@ static void __devinit it87_init_device(struct platform_device *pdev)
         *   channels to use when later setting to automatic mode later.
         *   Use a 1:1 mapping by default (we are clueless.)
         * In both cases, the value can (and should) be changed by the user
-        * prior to switching to a different mode. */
+        * prior to switching to a different mode.
+        * Note that this is no longer needed for the IT8721F and later, as
+        * these have separate registers for the temperature mapping and the
+        * manual duty cycle. */
        for (i = 0; i < 3; i++) {
                data->pwm_temp_map[i] = i;
                data->pwm_duty[i] = 0x7f;       /* Full speed */
@@ -2034,10 +2057,16 @@ static void __devinit it87_init_device(struct platform_device *pdev)
 static void it87_update_pwm_ctrl(struct it87_data *data, int nr)
 {
        data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM(nr));
-       if (data->pwm_ctrl[nr] & 0x80)  /* Automatic mode */
+       if (data->type == it8721) {
                data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
-       else                            /* Manual mode */
-               data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f;
+               data->pwm_duty[nr] = it87_read_value(data,
+                                                    IT87_REG_PWM_DUTY(nr));
+       } else {
+               if (data->pwm_ctrl[nr] & 0x80)  /* Automatic mode */
+                       data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
+               else                            /* Manual mode */
+                       data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f;
+       }
 
        if (has_old_autopwm(data)) {
                int i;
index 9f4bae07f7194ebff499b2902895dc44c507d974..8853afce85ce138464787fc9182e27be9206ef1f 100644 (file)
@@ -186,7 +186,7 @@ static int __devexit lis3lv02d_i2c_remove(struct i2c_client *client)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int lis3lv02d_i2c_suspend(struct device *dev)
 {
        struct i2c_client *client = container_of(dev, struct i2c_client, dev);
@@ -213,12 +213,9 @@ static int lis3lv02d_i2c_resume(struct device *dev)
 
        return 0;
 }
-#else
-#define lis3lv02d_i2c_suspend  NULL
-#define lis3lv02d_i2c_resume   NULL
-#define lis3lv02d_i2c_shutdown NULL
-#endif
+#endif /* CONFIG_PM_SLEEP */
 
+#ifdef CONFIG_PM_RUNTIME
 static int lis3_i2c_runtime_suspend(struct device *dev)
 {
        struct i2c_client *client = container_of(dev, struct i2c_client, dev);
@@ -236,6 +233,7 @@ static int lis3_i2c_runtime_resume(struct device *dev)
        lis3lv02d_poweron(lis3);
        return 0;
 }
+#endif /* CONFIG_PM_RUNTIME */
 
 static const struct i2c_device_id lis3lv02d_id[] = {
        {"lis3lv02d", 0 },
index 00d975eb5b83dcc86ddd8d5f5b6846c9d370f6e6..c7e6d8e81656391e7f7919d5e4c92d08a69b1700 100644 (file)
@@ -205,7 +205,6 @@ LTC4215_ALARM(curr1_max_alarm,      (1 << 2),       LTC4215_STATUS);
 
 /* Power (virtual) */
 LTC4215_POWER(power1_input);
-LTC4215_ALARM(power1_alarm,    (1 << 3),       LTC4215_STATUS);
 
 /* Input Voltage */
 LTC4215_VOLTAGE(in1_input,                     LTC4215_ADIN);
@@ -214,6 +213,7 @@ LTC4215_ALARM(in1_min_alarm,        (1 << 1),       LTC4215_STATUS);
 
 /* Output Voltage */
 LTC4215_VOLTAGE(in2_input,                     LTC4215_SOURCE);
+LTC4215_ALARM(in2_min_alarm,   (1 << 3),       LTC4215_STATUS);
 
 /* Finally, construct an array of pointers to members of the above objects,
  * as required for sysfs_create_group()
@@ -223,13 +223,13 @@ static struct attribute *ltc4215_attributes[] = {
        &sensor_dev_attr_curr1_max_alarm.dev_attr.attr,
 
        &sensor_dev_attr_power1_input.dev_attr.attr,
-       &sensor_dev_attr_power1_alarm.dev_attr.attr,
 
        &sensor_dev_attr_in1_input.dev_attr.attr,
        &sensor_dev_attr_in1_max_alarm.dev_attr.attr,
        &sensor_dev_attr_in1_min_alarm.dev_attr.attr,
 
        &sensor_dev_attr_in2_input.dev_attr.attr,
+       &sensor_dev_attr_in2_min_alarm.dev_attr.attr,
 
        NULL,
 };
index b923074b2cbebcef73d91b5b7f23cfd47cb133f1..30f06e956bfb77e4f183e524657c21dbc211d1fe 100644 (file)
@@ -75,8 +75,7 @@ config I2C_HELPER_AUTO
          In doubt, say Y.
 
 config I2C_SMBUS
-       tristate
-       prompt "SMBus-specific protocols" if !I2C_HELPER_AUTO
+       tristate "SMBus-specific protocols" if !I2C_HELPER_AUTO
        help
          Say Y here if you want support for SMBus extensions to the I2C
          specification. At the moment, the only supported extension is
index 3998dd620a032586970a60f556aa6292318ce84a..f1cfe7e5508bb1cf65a82fac5903472927c3d184 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 menu "I2C Algorithms"
-       depends on !I2C_HELPER_AUTO
+       visible if !I2C_HELPER_AUTO
 
 config I2C_ALGOBIT
        tristate "I2C bit-banging interfaces"
@@ -15,15 +15,3 @@ config I2C_ALGOPCA
        tristate "I2C PCA 9564 interfaces"
 
 endmenu
-
-# In automatic configuration mode, we still have to define the
-# symbols to avoid unmet dependencies.
-
-if I2C_HELPER_AUTO
-config I2C_ALGOBIT
-       tristate
-config I2C_ALGOPCF
-       tristate
-config I2C_ALGOPCA
-       tristate
-endif
index 80f70d3a744dc65024c868843a66cd336fd53ce5..c71492782bbd4dda6e1f4a585adbba419ce4694d 100644 (file)
@@ -999,7 +999,7 @@ static int __devinit intel_mid_i2c_probe(struct pci_dev *dev,
 
        /* Initialize struct members */
        snprintf(mrst->adap.name, sizeof(mrst->adap.name),
-               "MRST/Medfield I2C at %lx", start);
+               "Intel MID I2C at %lx", start);
        mrst->adap.owner = THIS_MODULE;
        mrst->adap.algo = &intel_mid_i2c_algorithm;
        mrst->adap.dev.parent = &dev->dev;
index 41665d2f9f93c1fa585533184468da72039fe7cf..c131d58bcb50d818e05ee0464581bceedfdbf20f 100644 (file)
@@ -273,8 +273,6 @@ static int intel_idle_probe(void)
 
        pr_debug(PREFIX "MWAIT substates: 0x%x\n", mwait_substates);
 
-       if (boot_cpu_has(X86_FEATURE_ARAT))     /* Always Reliable APIC Timer */
-               lapic_timer_reliable_states = 0xFFFFFFFF;
 
        if (boot_cpu_data.x86 != 6)     /* family 6 */
                return -ENODEV;
@@ -286,8 +284,6 @@ static int intel_idle_probe(void)
        case 0x1F:      /* Core i7 and i5 Processor - Nehalem */
        case 0x2E:      /* Nehalem-EX Xeon */
        case 0x2F:      /* Westmere-EX Xeon */
-               lapic_timer_reliable_states = (1 << 1);  /* C1 */
-
        case 0x25:      /* Westmere */
        case 0x2C:      /* Westmere */
                cpuidle_state_table = nehalem_cstates;
@@ -295,7 +291,6 @@ static int intel_idle_probe(void)
 
        case 0x1C:      /* 28 - Atom Processor */
        case 0x26:      /* 38 - Lincroft Atom Processor */
-               lapic_timer_reliable_states = (1 << 1); /* C1 */
                cpuidle_state_table = atom_cstates;
                break;
 
@@ -303,10 +298,6 @@ static int intel_idle_probe(void)
        case 0x2D:      /* SNB Xeon */
                cpuidle_state_table = snb_cstates;
                break;
-#ifdef FUTURE_USE
-       case 0x17:      /* 23 - Core 2 Duo */
-               lapic_timer_reliable_states = (1 << 2) | (1 << 1); /* C2, C1 */
-#endif
 
        default:
                pr_debug(PREFIX "does not run on family %d model %d\n",
@@ -314,6 +305,9 @@ static int intel_idle_probe(void)
                return -ENODEV;
        }
 
+       if (boot_cpu_has(X86_FEATURE_ARAT))     /* Always Reliable APIC Timer */
+               lapic_timer_reliable_states = 0xFFFFFFFF;
+
        pr_debug(PREFIX "v" INTEL_IDLE_VERSION
                " model 0x%X\n", boot_cpu_data.x86_model);
 
index bb7e19280821c1074c6efd23a992f243ba33d258..9b737ff133e21d143982a57df0a581753450a6f3 100644 (file)
@@ -277,36 +277,6 @@ void ib_ud_header_init(int                     payload_bytes,
 }
 EXPORT_SYMBOL(ib_ud_header_init);
 
-/**
- * ib_lrh_header_pack - Pack LRH header struct into wire format
- * @lrh:unpacked LRH header struct
- * @buf:Buffer to pack into
- *
- * ib_lrh_header_pack() packs the LRH header structure @lrh into
- * wire format in the buffer @buf.
- */
-int ib_lrh_header_pack(struct ib_unpacked_lrh *lrh, void *buf)
-{
-       ib_pack(lrh_table, ARRAY_SIZE(lrh_table), lrh, buf);
-       return 0;
-}
-EXPORT_SYMBOL(ib_lrh_header_pack);
-
-/**
- * ib_lrh_header_unpack - Unpack LRH structure from wire format
- * @lrh:unpacked LRH header struct
- * @buf:Buffer to pack into
- *
- * ib_lrh_header_unpack() unpacks the LRH header structure from
- * wire format (in buf) into @lrh.
- */
-int ib_lrh_header_unpack(void *buf, struct ib_unpacked_lrh *lrh)
-{
-       ib_unpack(lrh_table, ARRAY_SIZE(lrh_table), buf, lrh);
-       return 0;
-}
-EXPORT_SYMBOL(ib_lrh_header_unpack);
-
 /**
  * ib_ud_header_pack - Pack UD header struct into wire format
  * @header:UD header struct
index b342248aec059060e19f64ffd69ec28af256682a..c42699285f8eb0d67745c359afadc6e125e7815d 100644 (file)
@@ -893,68 +893,81 @@ out:
        return ret ? ret : in_len;
 }
 
+static int copy_wc_to_user(void __user *dest, struct ib_wc *wc)
+{
+       struct ib_uverbs_wc tmp;
+
+       tmp.wr_id               = wc->wr_id;
+       tmp.status              = wc->status;
+       tmp.opcode              = wc->opcode;
+       tmp.vendor_err          = wc->vendor_err;
+       tmp.byte_len            = wc->byte_len;
+       tmp.ex.imm_data         = (__u32 __force) wc->ex.imm_data;
+       tmp.qp_num              = wc->qp->qp_num;
+       tmp.src_qp              = wc->src_qp;
+       tmp.wc_flags            = wc->wc_flags;
+       tmp.pkey_index          = wc->pkey_index;
+       tmp.slid                = wc->slid;
+       tmp.sl                  = wc->sl;
+       tmp.dlid_path_bits      = wc->dlid_path_bits;
+       tmp.port_num            = wc->port_num;
+       tmp.reserved            = 0;
+
+       if (copy_to_user(dest, &tmp, sizeof tmp))
+               return -EFAULT;
+
+       return 0;
+}
+
 ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
                          const char __user *buf, int in_len,
                          int out_len)
 {
        struct ib_uverbs_poll_cq       cmd;
-       struct ib_uverbs_poll_cq_resp *resp;
+       struct ib_uverbs_poll_cq_resp  resp;
+       u8 __user                     *header_ptr;
+       u8 __user                     *data_ptr;
        struct ib_cq                  *cq;
-       struct ib_wc                  *wc;
-       int                            ret = 0;
-       int                            i;
-       int                            rsize;
+       struct ib_wc                   wc;
+       int                            ret;
 
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
-       wc = kmalloc(cmd.ne * sizeof *wc, GFP_KERNEL);
-       if (!wc)
-               return -ENOMEM;
-
-       rsize = sizeof *resp + cmd.ne * sizeof(struct ib_uverbs_wc);
-       resp = kmalloc(rsize, GFP_KERNEL);
-       if (!resp) {
-               ret = -ENOMEM;
-               goto out_wc;
-       }
-
        cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0);
-       if (!cq) {
-               ret = -EINVAL;
-               goto out;
-       }
+       if (!cq)
+               return -EINVAL;
 
-       resp->count = ib_poll_cq(cq, cmd.ne, wc);
+       /* we copy a struct ib_uverbs_poll_cq_resp to user space */
+       header_ptr = (void __user *)(unsigned long) cmd.response;
+       data_ptr = header_ptr + sizeof resp;
 
-       put_cq_read(cq);
+       memset(&resp, 0, sizeof resp);
+       while (resp.count < cmd.ne) {
+               ret = ib_poll_cq(cq, 1, &wc);
+               if (ret < 0)
+                       goto out_put;
+               if (!ret)
+                       break;
+
+               ret = copy_wc_to_user(data_ptr, &wc);
+               if (ret)
+                       goto out_put;
 
-       for (i = 0; i < resp->count; i++) {
-               resp->wc[i].wr_id          = wc[i].wr_id;
-               resp->wc[i].status         = wc[i].status;
-               resp->wc[i].opcode         = wc[i].opcode;
-               resp->wc[i].vendor_err     = wc[i].vendor_err;
-               resp->wc[i].byte_len       = wc[i].byte_len;
-               resp->wc[i].ex.imm_data    = (__u32 __force) wc[i].ex.imm_data;
-               resp->wc[i].qp_num         = wc[i].qp->qp_num;
-               resp->wc[i].src_qp         = wc[i].src_qp;
-               resp->wc[i].wc_flags       = wc[i].wc_flags;
-               resp->wc[i].pkey_index     = wc[i].pkey_index;
-               resp->wc[i].slid           = wc[i].slid;
-               resp->wc[i].sl             = wc[i].sl;
-               resp->wc[i].dlid_path_bits = wc[i].dlid_path_bits;
-               resp->wc[i].port_num       = wc[i].port_num;
+               data_ptr += sizeof(struct ib_uverbs_wc);
+               ++resp.count;
        }
 
-       if (copy_to_user((void __user *) (unsigned long) cmd.response, resp, rsize))
+       if (copy_to_user(header_ptr, &resp, sizeof resp)) {
                ret = -EFAULT;
+               goto out_put;
+       }
 
-out:
-       kfree(resp);
+       ret = in_len;
 
-out_wc:
-       kfree(wc);
-       return ret ? ret : in_len;
+out_put:
+       put_cq_read(cq);
+       return ret;
 }
 
 ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file,
index 5440da0e59b4d8b475c2cd3e437fcb04e456a334..1b1146f87124e2618ef80a8303fabe681a464782 100644 (file)
@@ -40,18 +40,21 @@ void ib_copy_ah_attr_to_user(struct ib_uverbs_ah_attr *dst,
        dst->grh.sgid_index        = src->grh.sgid_index;
        dst->grh.hop_limit         = src->grh.hop_limit;
        dst->grh.traffic_class     = src->grh.traffic_class;
+       memset(&dst->grh.reserved, 0, sizeof(dst->grh.reserved));
        dst->dlid                  = src->dlid;
        dst->sl                    = src->sl;
        dst->src_path_bits         = src->src_path_bits;
        dst->static_rate           = src->static_rate;
        dst->is_global             = src->ah_flags & IB_AH_GRH ? 1 : 0;
        dst->port_num              = src->port_num;
+       dst->reserved              = 0;
 }
 EXPORT_SYMBOL(ib_copy_ah_attr_to_user);
 
 void ib_copy_qp_attr_to_user(struct ib_uverbs_qp_attr *dst,
                             struct ib_qp_attr *src)
 {
+       dst->qp_state           = src->qp_state;
        dst->cur_qp_state       = src->cur_qp_state;
        dst->path_mtu           = src->path_mtu;
        dst->path_mig_state     = src->path_mig_state;
@@ -83,6 +86,7 @@ void ib_copy_qp_attr_to_user(struct ib_uverbs_qp_attr *dst,
        dst->rnr_retry          = src->rnr_retry;
        dst->alt_port_num       = src->alt_port_num;
        dst->alt_timeout        = src->alt_timeout;
+       memset(dst->reserved, 0, sizeof(dst->reserved));
 }
 EXPORT_SYMBOL(ib_copy_qp_attr_to_user);
 
index bf3e20cd029859f2beb23e962fa2640e30faf44c..30e09caf0da95af71ce17e4017eaefb13db6cb7d 100644 (file)
@@ -219,7 +219,7 @@ static int eth_link_query_port(struct ib_device *ibdev, u8 port,
        struct net_device *ndev;
        enum ib_mtu tmp;
 
-       props->active_width     = IB_WIDTH_4X;
+       props->active_width     = IB_WIDTH_1X;
        props->active_speed     = 4;
        props->port_cap_flags   = IB_PORT_CM_SUP;
        props->gid_tbl_len      = to_mdev(ibdev)->dev->caps.gid_table_len[port];
@@ -242,7 +242,7 @@ static int eth_link_query_port(struct ib_device *ibdev, u8 port,
        tmp = iboe_get_mtu(ndev->mtu);
        props->active_mtu = tmp ? min(props->max_mtu, tmp) : IB_MTU_256;
 
-       props->state            = netif_running(ndev) &&  netif_oper_up(ndev) ?
+       props->state            = (netif_running(ndev) && netif_carrier_ok(ndev)) ?
                                        IB_PORT_ACTIVE : IB_PORT_DOWN;
        props->phys_state       = state_to_phys_state(props->state);
 
index 9a7794ac34c1ead2f08a9da3078db777ee1ef1ec..2001f20a43618e74b927733d8d54b410af084979 100644 (file)
@@ -1816,6 +1816,11 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                ctrl->fence_size = (wr->send_flags & IB_SEND_FENCE ?
                                    MLX4_WQE_CTRL_FENCE : 0) | size;
 
+               if (be16_to_cpu(vlan) < 0x1000) {
+                       ctrl->ins_vlan = 1 << 6;
+                       ctrl->vlan_tag = vlan;
+               }
+
                /*
                 * Make sure descriptor is fully written before
                 * setting ownership bit (because HW can start
@@ -1831,11 +1836,6 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                ctrl->owner_opcode = mlx4_ib_opcode[wr->opcode] |
                        (ind & qp->sq.wqe_cnt ? cpu_to_be32(1 << 31) : 0) | blh;
 
-               if (be16_to_cpu(vlan) < 0x1000) {
-                       ctrl->ins_vlan = 1 << 6;
-                       ctrl->vlan_tag = vlan;
-               }
-
                stamp = ind + qp->sq_spare_wqes;
                ind += DIV_ROUND_UP(size * 16, 1U << qp->sq.wqe_shift);
 
index e3f7fc6f95657e2f4846cebc0efae905d309c31d..68f09a868434b52a6522c147dce8125f42f6505f 100644 (file)
@@ -534,76 +534,73 @@ static int handle_eviocgbit(struct input_dev *dev,
 }
 #undef OLD_KEY_MAX
 
-static int evdev_handle_get_keycode(struct input_dev *dev,
-                                   void __user *p, size_t size)
+static int evdev_handle_get_keycode(struct input_dev *dev, void __user *p)
 {
-       struct input_keymap_entry ke;
+       struct input_keymap_entry ke = {
+               .len    = sizeof(unsigned int),
+               .flags  = 0,
+       };
+       int __user *ip = (int __user *)p;
        int error;
 
-       memset(&ke, 0, sizeof(ke));
-
-       if (size == sizeof(unsigned int[2])) {
-               /* legacy case */
-               int __user *ip = (int __user *)p;
+       /* legacy case */
+       if (copy_from_user(ke.scancode, p, sizeof(unsigned int)))
+               return -EFAULT;
 
-               if (copy_from_user(ke.scancode, p, sizeof(unsigned int)))
-                       return -EFAULT;
+       error = input_get_keycode(dev, &ke);
+       if (error)
+               return error;
 
-               ke.len = sizeof(unsigned int);
-               ke.flags = 0;
+       if (put_user(ke.keycode, ip + 1))
+               return -EFAULT;
 
-               error = input_get_keycode(dev, &ke);
-               if (error)
-                       return error;
+       return 0;
+}
 
-               if (put_user(ke.keycode, ip + 1))
-                       return -EFAULT;
+static int evdev_handle_get_keycode_v2(struct input_dev *dev, void __user *p)
+{
+       struct input_keymap_entry ke;
+       int error;
 
-       } else {
-               size = min(size, sizeof(ke));
+       if (copy_from_user(&ke, p, sizeof(ke)))
+               return -EFAULT;
 
-               if (copy_from_user(&ke, p, size))
-                       return -EFAULT;
+       error = input_get_keycode(dev, &ke);
+       if (error)
+               return error;
 
-               error = input_get_keycode(dev, &ke);
-               if (error)
-                       return error;
+       if (copy_to_user(p, &ke, sizeof(ke)))
+               return -EFAULT;
 
-               if (copy_to_user(p, &ke, size))
-                       return -EFAULT;
-       }
        return 0;
 }
 
-static int evdev_handle_set_keycode(struct input_dev *dev,
-                                   void __user *p, size_t size)
+static int evdev_handle_set_keycode(struct input_dev *dev, void __user *p)
 {
-       struct input_keymap_entry ke;
-
-       memset(&ke, 0, sizeof(ke));
+       struct input_keymap_entry ke = {
+               .len    = sizeof(unsigned int),
+               .flags  = 0,
+       };
+       int __user *ip = (int __user *)p;
 
-       if (size == sizeof(unsigned int[2])) {
-               /* legacy case */
-               int __user *ip = (int __user *)p;
+       if (copy_from_user(ke.scancode, p, sizeof(unsigned int)))
+               return -EFAULT;
 
-               if (copy_from_user(ke.scancode, p, sizeof(unsigned int)))
-                       return -EFAULT;
+       if (get_user(ke.keycode, ip + 1))
+               return -EFAULT;
 
-               if (get_user(ke.keycode, ip + 1))
-                       return -EFAULT;
+       return input_set_keycode(dev, &ke);
+}
 
-               ke.len = sizeof(unsigned int);
-               ke.flags = 0;
+static int evdev_handle_set_keycode_v2(struct input_dev *dev, void __user *p)
+{
+       struct input_keymap_entry ke;
 
-       } else {
-               size = min(size, sizeof(ke));
+       if (copy_from_user(&ke, p, sizeof(ke)))
+               return -EFAULT;
 
-               if (copy_from_user(&ke, p, size))
-                       return -EFAULT;
-
-               if (ke.len > sizeof(ke.scancode))
-                       return -EINVAL;
-       }
+       if (ke.len > sizeof(ke.scancode))
+               return -EINVAL;
 
        return input_set_keycode(dev, &ke);
 }
@@ -669,6 +666,18 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                        return evdev_grab(evdev, client);
                else
                        return evdev_ungrab(evdev, client);
+
+       case EVIOCGKEYCODE:
+               return evdev_handle_get_keycode(dev, p);
+
+       case EVIOCSKEYCODE:
+               return evdev_handle_set_keycode(dev, p);
+
+       case EVIOCGKEYCODE_V2:
+               return evdev_handle_get_keycode_v2(dev, p);
+
+       case EVIOCSKEYCODE_V2:
+               return evdev_handle_set_keycode_v2(dev, p);
        }
 
        size = _IOC_SIZE(cmd);
@@ -708,12 +717,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                        return -EFAULT;
 
                return error;
-
-       case EVIOC_MASK_SIZE(EVIOCGKEYCODE):
-               return evdev_handle_get_keycode(dev, p, size);
-
-       case EVIOC_MASK_SIZE(EVIOCSKEYCODE):
-               return evdev_handle_set_keycode(dev, p, size);
        }
 
        /* Multi-number variable-length handlers */
index 90b7ecfb625757ee9505480566c26f6baed32a6a..db409d6bd5d2b9672ad94f370564f870bed25b19 100644 (file)
@@ -752,7 +752,7 @@ static int input_default_setkeycode(struct input_dev *dev,
        if (index >= dev->keycodemax)
                return -EINVAL;
 
-       if (dev->keycodesize < sizeof(dev->keycode) &&
+       if (dev->keycodesize < sizeof(ke->keycode) &&
                        (ke->keycode >> (dev->keycodesize * 8)))
                return -EINVAL;
 
index d53b9e900234e7ba95c2c0b9500a830b96c07803..27b6a3ce18caf2e996177e6c313fff2b21a4ad19 100644 (file)
@@ -245,6 +245,7 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
                goto err_free_tgfx;
         }
 
+       parport_put_port(pp);
        return tgfx;
 
  err_free_dev:
index b8c51b9781dbfb5e51c9a9d84071f534bf44e1d1..3a87f3ba5f75ee1f6a94973c2a5414f0653e48a8 100644 (file)
@@ -179,6 +179,22 @@ config KEYBOARD_GPIO
          To compile this driver as a module, choose M here: the
          module will be called gpio_keys.
 
+config KEYBOARD_GPIO_POLLED
+       tristate "Polled GPIO buttons"
+       depends on GENERIC_GPIO
+       select INPUT_POLLDEV
+       help
+         This driver implements support for buttons connected
+         to GPIO pins that are not capable of generating interrupts.
+
+         Say Y here if your device has buttons connected
+         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_polled.
+
 config KEYBOARD_TCA6416
        tristate "TCA6416 Keypad Support"
        depends on I2C
index a34452e8ebe2a1cb190f82d5c5f9c037860fcf07..622de73a445dbe620db5ae86d5e8ccd2bd90aeb2 100644 (file)
@@ -14,6 +14,7 @@ obj-$(CONFIG_KEYBOARD_BFIN)           += bf54x-keys.o
 obj-$(CONFIG_KEYBOARD_DAVINCI)         += davinci_keyscan.o
 obj-$(CONFIG_KEYBOARD_EP93XX)          += ep93xx_keypad.o
 obj-$(CONFIG_KEYBOARD_GPIO)            += gpio_keys.o
+obj-$(CONFIG_KEYBOARD_GPIO_POLLED)     += gpio_keys_polled.o
 obj-$(CONFIG_KEYBOARD_TCA6416)         += tca6416-keypad.o
 obj-$(CONFIG_KEYBOARD_HIL)             += hil_kbd.o
 obj-$(CONFIG_KEYBOARD_HIL_OLD)         += hilkbd.o
diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c
new file mode 100644 (file)
index 0000000..4c17aff
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ *  Driver for buttons on GPIO lines not capable of generating interrupts
+ *
+ *  Copyright (C) 2007-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2010 Nuno Goncalves <nunojpg@gmail.com>
+ *
+ *  This file was based on: /drivers/input/misc/cobalt_btns.c
+ *     Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ *  also was based on: /drivers/input/keyboard/gpio_keys.c
+ *     Copyright 2005 Phil Blundell
+ *
+ *  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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/input-polldev.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+
+#define DRV_NAME       "gpio-keys-polled"
+
+struct gpio_keys_button_data {
+       int last_state;
+       int count;
+       int threshold;
+       int can_sleep;
+};
+
+struct gpio_keys_polled_dev {
+       struct input_polled_dev *poll_dev;
+       struct device *dev;
+       struct gpio_keys_platform_data *pdata;
+       struct gpio_keys_button_data data[0];
+};
+
+static void gpio_keys_polled_check_state(struct input_dev *input,
+                                        struct gpio_keys_button *button,
+                                        struct gpio_keys_button_data *bdata)
+{
+       int state;
+
+       if (bdata->can_sleep)
+               state = !!gpio_get_value_cansleep(button->gpio);
+       else
+               state = !!gpio_get_value(button->gpio);
+
+       if (state != bdata->last_state) {
+               unsigned int type = button->type ?: EV_KEY;
+
+               input_event(input, type, button->code,
+                           !!(state ^ button->active_low));
+               input_sync(input);
+               bdata->count = 0;
+               bdata->last_state = state;
+       }
+}
+
+static void gpio_keys_polled_poll(struct input_polled_dev *dev)
+{
+       struct gpio_keys_polled_dev *bdev = dev->private;
+       struct gpio_keys_platform_data *pdata = bdev->pdata;
+       struct input_dev *input = dev->input;
+       int i;
+
+       for (i = 0; i < bdev->pdata->nbuttons; i++) {
+               struct gpio_keys_button_data *bdata = &bdev->data[i];
+
+               if (bdata->count < bdata->threshold)
+                       bdata->count++;
+               else
+                       gpio_keys_polled_check_state(input, &pdata->buttons[i],
+                                                    bdata);
+       }
+}
+
+static void gpio_keys_polled_open(struct input_polled_dev *dev)
+{
+       struct gpio_keys_polled_dev *bdev = dev->private;
+       struct gpio_keys_platform_data *pdata = bdev->pdata;
+
+       if (pdata->enable)
+               pdata->enable(bdev->dev);
+}
+
+static void gpio_keys_polled_close(struct input_polled_dev *dev)
+{
+       struct gpio_keys_polled_dev *bdev = dev->private;
+       struct gpio_keys_platform_data *pdata = bdev->pdata;
+
+       if (pdata->disable)
+               pdata->disable(bdev->dev);
+}
+
+static int __devinit gpio_keys_polled_probe(struct platform_device *pdev)
+{
+       struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
+       struct device *dev = &pdev->dev;
+       struct gpio_keys_polled_dev *bdev;
+       struct input_polled_dev *poll_dev;
+       struct input_dev *input;
+       int error;
+       int i;
+
+       if (!pdata || !pdata->poll_interval)
+               return -EINVAL;
+
+       bdev = kzalloc(sizeof(struct gpio_keys_polled_dev) +
+                      pdata->nbuttons * sizeof(struct gpio_keys_button_data),
+                      GFP_KERNEL);
+       if (!bdev) {
+               dev_err(dev, "no memory for private data\n");
+               return -ENOMEM;
+       }
+
+       poll_dev = input_allocate_polled_device();
+       if (!poll_dev) {
+               dev_err(dev, "no memory for polled device\n");
+               error = -ENOMEM;
+               goto err_free_bdev;
+       }
+
+       poll_dev->private = bdev;
+       poll_dev->poll = gpio_keys_polled_poll;
+       poll_dev->poll_interval = pdata->poll_interval;
+       poll_dev->open = gpio_keys_polled_open;
+       poll_dev->close = gpio_keys_polled_close;
+
+       input = poll_dev->input;
+
+       input->evbit[0] = BIT(EV_KEY);
+       input->name = pdev->name;
+       input->phys = DRV_NAME"/input0";
+       input->dev.parent = &pdev->dev;
+
+       input->id.bustype = BUS_HOST;
+       input->id.vendor = 0x0001;
+       input->id.product = 0x0001;
+       input->id.version = 0x0100;
+
+       for (i = 0; i < pdata->nbuttons; i++) {
+               struct gpio_keys_button *button = &pdata->buttons[i];
+               struct gpio_keys_button_data *bdata = &bdev->data[i];
+               unsigned int gpio = button->gpio;
+               unsigned int type = button->type ?: EV_KEY;
+
+               if (button->wakeup) {
+                       dev_err(dev, DRV_NAME " does not support wakeup\n");
+                       error = -EINVAL;
+                       goto err_free_gpio;
+               }
+
+               error = gpio_request(gpio,
+                                    button->desc ? button->desc : DRV_NAME);
+               if (error) {
+                       dev_err(dev, "unable to claim gpio %u, err=%d\n",
+                               gpio, error);
+                       goto err_free_gpio;
+               }
+
+               error = gpio_direction_input(gpio);
+               if (error) {
+                       dev_err(dev,
+                               "unable to set direction on gpio %u, err=%d\n",
+                               gpio, error);
+                       goto err_free_gpio;
+               }
+
+               bdata->can_sleep = gpio_cansleep(gpio);
+               bdata->last_state = -1;
+               bdata->threshold = DIV_ROUND_UP(button->debounce_interval,
+                                               pdata->poll_interval);
+
+               input_set_capability(input, type, button->code);
+       }
+
+       bdev->poll_dev = poll_dev;
+       bdev->dev = dev;
+       bdev->pdata = pdata;
+       platform_set_drvdata(pdev, bdev);
+
+       error = input_register_polled_device(poll_dev);
+       if (error) {
+               dev_err(dev, "unable to register polled device, err=%d\n",
+                       error);
+               goto err_free_gpio;
+       }
+
+       /* report initial state of the buttons */
+       for (i = 0; i < pdata->nbuttons; i++)
+               gpio_keys_polled_check_state(input, &pdata->buttons[i],
+                                        &bdev->data[i]);
+
+       return 0;
+
+err_free_gpio:
+       while (--i >= 0)
+               gpio_free(pdata->buttons[i].gpio);
+
+       input_free_polled_device(poll_dev);
+
+err_free_bdev:
+       kfree(bdev);
+
+       platform_set_drvdata(pdev, NULL);
+       return error;
+}
+
+static int __devexit gpio_keys_polled_remove(struct platform_device *pdev)
+{
+       struct gpio_keys_polled_dev *bdev = platform_get_drvdata(pdev);
+       struct gpio_keys_platform_data *pdata = bdev->pdata;
+       int i;
+
+       input_unregister_polled_device(bdev->poll_dev);
+
+       for (i = 0; i < pdata->nbuttons; i++)
+               gpio_free(pdata->buttons[i].gpio);
+
+       input_free_polled_device(bdev->poll_dev);
+
+       kfree(bdev);
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+static struct platform_driver gpio_keys_polled_driver = {
+       .probe  = gpio_keys_polled_probe,
+       .remove = __devexit_p(gpio_keys_polled_remove),
+       .driver = {
+               .name   = DRV_NAME,
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init gpio_keys_polled_init(void)
+{
+       return platform_driver_register(&gpio_keys_polled_driver);
+}
+
+static void __exit gpio_keys_polled_exit(void)
+{
+       platform_driver_unregister(&gpio_keys_polled_driver);
+}
+
+module_init(gpio_keys_polled_init);
+module_exit(gpio_keys_polled_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
+MODULE_DESCRIPTION("Polled GPIO Buttons driver");
+MODULE_ALIAS("platform:" DRV_NAME);
index 613a3652f98f5f787fa619807f10de67aa8634c5..0aefaa8858714ba6e9963a9e6cd1f0c13fbab963 100644 (file)
@@ -51,7 +51,8 @@
 #define SYN_EXT_CAP_REQUESTS(c)                (((c) & 0x700000) >> 20)
 #define SYN_CAP_MULTI_BUTTON_NO(ec)    (((ec) & 0x00f000) >> 12)
 #define SYN_CAP_PRODUCT_ID(ec)         (((ec) & 0xff0000) >> 16)
-#define SYN_CAP_CLICKPAD(ex0c)         ((ex0c) & 0x100100)
+#define SYN_CAP_CLICKPAD(ex0c)         ((ex0c) & 0x100000) /* 1-button ClickPad */
+#define SYN_CAP_CLICKPAD2BTN(ex0c)     ((ex0c) & 0x000100) /* 2-button ClickPad */
 #define SYN_CAP_MAX_DIMENSIONS(ex0c)   ((ex0c) & 0x020000)
 
 /* synaptics modes query bits */
index 3c287dd879d32be0b68f732ab020974c38ac10f5..4225f5d6b15f475e7822d78a1d26ce3e5e35301d 100644 (file)
@@ -358,7 +358,7 @@ static int __devinit gscps2_probe(struct parisc_device *dev)
        gscps2_reset(ps2port);
        ps2port->id = readb(ps2port->addr + GSC_ID) & 0x0f;
 
-       snprintf(serio->name, sizeof(serio->name), "GSC PS/2 %s",
+       snprintf(serio->name, sizeof(serio->name), "gsc-ps2-%s",
                 (ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse");
        strlcpy(serio->phys, dev_name(&dev->dev), sizeof(serio->phys));
        serio->id.type          = SERIO_8042;
index 57b25b84d1fcfded0408788dbd8cbd2d0dcb3e8f..0a619c558bfb40a8223c94301462d6387f7dc388 100644 (file)
@@ -1097,7 +1097,7 @@ store_tabletPointerMode(struct device *dev, struct device_attribute *attr, const
 }
 
 static DEVICE_ATTR(pointer_mode,
-                  S_IRUGO | S_IWUGO,
+                  S_IRUGO | S_IWUSR,
                   show_tabletPointerMode, store_tabletPointerMode);
 
 /***********************************************************************
@@ -1134,7 +1134,7 @@ store_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, co
 }
 
 static DEVICE_ATTR(coordinate_mode,
-                  S_IRUGO | S_IWUGO,
+                  S_IRUGO | S_IWUSR,
                   show_tabletCoordinateMode, store_tabletCoordinateMode);
 
 /***********************************************************************
@@ -1176,7 +1176,7 @@ store_tabletToolMode(struct device *dev, struct device_attribute *attr, const ch
 }
 
 static DEVICE_ATTR(tool_mode,
-                  S_IRUGO | S_IWUGO,
+                  S_IRUGO | S_IWUSR,
                   show_tabletToolMode, store_tabletToolMode);
 
 /***********************************************************************
@@ -1219,7 +1219,7 @@ store_tabletXtilt(struct device *dev, struct device_attribute *attr, const char
 }
 
 static DEVICE_ATTR(xtilt,
-                  S_IRUGO | S_IWUGO, show_tabletXtilt, store_tabletXtilt);
+                  S_IRUGO | S_IWUSR, show_tabletXtilt, store_tabletXtilt);
 
 /***********************************************************************
  * support routines for the 'ytilt' file. Note that this file
@@ -1261,7 +1261,7 @@ store_tabletYtilt(struct device *dev, struct device_attribute *attr, const char
 }
 
 static DEVICE_ATTR(ytilt,
-                  S_IRUGO | S_IWUGO, show_tabletYtilt, store_tabletYtilt);
+                  S_IRUGO | S_IWUSR, show_tabletYtilt, store_tabletYtilt);
 
 /***********************************************************************
  * support routines for the 'jitter' file. Note that this file
@@ -1288,7 +1288,7 @@ store_tabletJitterDelay(struct device *dev, struct device_attribute *attr, const
 }
 
 static DEVICE_ATTR(jitter,
-                  S_IRUGO | S_IWUGO,
+                  S_IRUGO | S_IWUSR,
                   show_tabletJitterDelay, store_tabletJitterDelay);
 
 /***********************************************************************
@@ -1317,7 +1317,7 @@ store_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr,
 }
 
 static DEVICE_ATTR(delay,
-                  S_IRUGO | S_IWUGO,
+                  S_IRUGO | S_IWUSR,
                   show_tabletProgrammableDelay, store_tabletProgrammableDelay);
 
 /***********************************************************************
@@ -1406,7 +1406,7 @@ store_tabletStylusUpper(struct device *dev, struct device_attribute *attr, const
 }
 
 static DEVICE_ATTR(stylus_upper,
-                  S_IRUGO | S_IWUGO,
+                  S_IRUGO | S_IWUSR,
                   show_tabletStylusUpper, store_tabletStylusUpper);
 
 /***********************************************************************
@@ -1437,7 +1437,7 @@ store_tabletStylusLower(struct device *dev, struct device_attribute *attr, const
 }
 
 static DEVICE_ATTR(stylus_lower,
-                  S_IRUGO | S_IWUGO,
+                  S_IRUGO | S_IWUSR,
                   show_tabletStylusLower, store_tabletStylusLower);
 
 /***********************************************************************
@@ -1475,7 +1475,7 @@ store_tabletMouseLeft(struct device *dev, struct device_attribute *attr, const c
 }
 
 static DEVICE_ATTR(mouse_left,
-                  S_IRUGO | S_IWUGO,
+                  S_IRUGO | S_IWUSR,
                   show_tabletMouseLeft, store_tabletMouseLeft);
 
 /***********************************************************************
@@ -1505,7 +1505,7 @@ store_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, const
 }
 
 static DEVICE_ATTR(mouse_middle,
-                  S_IRUGO | S_IWUGO,
+                  S_IRUGO | S_IWUSR,
                   show_tabletMouseMiddle, store_tabletMouseMiddle);
 
 /***********************************************************************
@@ -1535,7 +1535,7 @@ store_tabletMouseRight(struct device *dev, struct device_attribute *attr, const
 }
 
 static DEVICE_ATTR(mouse_right,
-                  S_IRUGO | S_IWUGO,
+                  S_IRUGO | S_IWUSR,
                   show_tabletMouseRight, store_tabletMouseRight);
 
 /***********************************************************************
@@ -1567,7 +1567,7 @@ store_tabletWheel(struct device *dev, struct device_attribute *attr, const char
 }
 
 static DEVICE_ATTR(wheel,
-                  S_IRUGO | S_IWUGO, show_tabletWheel, store_tabletWheel);
+                  S_IRUGO | S_IWUSR, show_tabletWheel, store_tabletWheel);
 
 /***********************************************************************
  * support routines for the 'execute' file. Note that this file
@@ -1600,7 +1600,7 @@ store_tabletExecute(struct device *dev, struct device_attribute *attr, const cha
 }
 
 static DEVICE_ATTR(execute,
-                  S_IRUGO | S_IWUGO, show_tabletExecute, store_tabletExecute);
+                  S_IRUGO | S_IWUSR, show_tabletExecute, store_tabletExecute);
 
 /***********************************************************************
  * support routines for the 'odm_code' file. Note that this file
index b3252ef1e2797e6b7f640322bb8cbf4a6ecc61bd..435b0af401e46e38b23fd6ffba9e862f90c9729b 100644 (file)
@@ -1436,6 +1436,14 @@ static struct wacom_features wacom_features_0xD2 =
        { "Wacom Bamboo Craft",   WACOM_PKGLEN_BBFUN,     14720,  9200, 1023, 63, BAMBOO_PT };
 static struct wacom_features wacom_features_0xD3 =
        { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN,     21648, 13530, 1023, 63, BAMBOO_PT };
+static const struct wacom_features wacom_features_0xD4 =
+       { "Wacom Bamboo Pen",     WACOM_PKGLEN_BBFUN,     14720,  9200,  255, 63, BAMBOO_PT };
+static struct wacom_features wacom_features_0xD8 =
+       { "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN,   21648, 13530, 1023, 63, BAMBOO_PT };
+static struct wacom_features wacom_features_0xDA =
+       { "Wacom Bamboo 2FG 4x5 SE", WACOM_PKGLEN_BBFUN,  14720,  9200, 1023, 63, BAMBOO_PT };
+static struct wacom_features wacom_features_0xDB =
+       { "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN,  21648, 13530, 1023, 63, BAMBOO_PT };
 
 #define USB_DEVICE_WACOM(prod)                                 \
        USB_DEVICE(USB_VENDOR_ID_WACOM, prod),                  \
@@ -1504,6 +1512,10 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0xD1) },
        { USB_DEVICE_WACOM(0xD2) },
        { USB_DEVICE_WACOM(0xD3) },
+       { USB_DEVICE_WACOM(0xD4) },
+       { USB_DEVICE_WACOM(0xD8) },
+       { USB_DEVICE_WACOM(0xDA) },
+       { USB_DEVICE_WACOM(0xDB) },
        { USB_DEVICE_WACOM(0xF0) },
        { USB_DEVICE_WACOM(0xCC) },
        { USB_DEVICE_WACOM(0x90) },
index f45f80f6d3369b03f8b6e1e6a8bcebc827cf3377..73fd6642b681b92a074b6e8ab2619b65768292f7 100644 (file)
@@ -178,6 +178,7 @@ static const struct usb_device_id usbtouch_devices[] = {
 
 #ifdef CONFIG_TOUCHSCREEN_USB_ITM
        {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM},
+       {USB_DEVICE(0x16e3, 0xf9e9), .driver_info = DEVTYPE_ITM},
 #endif
 
 #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO
index 2e847a90bad0d601f8bcc5f9a7bd4d7440f929c0..f2b5bab5e6a191761d2f56331c792ca8f7f78182 100644 (file)
@@ -1627,7 +1627,7 @@ __setup("icn=", icn_setup);
 static int __init icn_init(void)
 {
        char *p;
-       char rev[10];
+       char rev[20];
 
        memset(&dev, 0, sizeof(icn_dev));
        dev.memaddr = (membase & 0x0ffc000);
@@ -1637,9 +1637,10 @@ static int __init icn_init(void)
        spin_lock_init(&dev.devlock);
 
        if ((p = strchr(revision, ':'))) {
-               strcpy(rev, p + 1);
+               strncpy(rev, p + 1, 20);
                p = strchr(rev, '$');
-               *p = 0;
+               if (p)
+                       *p = 0;
        } else
                strcpy(rev, " ??? ");
        printk(KERN_NOTICE "ICN-ISDN-driver Rev%smem=0x%08lx\n", rev,
index 77b8fd20cd9046b8e0c785c041c7569285aa6043..6f190f4cdbc00e4917c457dcd004060c3b8976ba 100644 (file)
@@ -7,20 +7,20 @@ menuconfig NEW_LEDS
          This is not related to standard keyboard LEDs which are controlled
          via the input system.
 
-if NEW_LEDS
-
 config LEDS_CLASS
        bool "LED Class Support"
+       depends on NEW_LEDS
        help
          This option enables the led sysfs class in /sys/class/leds.  You'll
          need this to do anything useful with LEDs.  If unsure, say N.
 
-if LEDS_CLASS
+if NEW_LEDS
 
 comment "LED drivers"
 
 config LEDS_88PM860X
        tristate "LED Support for Marvell 88PM860x PMIC"
+       depends on LEDS_CLASS
        depends on MFD_88PM860X
        help
          This option enables support for on-chip LED drivers found on Marvell
@@ -28,6 +28,7 @@ config LEDS_88PM860X
 
 config LEDS_ATMEL_PWM
        tristate "LED Support using Atmel PWM outputs"
+       depends on LEDS_CLASS
        depends on ATMEL_PWM
        help
          This option enables support for LEDs driven using outputs
@@ -35,6 +36,7 @@ config LEDS_ATMEL_PWM
 
 config LEDS_LOCOMO
        tristate "LED Support for Locomo device"
+       depends on LEDS_CLASS
        depends on SHARP_LOCOMO
        help
          This option enables support for the LEDs on Sharp Locomo.
@@ -42,6 +44,7 @@ config LEDS_LOCOMO
 
 config LEDS_MIKROTIK_RB532
        tristate "LED Support for Mikrotik Routerboard 532"
+       depends on LEDS_CLASS
        depends on MIKROTIK_RB532
        help
          This option enables support for the so called "User LED" of
@@ -49,6 +52,7 @@ config LEDS_MIKROTIK_RB532
 
 config LEDS_S3C24XX
        tristate "LED Support for Samsung S3C24XX GPIO LEDs"
+       depends on LEDS_CLASS
        depends on ARCH_S3C2410
        help
          This option enables support for LEDs connected to GPIO lines
@@ -56,12 +60,14 @@ config LEDS_S3C24XX
 
 config LEDS_AMS_DELTA
        tristate "LED Support for the Amstrad Delta (E3)"
+       depends on LEDS_CLASS
        depends on MACH_AMS_DELTA
        help
          This option enables support for the LEDs on Amstrad Delta (E3).
 
 config LEDS_NET48XX
        tristate "LED Support for Soekris net48xx series Error LED"
+       depends on LEDS_CLASS
        depends on SCx200_GPIO
        help
          This option enables support for the Soekris net4801 and net4826 error
@@ -79,18 +85,21 @@ config LEDS_NET5501
 
 config LEDS_FSG
        tristate "LED Support for the Freecom FSG-3"
+       depends on LEDS_CLASS
        depends on MACH_FSG
        help
          This option enables support for the LEDs on the Freecom FSG-3.
 
 config LEDS_WRAP
        tristate "LED Support for the WRAP series LEDs"
+       depends on LEDS_CLASS
        depends on SCx200_GPIO
        help
          This option enables support for the PCEngines WRAP programmable LEDs.
 
 config LEDS_ALIX2
        tristate "LED Support for ALIX.2 and ALIX.3 series"
+       depends on LEDS_CLASS
        depends on X86 && !GPIO_CS5535 && !CS5535_GPIO
        help
          This option enables support for the PCEngines ALIX.2 and ALIX.3 LEDs.
@@ -98,12 +107,14 @@ config LEDS_ALIX2
 
 config LEDS_H1940
        tristate "LED Support for iPAQ H1940 device"
+       depends on LEDS_CLASS
        depends on ARCH_H1940
        help
          This option enables support for the LEDs on the h1940.
 
 config LEDS_COBALT_QUBE
        tristate "LED Support for the Cobalt Qube series front LED"
+       depends on LEDS_CLASS
        depends on MIPS_COBALT
        help
          This option enables support for the front LED on Cobalt Qube series
@@ -117,6 +128,7 @@ config LEDS_COBALT_RAQ
 
 config LEDS_SUNFIRE
        tristate "LED support for SunFire servers."
+       depends on LEDS_CLASS
        depends on SPARC64
        select LEDS_TRIGGERS
        help
@@ -125,6 +137,7 @@ config LEDS_SUNFIRE
 
 config LEDS_HP6XX
        tristate "LED Support for the HP Jornada 6xx"
+       depends on LEDS_CLASS
        depends on SH_HP6XX
        help
          This option enables LED support for the handheld
@@ -132,6 +145,7 @@ config LEDS_HP6XX
 
 config LEDS_PCA9532
        tristate "LED driver for PCA9532 dimmer"
+       depends on LEDS_CLASS
        depends on I2C && INPUT && EXPERIMENTAL
        help
          This option enables support for NXP pca9532
@@ -140,6 +154,7 @@ config LEDS_PCA9532
 
 config LEDS_GPIO
        tristate "LED Support for GPIO connected LEDs"
+       depends on LEDS_CLASS
        depends on GENERIC_GPIO
        help
          This option enables support for the LEDs connected to GPIO
@@ -167,6 +182,7 @@ config LEDS_GPIO_OF
 
 config LEDS_LP3944
        tristate "LED Support for N.S. LP3944 (Fun Light) I2C chip"
+       depends on LEDS_CLASS
        depends on I2C
        help
          This option enables support for LEDs connected to the National
@@ -196,6 +212,7 @@ config LEDS_LP5523
 
 config LEDS_CLEVO_MAIL
        tristate "Mail LED on Clevo notebook"
+       depends on LEDS_CLASS
        depends on X86 && SERIO_I8042 && DMI
        help
          This driver makes the mail LED accessible from userspace
@@ -226,6 +243,7 @@ config LEDS_CLEVO_MAIL
 
 config LEDS_PCA955X
        tristate "LED Support for PCA955x I2C chips"
+       depends on LEDS_CLASS
        depends on I2C
        help
          This option enables support for LEDs connected to PCA955x
@@ -234,6 +252,7 @@ config LEDS_PCA955X
 
 config LEDS_WM831X_STATUS
        tristate "LED support for status LEDs on WM831x PMICs"
+       depends on LEDS_CLASS
        depends on MFD_WM831X
        help
          This option enables support for the status LEDs of the WM831x
@@ -241,6 +260,7 @@ config LEDS_WM831X_STATUS
 
 config LEDS_WM8350
        tristate "LED Support for WM8350 AudioPlus PMIC"
+       depends on LEDS_CLASS
        depends on MFD_WM8350
        help
          This option enables support for LEDs driven by the Wolfson
@@ -248,6 +268,7 @@ config LEDS_WM8350
 
 config LEDS_DA903X
        tristate "LED Support for DA9030/DA9034 PMIC"
+       depends on LEDS_CLASS
        depends on PMIC_DA903X
        help
          This option enables support for on-chip LED drivers found
@@ -255,6 +276,7 @@ config LEDS_DA903X
 
 config LEDS_DAC124S085
        tristate "LED Support for DAC124S085 SPI DAC"
+       depends on LEDS_CLASS
        depends on SPI
        help
          This option enables support for DAC124S085 SPI DAC from NatSemi,
@@ -262,18 +284,21 @@ config LEDS_DAC124S085
 
 config LEDS_PWM
        tristate "PWM driven LED Support"
+       depends on LEDS_CLASS
        depends on HAVE_PWM
        help
          This option enables support for pwm driven LEDs
 
 config LEDS_REGULATOR
        tristate "REGULATOR driven LED support"
+       depends on LEDS_CLASS
        depends on REGULATOR
        help
          This option enables support for regulator driven LEDs.
 
 config LEDS_BD2802
        tristate "LED driver for BD2802 RGB LED"
+       depends on LEDS_CLASS
        depends on I2C
        help
          This option enables support for BD2802GU RGB LED driver chips
@@ -281,6 +306,7 @@ config LEDS_BD2802
 
 config LEDS_INTEL_SS4200
        tristate "LED driver for Intel NAS SS4200 series"
+       depends on LEDS_CLASS
        depends on PCI && DMI
        help
          This option enables support for the Intel SS4200 series of
@@ -290,6 +316,7 @@ config LEDS_INTEL_SS4200
 
 config LEDS_LT3593
        tristate "LED driver for LT3593 controllers"
+       depends on LEDS_CLASS
        depends on GENERIC_GPIO
        help
          This option enables support for LEDs driven by a Linear Technology
@@ -298,6 +325,7 @@ config LEDS_LT3593
 
 config LEDS_ADP5520
        tristate "LED Support for ADP5520/ADP5501 PMIC"
+       depends on LEDS_CLASS
        depends on PMIC_ADP5520
        help
          This option enables support for on-chip LED drivers found
@@ -308,6 +336,7 @@ config LEDS_ADP5520
 
 config LEDS_DELL_NETBOOKS
        tristate "External LED on Dell Business Netbooks"
+       depends on LEDS_CLASS
        depends on X86 && ACPI_WMI
        help
          This adds support for the Latitude 2100 and similar
@@ -315,6 +344,7 @@ config LEDS_DELL_NETBOOKS
 
 config LEDS_MC13783
        tristate "LED Support for MC13783 PMIC"
+       depends on LEDS_CLASS
        depends on MFD_MC13783
        help
          This option enable support for on-chip LED drivers found
@@ -322,6 +352,7 @@ config LEDS_MC13783
 
 config LEDS_NS2
        tristate "LED support for Network Space v2 GPIO LEDs"
+       depends on LEDS_CLASS
        depends on MACH_NETSPACE_V2 || MACH_INETSPACE_V2 || MACH_NETSPACE_MAX_V2 || D2NET_V2
        default y
        help
@@ -340,17 +371,17 @@ config LEDS_NETXBIG
 
 config LEDS_TRIGGERS
        bool "LED Trigger support"
+       depends on LEDS_CLASS
        help
          This option enables trigger support for the leds class.
          These triggers allow kernel events to drive the LEDs and can
          be configured via sysfs. If unsure, say Y.
 
-if LEDS_TRIGGERS
-
 comment "LED Triggers"
 
 config LEDS_TRIGGER_TIMER
        tristate "LED Timer Trigger"
+       depends on LEDS_TRIGGERS
        help
          This allows LEDs to be controlled by a programmable timer
          via sysfs. Some LED hardware can be programmed to start
@@ -362,12 +393,14 @@ config LEDS_TRIGGER_TIMER
 config LEDS_TRIGGER_IDE_DISK
        bool "LED IDE Disk Trigger"
        depends on IDE_GD_ATA
+       depends on LEDS_TRIGGERS
        help
          This allows LEDs to be controlled by IDE disk activity.
          If unsure, say Y.
 
 config LEDS_TRIGGER_HEARTBEAT
        tristate "LED Heartbeat Trigger"
+       depends on LEDS_TRIGGERS
        help
          This allows LEDs to be controlled by a CPU load average.
          The flash frequency is a hyperbolic function of the 1-minute
@@ -376,6 +409,7 @@ config LEDS_TRIGGER_HEARTBEAT
 
 config LEDS_TRIGGER_BACKLIGHT
        tristate "LED backlight Trigger"
+       depends on LEDS_TRIGGERS
        help
          This allows LEDs to be controlled as a backlight device: they
          turn off and on when the display is blanked and unblanked.
@@ -384,6 +418,7 @@ config LEDS_TRIGGER_BACKLIGHT
 
 config LEDS_TRIGGER_GPIO
        tristate "LED GPIO Trigger"
+       depends on LEDS_TRIGGERS
        depends on GPIOLIB
        help
          This allows LEDs to be controlled by gpio events. It's good
@@ -396,6 +431,7 @@ config LEDS_TRIGGER_GPIO
 
 config LEDS_TRIGGER_DEFAULT_ON
        tristate "LED Default ON Trigger"
+       depends on LEDS_TRIGGERS
        help
          This allows LEDs to be initialised in the ON state.
          If unsure, say Y.
@@ -403,8 +439,4 @@ config LEDS_TRIGGER_DEFAULT_ON
 comment "iptables trigger is under Netfilter config (LED target)"
        depends on LEDS_TRIGGERS
 
-endif # LEDS_TRIGGERS
-
-endif # LEDS_CLASS
-
 endif # NEW_LEDS
index 3782f31f06d20b413463e5f198c77bc9f4434bde..33facd0c45d10c146867cbf2e74c050a360166b5 100644 (file)
@@ -125,11 +125,22 @@ struct lp5521_chip {
        u8                      num_leds;
 };
 
-#define cdev_to_led(c)         container_of(c, struct lp5521_led, cdev)
-#define engine_to_lp5521(eng)  container_of((eng), struct lp5521_chip, \
-                                               engines[(eng)->id - 1])
-#define led_to_lp5521(led)     container_of((led), struct lp5521_chip, \
-                                               leds[(led)->id])
+static inline struct lp5521_led *cdev_to_led(struct led_classdev *cdev)
+{
+       return container_of(cdev, struct lp5521_led, cdev);
+}
+
+static inline struct lp5521_chip *engine_to_lp5521(struct lp5521_engine *engine)
+{
+       return container_of(engine, struct lp5521_chip,
+                           engines[engine->id - 1]);
+}
+
+static inline struct lp5521_chip *led_to_lp5521(struct lp5521_led *led)
+{
+       return container_of(led, struct lp5521_chip,
+                           leds[led->id]);
+}
 
 static void lp5521_led_brightness_work(struct work_struct *work);
 
@@ -185,14 +196,17 @@ static int lp5521_load_program(struct lp5521_engine *eng, const u8 *pattern)
 
        /* move current engine to direct mode and remember the state */
        ret = lp5521_set_engine_mode(eng, LP5521_CMD_DIRECT);
-       usleep_range(1000, 10000);
+       /* Mode change requires min 500 us delay. 1 - 2 ms  with margin */
+       usleep_range(1000, 2000);
        ret |= lp5521_read(client, LP5521_REG_OP_MODE, &mode);
 
        /* For loading, all the engines to load mode */
        lp5521_write(client, LP5521_REG_OP_MODE, LP5521_CMD_DIRECT);
-       usleep_range(1000, 10000);
+       /* Mode change requires min 500 us delay. 1 - 2 ms  with margin */
+       usleep_range(1000, 2000);
        lp5521_write(client, LP5521_REG_OP_MODE, LP5521_CMD_LOAD);
-       usleep_range(1000, 10000);
+       /* Mode change requires min 500 us delay. 1 - 2 ms  with margin */
+       usleep_range(1000, 2000);
 
        addr = LP5521_PROG_MEM_BASE + eng->prog_page * LP5521_PROG_MEM_SIZE;
        i2c_smbus_write_i2c_block_data(client,
@@ -231,10 +245,6 @@ static int lp5521_configure(struct i2c_client *client,
 
        lp5521_init_engine(chip, attr_group);
 
-       lp5521_write(client, LP5521_REG_RESET, 0xff);
-
-       usleep_range(10000, 20000);
-
        /* Set all PWMs to direct control mode */
        ret = lp5521_write(client, LP5521_REG_OP_MODE, 0x3F);
 
@@ -251,8 +261,8 @@ static int lp5521_configure(struct i2c_client *client,
        ret |= lp5521_write(client, LP5521_REG_ENABLE,
                        LP5521_MASTER_ENABLE | LP5521_LOGARITHMIC_PWM |
                        LP5521_EXEC_RUN);
-       /* enable takes 500us */
-       usleep_range(500, 20000);
+       /* enable takes 500us. 1 - 2 ms leaves some margin */
+       usleep_range(1000, 2000);
 
        return ret;
 }
@@ -305,7 +315,8 @@ static int lp5521_detect(struct i2c_client *client)
                        LP5521_MASTER_ENABLE | LP5521_LOGARITHMIC_PWM);
        if (ret)
                return ret;
-       usleep_range(1000, 10000);
+       /* enable takes 500us. 1 - 2 ms leaves some margin */
+       usleep_range(1000, 2000);
        ret = lp5521_read(client, LP5521_REG_ENABLE, &buf);
        if (ret)
                return ret;
@@ -693,11 +704,16 @@ static int lp5521_probe(struct i2c_client *client,
 
        if (pdata->enable) {
                pdata->enable(0);
-               usleep_range(1000, 10000);
+               usleep_range(1000, 2000); /* Keep enable down at least 1ms */
                pdata->enable(1);
-               usleep_range(1000, 10000); /* Spec says min 500us */
+               usleep_range(1000, 2000); /* 500us abs min. */
        }
 
+       lp5521_write(client, LP5521_REG_RESET, 0xff);
+       usleep_range(10000, 20000); /*
+                                    * Exact value is not available. 10 - 20ms
+                                    * appears to be enough for reset.
+                                    */
        ret = lp5521_detect(client);
 
        if (ret) {
index 1e11fcc08b285b9c7d61590621616bba6ad78411..0cc4ead2fd8b35cdeef653a211b40a2e885b1630 100644 (file)
@@ -134,15 +134,18 @@ struct lp5523_chip {
        u8                      num_leds;
 };
 
-#define cdev_to_led(c)          container_of(c, struct lp5523_led, cdev)
+static inline struct lp5523_led *cdev_to_led(struct led_classdev *cdev)
+{
+       return container_of(cdev, struct lp5523_led, cdev);
+}
 
-static struct lp5523_chip *engine_to_lp5523(struct lp5523_engine *engine)
+static inline struct lp5523_chip *engine_to_lp5523(struct lp5523_engine *engine)
 {
        return container_of(engine, struct lp5523_chip,
                            engines[engine->id - 1]);
 }
 
-static struct lp5523_chip *led_to_lp5523(struct lp5523_led *led)
+static inline struct lp5523_chip *led_to_lp5523(struct lp5523_led *led)
 {
        return container_of(led, struct lp5523_chip,
                            leds[led->id]);
@@ -200,13 +203,9 @@ static int lp5523_configure(struct i2c_client *client)
                { 0x9c, 0x50, 0x9c, 0xd0, 0x9d, 0x80, 0xd8, 0x00, 0},
        };
 
-       lp5523_write(client, LP5523_REG_RESET, 0xff);
-
-       usleep_range(10000, 100000);
-
        ret |= lp5523_write(client, LP5523_REG_ENABLE, LP5523_ENABLE);
-       /* Chip startup time after reset is 500 us */
-       usleep_range(1000, 10000);
+       /* Chip startup time is 500 us, 1 - 2 ms gives some margin */
+       usleep_range(1000, 2000);
 
        ret |= lp5523_write(client, LP5523_REG_CONFIG,
                            LP5523_AUTO_INC | LP5523_PWR_SAVE |
@@ -243,8 +242,8 @@ static int lp5523_configure(struct i2c_client *client)
                return -1;
        }
 
-       /* Wait 3ms and check the engine status */
-       usleep_range(3000, 20000);
+       /* Let the programs run for couple of ms and check the engine status */
+       usleep_range(3000, 6000);
        lp5523_read(client, LP5523_REG_STATUS, &status);
        status &= LP5523_ENG_STATUS_MASK;
 
@@ -449,10 +448,10 @@ static ssize_t lp5523_selftest(struct device *dev,
        /* Measure VDD (i.e. VBAT) first (channel 16 corresponds to VDD) */
        lp5523_write(chip->client, LP5523_REG_LED_TEST_CTRL,
                                    LP5523_EN_LEDTEST | 16);
-       usleep_range(3000, 10000);
+       usleep_range(3000, 6000); /* ADC conversion time is typically 2.7 ms */
        ret = lp5523_read(chip->client, LP5523_REG_STATUS, &status);
        if (!(status & LP5523_LEDTEST_DONE))
-               usleep_range(3000, 10000);
+               usleep_range(3000, 6000); /* Was not ready. Wait little bit */
 
        ret |= lp5523_read(chip->client, LP5523_REG_LED_TEST_ADC, &vdd);
        vdd--;  /* There may be some fluctuation in measurement */
@@ -468,16 +467,16 @@ static ssize_t lp5523_selftest(struct device *dev,
                        chip->pdata->led_config[i].led_current);
 
                lp5523_write(chip->client, LP5523_REG_LED_PWM_BASE + i, 0xff);
-               /* let current stabilize 2ms before measurements start */
-               usleep_range(2000, 10000);
+               /* let current stabilize 2 - 4ms before measurements start */
+               usleep_range(2000, 4000);
                lp5523_write(chip->client,
                             LP5523_REG_LED_TEST_CTRL,
                             LP5523_EN_LEDTEST | i);
-               /* ledtest takes 2.7ms */
-               usleep_range(3000, 10000);
+               /* ADC conversion time is 2.7 ms typically */
+               usleep_range(3000, 6000);
                ret = lp5523_read(chip->client, LP5523_REG_STATUS, &status);
                if (!(status & LP5523_LEDTEST_DONE))
-                       usleep_range(3000, 10000);
+                       usleep_range(3000, 6000);/* Was not ready. Wait. */
                ret |= lp5523_read(chip->client, LP5523_REG_LED_TEST_ADC, &adc);
 
                if (adc >= vdd || adc < LP5523_ADC_SHORTCIRC_LIM)
@@ -930,11 +929,16 @@ static int lp5523_probe(struct i2c_client *client,
 
        if (pdata->enable) {
                pdata->enable(0);
-               usleep_range(1000, 10000);
+               usleep_range(1000, 2000); /* Keep enable down at least 1ms */
                pdata->enable(1);
-               usleep_range(1000, 10000); /* Spec says min 500us */
+               usleep_range(1000, 2000); /* 500us abs min. */
        }
 
+       lp5523_write(client, LP5523_REG_RESET, 0xff);
+       usleep_range(10000, 20000); /*
+                                    * Exact value is not available. 10 - 20ms
+                                    * appears to be enough for reset.
+                                    */
        ret = lp5523_detect(client);
        if (ret)
                goto fail2;
index a688293abd0b43a0f9e8135d0ce4d43812307f0a..614ebebaaa28cdcf7d7c765b1c0c959fd7ac4782 100644 (file)
@@ -102,6 +102,7 @@ static struct dmi_system_id __initdata nas_led_whitelist[] = {
                        DMI_MATCH(DMI_PRODUCT_VERSION, "1.00.00")
                }
        },
+       {}
 };
 
 /*
index 3d7355ff7308eac1e578092149027bc54809ee84..fa51af11c6f1e9d927967753b86530ea45a2b600 100644 (file)
@@ -102,6 +102,7 @@ config ADB_PMU_LED
 config ADB_PMU_LED_IDE
        bool "Use front LED as IDE LED by default"
        depends on ADB_PMU_LED
+       depends on LEDS_CLASS
        select LEDS_TRIGGERS
        select LEDS_TRIGGER_IDE_DISK
        help
index 90267f8d64eeadf5d9e72afae174f6d4b22e6bf5..4d705cea0f8c74c4010e7fe6fbf8d77288f49c36 100644 (file)
@@ -517,9 +517,8 @@ int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev,
         */
 
        if (q->merge_bvec_fn && !ti->type->merge)
-               limits->max_sectors =
-                       min_not_zero(limits->max_sectors,
-                                    (unsigned int) (PAGE_SIZE >> 9));
+               blk_limits_max_hw_sectors(limits,
+                                         (unsigned int) (PAGE_SIZE >> 9));
        return 0;
 }
 EXPORT_SYMBOL_GPL(dm_set_device_limits);
@@ -1131,11 +1130,6 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
         */
        q->limits = *limits;
 
-       if (limits->no_cluster)
-               queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q);
-       else
-               queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q);
-
        if (!dm_table_supports_discards(t))
                queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q);
        else
index 324a3663fcdaa35dc9d0553f532543aa8019dd38..175c424f201f33caa0c50525a41b7f8fc3569387 100644 (file)
@@ -371,10 +371,15 @@ static void md_end_flush(struct bio *bio, int err)
        bio_put(bio);
 }
 
-static void submit_flushes(mddev_t *mddev)
+static void md_submit_flush_data(struct work_struct *ws);
+
+static void submit_flushes(struct work_struct *ws)
 {
+       mddev_t *mddev = container_of(ws, mddev_t, flush_work);
        mdk_rdev_t *rdev;
 
+       INIT_WORK(&mddev->flush_work, md_submit_flush_data);
+       atomic_set(&mddev->flush_pending, 1);
        rcu_read_lock();
        list_for_each_entry_rcu(rdev, &mddev->disks, same_set)
                if (rdev->raid_disk >= 0 &&
@@ -397,6 +402,8 @@ static void submit_flushes(mddev_t *mddev)
                        rdev_dec_pending(rdev, mddev);
                }
        rcu_read_unlock();
+       if (atomic_dec_and_test(&mddev->flush_pending))
+               queue_work(md_wq, &mddev->flush_work);
 }
 
 static void md_submit_flush_data(struct work_struct *ws)
@@ -404,8 +411,6 @@ static void md_submit_flush_data(struct work_struct *ws)
        mddev_t *mddev = container_of(ws, mddev_t, flush_work);
        struct bio *bio = mddev->flush_bio;
 
-       atomic_set(&mddev->flush_pending, 1);
-
        if (bio->bi_size == 0)
                /* an empty barrier - all done */
                bio_endio(bio, 0);
@@ -414,10 +419,9 @@ static void md_submit_flush_data(struct work_struct *ws)
                if (mddev->pers->make_request(mddev, bio))
                        generic_make_request(bio);
        }
-       if (atomic_dec_and_test(&mddev->flush_pending)) {
-               mddev->flush_bio = NULL;
-               wake_up(&mddev->sb_wait);
-       }
+
+       mddev->flush_bio = NULL;
+       wake_up(&mddev->sb_wait);
 }
 
 void md_flush_request(mddev_t *mddev, struct bio *bio)
@@ -429,13 +433,8 @@ void md_flush_request(mddev_t *mddev, struct bio *bio)
        mddev->flush_bio = bio;
        spin_unlock_irq(&mddev->write_lock);
 
-       atomic_set(&mddev->flush_pending, 1);
-       INIT_WORK(&mddev->flush_work, md_submit_flush_data);
-
-       submit_flushes(mddev);
-
-       if (atomic_dec_and_test(&mddev->flush_pending))
-               queue_work(md_wq, &mddev->flush_work);
+       INIT_WORK(&mddev->flush_work, submit_flushes);
+       queue_work(md_wq, &mddev->flush_work);
 }
 EXPORT_SYMBOL(md_flush_request);
 
@@ -1337,7 +1336,7 @@ super_90_rdev_size_change(mdk_rdev_t *rdev, sector_t num_sectors)
        md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size,
                       rdev->sb_page);
        md_super_wait(rdev->mddev);
-       return num_sectors / 2; /* kB for sysfs */
+       return num_sectors;
 }
 
 
@@ -1704,7 +1703,7 @@ super_1_rdev_size_change(mdk_rdev_t *rdev, sector_t num_sectors)
        md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size,
                       rdev->sb_page);
        md_super_wait(rdev->mddev);
-       return num_sectors / 2; /* kB for sysfs */
+       return num_sectors;
 }
 
 static struct super_type super_types[] = {
@@ -4296,9 +4295,6 @@ static int md_alloc(dev_t dev, char *name)
                goto abort;
        mddev->queue->queuedata = mddev;
 
-       /* Can be unlocked because the queue is new: no concurrency */
-       queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, mddev->queue);
-
        blk_queue_make_request(mddev->queue, md_make_request);
 
        disk = alloc_disk(1 << shift);
@@ -4338,6 +4334,8 @@ static int md_alloc(dev_t dev, char *name)
        if (mddev->kobj.sd &&
            sysfs_create_group(&mddev->kobj, &md_bitmap_group))
                printk(KERN_DEBUG "pointless warning\n");
+
+       blk_queue_flush(mddev->queue, REQ_FLUSH | REQ_FUA);
  abort:
        mutex_unlock(&disks_mutex);
        if (!error && mddev->kobj.sd) {
@@ -5158,7 +5156,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
                                PTR_ERR(rdev));
                        return PTR_ERR(rdev);
                }
-               /* set save_raid_disk if appropriate */
+               /* set saved_raid_disk if appropriate */
                if (!mddev->persistent) {
                        if (info->state & (1<<MD_DISK_SYNC)  &&
                            info->raid_disk < mddev->raid_disks)
@@ -5168,7 +5166,10 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
                } else
                        super_types[mddev->major_version].
                                validate_super(mddev, rdev);
-               rdev->saved_raid_disk = rdev->raid_disk;
+               if (test_bit(In_sync, &rdev->flags))
+                       rdev->saved_raid_disk = rdev->raid_disk;
+               else
+                       rdev->saved_raid_disk = -1;
 
                clear_bit(In_sync, &rdev->flags); /* just to be sure */
                if (info->state & (1<<MD_DISK_WRITEMOSTLY))
@@ -6040,9 +6041,8 @@ static int md_thread(void * arg)
                         || kthread_should_stop(),
                         thread->timeout);
 
-               clear_bit(THREAD_WAKEUP, &thread->flags);
-
-               thread->run(thread->mddev);
+               if (test_and_clear_bit(THREAD_WAKEUP, &thread->flags))
+                       thread->run(thread->mddev);
        }
 
        return 0;
index 45f8324196ec61c86cd7164868e3f8bc66ada03c..845cf95b612c452b799033f6b4f4a2903715b623 100644 (file)
@@ -1161,6 +1161,7 @@ static int raid1_remove_disk(mddev_t *mddev, int number)
                 * is not possible.
                 */
                if (!test_bit(Faulty, &rdev->flags) &&
+                   !mddev->recovery_disabled &&
                    mddev->degraded < conf->raid_disks) {
                        err = -EBUSY;
                        goto abort;
index c67aa54694ae72605b2165949fe1033dc2d542b9..0641674827f06786dee5549ada83b23820928748 100644 (file)
@@ -2397,13 +2397,13 @@ static int run(mddev_t *mddev)
        return 0;
 
 out_free_conf:
+       md_unregister_thread(mddev->thread);
        if (conf->r10bio_pool)
                mempool_destroy(conf->r10bio_pool);
        safe_put_page(conf->tmppage);
        kfree(conf->mirrors);
        kfree(conf);
        mddev->private = NULL;
-       md_unregister_thread(mddev->thread);
 out:
        return -EIO;
 }
index 05bde9ccb770b377eb327409a707ef38b5e25a17..1d1d8d200755a2c9af0ca241b983dd55f1a672a4 100644 (file)
@@ -558,7 +558,7 @@ static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, e
 static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field, u32 pixelformat)
 {
        struct saa7146_vv *vv = dev->vv_data;
-       struct saa7146_format *sfmt = format_by_fourcc(dev, pixelformat);
+       struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pixelformat);
 
        int b_depth = vv->ov_fmt->depth;
        int b_bpl = vv->ov_fb.fmt.bytesperline;
@@ -702,7 +702,7 @@ static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa71
        struct saa7146_vv *vv = dev->vv_data;
        struct saa7146_video_dma vdma1;
 
-       struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+       struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
 
        int width = buf->fmt->width;
        int height = buf->fmt->height;
@@ -827,7 +827,7 @@ static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa71
        struct saa7146_video_dma vdma2;
        struct saa7146_video_dma vdma3;
 
-       struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+       struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
 
        int width = buf->fmt->width;
        int height = buf->fmt->height;
@@ -994,7 +994,7 @@ static void program_capture_engine(struct saa7146_dev *dev, int planar)
 
 void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next)
 {
-       struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+       struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
        struct saa7146_vv *vv = dev->vv_data;
        u32 vdma1_prot_addr;
 
index 741c5732b430613ff816da949ba3116a4f23c1c9..d246910129e80c74065eeae233da090396614f45 100644 (file)
@@ -84,7 +84,7 @@ static struct saa7146_format formats[] = {
 
 static int NUM_FORMATS = sizeof(formats)/sizeof(struct saa7146_format);
 
-struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc)
+struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fourcc)
 {
        int i, j = NUM_FORMATS;
 
@@ -266,7 +266,7 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
        struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
        struct scatterlist *list = dma->sglist;
        int length = dma->sglen;
-       struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+       struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
 
        DEB_EE(("dev:%p, buf:%p, sg_len:%d\n",dev,buf,length));
 
@@ -408,7 +408,7 @@ static int video_begin(struct saa7146_fh *fh)
                }
        }
 
-       fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
+       fmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat);
        /* we need to have a valid format set here */
        BUG_ON(NULL == fmt);
 
@@ -460,7 +460,7 @@ static int video_end(struct saa7146_fh *fh, struct file *file)
                return -EBUSY;
        }
 
-       fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
+       fmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat);
        /* we need to have a valid format set here */
        BUG_ON(NULL == fmt);
 
@@ -536,7 +536,7 @@ static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *f
                return -EPERM;
 
        /* check args */
-       fmt = format_by_fourcc(dev, fb->fmt.pixelformat);
+       fmt = saa7146_format_by_fourcc(dev, fb->fmt.pixelformat);
        if (NULL == fmt)
                return -EINVAL;
 
@@ -760,7 +760,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_forma
 
        DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh));
 
-       fmt = format_by_fourcc(dev, f->fmt.pix.pixelformat);
+       fmt = saa7146_format_by_fourcc(dev, f->fmt.pix.pixelformat);
        if (NULL == fmt)
                return -EINVAL;
 
@@ -1264,7 +1264,7 @@ static int buffer_prepare(struct videobuf_queue *q,
                buf->fmt       = &fh->video_fmt;
                buf->vb.field  = fh->video_fmt.field;
 
-               sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+               sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
 
                release_all_pagetables(dev, buf);
                if( 0 != IS_PLANAR(sfmt->trans)) {
@@ -1378,7 +1378,7 @@ static int video_open(struct saa7146_dev *dev, struct file *file)
        fh->video_fmt.pixelformat = V4L2_PIX_FMT_BGR24;
        fh->video_fmt.bytesperline = 0;
        fh->video_fmt.field = V4L2_FIELD_ANY;
-       sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
+       sfmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat);
        fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8;
 
        videobuf_queue_sg_init(&fh->video_q, &video_qops,
index 2385e6cca63589f6ffff1445a4d2a564ef743207..78b089526e028745a30f32bccc90cd384ba632b3 100644 (file)
@@ -31,7 +31,7 @@ config MEDIA_TUNER
        select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMISE
        select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE
 
-menuconfig MEDIA_TUNER_CUSTOMISE
+config MEDIA_TUNER_CUSTOMISE
        bool "Customize analog and hybrid tuner modules to build"
        depends on MEDIA_TUNER
        default y if EMBEDDED
@@ -44,7 +44,8 @@ menuconfig MEDIA_TUNER_CUSTOMISE
 
          If unsure say N.
 
-if MEDIA_TUNER_CUSTOMISE
+menu "Customize TV tuners"
+       visible if MEDIA_TUNER_CUSTOMISE
 
 config MEDIA_TUNER_SIMPLE
        tristate "Simple tuner support"
@@ -185,5 +186,4 @@ config MEDIA_TUNER_TDA18218
        default m if MEDIA_TUNER_CUSTOMISE
        help
          NXP TDA18218 silicon tuner driver.
-
-endif # MEDIA_TUNER_CUSTOMISE
+endmenu
index e9062b08a4857e39896ca14adeebdbd300907d18..96b27016670e3c7f18091e167057172767271feb 100644 (file)
@@ -12,9 +12,8 @@ config DVB_FE_CUSTOMISE
 
          If unsure say N.
 
-if DVB_FE_CUSTOMISE
-
 menu "Customise DVB Frontends"
+       visible if DVB_FE_CUSTOMISE
 
 comment "Multistandard (satellite) frontends"
        depends on DVB_CORE
@@ -619,5 +618,3 @@ config DVB_DUMMY_FE
        tristate "Dummy frontend driver"
        default n
 endmenu
-
-endif
index 5bf4985daede6a49e9b35adcb3b3256b51a14924..05e832f61c3e88772e1ae8b3b1059a0825a5b86c 100644 (file)
@@ -361,7 +361,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations rtrack_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops rtrack_ioctl_ops = {
@@ -412,13 +412,6 @@ static int __init rtrack_init(void)
        rt->vdev.release = video_device_release_empty;
        video_set_drvdata(&rt->vdev, rt);
 
-       if (video_register_device(&rt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
-               v4l2_device_unregister(&rt->v4l2_dev);
-               release_region(rt->io, 2);
-               return -EINVAL;
-       }
-       v4l2_info(v4l2_dev, "AIMSlab RadioTrack/RadioReveal card driver.\n");
-
        /* Set up the I/O locking */
 
        mutex_init(&rt->lock);
@@ -430,6 +423,13 @@ static int __init rtrack_init(void)
        sleep_delay(2000000);   /* make sure it's totally down  */
        outb(0xc0, rt->io);             /* steady volume, mute card     */
 
+       if (video_register_device(&rt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+               v4l2_device_unregister(&rt->v4l2_dev);
+               release_region(rt->io, 2);
+               return -EINVAL;
+       }
+       v4l2_info(v4l2_dev, "AIMSlab RadioTrack/RadioReveal card driver.\n");
+
        return 0;
 }
 
index c22311393624d26ebfbe0d4db8776a7c536b3a70..dd8a6ab0d437ab10022d1b65f1d802cc8d2b006c 100644 (file)
@@ -324,7 +324,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
 
 static const struct v4l2_file_operations aztech_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops aztech_ioctl_ops = {
@@ -375,6 +375,8 @@ static int __init aztech_init(void)
        az->vdev.ioctl_ops = &aztech_ioctl_ops;
        az->vdev.release = video_device_release_empty;
        video_set_drvdata(&az->vdev, az);
+       /* mute card - prevents noisy bootups */
+       outb(0, az->io);
 
        if (video_register_device(&az->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
                v4l2_device_unregister(v4l2_dev);
@@ -383,8 +385,6 @@ static int __init aztech_init(void)
        }
 
        v4l2_info(v4l2_dev, "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n");
-       /* mute card - prevents noisy bootups */
-       outb(0, az->io);
        return 0;
 }
 
index b701ea6e7c7379fc0593fae6c22c4678152cd4e7..bc9ad0897c559b9142aea9ba7cbf486caaf1d5c4 100644 (file)
@@ -328,11 +328,10 @@ static ssize_t cadet_read(struct file *file, char __user *data, size_t count, lo
        unsigned char readbuf[RDS_BUFFER];
        int i = 0;
 
+       mutex_lock(&dev->lock);
        if (dev->rdsstat == 0) {
-               mutex_lock(&dev->lock);
                dev->rdsstat = 1;
                outb(0x80, dev->io);        /* Select RDS fifo */
-               mutex_unlock(&dev->lock);
                init_timer(&dev->readtimer);
                dev->readtimer.function = cadet_handler;
                dev->readtimer.data = (unsigned long)dev;
@@ -340,12 +339,15 @@ static ssize_t cadet_read(struct file *file, char __user *data, size_t count, lo
                add_timer(&dev->readtimer);
        }
        if (dev->rdsin == dev->rdsout) {
+               mutex_unlock(&dev->lock);
                if (file->f_flags & O_NONBLOCK)
                        return -EWOULDBLOCK;
                interruptible_sleep_on(&dev->read_queue);
+               mutex_lock(&dev->lock);
        }
        while (i < count && dev->rdsin != dev->rdsout)
                readbuf[i++] = dev->rdsbuf[dev->rdsout++];
+       mutex_unlock(&dev->lock);
 
        if (copy_to_user(data, readbuf, i))
                return -EFAULT;
@@ -525,9 +527,11 @@ static int cadet_open(struct file *file)
 {
        struct cadet *dev = video_drvdata(file);
 
+       mutex_lock(&dev->lock);
        dev->users++;
        if (1 == dev->users)
                init_waitqueue_head(&dev->read_queue);
+       mutex_unlock(&dev->lock);
        return 0;
 }
 
@@ -535,11 +539,13 @@ static int cadet_release(struct file *file)
 {
        struct cadet *dev = video_drvdata(file);
 
+       mutex_lock(&dev->lock);
        dev->users--;
        if (0 == dev->users) {
                del_timer_sync(&dev->readtimer);
                dev->rdsstat = 0;
        }
+       mutex_unlock(&dev->lock);
        return 0;
 }
 
@@ -559,7 +565,7 @@ static const struct v4l2_file_operations cadet_fops = {
        .open           = cadet_open,
        .release        = cadet_release,
        .read           = cadet_read,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .poll           = cadet_poll,
 };
 
index 79039674a0e0bddff9976de584437a60b948e789..28fa85ba2087cfd56c067ac51a9669945eb44757 100644 (file)
@@ -361,7 +361,7 @@ MODULE_DEVICE_TABLE(pci, gemtek_pci_id);
 
 static const struct v4l2_file_operations gemtek_pci_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops gemtek_pci_ioctl_ops = {
@@ -422,11 +422,11 @@ static int __devinit gemtek_pci_probe(struct pci_dev *pdev, const struct pci_dev
        card->vdev.release = video_device_release_empty;
        video_set_drvdata(&card->vdev, card);
 
+       gemtek_pci_mute(card);
+
        if (video_register_device(&card->vdev, VFL_TYPE_RADIO, nr_radio) < 0)
                goto err_video;
 
-       gemtek_pci_mute(card);
-
        v4l2_info(v4l2_dev, "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n",
                pdev->revision, card->iobase, card->iobase + card->length - 1);
 
index 73985f641f072d361d128f769530281b150ffbfb..259936422e493b4dcf6dd6742d17bc5acd5b2995 100644 (file)
@@ -378,7 +378,7 @@ static int gemtek_probe(struct gemtek *gt)
 
 static const struct v4l2_file_operations gemtek_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static int vidioc_querycap(struct file *file, void *priv,
@@ -577,12 +577,6 @@ static int __init gemtek_init(void)
        gt->vdev.release = video_device_release_empty;
        video_set_drvdata(&gt->vdev, gt);
 
-       if (video_register_device(&gt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
-               v4l2_device_unregister(v4l2_dev);
-               release_region(gt->io, 1);
-               return -EBUSY;
-       }
-
        /* Set defaults */
        gt->lastfreq = GEMTEK_LOWFREQ;
        gt->bu2614data = 0;
@@ -590,6 +584,12 @@ static int __init gemtek_init(void)
        if (initmute)
                gemtek_mute(gt);
 
+       if (video_register_device(&gt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+               v4l2_device_unregister(v4l2_dev);
+               release_region(gt->io, 1);
+               return -EBUSY;
+       }
+
        return 0;
 }
 
index 08f1051979cae6f7508026dc0e957a23de775795..6af61bfeb1780089718f96884f6dc0dfc8550943 100644 (file)
@@ -299,7 +299,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations maestro_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops maestro_ioctl_ops = {
@@ -383,22 +383,20 @@ static int __devinit maestro_probe(struct pci_dev *pdev,
        dev->vdev.release = video_device_release_empty;
        video_set_drvdata(&dev->vdev, dev);
 
+       if (!radio_power_on(dev)) {
+               retval = -EIO;
+               goto errfr1;
+       }
+
        retval = video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr);
        if (retval) {
                v4l2_err(v4l2_dev, "can't register video device!\n");
                goto errfr1;
        }
 
-       if (!radio_power_on(dev)) {
-               retval = -EIO;
-               goto errunr;
-       }
-
        v4l2_info(v4l2_dev, "version " DRIVER_VERSION "\n");
 
        return 0;
-errunr:
-       video_unregister_device(&dev->vdev);
 errfr1:
        v4l2_device_unregister(v4l2_dev);
 errfr:
index 255d40df4b461e9e5287462c08901a78758a565f..6459a220b0dd46ddb22326e0595f8964ae4915d2 100644 (file)
@@ -346,7 +346,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
 
 static const struct v4l2_file_operations maxiradio_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = {
index 4ff885445fd455371823ad55a00f82e4c2afdcfe..3fb76e3834c99da96e8621ab4ecd89458913d259 100644 (file)
@@ -33,6 +33,7 @@ struct pcm20 {
        unsigned long freq;
        int muted;
        struct snd_miro_aci *aci;
+       struct mutex lock;
 };
 
 static struct pcm20 pcm20_card = {
@@ -72,7 +73,7 @@ static int pcm20_setfreq(struct pcm20 *dev, unsigned long freq)
 
 static const struct v4l2_file_operations pcm20_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static int vidioc_querycap(struct file *file, void *priv,
@@ -229,7 +230,7 @@ static int __init pcm20_init(void)
                return -ENODEV;
        }
        strlcpy(v4l2_dev->name, "miropcm20", sizeof(v4l2_dev->name));
-
+       mutex_init(&dev->lock);
 
        res = v4l2_device_register(NULL, v4l2_dev);
        if (res < 0) {
@@ -242,6 +243,7 @@ static int __init pcm20_init(void)
        dev->vdev.fops = &pcm20_fops;
        dev->vdev.ioctl_ops = &pcm20_ioctl_ops;
        dev->vdev.release = video_device_release_empty;
+       dev->vdev.lock = &dev->lock;
        video_set_drvdata(&dev->vdev, dev);
 
        if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0)
index a79296aac9a9636e408a27a7da9a42cf9c4e21e3..8d6ea591bd188815c374ddf5c5e603a5aa3d6e8e 100644 (file)
@@ -266,7 +266,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations rtrack2_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops rtrack2_ioctl_ops = {
@@ -315,6 +315,10 @@ static int __init rtrack2_init(void)
        dev->vdev.release = video_device_release_empty;
        video_set_drvdata(&dev->vdev, dev);
 
+       /* mute card - prevents noisy bootups */
+       outb(1, dev->io);
+       dev->muted = 1;
+
        mutex_init(&dev->lock);
        if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
                v4l2_device_unregister(v4l2_dev);
@@ -324,10 +328,6 @@ static int __init rtrack2_init(void)
 
        v4l2_info(v4l2_dev, "AIMSlab Radiotrack II card driver.\n");
 
-       /* mute card - prevents noisy bootups */
-       outb(1, dev->io);
-       dev->muted = 1;
-
        return 0;
 }
 
index 985359d18aa58fd8e350d0e06b05b66020534bc5..b5a5f89e238a91fe432326d0da9487cf32ad9943 100644 (file)
@@ -260,7 +260,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations fmi_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops fmi_ioctl_ops = {
@@ -382,6 +382,9 @@ static int __init fmi_init(void)
 
        mutex_init(&fmi->lock);
 
+       /* mute card - prevents noisy bootups */
+       fmi_mute(fmi);
+
        if (video_register_device(&fmi->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
                v4l2_device_unregister(v4l2_dev);
                release_region(fmi->io, 2);
@@ -391,8 +394,6 @@ static int __init fmi_init(void)
        }
 
        v4l2_info(v4l2_dev, "card driver at 0x%x\n", fmi->io);
-       /* mute card - prevents noisy bootups */
-       fmi_mute(fmi);
        return 0;
 }
 
index 52c7bbb32b8b7ea10312ff58716c47f1ed472bd2..dc3f04c52d5e11e923829e74a548d78d1b3e6cad 100644 (file)
@@ -376,7 +376,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations fmr2_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops fmr2_ioctl_ops = {
@@ -424,6 +424,10 @@ static int __init fmr2_init(void)
        fmr2->vdev.release = video_device_release_empty;
        video_set_drvdata(&fmr2->vdev, fmr2);
 
+       /* mute card - prevents noisy bootups */
+       fmr2_mute(fmr2->io);
+       fmr2_product_info(fmr2);
+
        if (video_register_device(&fmr2->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
                v4l2_device_unregister(v4l2_dev);
                release_region(fmr2->io, 2);
@@ -431,11 +435,6 @@ static int __init fmr2_init(void)
        }
 
        v4l2_info(v4l2_dev, "SF16FMR2 radio card driver at 0x%x.\n", fmr2->io);
-       /* mute card - prevents noisy bootups */
-       mutex_lock(&fmr2->lock);
-       fmr2_mute(fmr2->io);
-       fmr2_product_info(fmr2);
-       mutex_unlock(&fmr2->lock);
        debug_print((KERN_DEBUG "card_type %d\n", fmr2->card_type));
        return 0;
 }
index 6a435786b63d96ee099aedceee8dca026f9ca935..726d367ad8d0f2119b5e832d8ccca593d2a6d3fa 100644 (file)
@@ -53,7 +53,8 @@ struct radio_si4713_device {
 /* radio_si4713_fops - file operations interface */
 static const struct v4l2_file_operations radio_si4713_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       /* Note: locking is done at the subdev level in the i2c driver. */
+       .unlocked_ioctl = video_ioctl2,
 };
 
 /* Video4Linux Interface */
@@ -291,7 +292,7 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev)
                goto unregister_v4l2_dev;
        }
 
-       sd = v4l2_i2c_new_subdev_board(&rsdev->v4l2_dev, adapter, NULL,
+       sd = v4l2_i2c_new_subdev_board(&rsdev->v4l2_dev, adapter,
                                        pdata->subdev_board_info, NULL);
        if (!sd) {
                dev_err(&pdev->dev, "Cannot get v4l2 subdevice\n");
index 789d2ec66e1948d2d071c3424f92dc820b0bcc0b..0e71d816c725885535cc4d1da4f992809d0d6257 100644 (file)
@@ -142,7 +142,6 @@ struct tea5764_device {
        struct video_device             *videodev;
        struct tea5764_regs             regs;
        struct mutex                    mutex;
-       int                             users;
 };
 
 /* I2C code related */
@@ -458,41 +457,10 @@ static int vidioc_s_audio(struct file *file, void *priv,
        return 0;
 }
 
-static int tea5764_open(struct file *file)
-{
-       /* Currently we support only one device */
-       struct tea5764_device *radio = video_drvdata(file);
-
-       mutex_lock(&radio->mutex);
-       /* Only exclusive access */
-       if (radio->users) {
-               mutex_unlock(&radio->mutex);
-               return -EBUSY;
-       }
-       radio->users++;
-       mutex_unlock(&radio->mutex);
-       file->private_data = radio;
-       return 0;
-}
-
-static int tea5764_close(struct file *file)
-{
-       struct tea5764_device *radio = video_drvdata(file);
-
-       if (!radio)
-               return -ENODEV;
-       mutex_lock(&radio->mutex);
-       radio->users--;
-       mutex_unlock(&radio->mutex);
-       return 0;
-}
-
 /* File system interface */
 static const struct v4l2_file_operations tea5764_fops = {
        .owner          = THIS_MODULE,
-       .open           = tea5764_open,
-       .release        = tea5764_close,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops tea5764_ioctl_ops = {
@@ -527,7 +495,7 @@ static int __devinit tea5764_i2c_probe(struct i2c_client *client,
        int ret;
 
        PDEBUG("probe");
-       radio = kmalloc(sizeof(struct tea5764_device), GFP_KERNEL);
+       radio = kzalloc(sizeof(struct tea5764_device), GFP_KERNEL);
        if (!radio)
                return -ENOMEM;
 
@@ -555,12 +523,7 @@ static int __devinit tea5764_i2c_probe(struct i2c_client *client,
 
        i2c_set_clientdata(client, radio);
        video_set_drvdata(radio->videodev, radio);
-
-       ret = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr);
-       if (ret < 0) {
-               PWARN("Could not register video device!");
-               goto errrel;
-       }
+       radio->videodev->lock = &radio->mutex;
 
        /* initialize and power off the chip */
        tea5764_i2c_read(radio);
@@ -568,6 +531,12 @@ static int __devinit tea5764_i2c_probe(struct i2c_client *client,
        tea5764_mute(radio, 1);
        tea5764_power_down(radio);
 
+       ret = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr);
+       if (ret < 0) {
+               PWARN("Could not register video device!");
+               goto errrel;
+       }
+
        PINFO("registered.");
        return 0;
 errrel:
index fc1c860fd43844c188d4e42cc845a5f40b4ae957..a32663917059c1cd4734247452c33444c02ad5d2 100644 (file)
@@ -338,7 +338,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations terratec_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops terratec_ioctl_ops = {
@@ -389,6 +389,9 @@ static int __init terratec_init(void)
 
        mutex_init(&tt->lock);
 
+       /* mute card - prevents noisy bootups */
+       tt_write_vol(tt, 0);
+
        if (video_register_device(&tt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
                v4l2_device_unregister(&tt->v4l2_dev);
                release_region(tt->io, 2);
@@ -396,9 +399,6 @@ static int __init terratec_init(void)
        }
 
        v4l2_info(v4l2_dev, "TERRATEC ActivRadio Standalone card driver.\n");
-
-       /* mute card - prevents noisy bootups */
-       tt_write_vol(tt, 0);
        return 0;
 }
 
index b8bb3ef47df5c72153e7e1964ddbc679b3c1b8ed..a185610b376be1a14e79b52751c7f95aab777dd0 100644 (file)
@@ -34,6 +34,7 @@ struct timbradio {
        struct v4l2_subdev      *sd_dsp;
        struct video_device     video_dev;
        struct v4l2_device      v4l2_dev;
+       struct mutex            lock;
 };
 
 
@@ -142,7 +143,7 @@ static const struct v4l2_ioctl_ops timbradio_ioctl_ops = {
 
 static const struct v4l2_file_operations timbradio_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static int __devinit timbradio_probe(struct platform_device *pdev)
@@ -164,6 +165,7 @@ static int __devinit timbradio_probe(struct platform_device *pdev)
        }
 
        tr->pdata = *pdata;
+       mutex_init(&tr->lock);
 
        strlcpy(tr->video_dev.name, "Timberdale Radio",
                sizeof(tr->video_dev.name));
@@ -171,6 +173,7 @@ static int __devinit timbradio_probe(struct platform_device *pdev)
        tr->video_dev.ioctl_ops = &timbradio_ioctl_ops;
        tr->video_dev.release = video_device_release_empty;
        tr->video_dev.minor = -1;
+       tr->video_dev.lock = &tr->lock;
 
        strlcpy(tr->v4l2_dev.name, DRIVER_NAME, sizeof(tr->v4l2_dev.name));
        err = v4l2_device_register(NULL, &tr->v4l2_dev);
index 9d6dcf8af5b01de328436a0955ae190fe651aa72..22fa9cc28abed060cff57e1e3a78227575c9ee36 100644 (file)
@@ -344,7 +344,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations trust_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops trust_ioctl_ops = {
@@ -396,14 +396,6 @@ static int __init trust_init(void)
        tr->vdev.release = video_device_release_empty;
        video_set_drvdata(&tr->vdev, tr);
 
-       if (video_register_device(&tr->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
-               v4l2_device_unregister(v4l2_dev);
-               release_region(tr->io, 2);
-               return -EINVAL;
-       }
-
-       v4l2_info(v4l2_dev, "Trust FM Radio card driver v1.0.\n");
-
        write_i2c(tr, 2, TDA7318_ADDR, 0x80);   /* speaker att. LF = 0 dB */
        write_i2c(tr, 2, TDA7318_ADDR, 0xa0);   /* speaker att. RF = 0 dB */
        write_i2c(tr, 2, TDA7318_ADDR, 0xc0);   /* speaker att. LR = 0 dB */
@@ -418,6 +410,14 @@ static int __init trust_init(void)
        /* mute card - prevents noisy bootups */
        tr_setmute(tr, 1);
 
+       if (video_register_device(&tr->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+               v4l2_device_unregister(v4l2_dev);
+               release_region(tr->io, 2);
+               return -EINVAL;
+       }
+
+       v4l2_info(v4l2_dev, "Trust FM Radio card driver v1.0.\n");
+
        return 0;
 }
 
index b1f630527dc12df962d9eeef051413e800e6a785..8dbbf08f22077ad2b7c84e8e3992d3b33eab88e7 100644 (file)
@@ -317,7 +317,7 @@ static int vidioc_log_status(struct file *file, void *priv)
 
 static const struct v4l2_file_operations typhoon_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops typhoon_ioctl_ops = {
@@ -344,18 +344,18 @@ static int __init typhoon_init(void)
 
        strlcpy(v4l2_dev->name, "typhoon", sizeof(v4l2_dev->name));
        dev->io = io;
-       dev->curfreq = dev->mutefreq = mutefreq;
 
        if (dev->io == -1) {
                v4l2_err(v4l2_dev, "You must set an I/O address with io=0x316 or io=0x336\n");
                return -EINVAL;
        }
 
-       if (dev->mutefreq < 87000 || dev->mutefreq > 108500) {
+       if (mutefreq < 87000 || mutefreq > 108500) {
                v4l2_err(v4l2_dev, "You must set a frequency (in kHz) used when muting the card,\n");
                v4l2_err(v4l2_dev, "e.g. with \"mutefreq=87500\" (87000 <= mutefreq <= 108500)\n");
                return -EINVAL;
        }
+       dev->curfreq = dev->mutefreq = mutefreq << 4;
 
        mutex_init(&dev->lock);
        if (!request_region(dev->io, 8, "typhoon")) {
@@ -378,17 +378,17 @@ static int __init typhoon_init(void)
        dev->vdev.ioctl_ops = &typhoon_ioctl_ops;
        dev->vdev.release = video_device_release_empty;
        video_set_drvdata(&dev->vdev, dev);
+
+       /* mute card - prevents noisy bootups */
+       typhoon_mute(dev);
+
        if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
                v4l2_device_unregister(&dev->v4l2_dev);
                release_region(dev->io, 8);
                return -EINVAL;
        }
        v4l2_info(v4l2_dev, "port 0x%x.\n", dev->io);
-       v4l2_info(v4l2_dev, "mute frequency is %lu kHz.\n", dev->mutefreq);
-       dev->mutefreq <<= 4;
-
-       /* mute card - prevents noisy bootups */
-       typhoon_mute(dev);
+       v4l2_info(v4l2_dev, "mute frequency is %lu kHz.\n", mutefreq);
 
        return 0;
 }
index f31eab99c943ba9cdc722e7b3163ed91f079d8a1..af99c5bd88c1f0ce15311ec63c137aeee2ce42ab 100644 (file)
@@ -377,7 +377,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 static const struct v4l2_file_operations zoltrix_fops =
 {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops zoltrix_ioctl_ops = {
@@ -424,20 +424,6 @@ static int __init zoltrix_init(void)
                return res;
        }
 
-       strlcpy(zol->vdev.name, v4l2_dev->name, sizeof(zol->vdev.name));
-       zol->vdev.v4l2_dev = v4l2_dev;
-       zol->vdev.fops = &zoltrix_fops;
-       zol->vdev.ioctl_ops = &zoltrix_ioctl_ops;
-       zol->vdev.release = video_device_release_empty;
-       video_set_drvdata(&zol->vdev, zol);
-
-       if (video_register_device(&zol->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
-               v4l2_device_unregister(v4l2_dev);
-               release_region(zol->io, 2);
-               return -EINVAL;
-       }
-       v4l2_info(v4l2_dev, "Zoltrix Radio Plus card driver.\n");
-
        mutex_init(&zol->lock);
 
        /* mute card - prevents noisy bootups */
@@ -452,6 +438,20 @@ static int __init zoltrix_init(void)
        zol->curvol = 0;
        zol->stereo = 1;
 
+       strlcpy(zol->vdev.name, v4l2_dev->name, sizeof(zol->vdev.name));
+       zol->vdev.v4l2_dev = v4l2_dev;
+       zol->vdev.fops = &zoltrix_fops;
+       zol->vdev.ioctl_ops = &zoltrix_ioctl_ops;
+       zol->vdev.release = video_device_release_empty;
+       video_set_drvdata(&zol->vdev, zol);
+
+       if (video_register_device(&zol->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+               v4l2_device_unregister(v4l2_dev);
+               release_region(zol->io, 2);
+               return -EINVAL;
+       }
+       v4l2_info(v4l2_dev, "Zoltrix Radio Plus card driver.\n");
+
        return 0;
 }
 
index ac16e815e2750e2e8e37295b082f6a7da988a0a1..6830d2848bd7f911d5084dcd7a757366a8567dc5 100644 (file)
@@ -112,7 +112,7 @@ config VIDEO_IR_I2C
 #
 
 menu "Encoders/decoders and other helper chips"
-       depends on !VIDEO_HELPER_CHIPS_AUTO
+       visible if !VIDEO_HELPER_CHIPS_AUTO
 
 comment "Audio decoders"
 
index 31e7a123d19a954f86808ec80ae8978fd044d3d8..f989f2820d88e90f49f5b4fc6081002126c0c3c2 100644 (file)
@@ -712,7 +712,7 @@ static int ar_initialize(struct ar *ar)
 static const struct v4l2_file_operations ar_fops = {
        .owner          = THIS_MODULE,
        .read           = ar_read,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops ar_ioctl_ops = {
index 0453816d4ec3a1e2f910b724c294224ccbd6eb20..01be89fa5c7896e7595f3fde2047db16f160121a 100644 (file)
@@ -212,7 +212,7 @@ void au0828_card_setup(struct au0828_dev *dev)
                   be abstracted out if we ever need to support a different
                   demod) */
                sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-                               NULL, "au8522", 0x8e >> 1, NULL);
+                               "au8522", 0x8e >> 1, NULL);
                if (sd == NULL)
                        printk(KERN_ERR "analog subdev registration failed\n");
        }
@@ -221,7 +221,7 @@ void au0828_card_setup(struct au0828_dev *dev)
        if (dev->board.tuner_type != TUNER_ABSENT) {
                /* Load the tuner module, which does the attach */
                sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-                               NULL, "tuner", dev->board.tuner_addr, NULL);
+                               "tuner", dev->board.tuner_addr, NULL);
                if (sd == NULL)
                        printk(KERN_ERR "tuner subdev registration fail\n");
 
index 87d8b006ef77deb182ace69eae34da0ce7db7348..49efcf660ba66cad6dc1e796beb23ea6282b7ca0 100644 (file)
@@ -3529,7 +3529,7 @@ void __devinit bttv_init_card2(struct bttv *btv)
                struct v4l2_subdev *sd;
 
                sd = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-                       &btv->c.i2c_adap, NULL, "saa6588", 0, addrs);
+                       &btv->c.i2c_adap, "saa6588", 0, addrs);
                btv->has_saa6588 = (sd != NULL);
        }
 
@@ -3554,7 +3554,7 @@ void __devinit bttv_init_card2(struct bttv *btv)
                };
 
                btv->sd_msp34xx = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-                       &btv->c.i2c_adap, NULL, "msp3400", 0, addrs);
+                       &btv->c.i2c_adap, "msp3400", 0, addrs);
                if (btv->sd_msp34xx)
                        return;
                goto no_audio;
@@ -3568,7 +3568,7 @@ void __devinit bttv_init_card2(struct bttv *btv)
                };
 
                if (v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-                               &btv->c.i2c_adap, NULL, "tda7432", 0, addrs))
+                               &btv->c.i2c_adap, "tda7432", 0, addrs))
                        return;
                goto no_audio;
        }
@@ -3576,7 +3576,7 @@ void __devinit bttv_init_card2(struct bttv *btv)
        case 3: {
                /* The user specified that we should probe for tvaudio */
                btv->sd_tvaudio = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-                       &btv->c.i2c_adap, NULL, "tvaudio", 0, tvaudio_addrs());
+                       &btv->c.i2c_adap, "tvaudio", 0, tvaudio_addrs());
                if (btv->sd_tvaudio)
                        return;
                goto no_audio;
@@ -3596,11 +3596,11 @@ void __devinit bttv_init_card2(struct bttv *btv)
           found is really something else (e.g. a tea6300). */
        if (!bttv_tvcards[btv->c.type].no_msp34xx) {
                btv->sd_msp34xx = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-                       &btv->c.i2c_adap, NULL, "msp3400",
+                       &btv->c.i2c_adap, "msp3400",
                        0, I2C_ADDRS(I2C_ADDR_MSP3400 >> 1));
        } else if (bttv_tvcards[btv->c.type].msp34xx_alt) {
                btv->sd_msp34xx = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-                       &btv->c.i2c_adap, NULL, "msp3400",
+                       &btv->c.i2c_adap, "msp3400",
                        0, I2C_ADDRS(I2C_ADDR_MSP3400_ALT >> 1));
        }
 
@@ -3616,13 +3616,13 @@ void __devinit bttv_init_card2(struct bttv *btv)
                };
 
                if (v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-                               &btv->c.i2c_adap, NULL, "tda7432", 0, addrs))
+                               &btv->c.i2c_adap, "tda7432", 0, addrs))
                        return;
        }
 
        /* Now see if we can find one of the tvaudio devices. */
        btv->sd_tvaudio = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-               &btv->c.i2c_adap, NULL, "tvaudio", 0, tvaudio_addrs());
+               &btv->c.i2c_adap, "tvaudio", 0, tvaudio_addrs());
        if (btv->sd_tvaudio)
                return;
 
@@ -3646,13 +3646,13 @@ void __devinit bttv_init_tuner(struct bttv *btv)
                /* Load tuner module before issuing tuner config call! */
                if (bttv_tvcards[btv->c.type].has_radio)
                        v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-                               &btv->c.i2c_adap, NULL, "tuner",
+                               &btv->c.i2c_adap, "tuner",
                                0, v4l2_i2c_tuner_addrs(ADDRS_RADIO));
                v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-                               &btv->c.i2c_adap, NULL, "tuner",
+                               &btv->c.i2c_adap, "tuner",
                                0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
                v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-                               &btv->c.i2c_adap, NULL, "tuner",
+                               &btv->c.i2c_adap, "tuner",
                                0, v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD));
 
                tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
index a529619e51f687d1386c6c673a0feaa9ba8d517a..0902ec041c7a71fd11842b3128de23dbb4ec5daf 100644 (file)
@@ -854,7 +854,6 @@ int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit)
                xbits |= RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM;
 
        /* is it free? */
-       mutex_lock(&btv->lock);
        if (btv->resources & xbits) {
                /* no, someone else uses it */
                goto fail;
@@ -884,11 +883,9 @@ int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit)
        /* it's free, grab it */
        fh->resources  |= bit;
        btv->resources |= bit;
-       mutex_unlock(&btv->lock);
        return 1;
 
  fail:
-       mutex_unlock(&btv->lock);
        return 0;
 }
 
@@ -940,7 +937,6 @@ void free_btres_lock(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->lock);
        fh->resources  &= ~bits;
        btv->resources &= ~bits;
 
@@ -951,8 +947,6 @@ void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits)
 
        if (0 == (bits & VBI_RESOURCES))
                disclaim_vbi_lines(btv);
-
-       mutex_unlock(&btv->lock);
 }
 
 /* ----------------------------------------------------------------------- */
@@ -1713,28 +1707,20 @@ static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,
 
                /* 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 {
-               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)
@@ -1858,7 +1844,6 @@ static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)
        unsigned int i;
        int err;
 
-       mutex_lock(&btv->lock);
        err = v4l2_prio_check(&btv->prio, fh->prio);
        if (err)
                goto err;
@@ -1874,7 +1859,6 @@ static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)
        set_tvnorm(btv, i);
 
 err:
-       mutex_unlock(&btv->lock);
 
        return err;
 }
@@ -1898,7 +1882,6 @@ static int bttv_enum_input(struct file *file, void *priv,
        struct bttv *btv = fh->btv;
        int rc = 0;
 
-       mutex_lock(&btv->lock);
        if (i->index >= bttv_tvcards[btv->c.type].video_inputs) {
                rc = -EINVAL;
                goto err;
@@ -1928,7 +1911,6 @@ static int bttv_enum_input(struct file *file, void *priv,
        i->std = BTTV_NORMS;
 
 err:
-       mutex_unlock(&btv->lock);
 
        return rc;
 }
@@ -1938,9 +1920,7 @@ static int bttv_g_input(struct file *file, void *priv, unsigned int *i)
        struct bttv_fh *fh = priv;
        struct bttv *btv = fh->btv;
 
-       mutex_lock(&btv->lock);
        *i = btv->input;
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -1952,7 +1932,6 @@ static int bttv_s_input(struct file *file, void *priv, unsigned int i)
 
        int err;
 
-       mutex_lock(&btv->lock);
        err = v4l2_prio_check(&btv->prio, fh->prio);
        if (unlikely(err))
                goto err;
@@ -1965,7 +1944,6 @@ static int bttv_s_input(struct file *file, void *priv, unsigned int i)
        set_input(btv, i, btv->tvnorm);
 
 err:
-       mutex_unlock(&btv->lock);
        return 0;
 }
 
@@ -1979,7 +1957,6 @@ static int bttv_s_tuner(struct file *file, void *priv,
        if (unlikely(0 != t->index))
                return -EINVAL;
 
-       mutex_lock(&btv->lock);
        if (unlikely(btv->tuner_type == TUNER_ABSENT)) {
                err = -EINVAL;
                goto err;
@@ -1995,7 +1972,6 @@ static int bttv_s_tuner(struct file *file, void *priv,
                btv->audio_mode_gpio(btv, t, 1);
 
 err:
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -2006,10 +1982,8 @@ static int bttv_g_frequency(struct file *file, void *priv,
        struct bttv_fh *fh  = priv;
        struct bttv *btv = fh->btv;
 
-       mutex_lock(&btv->lock);
        f->type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
        f->frequency = btv->freq;
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -2024,7 +1998,6 @@ static int bttv_s_frequency(struct file *file, void *priv,
        if (unlikely(f->tuner != 0))
                return -EINVAL;
 
-       mutex_lock(&btv->lock);
        err = v4l2_prio_check(&btv->prio, fh->prio);
        if (unlikely(err))
                goto err;
@@ -2039,7 +2012,6 @@ static int bttv_s_frequency(struct file *file, void *priv,
        if (btv->has_matchbox && btv->radio_user)
                tea5757_set_freq(btv, btv->freq);
 err:
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -2172,7 +2144,6 @@ limit_scaled_size_lock       (struct bttv_fh *               fh,
 
        /* 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;
 
@@ -2250,7 +2221,6 @@ limit_scaled_size_lock       (struct bttv_fh *               fh,
        rc = 0; /* success */
 
  fail:
-       mutex_unlock(&btv->lock);
 
        return rc;
 }
@@ -2282,9 +2252,7 @@ verify_window_lock                (struct bttv_fh *               fh,
        if (V4L2_FIELD_ANY == field) {
                __s32 height2;
 
-               mutex_lock(&fh->btv->lock);
                height2 = fh->btv->crop[!!fh->do_crop].rect.height >> 1;
-               mutex_unlock(&fh->btv->lock);
                field = (win->w.height > height2)
                        ? V4L2_FIELD_INTERLACED
                        : V4L2_FIELD_TOP;
@@ -2360,7 +2328,6 @@ static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,
                }
        }
 
-       mutex_lock(&fh->cap.vb_lock);
        /* clip against screen */
        if (NULL != btv->fbuf.base)
                n = btcx_screen_clips(btv->fbuf.fmt.width, btv->fbuf.fmt.height,
@@ -2391,13 +2358,6 @@ static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,
        fh->ov.field    = win->field;
        fh->ov.setup_ok = 1;
 
-       /*
-        * FIXME: btv is protected by btv->lock mutex, while btv->init
-        *        is protected by fh->cap.vb_lock. This seems to open the
-        *        possibility for some race situations. Maybe the better would
-        *        be to unify those locks or to use another way to store the
-        *        init values that will be consumed by videobuf callbacks
-        */
        btv->init.ov.w.width   = win->w.width;
        btv->init.ov.w.height  = win->w.height;
        btv->init.ov.field     = win->field;
@@ -2412,7 +2372,6 @@ static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,
                bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
                retval = bttv_switch_overlay(btv,fh,new);
        }
-       mutex_unlock(&fh->cap.vb_lock);
        return retval;
 }
 
@@ -2526,9 +2485,7 @@ static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
        if (V4L2_FIELD_ANY == field) {
                __s32 height2;
 
-               mutex_lock(&btv->lock);
                height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
-               mutex_unlock(&btv->lock);
                field = (f->fmt.pix.height > height2)
                        ? V4L2_FIELD_INTERLACED
                        : V4L2_FIELD_BOTTOM;
@@ -2614,7 +2571,6 @@ static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
        fmt = format_by_fourcc(f->fmt.pix.pixelformat);
 
        /* update our state informations */
-       mutex_lock(&fh->cap.vb_lock);
        fh->fmt              = fmt;
        fh->cap.field        = f->fmt.pix.field;
        fh->cap.last         = V4L2_FIELD_NONE;
@@ -2623,7 +2579,6 @@ static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
        btv->init.fmt        = fmt;
        btv->init.width      = f->fmt.pix.width;
        btv->init.height     = f->fmt.pix.height;
-       mutex_unlock(&fh->cap.vb_lock);
 
        return 0;
 }
@@ -2649,11 +2604,9 @@ static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
        unsigned int i;
        struct bttv_fh *fh = priv;
 
-       mutex_lock(&fh->cap.vb_lock);
        retval = __videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize,
                                     V4L2_MEMORY_MMAP);
        if (retval < 0) {
-               mutex_unlock(&fh->cap.vb_lock);
                return retval;
        }
 
@@ -2665,7 +2618,6 @@ static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
        for (i = 0; i < gbuffers; i++)
                mbuf->offsets[i] = i * gbufsize;
 
-       mutex_unlock(&fh->cap.vb_lock);
        return 0;
 }
 #endif
@@ -2775,10 +2727,8 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)
        int retval = 0;
 
        if (on) {
-               mutex_lock(&fh->cap.vb_lock);
                /* verify args */
                if (unlikely(!btv->fbuf.base)) {
-                       mutex_unlock(&fh->cap.vb_lock);
                        return -EINVAL;
                }
                if (unlikely(!fh->ov.setup_ok)) {
@@ -2787,13 +2737,11 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)
                }
                if (retval)
                        return retval;
-               mutex_unlock(&fh->cap.vb_lock);
        }
 
        if (!check_alloc_btres_lock(btv, fh, RESOURCE_OVERLAY))
                return -EBUSY;
 
-       mutex_lock(&fh->cap.vb_lock);
        if (on) {
                fh->ov.tvnorm = btv->tvnorm;
                new = videobuf_sg_alloc(sizeof(*new));
@@ -2805,7 +2753,6 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)
 
        /* switch over */
        retval = bttv_switch_overlay(btv, fh, new);
-       mutex_unlock(&fh->cap.vb_lock);
        return retval;
 }
 
@@ -2844,7 +2791,6 @@ static int bttv_s_fbuf(struct file *file, void *f,
        }
 
        /* ok, accept it */
-       mutex_lock(&fh->cap.vb_lock);
        btv->fbuf.base       = fb->base;
        btv->fbuf.fmt.width  = fb->fmt.width;
        btv->fbuf.fmt.height = fb->fmt.height;
@@ -2876,7 +2822,6 @@ static int bttv_s_fbuf(struct file *file, void *f,
                        retval = bttv_switch_overlay(btv, fh, new);
                }
        }
-       mutex_unlock(&fh->cap.vb_lock);
        return retval;
 }
 
@@ -2955,7 +2900,6 @@ static int bttv_queryctrl(struct file *file, void *priv,
             c->id >= V4L2_CID_PRIVATE_LASTP1))
                return -EINVAL;
 
-       mutex_lock(&btv->lock);
        if (!btv->volume_gpio && (c->id == V4L2_CID_AUDIO_VOLUME))
                *c = no_ctl;
        else {
@@ -2963,7 +2907,6 @@ static int bttv_queryctrl(struct file *file, void *priv,
 
                *c = (NULL != ctrl) ? *ctrl : no_ctl;
        }
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -2974,10 +2917,8 @@ static int bttv_g_parm(struct file *file, void *f,
        struct bttv_fh *fh = f;
        struct bttv *btv = fh->btv;
 
-       mutex_lock(&btv->lock);
        v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id,
                                    &parm->parm.capture.timeperframe);
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -2993,7 +2934,6 @@ static int bttv_g_tuner(struct file *file, void *priv,
        if (0 != t->index)
                return -EINVAL;
 
-       mutex_lock(&btv->lock);
        t->rxsubchans = V4L2_TUNER_SUB_MONO;
        bttv_call_all(btv, tuner, g_tuner, t);
        strcpy(t->name, "Television");
@@ -3005,7 +2945,6 @@ static int bttv_g_tuner(struct file *file, void *priv,
        if (btv->audio_mode_gpio)
                btv->audio_mode_gpio(btv, t, 0);
 
-       mutex_unlock(&btv->lock);
        return 0;
 }
 
@@ -3014,9 +2953,7 @@ static int bttv_g_priority(struct file *file, void *f, enum v4l2_priority *p)
        struct bttv_fh *fh = f;
        struct bttv *btv = fh->btv;
 
-       mutex_lock(&btv->lock);
        *p = v4l2_prio_max(&btv->prio);
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -3028,9 +2965,7 @@ static int bttv_s_priority(struct file *file, void *f,
        struct bttv *btv = fh->btv;
        int     rc;
 
-       mutex_lock(&btv->lock);
        rc = v4l2_prio_change(&btv->prio, &fh->prio, prio);
-       mutex_unlock(&btv->lock);
 
        return rc;
 }
@@ -3045,9 +2980,7 @@ static int bttv_cropcap(struct file *file, void *priv,
            cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
                return -EINVAL;
 
-       mutex_lock(&btv->lock);
        *cap = bttv_tvnorms[btv->tvnorm].cropcap;
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -3065,9 +2998,7 @@ static int bttv_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
           inconsistent with fh->width or fh->height and apps
           do not expect a change here. */
 
-       mutex_lock(&btv->lock);
        crop->c = btv->crop[!!fh->do_crop].rect;
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -3091,17 +3022,14 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
        /* 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_lock(). */
-       mutex_lock(&btv->lock);
        retval = v4l2_prio_check(&btv->prio, fh->prio);
        if (0 != retval) {
-               mutex_unlock(&btv->lock);
                return retval;
        }
 
        retval = -EBUSY;
 
        if (locked_btres(fh->btv, VIDEO_RESOURCES)) {
-               mutex_unlock(&btv->lock);
                return retval;
        }
 
@@ -3113,7 +3041,6 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
 
        b_top = max(b->top, btv->vbi_end);
        if (b_top + 32 >= b_bottom) {
-               mutex_unlock(&btv->lock);
                return retval;
        }
 
@@ -3136,12 +3063,8 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
 
        btv->crop[1] = c;
 
-       mutex_unlock(&btv->lock);
-
        fh->do_crop = 1;
 
-       mutex_lock(&fh->cap.vb_lock);
-
        if (fh->width < c.min_scaled_width) {
                fh->width = c.min_scaled_width;
                btv->init.width = c.min_scaled_width;
@@ -3158,8 +3081,6 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
                btv->init.height = c.max_scaled_height;
        }
 
-       mutex_unlock(&fh->cap.vb_lock);
-
        return 0;
 }
 
@@ -3227,7 +3148,6 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
                return videobuf_poll_stream(file, &fh->vbi, wait);
        }
 
-       mutex_lock(&fh->cap.vb_lock);
        if (check_btres(fh,RESOURCE_VIDEO_STREAM)) {
                /* streaming capture */
                if (list_empty(&fh->cap.stream))
@@ -3262,7 +3182,6 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
        else
                rc = 0;
 err:
-       mutex_unlock(&fh->cap.vb_lock);
        return rc;
 }
 
@@ -3293,23 +3212,11 @@ static int bttv_open(struct file *file)
                return -ENOMEM;
        file->private_data = fh;
 
-       /*
-        * btv is protected by btv->lock mutex, while btv->init and other
-        * streaming vars are protected by fh->cap.vb_lock. We need to take
-        * care of both locks to avoid troubles. However, vb_lock is used also
-        * inside videobuf, without calling buf->lock. So, it is a very bad
-        * idea to hold both locks at the same time.
-        * Let's first copy btv->init at fh, holding cap.vb_lock, and then work
-        * with the rest of init, holding btv->lock.
-        */
-       mutex_lock(&fh->cap.vb_lock);
        *fh = btv->init;
-       mutex_unlock(&fh->cap.vb_lock);
 
        fh->type = type;
        fh->ov.setup_ok = 0;
 
-       mutex_lock(&btv->lock);
        v4l2_prio_open(&btv->prio, &fh->prio);
 
        videobuf_queue_sg_init(&fh->cap, &bttv_video_qops,
@@ -3317,13 +3224,13 @@ static int bttv_open(struct file *file)
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_INTERLACED,
                            sizeof(struct bttv_buffer),
-                           fh, NULL);
+                           fh, &btv->lock);
        videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops,
                            &btv->c.pci->dev, &btv->s_lock,
                            V4L2_BUF_TYPE_VBI_CAPTURE,
                            V4L2_FIELD_SEQ_TB,
                            sizeof(struct bttv_buffer),
-                           fh, NULL);
+                           fh, &btv->lock);
        set_tvnorm(btv,btv->tvnorm);
        set_input(btv, btv->input, btv->tvnorm);
 
@@ -3346,7 +3253,6 @@ static int bttv_open(struct file *file)
        bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm);
 
        bttv_field_count(btv);
-       mutex_unlock(&btv->lock);
        return 0;
 }
 
@@ -3355,7 +3261,6 @@ static int bttv_release(struct file *file)
        struct bttv_fh *fh = file->private_data;
        struct bttv *btv = fh->btv;
 
-       mutex_lock(&btv->lock);
        /* turn off overlay */
        if (check_btres(fh, RESOURCE_OVERLAY))
                bttv_switch_overlay(btv,fh,NULL);
@@ -3381,14 +3286,8 @@ static int bttv_release(struct file *file)
 
        /* free stuff */
 
-       /*
-        * videobuf uses cap.vb_lock - we should avoid holding btv->lock,
-        * otherwise we may have dead lock conditions
-        */
-       mutex_unlock(&btv->lock);
        videobuf_mmap_free(&fh->cap);
        videobuf_mmap_free(&fh->vbi);
-       mutex_lock(&btv->lock);
        v4l2_prio_close(&btv->prio, fh->prio);
        file->private_data = NULL;
        kfree(fh);
@@ -3398,7 +3297,6 @@ static int bttv_release(struct file *file)
 
        if (!btv->users)
                audio_mute(btv, 1);
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -3502,11 +3400,8 @@ static int radio_open(struct file *file)
        if (unlikely(!fh))
                return -ENOMEM;
        file->private_data = fh;
-       mutex_lock(&fh->cap.vb_lock);
        *fh = btv->init;
-       mutex_unlock(&fh->cap.vb_lock);
 
-       mutex_lock(&btv->lock);
        v4l2_prio_open(&btv->prio, &fh->prio);
 
        btv->radio_user++;
@@ -3514,7 +3409,6 @@ static int radio_open(struct file *file)
        bttv_call_all(btv, tuner, s_radio);
        audio_input(btv,TVAUDIO_INPUT_RADIO);
 
-       mutex_unlock(&btv->lock);
        return 0;
 }
 
@@ -3524,7 +3418,6 @@ static int radio_release(struct file *file)
        struct bttv *btv = fh->btv;
        struct rds_command cmd;
 
-       mutex_lock(&btv->lock);
        v4l2_prio_close(&btv->prio, fh->prio);
        file->private_data = NULL;
        kfree(fh);
@@ -3532,7 +3425,6 @@ static int radio_release(struct file *file)
        btv->radio_user--;
 
        bttv_call_all(btv, core, ioctl, RDS_CMD_CLOSE, &cmd);
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -3561,7 +3453,6 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
                return -EINVAL;
        if (0 != t->index)
                return -EINVAL;
-       mutex_lock(&btv->lock);
        strcpy(t->name, "Radio");
        t->type = V4L2_TUNER_RADIO;
 
@@ -3570,8 +3461,6 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
        if (btv->audio_mode_gpio)
                btv->audio_mode_gpio(btv, t, 0);
 
-       mutex_unlock(&btv->lock);
-
        return 0;
 }
 
@@ -3692,7 +3581,7 @@ static const struct v4l2_file_operations radio_fops =
        .open     = radio_open,
        .read     = radio_read,
        .release  = radio_release,
-       .ioctl    = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .poll     = radio_poll,
 };
 
index 935e0c9a96744aa1e4f0cd3d443c8ee4c8b407d2..c1193506131c3a37e3c347a8703771a98f3938af 100644 (file)
@@ -860,7 +860,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
 
 static const struct v4l2_file_operations qcam_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .read           = qcam_read,
 };
 
index 6e4b19698c13fe6212ee08cfd0d9bee7be3cf964..24fc00965a12d048be055498230b734b794283fa 100644 (file)
@@ -718,7 +718,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
 
 static const struct v4l2_file_operations qcam_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .read           = qcam_read,
 };
 
index 7bc36670071a8ba333ed0d67999d5f9079adc895..0dfff50891e404056059eaf18316bd81fed0824f 100644 (file)
@@ -1775,7 +1775,7 @@ static const struct v4l2_file_operations cafe_v4l_fops = {
        .read = cafe_v4l_read,
        .poll = cafe_v4l_poll,
        .mmap = cafe_v4l_mmap,
-       .ioctl = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops cafe_v4l_ioctl_ops = {
@@ -2066,8 +2066,7 @@ static int cafe_pci_probe(struct pci_dev *pdev,
 
        cam->sensor_addr = 0x42;
        cam->sensor = v4l2_i2c_new_subdev_cfg(&cam->v4l2_dev, &cam->i2c_adapter,
-                       "ov7670", "ov7670", 0, &sensor_cfg, cam->sensor_addr,
-                       NULL);
+                       "ov7670", 0, &sensor_cfg, cam->sensor_addr, NULL);
        if (cam->sensor == NULL) {
                ret = -ENODEV;
                goto out_smbus;
index 8f55692db36d278e01191bd3fd2ea9e380c90965..82d195be91976ad18ae3cb9059e64efcf2c44788 100644 (file)
@@ -218,7 +218,13 @@ static int snd_cx18_pcm_capture_close(struct snd_pcm_substream *substream)
 static int snd_cx18_pcm_ioctl(struct snd_pcm_substream *substream,
                     unsigned int cmd, void *arg)
 {
-       return snd_pcm_lib_ioctl(substream, cmd, arg);
+       struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
+       int ret;
+
+       snd_cx18_lock(cxsc);
+       ret = snd_pcm_lib_ioctl(substream, cmd, arg);
+       snd_cx18_unlock(cxsc);
+       return ret;
 }
 
 
index a09caf8831705b3381892eb72b8e8304918eb5b9..e71a026f3419140a314217b923c428d25e9b9f73 100644 (file)
@@ -122,15 +122,15 @@ int cx18_i2c_register(struct cx18 *cx, unsigned idx)
        if (hw == CX18_HW_TUNER) {
                /* special tuner group handling */
                sd = v4l2_i2c_new_subdev(&cx->v4l2_dev,
-                               adap, NULL, type, 0, cx->card_i2c->radio);
+                               adap, type, 0, cx->card_i2c->radio);
                if (sd != NULL)
                        sd->grp_id = hw;
                sd = v4l2_i2c_new_subdev(&cx->v4l2_dev,
-                               adap, NULL, type, 0, cx->card_i2c->demod);
+                               adap, type, 0, cx->card_i2c->demod);
                if (sd != NULL)
                        sd->grp_id = hw;
                sd = v4l2_i2c_new_subdev(&cx->v4l2_dev,
-                               adap, NULL, type, 0, cx->card_i2c->tv);
+                               adap, type, 0, cx->card_i2c->tv);
                if (sd != NULL)
                        sd->grp_id = hw;
                return sd != NULL ? 0 : -1;
@@ -144,7 +144,7 @@ int cx18_i2c_register(struct cx18 *cx, unsigned idx)
                return -1;
 
        /* It's an I2C device other than an analog tuner or IR chip */
-       sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, adap, NULL, type, hw_addrs[idx],
+       sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, adap, type, hw_addrs[idx],
                                 NULL);
        if (sd != NULL)
                sd->grp_id = hw;
index 9045f1ece0ebb35cdb1b85eec68b96cc2344fcfc..ab461e27d9dd1ad6206e9054f391605556563a74 100644 (file)
@@ -41,7 +41,7 @@ static struct v4l2_file_operations cx18_v4l2_enc_fops = {
        .read = cx18_v4l2_read,
        .open = cx18_v4l2_open,
        /* FIXME change to video_ioctl2 if serialization lock can be removed */
-       .ioctl = cx18_v4l2_ioctl,
+       .unlocked_ioctl = cx18_v4l2_ioctl,
        .release = cx18_v4l2_close,
        .poll = cx18_v4l2_enc_poll,
 };
index 56c2d8195ac6fb301f27016f18543fa13c5b4904..2c78d188bb0650dcd9c33b5a5495cf568c49043a 100644 (file)
@@ -560,7 +560,7 @@ void cx231xx_card_setup(struct cx231xx *dev)
        if (dev->board.decoder == CX231XX_AVDECODER) {
                dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
                                        &dev->i2c_bus[0].i2c_adap,
-                                       NULL, "cx25840", 0x88 >> 1, NULL);
+                                       "cx25840", 0x88 >> 1, NULL);
                if (dev->sd_cx25840 == NULL)
                        cx231xx_info("cx25840 subdev registration failure\n");
                cx25840_call(dev, core, load_fw);
@@ -571,7 +571,7 @@ void cx231xx_card_setup(struct cx231xx *dev)
        if (dev->board.tuner_type != TUNER_ABSENT) {
                dev->sd_tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev,
                                                    &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
-                                                   NULL, "tuner",
+                                                   "tuner",
                                                    dev->tuner_addr, NULL);
                if (dev->sd_tuner == NULL)
                        cx231xx_info("tuner subdev registration failure\n");
index db054004e462fe4f0fab90705066b24ae3a4abed..8861309268b170d8f6effd11b17365e11ea846a5 100644 (file)
@@ -1247,7 +1247,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
        case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200:
                dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
                                &dev->i2c_bus[2].i2c_adap,
-                               NULL, "cx25840", 0x88 >> 1, NULL);
+                               "cx25840", 0x88 >> 1, NULL);
                if (dev->sd_cx25840) {
                        dev->sd_cx25840->grp_id = CX23885_HW_AV_CORE;
                        v4l2_subdev_call(dev->sd_cx25840, core, load_fw);
index 3cc9f462d08d9d1d391b8cfcec5fbebc6b6c66d4..8b2fb8a4375cf21313d766eaec0e35f41aacf9d7 100644 (file)
@@ -1507,10 +1507,10 @@ int cx23885_video_register(struct cx23885_dev *dev)
                if (dev->tuner_addr)
                        sd = v4l2_i2c_new_subdev(&dev->v4l2_dev,
                                &dev->i2c_bus[1].i2c_adap,
-                               NULL, "tuner", dev->tuner_addr, NULL);
+                               "tuner", dev->tuner_addr, NULL);
                else
                        sd = v4l2_i2c_new_subdev(&dev->v4l2_dev,
-                               &dev->i2c_bus[1].i2c_adap, NULL,
+                               &dev->i2c_bus[1].i2c_adap,
                                "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_TV));
                if (sd) {
                        struct tuner_setup tun_setup;
index b26fcba8600cf49bb4761f3194958e093081f0c1..9b9e169cce90862ee92f7d80ab7851cdb3cf81cb 100644 (file)
@@ -3515,19 +3515,18 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
                   later code configures a tea5767.
                 */
                v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap,
-                               NULL, "tuner",
-                               0, v4l2_i2c_tuner_addrs(ADDRS_RADIO));
+                               "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_RADIO));
                if (has_demod)
                        v4l2_i2c_new_subdev(&core->v4l2_dev,
-                               &core->i2c_adap, NULL, "tuner",
+                               &core->i2c_adap, "tuner",
                                0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
                if (core->board.tuner_addr == ADDR_UNSET) {
                        v4l2_i2c_new_subdev(&core->v4l2_dev,
-                               &core->i2c_adap, NULL, "tuner",
+                               &core->i2c_adap, "tuner",
                                0, has_demod ? tv_addrs + 4 : tv_addrs);
                } else {
                        v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap,
-                               NULL, "tuner", core->board.tuner_addr, NULL);
+                               "tuner", core->board.tuner_addr, NULL);
                }
        }
 
index 88b51194f917956a17c734a21d9c2a893b2e5104..62cea9549404bf29d3d58e004af015dcb132f779 100644 (file)
@@ -1895,14 +1895,13 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
 
        if (core->board.audio_chip == V4L2_IDENT_WM8775)
                v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap,
-                               NULL, "wm8775", 0x36 >> 1, NULL);
+                               "wm8775", 0x36 >> 1, NULL);
 
        if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) {
                /* This probes for a tda9874 as is used on some
                   Pixelview Ultra boards. */
-               v4l2_i2c_new_subdev(&core->v4l2_dev,
-                               &core->i2c_adap,
-                               NULL, "tvaudio", 0, I2C_ADDRS(0xb0 >> 1));
+               v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap,
+                               "tvaudio", 0, I2C_ADDRS(0xb0 >> 1));
        }
 
        switch (core->boardnr) {
index d8e38cc4ec40c8b1a7dd8803f3d6e6b8e0d95bff..7333a9bb2549deeffc8b122d16406a6308f4b812 100644 (file)
@@ -1986,7 +1986,6 @@ static __init int vpfe_probe(struct platform_device *pdev)
                vpfe_dev->sd[i] =
                        v4l2_i2c_new_subdev_board(&vpfe_dev->v4l2_dev,
                                                  i2c_adap,
-                                                 NULL,
                                                  &sdinfo->board_info,
                                                  NULL);
                if (vpfe_dev->sd[i]) {
index 6ac6acd16352b6ee4f277a1790b74d0c5c2a56fc..193abab6b355e90b619a3a57d4ab434a551640b5 100644 (file)
@@ -2013,7 +2013,6 @@ static __init int vpif_probe(struct platform_device *pdev)
                vpif_obj.sd[i] =
                        v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
                                                  i2c_adap,
-                                                 NULL,
                                                  &subdevdata->board_info,
                                                  NULL);
 
index 685f6a6ee603cf40456d17c80c5fe9ef9a526909..412c65d54fe1a3e9397aae9455edf49fc295862c 100644 (file)
@@ -1553,7 +1553,7 @@ static __init int vpif_probe(struct platform_device *pdev)
 
        for (i = 0; i < subdev_count; i++) {
                vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
-                                               i2c_adap, NULL,
+                                               i2c_adap,
                                                &subdevdata[i].board_info,
                                                NULL);
                if (!vpif_obj.sd[i]) {
index 54859233f31188e3b1e4d6f7aed45b37113ae27a..f7e9168157a502d38b543ec89212984fa5620531 100644 (file)
@@ -2554,39 +2554,39 @@ void em28xx_card_setup(struct em28xx *dev)
        /* request some modules */
        if (dev->board.has_msp34xx)
                v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-                       NULL, "msp3400", 0, msp3400_addrs);
+                       "msp3400", 0, msp3400_addrs);
 
        if (dev->board.decoder == EM28XX_SAA711X)
                v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-                       NULL, "saa7115_auto", 0, saa711x_addrs);
+                       "saa7115_auto", 0, saa711x_addrs);
 
        if (dev->board.decoder == EM28XX_TVP5150)
                v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-                       NULL, "tvp5150", 0, tvp5150_addrs);
+                       "tvp5150", 0, tvp5150_addrs);
 
        if (dev->em28xx_sensor == EM28XX_MT9V011) {
                struct v4l2_subdev *sd;
 
                sd = v4l2_i2c_new_subdev(&dev->v4l2_dev,
-                        &dev->i2c_adap, NULL, "mt9v011", 0, mt9v011_addrs);
+                        &dev->i2c_adap, "mt9v011", 0, mt9v011_addrs);
                v4l2_subdev_call(sd, core, s_config, 0, &dev->sensor_xtal);
        }
 
 
        if (dev->board.adecoder == EM28XX_TVAUDIO)
                v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-                       NULL, "tvaudio", dev->board.tvaudio_addr, NULL);
+                       "tvaudio", dev->board.tvaudio_addr, NULL);
 
        if (dev->board.tuner_type != TUNER_ABSENT) {
                int has_demod = (dev->tda9887_conf & TDA9887_PRESENT);
 
                if (dev->board.radio.type)
                        v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-                               NULL, "tuner", dev->board.radio_addr, NULL);
+                               "tuner", dev->board.radio_addr, NULL);
 
                if (has_demod)
                        v4l2_i2c_new_subdev(&dev->v4l2_dev,
-                               &dev->i2c_adap, NULL, "tuner",
+                               &dev->i2c_adap, "tuner",
                                0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
                if (dev->tuner_addr == 0) {
                        enum v4l2_i2c_tuner_type type =
@@ -2594,14 +2594,14 @@ void em28xx_card_setup(struct em28xx *dev)
                        struct v4l2_subdev *sd;
 
                        sd = v4l2_i2c_new_subdev(&dev->v4l2_dev,
-                               &dev->i2c_adap, NULL, "tuner",
+                               &dev->i2c_adap, "tuner",
                                0, v4l2_i2c_tuner_addrs(type));
 
                        if (sd)
                                dev->tuner_addr = v4l2_i2c_subdev_addr(sd);
                } else {
                        v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-                               NULL, "tuner", dev->tuner_addr, NULL);
+                               "tuner", dev->tuner_addr, NULL);
                }
        }
 
index a5cfc76b40b71e26dcc68e41f1f0b8acdf128e51..bb164099ea2c866a4a250664dbd7f06ddf48767c 100644 (file)
@@ -2530,7 +2530,7 @@ static const struct v4l2_file_operations et61x251_fops = {
        .owner = THIS_MODULE,
        .open =    et61x251_open,
        .release = et61x251_release,
-       .ioctl =   et61x251_ioctl,
+       .unlocked_ioctl =   et61x251_ioctl,
        .read =    et61x251_read,
        .poll =    et61x251_poll,
        .mmap =    et61x251_mmap,
index 9a075d83dd1fcda95715b12bdf2ee38b2b1aa1fd..b8faff2dd711c7d2c014813996da862106f48d2c 100644 (file)
@@ -1486,7 +1486,7 @@ static int __devinit viu_of_probe(struct platform_device *op,
 
        ad = i2c_get_adapter(0);
        viu_dev->decoder = v4l2_i2c_new_subdev(&viu_dev->v4l2_dev, ad,
-                       NULL, "saa7113", VIU_VIDEO_DECODER_ADDR, NULL);
+                       "saa7113", VIU_VIDEO_DECODER_ADDR, NULL);
 
        viu_dev->vidq.timeout.function = viu_vid_timeout;
        viu_dev->vidq.timeout.data     = (unsigned long)viu_dev;
index 330dadc001064e1a477e16acd65723ad72adcc76..e23de57e2c73de5d3c575eb4f52ae2a96be3259c 100644 (file)
@@ -63,7 +63,10 @@ struct sd {
 #define QUALITY_DEF 80
        u8 jpegqual;                    /* webcam quality */
 
+       u8 reg01;
+       u8 reg17;
        u8 reg18;
+       u8 flags;
 
        s8 ag_cnt;
 #define AG_CNT_START 13
@@ -96,6 +99,22 @@ enum sensors {
        SENSOR_SP80708,
 };
 
+/* device flags */
+#define PDN_INV        1               /* inverse pin S_PWR_DN / sn_xxx tables */
+
+/* sn9c1xx definitions */
+/* register 0x01 */
+#define S_PWR_DN       0x01    /* sensor power down */
+#define S_PDN_INV      0x02    /* inverse pin S_PWR_DN */
+#define V_TX_EN                0x04    /* video transfer enable */
+#define LED            0x08    /* output to pin LED */
+#define SCL_SEL_OD     0x20    /* open-drain mode */
+#define SYS_SEL_48M    0x40    /* system clock 0: 24MHz, 1: 48MHz */
+/* register 0x17 */
+#define MCK_SIZE_MASK  0x1f    /* sensor master clock */
+#define SEN_CLK_EN     0x20    /* enable sensor clock */
+#define DEF_EN         0x80    /* defect pixel by 0: soft, 1: hard */
+
 /* V4L2 controls supported by the driver */
 static void setbrightness(struct gspca_dev *gspca_dev);
 static void setcontrast(struct gspca_dev *gspca_dev);
@@ -1755,141 +1774,6 @@ static void po2030n_probe(struct gspca_dev *gspca_dev)
        }
 }
 
-static void bridge_init(struct gspca_dev *gspca_dev,
-                         const u8 *sn9c1xx)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 reg0102[2];
-       const u8 *reg9a;
-       static const u8 reg9a_def[] =
-               {0x00, 0x40, 0x20, 0x00, 0x00, 0x00};
-       static const u8 reg9a_spec[] =
-               {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
-       static const u8 regd4[] = {0x60, 0x00, 0x00};
-
-       /* sensor clock already enabled in sd_init */
-       /* reg_w1(gspca_dev, 0xf1, 0x00); */
-       reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
-
-       /* configure gpio */
-       reg0102[0] = sn9c1xx[1];
-       reg0102[1] = sn9c1xx[2];
-       if (gspca_dev->audio)
-               reg0102[1] |= 0x04;     /* keep the audio connection */
-       reg_w(gspca_dev, 0x01, reg0102, 2);
-       reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
-       reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5);
-       switch (sd->sensor) {
-       case SENSOR_GC0307:
-       case SENSOR_OV7660:
-       case SENSOR_PO1030:
-       case SENSOR_PO2030N:
-       case SENSOR_SOI768:
-       case SENSOR_SP80708:
-               reg9a = reg9a_spec;
-               break;
-       default:
-               reg9a = reg9a_def;
-               break;
-       }
-       reg_w(gspca_dev, 0x9a, reg9a, 6);
-
-       reg_w(gspca_dev, 0xd4, regd4, sizeof regd4);
-
-       reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
-
-       switch (sd->sensor) {
-       case SENSOR_ADCM1700:
-               reg_w1(gspca_dev, 0x01, 0x43);
-               reg_w1(gspca_dev, 0x17, 0x62);
-               reg_w1(gspca_dev, 0x01, 0x42);
-               reg_w1(gspca_dev, 0x01, 0x42);
-               break;
-       case SENSOR_GC0307:
-               msleep(50);
-               reg_w1(gspca_dev, 0x01, 0x61);
-               reg_w1(gspca_dev, 0x17, 0x22);
-               reg_w1(gspca_dev, 0x01, 0x60);
-               reg_w1(gspca_dev, 0x01, 0x40);
-               msleep(50);
-               break;
-       case SENSOR_MI0360B:
-               reg_w1(gspca_dev, 0x01, 0x61);
-               reg_w1(gspca_dev, 0x17, 0x60);
-               reg_w1(gspca_dev, 0x01, 0x60);
-               reg_w1(gspca_dev, 0x01, 0x40);
-               break;
-       case SENSOR_MT9V111:
-               reg_w1(gspca_dev, 0x01, 0x61);
-               reg_w1(gspca_dev, 0x17, 0x61);
-               reg_w1(gspca_dev, 0x01, 0x60);
-               reg_w1(gspca_dev, 0x01, 0x40);
-               break;
-       case SENSOR_OM6802:
-               msleep(10);
-               reg_w1(gspca_dev, 0x02, 0x73);
-               reg_w1(gspca_dev, 0x17, 0x60);
-               reg_w1(gspca_dev, 0x01, 0x22);
-               msleep(100);
-               reg_w1(gspca_dev, 0x01, 0x62);
-               reg_w1(gspca_dev, 0x17, 0x64);
-               reg_w1(gspca_dev, 0x17, 0x64);
-               reg_w1(gspca_dev, 0x01, 0x42);
-               msleep(10);
-               reg_w1(gspca_dev, 0x01, 0x42);
-               i2c_w8(gspca_dev, om6802_init0[0]);
-               i2c_w8(gspca_dev, om6802_init0[1]);
-               msleep(15);
-               reg_w1(gspca_dev, 0x02, 0x71);
-               msleep(150);
-               break;
-       case SENSOR_OV7630:
-               reg_w1(gspca_dev, 0x01, 0x61);
-               reg_w1(gspca_dev, 0x17, 0xe2);
-               reg_w1(gspca_dev, 0x01, 0x60);
-               reg_w1(gspca_dev, 0x01, 0x40);
-               break;
-       case SENSOR_OV7648:
-               reg_w1(gspca_dev, 0x01, 0x63);
-               reg_w1(gspca_dev, 0x17, 0x20);
-               reg_w1(gspca_dev, 0x01, 0x62);
-               reg_w1(gspca_dev, 0x01, 0x42);
-               break;
-       case SENSOR_PO1030:
-       case SENSOR_SOI768:
-               reg_w1(gspca_dev, 0x01, 0x61);
-               reg_w1(gspca_dev, 0x17, 0x20);
-               reg_w1(gspca_dev, 0x01, 0x60);
-               reg_w1(gspca_dev, 0x01, 0x40);
-               break;
-       case SENSOR_PO2030N:
-       case SENSOR_OV7660:
-               reg_w1(gspca_dev, 0x01, 0x63);
-               reg_w1(gspca_dev, 0x17, 0x20);
-               reg_w1(gspca_dev, 0x01, 0x62);
-               reg_w1(gspca_dev, 0x01, 0x42);
-               break;
-       case SENSOR_SP80708:
-               reg_w1(gspca_dev, 0x01, 0x63);
-               reg_w1(gspca_dev, 0x17, 0x20);
-               reg_w1(gspca_dev, 0x01, 0x62);
-               reg_w1(gspca_dev, 0x01, 0x42);
-               msleep(100);
-               reg_w1(gspca_dev, 0x02, 0x62);
-               break;
-       default:
-/*     case SENSOR_HV7131R: */
-/*     case SENSOR_MI0360: */
-/*     case SENSOR_MO4000: */
-               reg_w1(gspca_dev, 0x01, 0x43);
-               reg_w1(gspca_dev, 0x17, 0x61);
-               reg_w1(gspca_dev, 0x01, 0x42);
-               if (sd->sensor == SENSOR_HV7131R)
-                       hv7131r_probe(gspca_dev);
-               break;
-       }
-}
-
 /* this function is called at probe time */
 static int sd_config(struct gspca_dev *gspca_dev,
                        const struct usb_device_id *id)
@@ -1898,7 +1782,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
        struct cam *cam;
 
        sd->bridge = id->driver_info >> 16;
-       sd->sensor = id->driver_info;
+       sd->sensor = id->driver_info >> 8;
+       sd->flags = id->driver_info;
 
        cam = &gspca_dev->cam;
        if (sd->sensor == SENSOR_ADCM1700) {
@@ -1929,7 +1814,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
        /* setup a selector by bridge */
        reg_w1(gspca_dev, 0xf1, 0x01);
        reg_r(gspca_dev, 0x00, 1);
-       reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
+       reg_w1(gspca_dev, 0xf1, 0x00);
        reg_r(gspca_dev, 0x00, 1);              /* get sonix chip id */
        regF1 = gspca_dev->usb_buf[0];
        if (gspca_dev->usb_err < 0)
@@ -2423,10 +2308,17 @@ static int sd_start(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        int i;
-       u8 reg1, reg17;
+       u8 reg01, reg17;
+       u8 reg0102[2];
        const u8 *sn9c1xx;
        const u8 (*init)[8];
+       const u8 *reg9a;
        int mode;
+       static const u8 reg9a_def[] =
+               {0x00, 0x40, 0x20, 0x00, 0x00, 0x00};
+       static const u8 reg9a_spec[] =
+               {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
+       static const u8 regd4[] = {0x60, 0x00, 0x00};
        static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
        static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
        static const u8 CA_adcm1700[] =
@@ -2448,7 +2340,85 @@ static int sd_start(struct gspca_dev *gspca_dev)
 
        /* initialize the bridge */
        sn9c1xx = sn_tb[sd->sensor];
-       bridge_init(gspca_dev, sn9c1xx);
+
+       /* sensor clock already enabled in sd_init */
+       /* reg_w1(gspca_dev, 0xf1, 0x00); */
+       reg01 = sn9c1xx[1];
+       if (sd->flags & PDN_INV)
+               reg01 ^= S_PDN_INV;             /* power down inverted */
+       reg_w1(gspca_dev, 0x01, reg01);
+
+       /* configure gpio */
+       reg0102[0] = reg01;
+       reg0102[1] = sn9c1xx[2];
+       if (gspca_dev->audio)
+               reg0102[1] |= 0x04;     /* keep the audio connection */
+       reg_w(gspca_dev, 0x01, reg0102, 2);
+       reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
+       reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5);
+       switch (sd->sensor) {
+       case SENSOR_GC0307:
+       case SENSOR_OV7660:
+       case SENSOR_PO1030:
+       case SENSOR_PO2030N:
+       case SENSOR_SOI768:
+       case SENSOR_SP80708:
+               reg9a = reg9a_spec;
+               break;
+       default:
+               reg9a = reg9a_def;
+               break;
+       }
+       reg_w(gspca_dev, 0x9a, reg9a, 6);
+
+       reg_w(gspca_dev, 0xd4, regd4, sizeof regd4);
+
+       reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
+
+       reg17 = sn9c1xx[0x17];
+       switch (sd->sensor) {
+       case SENSOR_GC0307:
+               msleep(50);             /*fixme: is it useful? */
+               break;
+       case SENSOR_OM6802:
+               msleep(10);
+               reg_w1(gspca_dev, 0x02, 0x73);
+               reg17 |= SEN_CLK_EN;
+               reg_w1(gspca_dev, 0x17, reg17);
+               reg_w1(gspca_dev, 0x01, 0x22);
+               msleep(100);
+               reg01 = SCL_SEL_OD | S_PDN_INV;
+               reg17 &= MCK_SIZE_MASK;
+               reg17 |= 0x04;          /* clock / 4 */
+               break;
+       }
+       reg01 |= SYS_SEL_48M;
+       reg_w1(gspca_dev, 0x01, reg01);
+       reg17 |= SEN_CLK_EN;
+       reg_w1(gspca_dev, 0x17, reg17);
+       reg01 &= ~S_PWR_DN;             /* sensor power on */
+       reg_w1(gspca_dev, 0x01, reg01);
+       reg01 &= ~SYS_SEL_48M;
+       reg_w1(gspca_dev, 0x01, reg01);
+
+       switch (sd->sensor) {
+       case SENSOR_HV7131R:
+               hv7131r_probe(gspca_dev);       /*fixme: is it useful? */
+               break;
+       case SENSOR_OM6802:
+               msleep(10);
+               reg_w1(gspca_dev, 0x01, reg01);
+               i2c_w8(gspca_dev, om6802_init0[0]);
+               i2c_w8(gspca_dev, om6802_init0[1]);
+               msleep(15);
+               reg_w1(gspca_dev, 0x02, 0x71);
+               msleep(150);
+               break;
+       case SENSOR_SP80708:
+               msleep(100);
+               reg_w1(gspca_dev, 0x02, 0x62);
+               break;
+       }
 
        /* initialize the sensor */
        i2c_w_seq(gspca_dev, sensor_init[sd->sensor]);
@@ -2476,30 +2446,11 @@ static int sd_start(struct gspca_dev *gspca_dev)
        }
        reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
        switch (sd->sensor) {
-       case SENSOR_GC0307:
-               reg17 = 0xa2;
-               break;
-       case SENSOR_MT9V111:
-       case SENSOR_MI0360B:
-               reg17 = 0xe0;
-               break;
-       case SENSOR_ADCM1700:
-       case SENSOR_OV7630:
-               reg17 = 0xe2;
-               break;
-       case SENSOR_OV7648:
-               reg17 = 0x20;
-               break;
-       case SENSOR_OV7660:
-       case SENSOR_SOI768:
-               reg17 = 0xa0;
-               break;
-       case SENSOR_PO1030:
-       case SENSOR_PO2030N:
-               reg17 = 0xa0;
+       case SENSOR_OM6802:
+/*     case SENSOR_OV7648:             * fixme: sometimes */
                break;
        default:
-               reg17 = 0x60;
+               reg17 |= DEF_EN;
                break;
        }
        reg_w1(gspca_dev, 0x17, reg17);
@@ -2546,95 +2497,67 @@ static int sd_start(struct gspca_dev *gspca_dev)
 
        init = NULL;
        mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
-       if (mode)
-               reg1 = 0x46;    /* 320x240: clk 48Mhz, video trf enable */
-       else
-               reg1 = 0x06;    /* 640x480: clk 24Mhz, video trf enable */
-       reg17 = 0x61;           /* 0x:20: enable sensor clock */
+       reg01 |= SYS_SEL_48M | V_TX_EN;
+       reg17 &= ~MCK_SIZE_MASK;
+       reg17 |= 0x02;                  /* clock / 2 */
        switch (sd->sensor) {
        case SENSOR_ADCM1700:
                init = adcm1700_sensor_param1;
-               reg1 = 0x46;
-               reg17 = 0xe2;
                break;
        case SENSOR_GC0307:
                init = gc0307_sensor_param1;
-               reg17 = 0xa2;
-               reg1 = 0x44;
+               break;
+       case SENSOR_HV7131R:
+       case SENSOR_MI0360:
+               if (mode)
+                       reg01 |= SYS_SEL_48M;   /* 320x240: clk 48Mhz */
+               else
+                       reg01 &= ~SYS_SEL_48M;  /* 640x480: clk 24Mhz */
+               reg17 &= ~MCK_SIZE_MASK;
+               reg17 |= 0x01;                  /* clock / 1 */
                break;
        case SENSOR_MI0360B:
                init = mi0360b_sensor_param1;
-               reg1 &= ~0x02;          /* don't inverse pin S_PWR_DN */
-               reg17 = 0xe2;
                break;
        case SENSOR_MO4000:
-               if (mode) {
-/*                     reg1 = 0x46;     * 320 clk 48Mhz 60fp/s */
-                       reg1 = 0x06;    /* clk 24Mz */
-               } else {
-                       reg17 = 0x22;   /* 640 MCKSIZE */
-/*                     reg1 = 0x06;     * 640 clk 24Mz (done) */
+               if (mode) {                     /* if 320x240 */
+                       reg01 &= ~SYS_SEL_48M;  /* clk 24Mz */
+                       reg17 &= ~MCK_SIZE_MASK;
+                       reg17 |= 0x01;          /* clock / 1 */
                }
                break;
        case SENSOR_MT9V111:
                init = mt9v111_sensor_param1;
-               if (mode) {
-                       reg1 = 0x04;    /* 320 clk 48Mhz */
-               } else {
-/*                     reg1 = 0x06;     * 640 clk 24Mz (done) */
-                       reg17 = 0xc2;
-               }
                break;
        case SENSOR_OM6802:
                init = om6802_sensor_param1;
-               reg17 = 0x64;           /* 640 MCKSIZE */
+               if (!mode) {                    /* if 640x480 */
+                       reg17 &= ~MCK_SIZE_MASK;
+                       reg17 |= 0x01;          /* clock / 4 */
+               }
                break;
        case SENSOR_OV7630:
                init = ov7630_sensor_param1;
-               reg17 = 0xe2;
-               reg1 = 0x44;
                break;
        case SENSOR_OV7648:
                init = ov7648_sensor_param1;
-               reg17 = 0x21;
-/*             reg1 = 0x42;             * 42 - 46? */
+               reg17 &= ~MCK_SIZE_MASK;
+               reg17 |= 0x01;                  /* clock / 1 */
                break;
        case SENSOR_OV7660:
                init = ov7660_sensor_param1;
-               if (sd->bridge == BRIDGE_SN9C120) {
-                       if (mode) {             /* 320x240 - 160x120 */
-                               reg17 = 0xa2;
-                               reg1 = 0x44;    /* 48 Mhz, video trf eneble */
-                       }
-               } else {
-                       reg17 = 0x22;
-                       reg1 = 0x06;    /* 24 Mhz, video trf eneble
-                                        * inverse power down */
-               }
                break;
        case SENSOR_PO1030:
                init = po1030_sensor_param1;
-               reg17 = 0xa2;
-               reg1 = 0x44;
                break;
        case SENSOR_PO2030N:
                init = po2030n_sensor_param1;
-               reg1 = 0x46;
-               reg17 = 0xa2;
                break;
        case SENSOR_SOI768:
                init = soi768_sensor_param1;
-               reg1 = 0x44;
-               reg17 = 0xa2;
                break;
        case SENSOR_SP80708:
                init = sp80708_sensor_param1;
-               if (mode) {
-/*??                   reg1 = 0x04;     * 320 clk 48Mhz */
-               } else {
-                       reg1 = 0x46;     /* 640 clk 48Mz */
-                       reg17 = 0xa2;
-               }
                break;
        }
 
@@ -2684,7 +2607,9 @@ static int sd_start(struct gspca_dev *gspca_dev)
        setjpegqual(gspca_dev);
 
        reg_w1(gspca_dev, 0x17, reg17);
-       reg_w1(gspca_dev, 0x01, reg1);
+       reg_w1(gspca_dev, 0x01, reg01);
+       sd->reg01 = reg01;
+       sd->reg17 = reg17;
 
        sethvflip(gspca_dev);
        setbrightness(gspca_dev);
@@ -2706,41 +2631,64 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
                { 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };
        static const u8 stopsoi768[] =
                { 0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10 };
-       u8 data;
-       const u8 *sn9c1xx;
+       u8 reg01;
+       u8 reg17;
 
-       data = 0x0b;
+       reg01 = sd->reg01;
+       reg17 = sd->reg17 & ~SEN_CLK_EN;
        switch (sd->sensor) {
+       case SENSOR_ADCM1700:
        case SENSOR_GC0307:
-               data = 0x29;
+       case SENSOR_PO2030N:
+       case SENSOR_SP80708:
+               reg01 |= LED;
+               reg_w1(gspca_dev, 0x01, reg01);
+               reg01 &= ~(LED | V_TX_EN);
+               reg_w1(gspca_dev, 0x01, reg01);
+/*             reg_w1(gspca_dev, 0x02, 0x??);   * LED off ? */
                break;
        case SENSOR_HV7131R:
+               reg01 &= ~V_TX_EN;
+               reg_w1(gspca_dev, 0x01, reg01);
                i2c_w8(gspca_dev, stophv7131);
-               data = 0x2b;
                break;
        case SENSOR_MI0360:
        case SENSOR_MI0360B:
+               reg01 &= ~V_TX_EN;
+               reg_w1(gspca_dev, 0x01, reg01);
+/*             reg_w1(gspca_dev, 0x02, 0x40);    * LED off ? */
                i2c_w8(gspca_dev, stopmi0360);
-               data = 0x29;
                break;
-       case SENSOR_OV7648:
-               i2c_w8(gspca_dev, stopov7648);
-               /* fall thru */
        case SENSOR_MT9V111:
-       case SENSOR_OV7630:
+       case SENSOR_OM6802:
        case SENSOR_PO1030:
-               data = 0x29;
+               reg01 &= ~V_TX_EN;
+               reg_w1(gspca_dev, 0x01, reg01);
+               break;
+       case SENSOR_OV7630:
+       case SENSOR_OV7648:
+               reg01 &= ~V_TX_EN;
+               reg_w1(gspca_dev, 0x01, reg01);
+               i2c_w8(gspca_dev, stopov7648);
+               break;
+       case SENSOR_OV7660:
+               reg01 &= ~V_TX_EN;
+               reg_w1(gspca_dev, 0x01, reg01);
                break;
        case SENSOR_SOI768:
                i2c_w8(gspca_dev, stopsoi768);
-               data = 0x29;
                break;
        }
-       sn9c1xx = sn_tb[sd->sensor];
-       reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
-       reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
-       reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
-       reg_w1(gspca_dev, 0x01, data);
+
+       reg01 |= SCL_SEL_OD;
+       reg_w1(gspca_dev, 0x01, reg01);
+       reg01 |= S_PWR_DN;              /* sensor power down */
+       reg_w1(gspca_dev, 0x01, reg01);
+       reg_w1(gspca_dev, 0x17, reg17);
+       reg01 &= ~SYS_SEL_48M;          /* clock 24MHz */
+       reg_w1(gspca_dev, 0x01, reg01);
+       reg01 |= LED;
+       reg_w1(gspca_dev, 0x01, reg01);
        /* Don't disable sensor clock as that disables the button on the cam */
        /* reg_w1(gspca_dev, 0xf1, 0x01); */
 }
@@ -2954,14 +2902,18 @@ static const struct sd_desc sd_desc = {
 /* -- module initialisation -- */
 #define BS(bridge, sensor) \
        .driver_info = (BRIDGE_ ## bridge << 16) \
-                       | SENSOR_ ## sensor
+                       | (SENSOR_ ## sensor << 8)
+#define BSF(bridge, sensor, flags) \
+       .driver_info = (BRIDGE_ ## bridge << 16) \
+                       | (SENSOR_ ## sensor << 8) \
+                       | (flags)
 static const __devinitdata struct usb_device_id device_table[] = {
 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
        {USB_DEVICE(0x0458, 0x7025), BS(SN9C120, MI0360)},
        {USB_DEVICE(0x0458, 0x702e), BS(SN9C120, OV7660)},
 #endif
-       {USB_DEVICE(0x045e, 0x00f5), BS(SN9C105, OV7660)},
-       {USB_DEVICE(0x045e, 0x00f7), BS(SN9C105, OV7660)},
+       {USB_DEVICE(0x045e, 0x00f5), BSF(SN9C105, OV7660, PDN_INV)},
+       {USB_DEVICE(0x045e, 0x00f7), BSF(SN9C105, OV7660, PDN_INV)},
        {USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)},
        {USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)},
        {USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)},
index 9e8039ac909edeba272093a9d640abd021e975e8..665191c9b4079a2cae48f453c74832acb21d7b8d 100644 (file)
@@ -239,19 +239,16 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx)
                return -1;
        if (hw == IVTV_HW_TUNER) {
                /* special tuner handling */
-               sd = v4l2_i2c_new_subdev(&itv->v4l2_dev,
-                               adap, NULL, type,
-                               0, itv->card_i2c->radio);
+               sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, type, 0,
+                               itv->card_i2c->radio);
                if (sd)
                        sd->grp_id = 1 << idx;
-               sd = v4l2_i2c_new_subdev(&itv->v4l2_dev,
-                               adap, NULL, type,
-                               0, itv->card_i2c->demod);
+               sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, type, 0,
+                               itv->card_i2c->demod);
                if (sd)
                        sd->grp_id = 1 << idx;
-               sd = v4l2_i2c_new_subdev(&itv->v4l2_dev,
-                               adap, NULL, type,
-                               0, itv->card_i2c->tv);
+               sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, type, 0,
+                               itv->card_i2c->tv);
                if (sd)
                        sd->grp_id = 1 << idx;
                return sd ? 0 : -1;
@@ -267,17 +264,16 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx)
        /* It's an I2C device other than an analog tuner or IR chip */
        if (hw == IVTV_HW_UPD64031A || hw == IVTV_HW_UPD6408X) {
                sd = v4l2_i2c_new_subdev(&itv->v4l2_dev,
-                               adap, NULL, type, 0, I2C_ADDRS(hw_addrs[idx]));
+                               adap, type, 0, I2C_ADDRS(hw_addrs[idx]));
        } else if (hw == IVTV_HW_CX25840) {
                struct cx25840_platform_data pdata;
 
                pdata.pvr150_workaround = itv->pvr150_workaround;
                sd = v4l2_i2c_new_subdev_cfg(&itv->v4l2_dev,
-                               adap, NULL, type, 0, &pdata, hw_addrs[idx],
-                               NULL);
+                               adap, type, 0, &pdata, hw_addrs[idx], NULL);
        } else {
                sd = v4l2_i2c_new_subdev(&itv->v4l2_dev,
-                               adap, NULL, type, hw_addrs[idx], NULL);
+                               adap, type, hw_addrs[idx], NULL);
        }
        if (sd)
                sd->grp_id = 1 << idx;
index 2be23bccd3c89e9a72b1131cb6bf1804df1434d0..48d2c2419c13134abf0c55cdf347bdfd97c897bd 100644 (file)
@@ -1659,7 +1659,7 @@ static const struct v4l2_file_operations meye_fops = {
        .open           = meye_open,
        .release        = meye_release,
        .mmap           = meye_mmap,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .poll           = meye_poll,
 };
 
@@ -1831,12 +1831,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
        msleep(1);
        mchip_set(MCHIP_MM_INTA, MCHIP_MM_INTA_HIC_1_MASK);
 
-       if (video_register_device(meye.vdev, VFL_TYPE_GRABBER,
-                                 video_nr) < 0) {
-               v4l2_err(v4l2_dev, "video_register_device failed\n");
-               goto outvideoreg;
-       }
-
        mutex_init(&meye.lock);
        init_waitqueue_head(&meye.proc_list);
        meye.brightness = 32 << 10;
@@ -1858,6 +1852,12 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
        sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE, 0);
        sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC, 48);
 
+       if (video_register_device(meye.vdev, VFL_TYPE_GRABBER,
+                                 video_nr) < 0) {
+               v4l2_err(v4l2_dev, "video_register_device failed\n");
+               goto outvideoreg;
+       }
+
        v4l2_info(v4l2_dev, "Motion Eye Camera Driver v%s.\n",
               MEYE_DRIVER_VERSION);
        v4l2_info(v4l2_dev, "mchip KL5A72002 rev. %d, base %lx, irq %d\n",
index 94ba698d0ad4228d3d07e6653d594773c42ab3c0..4e8fd965f151c64f493f08f3c088c5055af79877 100644 (file)
@@ -185,17 +185,17 @@ static int mxb_probe(struct saa7146_dev *dev)
        }
 
        mxb->saa7111a = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
-                       NULL, "saa7111", I2C_SAA7111A, NULL);
+                       "saa7111", I2C_SAA7111A, NULL);
        mxb->tea6420_1 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
-                       NULL, "tea6420", I2C_TEA6420_1, NULL);
+                       "tea6420", I2C_TEA6420_1, NULL);
        mxb->tea6420_2 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
-                       NULL, "tea6420", I2C_TEA6420_2, NULL);
+                       "tea6420", I2C_TEA6420_2, NULL);
        mxb->tea6415c = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
-                       NULL, "tea6415c", I2C_TEA6415C, NULL);
+                       "tea6415c", I2C_TEA6415C, NULL);
        mxb->tda9840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
-                       NULL, "tda9840", I2C_TDA9840, NULL);
+                       "tda9840", I2C_TDA9840, NULL);
        mxb->tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
-                       NULL, "tuner", I2C_TUNER, NULL);
+                       "tuner", I2C_TUNER, NULL);
 
        /* check if all devices are present */
        if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c ||
index 7129b50757dbd7605fa13449bd7793511019f52f..7551907f8c280f4b9f896094ea9fe0cc079bfd19 100644 (file)
@@ -932,7 +932,7 @@ static ssize_t pms_read(struct file *file, char __user *buf,
 
 static const struct v4l2_file_operations pms_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .read           = pms_read,
 };
 
index bef202752cc8da599aa08f05262c328628bd1e0a..66ad516bdfd97070380b1592d14be35ea978acc0 100644 (file)
@@ -2088,16 +2088,14 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw,
                           " Setting up with specified i2c address 0x%x",
                           mid, i2caddr[0]);
                sd = v4l2_i2c_new_subdev(&hdw->v4l2_dev, &hdw->i2c_adap,
-                                        NULL, fname,
-                                        i2caddr[0], NULL);
+                                        fname, i2caddr[0], NULL);
        } else {
                pvr2_trace(PVR2_TRACE_INIT,
                           "Module ID %u:"
                           " Setting up with address probe list",
                           mid);
                sd = v4l2_i2c_new_subdev(&hdw->v4l2_dev, &hdw->i2c_adap,
-                                               NULL, fname,
-                                               0, i2caddr);
+                                        fname, 0, i2caddr);
        }
 
        if (!sd) {
index e8f13d3e2df14f4b226ac50c6a798f506365f002..1b93207c89e84efbbf6a4e3e8357a7af7f32f90d 100644 (file)
@@ -44,7 +44,7 @@ static struct v4l2_subdev *fimc_subdev_register(struct fimc_dev *fimc,
                return ERR_PTR(-ENOMEM);
 
        sd = v4l2_i2c_new_subdev_board(&vid_cap->v4l2_dev, i2c_adap,
-                                      MODULE_NAME, isp_info->board_info, NULL);
+                                      isp_info->board_info, NULL);
        if (!sd) {
                v4l2_err(&vid_cap->v4l2_dev, "failed to acquire subdev\n");
                return NULL;
index 0911cb580e186a61ac8a2f781eea1eee05954089..1d4d0a49ea52d78405b952acc8c4c2a2f9b844af 100644 (file)
@@ -7551,22 +7551,22 @@ int saa7134_board_init2(struct saa7134_dev *dev)
                   so we do not need to probe for a radio tuner device. */
                if (dev->radio_type != UNSET)
                        v4l2_i2c_new_subdev(&dev->v4l2_dev,
-                               &dev->i2c_adap, NULL, "tuner",
+                               &dev->i2c_adap, "tuner",
                                dev->radio_addr, NULL);
                if (has_demod)
                        v4l2_i2c_new_subdev(&dev->v4l2_dev,
-                               &dev->i2c_adap, NULL, "tuner",
+                               &dev->i2c_adap, "tuner",
                                0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
                if (dev->tuner_addr == ADDR_UNSET) {
                        enum v4l2_i2c_tuner_type type =
                                has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
 
                        v4l2_i2c_new_subdev(&dev->v4l2_dev,
-                               &dev->i2c_adap, NULL, "tuner",
+                               &dev->i2c_adap, "tuner",
                                0, v4l2_i2c_tuner_addrs(type));
                } else {
                        v4l2_i2c_new_subdev(&dev->v4l2_dev,
-                               &dev->i2c_adap, NULL, "tuner",
+                               &dev->i2c_adap, "tuner",
                                dev->tuner_addr, NULL);
                }
        }
index 764d7d219fedb8bef804630b940d6a39a29e0649..756a27812260ac2882dfbfa384ca9b2e3a32be4d 100644 (file)
@@ -991,7 +991,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
        if (card_is_empress(dev)) {
                struct v4l2_subdev *sd =
                        v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-                               NULL, "saa6752hs",
+                               "saa6752hs",
                                saa7134_boards[dev->board].empress_addr, NULL);
 
                if (sd)
@@ -1002,7 +1002,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
                struct v4l2_subdev *sd;
 
                sd = v4l2_i2c_new_subdev(&dev->v4l2_dev,
-                               &dev->i2c_adap, NULL, "saa6588",
+                               &dev->i2c_adap, "saa6588",
                                0, I2C_ADDRS(saa7134_boards[dev->board].rds_addr));
                if (sd) {
                        printk(KERN_INFO "%s: found RDS decoder\n", dev->name);
index 0f4906136b8f9d1fb48054c7b88903f53f00a218..07cf0c6c7c1f7a210c3a078fc580ee68845535c6 100644 (file)
@@ -75,6 +75,7 @@ struct sh_vou_device {
        int pix_idx;
        struct videobuf_buffer *active;
        enum sh_vou_status status;
+       struct mutex fop_lock;
 };
 
 struct sh_vou_file {
@@ -235,7 +236,7 @@ static void free_buffer(struct videobuf_queue *vq, struct videobuf_buffer *vb)
        vb->state = VIDEOBUF_NEEDS_INIT;
 }
 
-/* Locking: caller holds vq->vb_lock mutex */
+/* Locking: caller holds fop_lock mutex */
 static int sh_vou_buf_setup(struct videobuf_queue *vq, unsigned int *count,
                            unsigned int *size)
 {
@@ -257,7 +258,7 @@ static int sh_vou_buf_setup(struct videobuf_queue *vq, unsigned int *count,
        return 0;
 }
 
-/* Locking: caller holds vq->vb_lock mutex */
+/* Locking: caller holds fop_lock mutex */
 static int sh_vou_buf_prepare(struct videobuf_queue *vq,
                              struct videobuf_buffer *vb,
                              enum v4l2_field field)
@@ -306,7 +307,7 @@ static int sh_vou_buf_prepare(struct videobuf_queue *vq,
        return 0;
 }
 
-/* Locking: caller holds vq->vb_lock mutex and vq->irqlock spinlock */
+/* Locking: caller holds fop_lock mutex and vq->irqlock spinlock */
 static void sh_vou_buf_queue(struct videobuf_queue *vq,
                             struct videobuf_buffer *vb)
 {
@@ -1190,7 +1191,7 @@ static int sh_vou_open(struct file *file)
                                       V4L2_BUF_TYPE_VIDEO_OUTPUT,
                                       V4L2_FIELD_NONE,
                                       sizeof(struct videobuf_buffer), vdev,
-                                      NULL);
+                                      &vou_dev->fop_lock);
 
        return 0;
 }
@@ -1292,7 +1293,7 @@ static const struct v4l2_file_operations sh_vou_fops = {
        .owner          = THIS_MODULE,
        .open           = sh_vou_open,
        .release        = sh_vou_release,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .mmap           = sh_vou_mmap,
        .poll           = sh_vou_poll,
 };
@@ -1331,6 +1332,7 @@ static int __devinit sh_vou_probe(struct platform_device *pdev)
 
        INIT_LIST_HEAD(&vou_dev->queue);
        spin_lock_init(&vou_dev->lock);
+       mutex_init(&vou_dev->fop_lock);
        atomic_set(&vou_dev->use_count, 0);
        vou_dev->pdata = vou_pdata;
        vou_dev->status = SH_VOU_IDLE;
@@ -1388,6 +1390,7 @@ static int __devinit sh_vou_probe(struct platform_device *pdev)
                vdev->tvnorms |= V4L2_STD_PAL;
        vdev->v4l2_dev = &vou_dev->v4l2_dev;
        vdev->release = video_device_release;
+       vdev->lock = &vou_dev->fop_lock;
 
        vou_dev->vdev = vdev;
        video_set_drvdata(vdev, vou_dev);
@@ -1406,7 +1409,7 @@ static int __devinit sh_vou_probe(struct platform_device *pdev)
                goto ereset;
 
        subdev = v4l2_i2c_new_subdev_board(&vou_dev->v4l2_dev, i2c_adap,
-                       NULL, vou_pdata->board_info, NULL);
+                       vou_pdata->board_info, NULL);
        if (!subdev) {
                ret = -ENOMEM;
                goto ei2cnd;
index 28e19daadec953b879084ec539a17eed2da147a6..f49fbfb7dc1377800da49d0c723caa13a5d14e27 100644 (file)
@@ -3238,7 +3238,7 @@ static const struct v4l2_file_operations sn9c102_fops = {
        .owner = THIS_MODULE,
        .open = sn9c102_open,
        .release = sn9c102_release,
-       .ioctl = sn9c102_ioctl,
+       .unlocked_ioctl = sn9c102_ioctl,
        .read = sn9c102_read,
        .poll = sn9c102_poll,
        .mmap = sn9c102_mmap,
index 43848a751d11510c20b82205fe92bf43b2260aed..335120c2021bc2cdbf5de98b59f58cc001144ad5 100644 (file)
@@ -896,7 +896,7 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd,
        icl->board_info->platform_data = icd;
 
        subdev = v4l2_i2c_new_subdev_board(&ici->v4l2_dev, adap,
-                               NULL, icl->board_info, NULL);
+                               icl->board_info, NULL);
        if (!subdev)
                goto ei2cnd;
 
index e3bbae26e3ce7c7112f6abce46a41e856424b056..81dd53bb52673c5e5efdc1ba20a9b73429e80cfc 100644 (file)
@@ -251,7 +251,7 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision)
                   hit-and-miss. */
                mdelay(10);
                v4l2_i2c_new_subdev(&usbvision->v4l2_dev,
-                               &usbvision->i2c_adap, NULL,
+                               &usbvision->i2c_adap,
                                "saa7115_auto", 0, saa711x_addrs);
                break;
        }
@@ -261,14 +261,14 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision)
                struct tuner_setup tun_setup;
 
                sd = v4l2_i2c_new_subdev(&usbvision->v4l2_dev,
-                               &usbvision->i2c_adap, NULL,
+                               &usbvision->i2c_adap,
                                "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
                /* depending on whether we found a demod or not, select
                   the tuner type. */
                type = sd ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
 
                sd = v4l2_i2c_new_subdev(&usbvision->v4l2_dev,
-                               &usbvision->i2c_adap, NULL,
+                               &usbvision->i2c_adap,
                                "tuner", 0, v4l2_i2c_tuner_addrs(type));
 
                if (sd == NULL)
index f169f77366771a925978e65a9eeae7c18d49b812..59f8a9ad3796c3ef5960b4e77f12a7269ea7b7b9 100644 (file)
@@ -785,7 +785,7 @@ static void __uvc_find_control(struct uvc_entity *entity, __u32 v4l2_id,
        }
 }
 
-struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,
+static struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,
        __u32 v4l2_id, struct uvc_control_mapping **mapping)
 {
        struct uvc_control *ctrl = NULL;
@@ -944,6 +944,52 @@ done:
        return ret;
 }
 
+/*
+ * Mapping V4L2 controls to UVC controls can be straighforward if done well.
+ * Most of the UVC controls exist in V4L2, and can be mapped directly. Some
+ * must be grouped (for instance the Red Balance, Blue Balance and Do White
+ * Balance V4L2 controls use the White Balance Component UVC control) or
+ * otherwise translated. The approach we take here is to use a translation
+ * table for the controls that can be mapped directly, and handle the others
+ * manually.
+ */
+int uvc_query_v4l2_menu(struct uvc_video_chain *chain,
+       struct v4l2_querymenu *query_menu)
+{
+       struct uvc_menu_info *menu_info;
+       struct uvc_control_mapping *mapping;
+       struct uvc_control *ctrl;
+       u32 index = query_menu->index;
+       u32 id = query_menu->id;
+       int ret;
+
+       memset(query_menu, 0, sizeof(*query_menu));
+       query_menu->id = id;
+       query_menu->index = index;
+
+       ret = mutex_lock_interruptible(&chain->ctrl_mutex);
+       if (ret < 0)
+               return -ERESTARTSYS;
+
+       ctrl = uvc_find_control(chain, query_menu->id, &mapping);
+       if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       if (query_menu->index >= mapping->menu_count) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       menu_info = &mapping->menu_info[query_menu->index];
+       strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name);
+
+done:
+       mutex_unlock(&chain->ctrl_mutex);
+       return ret;
+}
+
 
 /* --------------------------------------------------------------------------
  * Control transactions
index ed6d5449741c58cb7b546b8a09a0b21f82759794..f14581bd707f0155248f788382fe6452cad7198c 100644 (file)
@@ -89,6 +89,39 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
        queue->type = type;
 }
 
+/*
+ * Free the video buffers.
+ *
+ * This function must be called with the queue lock held.
+ */
+static int __uvc_free_buffers(struct uvc_video_queue *queue)
+{
+       unsigned int i;
+
+       for (i = 0; i < queue->count; ++i) {
+               if (queue->buffer[i].vma_use_count != 0)
+                       return -EBUSY;
+       }
+
+       if (queue->count) {
+               vfree(queue->mem);
+               queue->count = 0;
+       }
+
+       return 0;
+}
+
+int uvc_free_buffers(struct uvc_video_queue *queue)
+{
+       int ret;
+
+       mutex_lock(&queue->mutex);
+       ret = __uvc_free_buffers(queue);
+       mutex_unlock(&queue->mutex);
+
+       return ret;
+}
+
 /*
  * Allocate the video buffers.
  *
@@ -110,7 +143,7 @@ int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
 
        mutex_lock(&queue->mutex);
 
-       if ((ret = uvc_free_buffers(queue)) < 0)
+       if ((ret = __uvc_free_buffers(queue)) < 0)
                goto done;
 
        /* Bail out if no buffers should be allocated. */
@@ -151,28 +184,6 @@ done:
        return ret;
 }
 
-/*
- * Free the video buffers.
- *
- * This function must be called with the queue lock held.
- */
-int uvc_free_buffers(struct uvc_video_queue *queue)
-{
-       unsigned int i;
-
-       for (i = 0; i < queue->count; ++i) {
-               if (queue->buffer[i].vma_use_count != 0)
-                       return -EBUSY;
-       }
-
-       if (queue->count) {
-               vfree(queue->mem);
-               queue->count = 0;
-       }
-
-       return 0;
-}
-
 /*
  * Check if buffers have been allocated.
  */
@@ -368,6 +379,82 @@ done:
        return ret;
 }
 
+/*
+ * VMA operations.
+ */
+static void uvc_vm_open(struct vm_area_struct *vma)
+{
+       struct uvc_buffer *buffer = vma->vm_private_data;
+       buffer->vma_use_count++;
+}
+
+static void uvc_vm_close(struct vm_area_struct *vma)
+{
+       struct uvc_buffer *buffer = vma->vm_private_data;
+       buffer->vma_use_count--;
+}
+
+static const struct vm_operations_struct uvc_vm_ops = {
+       .open           = uvc_vm_open,
+       .close          = uvc_vm_close,
+};
+
+/*
+ * Memory-map a video buffer.
+ *
+ * This function implements video buffers memory mapping and is intended to be
+ * used by the device mmap handler.
+ */
+int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
+{
+       struct uvc_buffer *uninitialized_var(buffer);
+       struct page *page;
+       unsigned long addr, start, size;
+       unsigned int i;
+       int ret = 0;
+
+       start = vma->vm_start;
+       size = vma->vm_end - vma->vm_start;
+
+       mutex_lock(&queue->mutex);
+
+       for (i = 0; i < queue->count; ++i) {
+               buffer = &queue->buffer[i];
+               if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
+                       break;
+       }
+
+       if (i == queue->count || size != queue->buf_size) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       /*
+        * VM_IO marks the area as being an mmaped region for I/O to a
+        * device. It also prevents the region from being core dumped.
+        */
+       vma->vm_flags |= VM_IO;
+
+       addr = (unsigned long)queue->mem + buffer->buf.m.offset;
+       while (size > 0) {
+               page = vmalloc_to_page((void *)addr);
+               if ((ret = vm_insert_page(vma, start, page)) < 0)
+                       goto done;
+
+               start += PAGE_SIZE;
+               addr += PAGE_SIZE;
+               size -= PAGE_SIZE;
+       }
+
+       vma->vm_ops = &uvc_vm_ops;
+       vma->vm_private_data = buffer;
+       uvc_vm_open(vma);
+
+done:
+       mutex_unlock(&queue->mutex);
+       return ret;
+}
+
 /*
  * Poll the video queue.
  *
index 6d15de9b520437a4440dc8da2071efd0b91fe306..8cf61e8a634ffeb7cb23bfe004efc2c60053f1e8 100644 (file)
@@ -100,40 +100,6 @@ done:
  * V4L2 interface
  */
 
-/*
- * Mapping V4L2 controls to UVC controls can be straighforward if done well.
- * Most of the UVC controls exist in V4L2, and can be mapped directly. Some
- * must be grouped (for instance the Red Balance, Blue Balance and Do White
- * Balance V4L2 controls use the White Balance Component UVC control) or
- * otherwise translated. The approach we take here is to use a translation
- * table for the controls that can be mapped directly, and handle the others
- * manually.
- */
-static int uvc_v4l2_query_menu(struct uvc_video_chain *chain,
-       struct v4l2_querymenu *query_menu)
-{
-       struct uvc_menu_info *menu_info;
-       struct uvc_control_mapping *mapping;
-       struct uvc_control *ctrl;
-       u32 index = query_menu->index;
-       u32 id = query_menu->id;
-
-       ctrl = uvc_find_control(chain, query_menu->id, &mapping);
-       if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU)
-               return -EINVAL;
-
-       if (query_menu->index >= mapping->menu_count)
-               return -EINVAL;
-
-       memset(query_menu, 0, sizeof(*query_menu));
-       query_menu->id = id;
-       query_menu->index = index;
-
-       menu_info = &mapping->menu_info[query_menu->index];
-       strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name);
-       return 0;
-}
-
 /*
  * Find the frame interval closest to the requested frame interval for the
  * given frame format and size. This should be done by the device as part of
@@ -260,12 +226,14 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream,
         * developers test their webcams with the Linux driver as well as with
         * the Windows driver).
         */
+       mutex_lock(&stream->mutex);
        if (stream->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS)
                probe->dwMaxVideoFrameSize =
                        stream->ctrl.dwMaxVideoFrameSize;
 
        /* Probe the device. */
        ret = uvc_probe_video(stream, probe);
+       mutex_unlock(&stream->mutex);
        if (ret < 0)
                goto done;
 
@@ -289,14 +257,21 @@ done:
 static int uvc_v4l2_get_format(struct uvc_streaming *stream,
        struct v4l2_format *fmt)
 {
-       struct uvc_format *format = stream->cur_format;
-       struct uvc_frame *frame = stream->cur_frame;
+       struct uvc_format *format;
+       struct uvc_frame *frame;
+       int ret = 0;
 
        if (fmt->type != stream->type)
                return -EINVAL;
 
-       if (format == NULL || frame == NULL)
-               return -EINVAL;
+       mutex_lock(&stream->mutex);
+       format = stream->cur_format;
+       frame = stream->cur_frame;
+
+       if (format == NULL || frame == NULL) {
+               ret = -EINVAL;
+               goto done;
+       }
 
        fmt->fmt.pix.pixelformat = format->fcc;
        fmt->fmt.pix.width = frame->wWidth;
@@ -307,7 +282,9 @@ static int uvc_v4l2_get_format(struct uvc_streaming *stream,
        fmt->fmt.pix.colorspace = format->colorspace;
        fmt->fmt.pix.priv = 0;
 
-       return 0;
+done:
+       mutex_unlock(&stream->mutex);
+       return ret;
 }
 
 static int uvc_v4l2_set_format(struct uvc_streaming *stream,
@@ -321,18 +298,24 @@ static int uvc_v4l2_set_format(struct uvc_streaming *stream,
        if (fmt->type != stream->type)
                return -EINVAL;
 
-       if (uvc_queue_allocated(&stream->queue))
-               return -EBUSY;
-
        ret = uvc_v4l2_try_format(stream, fmt, &probe, &format, &frame);
        if (ret < 0)
                return ret;
 
+       mutex_lock(&stream->mutex);
+
+       if (uvc_queue_allocated(&stream->queue)) {
+               ret = -EBUSY;
+               goto done;
+       }
+
        memcpy(&stream->ctrl, &probe, sizeof probe);
        stream->cur_format = format;
        stream->cur_frame = frame;
 
-       return 0;
+done:
+       mutex_unlock(&stream->mutex);
+       return ret;
 }
 
 static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,
@@ -343,7 +326,10 @@ static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,
        if (parm->type != stream->type)
                return -EINVAL;
 
+       mutex_lock(&stream->mutex);
        numerator = stream->ctrl.dwFrameInterval;
+       mutex_unlock(&stream->mutex);
+
        denominator = 10000000;
        uvc_simplify_fraction(&numerator, &denominator, 8, 333);
 
@@ -370,7 +356,6 @@ static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,
 static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream,
                struct v4l2_streamparm *parm)
 {
-       struct uvc_frame *frame = stream->cur_frame;
        struct uvc_streaming_control probe;
        struct v4l2_fract timeperframe;
        uint32_t interval;
@@ -379,28 +364,36 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream,
        if (parm->type != stream->type)
                return -EINVAL;
 
-       if (uvc_queue_streaming(&stream->queue))
-               return -EBUSY;
-
        if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
                timeperframe = parm->parm.capture.timeperframe;
        else
                timeperframe = parm->parm.output.timeperframe;
 
-       memcpy(&probe, &stream->ctrl, sizeof probe);
        interval = uvc_fraction_to_interval(timeperframe.numerator,
                timeperframe.denominator);
-
        uvc_trace(UVC_TRACE_FORMAT, "Setting frame interval to %u/%u (%u).\n",
                timeperframe.numerator, timeperframe.denominator, interval);
-       probe.dwFrameInterval = uvc_try_frame_interval(frame, interval);
+
+       mutex_lock(&stream->mutex);
+
+       if (uvc_queue_streaming(&stream->queue)) {
+               mutex_unlock(&stream->mutex);
+               return -EBUSY;
+       }
+
+       memcpy(&probe, &stream->ctrl, sizeof probe);
+       probe.dwFrameInterval =
+               uvc_try_frame_interval(stream->cur_frame, interval);
 
        /* Probe the device with the new settings. */
        ret = uvc_probe_video(stream, &probe);
-       if (ret < 0)
+       if (ret < 0) {
+               mutex_unlock(&stream->mutex);
                return ret;
+       }
 
        memcpy(&stream->ctrl, &probe, sizeof probe);
+       mutex_unlock(&stream->mutex);
 
        /* Return the actual frame period. */
        timeperframe.numerator = probe.dwFrameInterval;
@@ -528,11 +521,9 @@ static int uvc_v4l2_release(struct file *file)
        if (uvc_has_privileges(handle)) {
                uvc_video_enable(stream, 0);
 
-               mutex_lock(&stream->queue.mutex);
                if (uvc_free_buffers(&stream->queue) < 0)
                        uvc_printk(KERN_ERR, "uvc_v4l2_release: Unable to "
                                        "free buffers.\n");
-               mutex_unlock(&stream->queue.mutex);
        }
 
        /* Release the file handle. */
@@ -624,7 +615,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        }
 
        case VIDIOC_QUERYMENU:
-               return uvc_v4l2_query_menu(chain, arg);
+               return uvc_query_v4l2_menu(chain, arg);
 
        case VIDIOC_G_EXT_CTRLS:
        {
@@ -905,15 +896,17 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        case VIDIOC_CROPCAP:
        {
                struct v4l2_cropcap *ccap = arg;
-               struct uvc_frame *frame = stream->cur_frame;
 
                if (ccap->type != stream->type)
                        return -EINVAL;
 
                ccap->bounds.left = 0;
                ccap->bounds.top = 0;
-               ccap->bounds.width = frame->wWidth;
-               ccap->bounds.height = frame->wHeight;
+
+               mutex_lock(&stream->mutex);
+               ccap->bounds.width = stream->cur_frame->wWidth;
+               ccap->bounds.height = stream->cur_frame->wHeight;
+               mutex_unlock(&stream->mutex);
 
                ccap->defrect = ccap->bounds;
 
@@ -930,8 +923,6 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        case VIDIOC_REQBUFS:
        {
                struct v4l2_requestbuffers *rb = arg;
-               unsigned int bufsize =
-                       stream->ctrl.dwMaxVideoFrameSize;
 
                if (rb->type != stream->type ||
                    rb->memory != V4L2_MEMORY_MMAP)
@@ -940,7 +931,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                if ((ret = uvc_acquire_privileges(handle)) < 0)
                        return ret;
 
-               ret = uvc_alloc_buffers(&stream->queue, rb->count, bufsize);
+               mutex_lock(&stream->mutex);
+               ret = uvc_alloc_buffers(&stream->queue, rb->count,
+                                       stream->ctrl.dwMaxVideoFrameSize);
+               mutex_unlock(&stream->mutex);
                if (ret < 0)
                        return ret;
 
@@ -988,7 +982,9 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                if (!uvc_has_privileges(handle))
                        return -EBUSY;
 
+               mutex_lock(&stream->mutex);
                ret = uvc_video_enable(stream, 1);
+               mutex_unlock(&stream->mutex);
                if (ret < 0)
                        return ret;
                break;
@@ -1068,79 +1064,14 @@ static ssize_t uvc_v4l2_read(struct file *file, char __user *data,
        return -EINVAL;
 }
 
-/*
- * VMA operations.
- */
-static void uvc_vm_open(struct vm_area_struct *vma)
-{
-       struct uvc_buffer *buffer = vma->vm_private_data;
-       buffer->vma_use_count++;
-}
-
-static void uvc_vm_close(struct vm_area_struct *vma)
-{
-       struct uvc_buffer *buffer = vma->vm_private_data;
-       buffer->vma_use_count--;
-}
-
-static const struct vm_operations_struct uvc_vm_ops = {
-       .open           = uvc_vm_open,
-       .close          = uvc_vm_close,
-};
-
 static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct uvc_fh *handle = file->private_data;
        struct uvc_streaming *stream = handle->stream;
-       struct uvc_video_queue *queue = &stream->queue;
-       struct uvc_buffer *uninitialized_var(buffer);
-       struct page *page;
-       unsigned long addr, start, size;
-       unsigned int i;
-       int ret = 0;
 
        uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_mmap\n");
 
-       start = vma->vm_start;
-       size = vma->vm_end - vma->vm_start;
-
-       mutex_lock(&queue->mutex);
-
-       for (i = 0; i < queue->count; ++i) {
-               buffer = &queue->buffer[i];
-               if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
-                       break;
-       }
-
-       if (i == queue->count || size != queue->buf_size) {
-               ret = -EINVAL;
-               goto done;
-       }
-
-       /*
-        * VM_IO marks the area as being an mmaped region for I/O to a
-        * device. It also prevents the region from being core dumped.
-        */
-       vma->vm_flags |= VM_IO;
-
-       addr = (unsigned long)queue->mem + buffer->buf.m.offset;
-       while (size > 0) {
-               page = vmalloc_to_page((void *)addr);
-               if ((ret = vm_insert_page(vma, start, page)) < 0)
-                       goto done;
-
-               start += PAGE_SIZE;
-               addr += PAGE_SIZE;
-               size -= PAGE_SIZE;
-       }
-
-       vma->vm_ops = &uvc_vm_ops;
-       vma->vm_private_data = buffer;
-       uvc_vm_open(vma);
-
-done:
-       mutex_unlock(&queue->mutex);
-       return ret;
+       return uvc_queue_mmap(&stream->queue, vma);
 }
 
 static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait)
@@ -1157,7 +1088,7 @@ const struct v4l2_file_operations uvc_fops = {
        .owner          = THIS_MODULE,
        .open           = uvc_v4l2_open,
        .release        = uvc_v4l2_release,
-       .ioctl          = uvc_v4l2_ioctl,
+       .unlocked_ioctl = uvc_v4l2_ioctl,
        .read           = uvc_v4l2_read,
        .mmap           = uvc_v4l2_mmap,
        .poll           = uvc_v4l2_poll,
index 5555f01028385b3287952a53d45b2477db021582..5673d673504b838f510966c31c46c078da032bdd 100644 (file)
@@ -293,8 +293,6 @@ int uvc_probe_video(struct uvc_streaming *stream,
        unsigned int i;
        int ret;
 
-       mutex_lock(&stream->mutex);
-
        /* Perform probing. The device should adjust the requested values
         * according to its capabilities. However, some devices, namely the
         * first generation UVC Logitech webcams, don't implement the Video
@@ -346,7 +344,6 @@ int uvc_probe_video(struct uvc_streaming *stream,
        }
 
 done:
-       mutex_unlock(&stream->mutex);
        return ret;
 }
 
index d97cf6d6a4f96c5ef6da3c3b48de0c83652ace70..45f01e7e13d2f90abd30466c8390c8fcecc4fb5a 100644 (file)
@@ -436,7 +436,9 @@ struct uvc_streaming {
        struct uvc_streaming_control ctrl;
        struct uvc_format *cur_format;
        struct uvc_frame *cur_frame;
-
+       /* Protect access to ctrl, cur_format, cur_frame and hardware video
+        * probe control.
+        */
        struct mutex mutex;
 
        unsigned int frozen : 1;
@@ -574,6 +576,8 @@ extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable);
 extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect);
 extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
                struct uvc_buffer *buf);
+extern int uvc_queue_mmap(struct uvc_video_queue *queue,
+               struct vm_area_struct *vma);
 extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
                struct file *file, poll_table *wait);
 extern int uvc_queue_allocated(struct uvc_video_queue *queue);
@@ -606,10 +610,10 @@ extern int uvc_status_suspend(struct uvc_device *dev);
 extern int uvc_status_resume(struct uvc_device *dev);
 
 /* Controls */
-extern struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,
-               __u32 v4l2_id, struct uvc_control_mapping **mapping);
 extern int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
                struct v4l2_queryctrl *v4l2_ctrl);
+extern int uvc_query_v4l2_menu(struct uvc_video_chain *chain,
+               struct v4l2_querymenu *query_menu);
 
 extern int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
                const struct uvc_control_mapping *mapping);
index 9294282b5add27c04ada832d498f7f11aa0ef323..b5eb1f3950b133c6ed76b5e32adc894b07fb3bdf 100644 (file)
@@ -368,18 +368,15 @@ EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_init);
 
 /* Load an i2c sub-device. */
 struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev,
-               struct i2c_adapter *adapter, const char *module_name,
-               struct i2c_board_info *info, const unsigned short *probe_addrs)
+               struct i2c_adapter *adapter, struct i2c_board_info *info,
+               const unsigned short *probe_addrs)
 {
        struct v4l2_subdev *sd = NULL;
        struct i2c_client *client;
 
        BUG_ON(!v4l2_dev);
 
-       if (module_name)
-               request_module(module_name);
-       else
-               request_module(I2C_MODULE_PREFIX "%s", info->type);
+       request_module(I2C_MODULE_PREFIX "%s", info->type);
 
        /* Create the i2c client */
        if (info->addr == 0 && probe_addrs)
@@ -432,8 +429,7 @@ error:
 EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_board);
 
 struct v4l2_subdev *v4l2_i2c_new_subdev_cfg(struct v4l2_device *v4l2_dev,
-               struct i2c_adapter *adapter,
-               const char *module_name, const char *client_type,
+               struct i2c_adapter *adapter, const char *client_type,
                int irq, void *platform_data,
                u8 addr, const unsigned short *probe_addrs)
 {
@@ -447,8 +443,7 @@ struct v4l2_subdev *v4l2_i2c_new_subdev_cfg(struct v4l2_device *v4l2_dev,
        info.irq = irq;
        info.platform_data = platform_data;
 
-       return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, module_name,
-                       &info, probe_addrs);
+       return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, probe_addrs);
 }
 EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_cfg);
 
index 03f7f4670e9badd4491f8cddb8e748a848c14119..359e23290a7e99ae0301a6d6844a445343cb900e 100644 (file)
@@ -186,12 +186,12 @@ static ssize_t v4l2_read(struct file *filp, char __user *buf,
                size_t sz, loff_t *off)
 {
        struct video_device *vdev = video_devdata(filp);
-       int ret = -EIO;
+       int ret = -ENODEV;
 
        if (!vdev->fops->read)
                return -EINVAL;
-       if (vdev->lock)
-               mutex_lock(vdev->lock);
+       if (vdev->lock && mutex_lock_interruptible(vdev->lock))
+               return -ERESTARTSYS;
        if (video_is_registered(vdev))
                ret = vdev->fops->read(filp, buf, sz, off);
        if (vdev->lock)
@@ -203,12 +203,12 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf,
                size_t sz, loff_t *off)
 {
        struct video_device *vdev = video_devdata(filp);
-       int ret = -EIO;
+       int ret = -ENODEV;
 
        if (!vdev->fops->write)
                return -EINVAL;
-       if (vdev->lock)
-               mutex_lock(vdev->lock);
+       if (vdev->lock && mutex_lock_interruptible(vdev->lock))
+               return -ERESTARTSYS;
        if (video_is_registered(vdev))
                ret = vdev->fops->write(filp, buf, sz, off);
        if (vdev->lock)
@@ -219,10 +219,10 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf,
 static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll)
 {
        struct video_device *vdev = video_devdata(filp);
-       int ret = DEFAULT_POLLMASK;
+       int ret = POLLERR | POLLHUP;
 
        if (!vdev->fops->poll)
-               return ret;
+               return DEFAULT_POLLMASK;
        if (vdev->lock)
                mutex_lock(vdev->lock);
        if (video_is_registered(vdev))
@@ -238,20 +238,45 @@ static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        int ret = -ENODEV;
 
        if (vdev->fops->unlocked_ioctl) {
-               if (vdev->lock)
-                       mutex_lock(vdev->lock);
+               if (vdev->lock && mutex_lock_interruptible(vdev->lock))
+                       return -ERESTARTSYS;
                if (video_is_registered(vdev))
                        ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);
                if (vdev->lock)
                        mutex_unlock(vdev->lock);
        } else if (vdev->fops->ioctl) {
-               /* TODO: convert all drivers to unlocked_ioctl */
+               /* This code path is a replacement for the BKL. It is a major
+                * hack but it will have to do for those drivers that are not
+                * yet converted to use unlocked_ioctl.
+                *
+                * There are two options: if the driver implements struct
+                * v4l2_device, then the lock defined there is used to
+                * serialize the ioctls. Otherwise the v4l2 core lock defined
+                * below is used. This lock is really bad since it serializes
+                * completely independent devices.
+                *
+                * Both variants suffer from the same problem: if the driver
+                * sleeps, then it blocks all ioctls since the lock is still
+                * held. This is very common for VIDIOC_DQBUF since that
+                * normally waits for a frame to arrive. As a result any other
+                * ioctl calls will proceed very, very slowly since each call
+                * will have to wait for the VIDIOC_QBUF to finish. Things that
+                * should take 0.01s may now take 10-20 seconds.
+                *
+                * The workaround is to *not* take the lock for VIDIOC_DQBUF.
+                * This actually works OK for videobuf-based drivers, since
+                * videobuf will take its own internal lock.
+                */
                static DEFINE_MUTEX(v4l2_ioctl_mutex);
+               struct mutex *m = vdev->v4l2_dev ?
+                       &vdev->v4l2_dev->ioctl_lock : &v4l2_ioctl_mutex;
 
-               mutex_lock(&v4l2_ioctl_mutex);
+               if (cmd != VIDIOC_DQBUF && mutex_lock_interruptible(m))
+                       return -ERESTARTSYS;
                if (video_is_registered(vdev))
                        ret = vdev->fops->ioctl(filp, cmd, arg);
-               mutex_unlock(&v4l2_ioctl_mutex);
+               if (cmd != VIDIOC_DQBUF)
+                       mutex_unlock(m);
        } else
                ret = -ENOTTY;
 
@@ -265,8 +290,8 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm)
 
        if (!vdev->fops->mmap)
                return ret;
-       if (vdev->lock)
-               mutex_lock(vdev->lock);
+       if (vdev->lock && mutex_lock_interruptible(vdev->lock))
+               return -ERESTARTSYS;
        if (video_is_registered(vdev))
                ret = vdev->fops->mmap(filp, vm);
        if (vdev->lock)
@@ -284,7 +309,7 @@ static int v4l2_open(struct inode *inode, struct file *filp)
        mutex_lock(&videodev_lock);
        vdev = video_devdata(filp);
        /* return ENODEV if the video device has already been removed. */
-       if (vdev == NULL) {
+       if (vdev == NULL || !video_is_registered(vdev)) {
                mutex_unlock(&videodev_lock);
                return -ENODEV;
        }
@@ -292,8 +317,10 @@ static int v4l2_open(struct inode *inode, struct file *filp)
        video_get(vdev);
        mutex_unlock(&videodev_lock);
        if (vdev->fops->open) {
-               if (vdev->lock)
-                       mutex_lock(vdev->lock);
+               if (vdev->lock && mutex_lock_interruptible(vdev->lock)) {
+                       ret = -ERESTARTSYS;
+                       goto err;
+               }
                if (video_is_registered(vdev))
                        ret = vdev->fops->open(filp);
                else
@@ -302,6 +329,7 @@ static int v4l2_open(struct inode *inode, struct file *filp)
                        mutex_unlock(vdev->lock);
        }
 
+err:
        /* decrease the refcount in case of an error */
        if (ret)
                video_put(vdev);
@@ -596,7 +624,12 @@ void video_unregister_device(struct video_device *vdev)
        if (!vdev || !video_is_registered(vdev))
                return;
 
+       mutex_lock(&videodev_lock);
+       /* This must be in a critical section to prevent a race with v4l2_open.
+        * Once this bit has been cleared video_get may never be called again.
+        */
        clear_bit(V4L2_FL_REGISTERED, &vdev->flags);
+       mutex_unlock(&videodev_lock);
        device_unregister(&vdev->dev);
 }
 EXPORT_SYMBOL(video_unregister_device);
index 0b08f96b74a5ed5c750fdcc7541d2e38f069d79f..7fe6f92af480bc46288b3eff1d0358a30bd501e4 100644 (file)
@@ -35,6 +35,7 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)
 
        INIT_LIST_HEAD(&v4l2_dev->subdevs);
        spin_lock_init(&v4l2_dev->lock);
+       mutex_init(&v4l2_dev->ioctl_lock);
        v4l2_dev->dev = dev;
        if (dev == NULL) {
                /* If dev == NULL, then name must be filled in by the caller */
index 02a21bccae1836b464455eb14d6e64788715f228..9eda7cc03121c1c1ceb3632fca58bff4e8701ca8 100644 (file)
@@ -1360,7 +1360,7 @@ static __devinit int viacam_probe(struct platform_device *pdev)
         */
        sensor_adapter = viafb_find_i2c_adapter(VIA_PORT_31);
        cam->sensor = v4l2_i2c_new_subdev(&cam->v4l2_dev, sensor_adapter,
-                       "ov7670", "ov7670", 0x42 >> 1, NULL);
+                       "ov7670", 0x42 >> 1, NULL);
        if (cam->sensor == NULL) {
                dev_err(&pdev->dev, "Unable to find the sensor!\n");
                ret = -ENODEV;
index e5e005dc15543a2ab7d86aa6c0331ff60b540f46..7e7eec48f8b12bd305a6f92539ba650ec727f9f2 100644 (file)
@@ -4334,10 +4334,10 @@ static int __init vino_module_init(void)
 
        vino_drvdata->decoder =
                v4l2_i2c_new_subdev(&vino_drvdata->v4l2_dev, &vino_i2c_adapter,
-                              NULL, "saa7191", 0, I2C_ADDRS(0x45));
+                              "saa7191", 0, I2C_ADDRS(0x45));
        vino_drvdata->camera =
                v4l2_i2c_new_subdev(&vino_drvdata->v4l2_dev, &vino_i2c_adapter,
-                              NULL, "indycam", 0, I2C_ADDRS(0x2b));
+                              "indycam", 0, I2C_ADDRS(0x2b));
 
        dprintk("init complete!\n");
 
index 635420d8d84a0536557582bbf507b4ae14f86f01..019ee206cbee0224fb71c9a86678c05ecf3da7d2 100644 (file)
@@ -815,7 +815,7 @@ out:
 
 static const struct v4l2_file_operations w9966_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .read           = w9966_v4l_read,
 };
 
index 7e6d62467eaaa7bd1e913d5ce104608005ccbc58..e520abf9f4c3d8fc40d108ef2fbf47e55db772f5 100644 (file)
@@ -1343,13 +1343,12 @@ static int __devinit zoran_probe(struct pci_dev *pdev,
        }
 
        zr->decoder = v4l2_i2c_new_subdev(&zr->v4l2_dev,
-               &zr->i2c_adapter, NULL, zr->card.i2c_decoder,
+               &zr->i2c_adapter, zr->card.i2c_decoder,
                0, zr->card.addrs_decoder);
 
        if (zr->card.i2c_encoder)
                zr->encoder = v4l2_i2c_new_subdev(&zr->v4l2_dev,
-                       &zr->i2c_adapter,
-                       NULL, zr->card.i2c_encoder,
+                       &zr->i2c_adapter, zr->card.i2c_encoder,
                        0, zr->card.addrs_encoder);
 
        dprintk(2,
index ca47e62850752b80772bd3d77a246bfe1109b742..307aada5fffeca067520a55eecb6c020c80bd7a6 100644 (file)
@@ -183,9 +183,7 @@ static int  isl29020_probe(struct i2c_client *client,
 
 static int isl29020_remove(struct i2c_client *client)
 {
-       struct als_data *data = i2c_get_clientdata(client);
        sysfs_remove_group(&client->dev.kobj, &m_als_gr);
-       kfree(data);
        return 0;
 }
 
@@ -245,6 +243,6 @@ static void  __exit sensor_isl29020_exit(void)
 module_init(sensor_isl29020_init);
 module_exit(sensor_isl29020_exit);
 
-MODULE_AUTHOR("Kalhan Trisal <kalhan.trisal@intel.com");
+MODULE_AUTHOR("Kalhan Trisal <kalhan.trisal@intel.com>");
 MODULE_DESCRIPTION("Intersil isl29020 ALS Driver");
 MODULE_LICENSE("GPL v2");
index d551f09ccb792175d49a83c4a929df7394f50a8a..6956f7e7d43921ec80f5e450a471429bc21f55fc 100644 (file)
@@ -439,18 +439,23 @@ xpc_discovery(void)
         * nodes that can comprise an access protection grouping. The access
         * protection is in regards to memory, IOI and IPI.
         */
-       max_regions = 64;
        region_size = xp_region_size;
 
-       switch (region_size) {
-       case 128:
-               max_regions *= 2;
-       case 64:
-               max_regions *= 2;
-       case 32:
-               max_regions *= 2;
-               region_size = 16;
-               DBUG_ON(!is_shub2());
+       if (is_uv())
+               max_regions = 256;
+       else {
+               max_regions = 64;
+
+               switch (region_size) {
+               case 128:
+                       max_regions *= 2;
+               case 64:
+                       max_regions *= 2;
+               case 32:
+                       max_regions *= 2;
+                       region_size = 16;
+                       DBUG_ON(!is_shub2());
+               }
        }
 
        for (region = 0; region < max_regions; region++) {
index 8f86d702e46eebce56bdb00f6f22d4d6b8205100..31ae07a36576678fb27dbd294623f6f8ac21cc9d 100644 (file)
@@ -1559,7 +1559,7 @@ void mmc_stop_host(struct mmc_host *host)
 
        if (host->caps & MMC_CAP_DISABLE)
                cancel_delayed_work(&host->disable);
-       cancel_delayed_work(&host->detect);
+       cancel_delayed_work_sync(&host->detect);
        mmc_flush_scheduled_work();
 
        /* clear pm flags now and let card drivers set them as needed */
index 995261f7fd70165e92caa8a3ec16f0e75e2e2fcc..77f93c3b88086d5ee802da97ae03754d86c82e9a 100644 (file)
@@ -375,7 +375,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        struct mmc_card *oldcard)
 {
        struct mmc_card *card;
-       int err, ddr = MMC_SDR_MODE;
+       int err, ddr = 0;
        u32 cid[4];
        unsigned int max_dtr;
 
@@ -562,7 +562,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                               1 << bus_width, ddr);
                        err = 0;
                } else {
-                       mmc_card_set_ddr_mode(card);
+                       if (ddr)
+                               mmc_card_set_ddr_mode(card);
+                       else
+                               ddr = MMC_SDR_MODE;
+
                        mmc_set_bus_width_ddr(card->host, bus_width, ddr);
                }
        }
index c3ad1058cd318627b8290c756c6a2f2e0d2d8027..efef5f94ac429081c5211a984a100b575c5fd986 100644 (file)
@@ -547,9 +547,11 @@ static void mmc_sdio_detect(struct mmc_host *host)
        BUG_ON(!host->card);
 
        /* Make sure card is powered before detecting it */
-       err = pm_runtime_get_sync(&host->card->dev);
-       if (err < 0)
-               goto out;
+       if (host->caps & MMC_CAP_POWER_OFF_CARD) {
+               err = pm_runtime_get_sync(&host->card->dev);
+               if (err < 0)
+                       goto out;
+       }
 
        mmc_claim_host(host);
 
@@ -560,6 +562,20 @@ static void mmc_sdio_detect(struct mmc_host *host)
 
        mmc_release_host(host);
 
+       /*
+        * Tell PM core it's OK to power off the card now.
+        *
+        * The _sync variant is used in order to ensure that the card
+        * is left powered off in case an error occurred, and the card
+        * is going to be removed.
+        *
+        * Since there is no specific reason to believe a new user
+        * is about to show up at this point, the _sync variant is
+        * desirable anyway.
+        */
+       if (host->caps & MMC_CAP_POWER_OFF_CARD)
+               pm_runtime_put_sync(&host->card->dev);
+
 out:
        if (err) {
                mmc_sdio_remove(host);
@@ -568,9 +584,6 @@ out:
                mmc_detach_bus(host);
                mmc_release_host(host);
        }
-
-       /* Tell PM core that we're done */
-       pm_runtime_put(&host->card->dev);
 }
 
 /*
@@ -718,16 +731,21 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
        card = host->card;
 
        /*
-        * Let runtime PM core know our card is active
+        * Enable runtime PM only if supported by host+card+board
         */
-       err = pm_runtime_set_active(&card->dev);
-       if (err)
-               goto remove;
+       if (host->caps & MMC_CAP_POWER_OFF_CARD) {
+               /*
+                * Let runtime PM core know our card is active
+                */
+               err = pm_runtime_set_active(&card->dev);
+               if (err)
+                       goto remove;
 
-       /*
-        * Enable runtime PM for this card
-        */
-       pm_runtime_enable(&card->dev);
+               /*
+                * Enable runtime PM for this card
+                */
+               pm_runtime_enable(&card->dev);
+       }
 
        /*
         * The number of functions on the card is encoded inside
@@ -745,9 +763,10 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
                        goto remove;
 
                /*
-                * Enable Runtime PM for this func
+                * Enable Runtime PM for this func (if supported)
                 */
-               pm_runtime_enable(&card->sdio_func[i]->dev);
+               if (host->caps & MMC_CAP_POWER_OFF_CARD)
+                       pm_runtime_enable(&card->sdio_func[i]->dev);
        }
 
        mmc_release_host(host);
index 2716c7ab6bbfb6fd76ae2ff3084f7d61b4dcc198..203da443e339a65b90e1ff47bc5240f9ba2ca07e 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/pm_runtime.h>
 
 #include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
 #include <linux/mmc/sdio_func.h>
 
 #include "sdio_cis.h"
@@ -132,9 +133,11 @@ static int sdio_bus_probe(struct device *dev)
         * it should call pm_runtime_put_noidle() in its probe routine and
         * pm_runtime_get_noresume() in its remove routine.
         */
-       ret = pm_runtime_get_sync(dev);
-       if (ret < 0)
-               goto out;
+       if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) {
+               ret = pm_runtime_get_sync(dev);
+               if (ret < 0)
+                       goto out;
+       }
 
        /* Set the default block size so the driver is sure it's something
         * sensible. */
@@ -151,7 +154,8 @@ static int sdio_bus_probe(struct device *dev)
        return 0;
 
 disable_runtimepm:
-       pm_runtime_put_noidle(dev);
+       if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
+               pm_runtime_put_noidle(dev);
 out:
        return ret;
 }
@@ -160,12 +164,14 @@ static int sdio_bus_remove(struct device *dev)
 {
        struct sdio_driver *drv = to_sdio_driver(dev->driver);
        struct sdio_func *func = dev_to_sdio_func(dev);
-       int ret;
+       int ret = 0;
 
        /* Make sure card is powered before invoking ->remove() */
-       ret = pm_runtime_get_sync(dev);
-       if (ret < 0)
-               goto out;
+       if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) {
+               ret = pm_runtime_get_sync(dev);
+               if (ret < 0)
+                       goto out;
+       }
 
        drv->remove(func);
 
@@ -178,10 +184,12 @@ static int sdio_bus_remove(struct device *dev)
        }
 
        /* First, undo the increment made directly above */
-       pm_runtime_put_noidle(dev);
+       if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
+               pm_runtime_put_noidle(dev);
 
        /* Then undo the runtime PM settings in sdio_bus_probe() */
-       pm_runtime_put_noidle(dev);
+       if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
+               pm_runtime_put_noidle(dev);
 
 out:
        return ret;
@@ -191,6 +199,8 @@ out:
 
 static int sdio_bus_pm_prepare(struct device *dev)
 {
+       struct sdio_func *func = dev_to_sdio_func(dev);
+
        /*
         * Resume an SDIO device which was suspended at run time at this
         * point, in order to allow standard SDIO suspend/resume paths
@@ -212,7 +222,8 @@ static int sdio_bus_pm_prepare(struct device *dev)
         * since there is little point in failing system suspend if a
         * device can't be resumed.
         */
-       pm_runtime_resume(dev);
+       if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
+               pm_runtime_resume(dev);
 
        return 0;
 }
index 82a1079bbdc78bff7afc459b7aa3444461bcfe9b..5d46021cbb57f3a75b995ba11c25fa518aae9f37 100644 (file)
@@ -1002,7 +1002,7 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host,
         * Monitor a 0->1 transition first
         */
        if (mmc_slot(host).features & HSMMC_HAS_UPDATED_RESET) {
-               while ((!(OMAP_HSMMC_READ(host, SYSCTL) & bit))
+               while ((!(OMAP_HSMMC_READ(host->base, SYSCTL) & bit))
                                        && (i++ < limit))
                        cpu_relax();
        }
index 2e9cca19c90b62b6ac3ac5bdbf86d92155b9e1fe..9b82910b9dbb3ec01ab07a0ff2f19f6ec59a9ed7 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/clk.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/sdhci-pltfm.h>
+#include <mach/hardware.h>
 #include "sdhci.h"
 #include "sdhci-pltfm.h"
 #include "sdhci-esdhc.h"
@@ -112,6 +113,13 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
        clk_enable(clk);
        pltfm_host->clk = clk;
 
+       if (cpu_is_mx35() || cpu_is_mx51())
+               host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
+
+       /* Fix errata ENGcm07207 which is present on i.MX25 and i.MX35 */
+       if (cpu_is_mx25() || cpu_is_mx35())
+               host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
+
        return 0;
 }
 
@@ -133,10 +141,8 @@ static struct sdhci_ops sdhci_esdhc_ops = {
 };
 
 struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
-       .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_NO_MULTIBLOCK
-                       | SDHCI_QUIRK_BROKEN_ADMA,
+       .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA,
        /* ADMA has issues. Might be fixable */
-       /* NO_MULTIBLOCK might be MX35 only (Errata: ENGcm07207) */
        .ops = &sdhci_esdhc_ops,
        .init = esdhc_pltfm_init,
        .exit = esdhc_pltfm_exit,
index 55746bac2f440bea1b982b48e9add0e35f57a6db..3d9c2460d437ca7e8171e490becb7e6c5211ce7f 100644 (file)
@@ -149,11 +149,11 @@ static const struct sdhci_pci_fixes sdhci_cafe = {
  * ADMA operation is disabled for Moorestown platform due to
  * hardware bugs.
  */
-static int mrst_hc1_probe(struct sdhci_pci_chip *chip)
+static int mrst_hc_probe(struct sdhci_pci_chip *chip)
 {
        /*
-        * slots number is fixed here for MRST as SDIO3 is never used and has
-        * hardware bugs.
+        * slots number is fixed here for MRST as SDIO3/5 are never used and
+        * have hardware bugs.
         */
        chip->num_slots = 1;
        return 0;
@@ -163,9 +163,9 @@ static const struct sdhci_pci_fixes sdhci_intel_mrst_hc0 = {
        .quirks         = SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_NO_HISPD_BIT,
 };
 
-static const struct sdhci_pci_fixes sdhci_intel_mrst_hc1 = {
+static const struct sdhci_pci_fixes sdhci_intel_mrst_hc1_hc2 = {
        .quirks         = SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_NO_HISPD_BIT,
-       .probe          = mrst_hc1_probe,
+       .probe          = mrst_hc_probe,
 };
 
 static const struct sdhci_pci_fixes sdhci_intel_mfd_sd = {
@@ -538,7 +538,15 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
                .device         = PCI_DEVICE_ID_INTEL_MRST_SD1,
                .subvendor      = PCI_ANY_ID,
                .subdevice      = PCI_ANY_ID,
-               .driver_data    = (kernel_ulong_t)&sdhci_intel_mrst_hc1,
+               .driver_data    = (kernel_ulong_t)&sdhci_intel_mrst_hc1_hc2,
+       },
+
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = PCI_DEVICE_ID_INTEL_MRST_SD2,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .driver_data    = (kernel_ulong_t)&sdhci_intel_mrst_hc1_hc2,
        },
 
        {
@@ -637,6 +645,7 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
 {
        struct sdhci_pci_chip *chip;
        struct sdhci_pci_slot *slot;
+       mmc_pm_flag_t slot_pm_flags;
        mmc_pm_flag_t pm_flags = 0;
        int i, ret;
 
@@ -657,7 +666,11 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
                        return ret;
                }
 
-               pm_flags |= slot->host->mmc->pm_flags;
+               slot_pm_flags = slot->host->mmc->pm_flags;
+               if (slot_pm_flags & MMC_PM_WAKE_SDIO_IRQ)
+                       sdhci_enable_irq_wakeups(slot->host);
+
+               pm_flags |= slot_pm_flags;
        }
 
        if (chip->fixes && chip->fixes->suspend) {
@@ -671,8 +684,10 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
 
        pci_save_state(pdev);
        if (pm_flags & MMC_PM_KEEP_POWER) {
-               if (pm_flags & MMC_PM_WAKE_SDIO_IRQ)
+               if (pm_flags & MMC_PM_WAKE_SDIO_IRQ) {
+                       pci_pme_active(pdev, true);
                        pci_enable_wake(pdev, PCI_D3hot, 1);
+               }
                pci_set_power_state(pdev, PCI_D3hot);
        } else {
                pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
index fc406ac5d1933166e9f08757a936d285f2843170..5a61208cbc66c8f41f2f760b7321f07f1cd8e131 100644 (file)
@@ -141,6 +141,10 @@ static int __devinit sdhci_pxa_probe(struct platform_device *pdev)
        if (pdata->quirks)
                host->quirks |= pdata->quirks;
 
+       /* If slot design supports 8 bit data, indicate this to MMC. */
+       if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT)
+               host->mmc->caps |= MMC_CAP_8_BIT_DATA;
+
        ret = sdhci_add_host(host);
        if (ret) {
                dev_err(&pdev->dev, "failed to add host\n");
index 782c0ee3c9251c6f804087308b097b44faca4f04..a25db426c91026ad4368d7e2ae0c700f28231a08 100644 (file)
@@ -1185,17 +1185,31 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        if (host->ops->platform_send_init_74_clocks)
                host->ops->platform_send_init_74_clocks(host, ios->power_mode);
 
-       ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
-
-       if (ios->bus_width == MMC_BUS_WIDTH_8)
-               ctrl |= SDHCI_CTRL_8BITBUS;
-       else
-               ctrl &= ~SDHCI_CTRL_8BITBUS;
+       /*
+        * If your platform has 8-bit width support but is not a v3 controller,
+        * or if it requires special setup code, you should implement that in
+        * platform_8bit_width().
+        */
+       if (host->ops->platform_8bit_width)
+               host->ops->platform_8bit_width(host, ios->bus_width);
+       else {
+               ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
+               if (ios->bus_width == MMC_BUS_WIDTH_8) {
+                       ctrl &= ~SDHCI_CTRL_4BITBUS;
+                       if (host->version >= SDHCI_SPEC_300)
+                               ctrl |= SDHCI_CTRL_8BITBUS;
+               } else {
+                       if (host->version >= SDHCI_SPEC_300)
+                               ctrl &= ~SDHCI_CTRL_8BITBUS;
+                       if (ios->bus_width == MMC_BUS_WIDTH_4)
+                               ctrl |= SDHCI_CTRL_4BITBUS;
+                       else
+                               ctrl &= ~SDHCI_CTRL_4BITBUS;
+               }
+               sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+       }
 
-       if (ios->bus_width == MMC_BUS_WIDTH_4)
-               ctrl |= SDHCI_CTRL_4BITBUS;
-       else
-               ctrl &= ~SDHCI_CTRL_4BITBUS;
+       ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
 
        if ((ios->timing == MMC_TIMING_SD_HS ||
             ios->timing == MMC_TIMING_MMC_HS)
@@ -1681,6 +1695,16 @@ int sdhci_resume_host(struct sdhci_host *host)
 
 EXPORT_SYMBOL_GPL(sdhci_resume_host);
 
+void sdhci_enable_irq_wakeups(struct sdhci_host *host)
+{
+       u8 val;
+       val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL);
+       val |= SDHCI_WAKE_ON_INT;
+       sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL);
+}
+
+EXPORT_SYMBOL_GPL(sdhci_enable_irq_wakeups);
+
 #endif /* CONFIG_PM */
 
 /*****************************************************************************\
@@ -1845,11 +1869,19 @@ int sdhci_add_host(struct sdhci_host *host)
                mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300;
        else
                mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200;
+
        mmc->f_max = host->max_clk;
        mmc->caps |= MMC_CAP_SDIO_IRQ;
 
+       /*
+        * A controller may support 8-bit width, but the board itself
+        * might not have the pins brought out.  Boards that support
+        * 8-bit width must set "mmc->caps |= MMC_CAP_8_BIT_DATA;" in
+        * their platform code before calling sdhci_add_host(), and we
+        * won't assume 8-bit width for hosts without that CAP.
+        */
        if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA))
-               mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
+               mmc->caps |= MMC_CAP_4_BIT_DATA;
 
        if (caps & SDHCI_CAN_DO_HISPD)
                mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
index b7b8a3b28b01b00ff41b311cc6d3afde3bafeff3..e42d7f00c06050cfc25079c6b0a3e9942f2a66b4 100644 (file)
@@ -76,7 +76,7 @@
 #define   SDHCI_CTRL_ADMA1     0x08
 #define   SDHCI_CTRL_ADMA32    0x10
 #define   SDHCI_CTRL_ADMA64    0x18
-#define  SDHCI_CTRL_8BITBUS    0x20
+#define   SDHCI_CTRL_8BITBUS   0x20
 
 #define SDHCI_POWER_CONTROL    0x29
 #define  SDHCI_POWER_ON                0x01
@@ -87,6 +87,9 @@
 #define SDHCI_BLOCK_GAP_CONTROL        0x2A
 
 #define SDHCI_WAKE_UP_CONTROL  0x2B
+#define  SDHCI_WAKE_ON_INT     0x01
+#define  SDHCI_WAKE_ON_INSERT  0x02
+#define  SDHCI_WAKE_ON_REMOVE  0x04
 
 #define SDHCI_CLOCK_CONTROL    0x2C
 #define  SDHCI_DIVIDER_SHIFT   8
 #define  SDHCI_CLOCK_BASE_SHIFT        8
 #define  SDHCI_MAX_BLOCK_MASK  0x00030000
 #define  SDHCI_MAX_BLOCK_SHIFT  16
+#define  SDHCI_CAN_DO_8BIT     0x00040000
 #define  SDHCI_CAN_DO_ADMA2    0x00080000
 #define  SDHCI_CAN_DO_ADMA1    0x00100000
 #define  SDHCI_CAN_DO_HISPD    0x00200000
@@ -212,6 +216,8 @@ struct sdhci_ops {
        unsigned int    (*get_max_clock)(struct sdhci_host *host);
        unsigned int    (*get_min_clock)(struct sdhci_host *host);
        unsigned int    (*get_timeout_clock)(struct sdhci_host *host);
+       int             (*platform_8bit_width)(struct sdhci_host *host,
+                                              int width);
        void (*platform_send_init_74_clocks)(struct sdhci_host *host,
                                             u8 power_mode);
        unsigned int    (*get_ro)(struct sdhci_host *host);
@@ -317,6 +323,7 @@ extern void sdhci_remove_host(struct sdhci_host *host, int dead);
 #ifdef CONFIG_PM
 extern int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state);
 extern int sdhci_resume_host(struct sdhci_host *host);
+extern void sdhci_enable_irq_wakeups(struct sdhci_host *host);
 #endif
 
 #endif /* __SDHCI_HW_H */
index b4ead4a13c98a255d0d280ad4bec6ad5ee50b518..f8f65df9b01746052a5fe457f3e9419a98e63ee2 100644 (file)
@@ -425,7 +425,7 @@ static int ushc_probe(struct usb_interface *intf, const struct usb_device_id *id
        struct usb_device *usb_dev = interface_to_usbdev(intf);
        struct mmc_host *mmc;
        struct ushc_data *ushc;
-       int ret = -ENOMEM;
+       int ret;
 
        mmc = mmc_alloc_host(sizeof(struct ushc_data), &intf->dev);
        if (mmc == NULL)
@@ -462,11 +462,15 @@ static int ushc_probe(struct usb_interface *intf, const struct usb_device_id *id
        mmc->max_blk_count = 511;
 
        ushc->int_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (ushc->int_urb == NULL)
+       if (ushc->int_urb == NULL) {
+               ret = -ENOMEM;
                goto err;
+       }
        ushc->int_data = kzalloc(sizeof(struct ushc_int_data), GFP_KERNEL);
-       if (ushc->int_data == NULL)
+       if (ushc->int_data == NULL) {
+               ret = -ENOMEM;
                goto err;
+       }
        usb_fill_int_urb(ushc->int_urb, ushc->usb_dev,
                         usb_rcvintpipe(usb_dev,
                                        intf->cur_altsetting->endpoint[0].desc.bEndpointAddress),
@@ -475,11 +479,15 @@ static int ushc_probe(struct usb_interface *intf, const struct usb_device_id *id
                         intf->cur_altsetting->endpoint[0].desc.bInterval);
 
        ushc->cbw_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (ushc->cbw_urb == NULL)
+       if (ushc->cbw_urb == NULL) {
+               ret = -ENOMEM;
                goto err;
+       }
        ushc->cbw = kzalloc(sizeof(struct ushc_cbw), GFP_KERNEL);
-       if (ushc->cbw == NULL)
+       if (ushc->cbw == NULL) {
+               ret = -ENOMEM;
                goto err;
+       }
        ushc->cbw->signature = USHC_CBW_SIGNATURE;
 
        usb_fill_bulk_urb(ushc->cbw_urb, ushc->usb_dev, usb_sndbulkpipe(usb_dev, 2),
@@ -487,15 +495,21 @@ static int ushc_probe(struct usb_interface *intf, const struct usb_device_id *id
                          cbw_callback, ushc);
 
        ushc->data_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (ushc->data_urb == NULL)
+       if (ushc->data_urb == NULL) {
+               ret = -ENOMEM;
                goto err;
+       }
 
        ushc->csw_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (ushc->csw_urb == NULL)
+       if (ushc->csw_urb == NULL) {
+               ret = -ENOMEM;
                goto err;
+       }
        ushc->csw = kzalloc(sizeof(struct ushc_cbw), GFP_KERNEL);
-       if (ushc->csw == NULL)
+       if (ushc->csw == NULL) {
+               ret = -ENOMEM;
                goto err;
+       }
        usb_fill_bulk_urb(ushc->csw_urb, ushc->usb_dev, usb_rcvbulkpipe(usb_dev, 6),
                          ushc->csw, sizeof(struct ushc_csw),
                          csw_callback, ushc);
index dd90880048cf3fe2f8d209ad654159565a5987e4..d8ae634d347ebc4262704188adb1dea943c909e6 100644 (file)
@@ -51,7 +51,7 @@ struct pxa2xx_flash_info {
 static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
 
 
-static int __init pxa2xx_flash_probe(struct platform_device *pdev)
+static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
 {
        struct flash_platform_data *flash = pdev->dev.platform_data;
        struct pxa2xx_flash_info *info;
index cd41c58b5bbd50f8ed905a1a6da71dedc5cfca7e..15682ec8530ed008f8f3f8ddbd16e577306a6407 100644 (file)
@@ -7,7 +7,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#define CONFIG_MTD_NAND_OMAP_HWECC
 
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
index c2960ac9f39c9e863216c91b607e157c0ff65271..811775aa8ee80082aa5803a13b3537f2022e5936 100644 (file)
@@ -482,10 +482,17 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
        uint32_t data = 0;
        struct ubi_vid_hdr vid_hdr;
 
-       addr = (loff_t)pnum * ubi->peb_size + ubi->vid_hdr_aloffset;
+       /*
+        * It is important to first invalidate the EC header, and then the VID
+        * header. Otherwise a power cut may lead to valid EC header and
+        * invalid VID header, in which case UBI will treat this PEB as
+        * corrupted and will try to preserve it, and print scary warnings (see
+        * the header comment in scan.c for more information).
+        */
+       addr = (loff_t)pnum * ubi->peb_size;
        err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data);
        if (!err) {
-               addr -= ubi->vid_hdr_aloffset;
+               addr += ubi->vid_hdr_aloffset;
                err = ubi->mtd->write(ubi->mtd, addr, 4, &written,
                                      (void *)&data);
                if (!err)
@@ -494,18 +501,24 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
 
        /*
         * We failed to write to the media. This was observed with Spansion
-        * S29GL512N NOR flash. Most probably the eraseblock erasure was
-        * interrupted at a very inappropriate moment, so it became unwritable.
-        * In this case we probably anyway have garbage in this PEB.
+        * S29GL512N NOR flash. Most probably the previously eraseblock erasure
+        * was interrupted at a very inappropriate moment, so it became
+        * unwritable. In this case we probably anyway have garbage in this
+        * PEB.
         */
        err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0);
-       if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR)
-               /*
-                * The VID header is corrupted, so we can safely erase this
-                * PEB and not afraid that it will be treated as a valid PEB in
-                * case of an unclean reboot.
-                */
-               return 0;
+       if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR) {
+               struct ubi_ec_hdr ec_hdr;
+
+               err1 = ubi_io_read_ec_hdr(ubi, pnum, &ec_hdr, 0);
+               if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR)
+                       /*
+                        * Both VID and EC headers are corrupted, so we can
+                        * safely erase this PEB and not afraid that it will be
+                        * treated as a valid PEB in case of an unclean reboot.
+                        */
+                       return 0;
+       }
 
        /*
         * The PEB contains a valid VID header, but we cannot invalidate it.
index 3c631863bf40b5b3b5db70e28f4e6b3937e4be49..79ca304fc4db61e9a6be5b44223d3d8af895dd63 100644 (file)
@@ -787,16 +787,15 @@ static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr,
                 * erased, so it became unstable and corrupted, and should be
                 * erased.
                 */
-               return 0;
+               err = 0;
+               goto out_unlock;
        }
 
        if (err)
-               return err;
+               goto out_unlock;
 
-       if (ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->leb_size)) {
-               mutex_unlock(&ubi->buf_mutex);
-               return 0;
-       }
+       if (ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->leb_size))
+               goto out_unlock;
 
        ubi_err("PEB %d contains corrupted VID header, and the data does not "
                "contain all 0xFF, this may be a non-UBI PEB or a severe VID "
@@ -806,8 +805,11 @@ static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr,
                pnum, ubi->leb_start, ubi->leb_size);
        ubi_dbg_print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
                               ubi->peb_buf1, ubi->leb_size, 1);
+       err = 1;
+
+out_unlock:
        mutex_unlock(&ubi->buf_mutex);
-       return 1;
+       return err;
 }
 
 /**
@@ -951,6 +953,10 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
                         * impossible to distinguish it from a PEB which just
                         * contains garbage because of a power cut during erase
                         * operation. So we just schedule this PEB for erasure.
+                        *
+                        * Besides, in case of NOR flash, we deliberatly
+                        * corrupt both headers because NOR flash erasure is
+                        * slow and can start from the end.
                         */
                        err = 0;
                else
index e1da258bbfb7bfd89c24354e7deb626f4da777f9..0a92436f05389883e8485bdf13fafc19cccd2ca2 100644 (file)
@@ -699,7 +699,8 @@ DEFINE_WINDOW_IO(32)
 #define DEVICE_PCI(dev) NULL
 #endif
 
-#define VORTEX_PCI(vp) (((vp)->gendev) ? DEVICE_PCI((vp)->gendev) : NULL)
+#define VORTEX_PCI(vp)                                                 \
+       ((struct pci_dev *) (((vp)->gendev) ? DEVICE_PCI((vp)->gendev) : NULL))
 
 #ifdef CONFIG_EISA
 #define DEVICE_EISA(dev) (((dev)->bus == &eisa_bus_type) ? to_eisa_device((dev)) : NULL)
@@ -707,7 +708,8 @@ DEFINE_WINDOW_IO(32)
 #define DEVICE_EISA(dev) NULL
 #endif
 
-#define VORTEX_EISA(vp) (((vp)->gendev) ? DEVICE_EISA((vp)->gendev) : NULL)
+#define VORTEX_EISA(vp)                                                        \
+       ((struct eisa_device *) (((vp)->gendev) ? DEVICE_EISA((vp)->gendev) : NULL))
 
 /* The action to take with a media selection timer tick.
    Note that we deviate from the 3Com order by checking 10base2 before AUI.
index ac422cd332eadd687823fcc4db7ca2eaef997fea..dd16e83933a28f817c1eaa0d47003cb4482c3aa5 100644 (file)
@@ -490,13 +490,11 @@ static inline unsigned int cp_rx_csum_ok (u32 status)
 {
        unsigned int protocol = (status >> 16) & 0x3;
 
-       if (likely((protocol == RxProtoTCP) && (!(status & TCPFail))))
+       if (((protocol == RxProtoTCP) && !(status & TCPFail)) ||
+           ((protocol == RxProtoUDP) && !(status & UDPFail)))
                return 1;
-       else if ((protocol == RxProtoUDP) && (!(status & UDPFail)))
-               return 1;
-       else if ((protocol == RxProtoIP) && (!(status & IPFail)))
-               return 1;
-       return 0;
+       else
+               return 0;
 }
 
 static int cp_rx_poll(struct napi_struct *napi, int budget)
index f6668cdaac85487b3c621b881af0c9afd975595b..4f1755bddf6b05d97b42433c3595a304976504fb 100644 (file)
@@ -2543,10 +2543,10 @@ config PCH_GBE
        depends on PCI
        select MII
        ---help---
-         This is a gigabit ethernet driver for Topcliff PCH.
-         Topcliff PCH is the platform controller hub that is used in Intel's
+         This is a gigabit ethernet driver for EG20T PCH.
+         EG20T PCH is the platform controller hub that is used in Intel's
          general embedded platform.
-         Topcliff PCH has Gigabit Ethernet interface.
+         EG20T PCH has Gigabit Ethernet interface.
          Using this interface, it is able to access system devices connected
          to Gigabit Ethernet.
          This driver enables Gigabit Ethernet function.
@@ -2945,6 +2945,18 @@ source "drivers/s390/net/Kconfig"
 
 source "drivers/net/caif/Kconfig"
 
+config TILE_NET
+       tristate "Tilera GBE/XGBE network driver support"
+       depends on TILE
+       default y
+       select CRC32
+       help
+         This is a standard Linux network device driver for the
+         on-chip Tilera Gigabit Ethernet and XAUI interfaces.
+
+         To compile this driver as a module, choose M here: the module
+         will be called tile_net.
+
 config XEN_NETDEV_FRONTEND
        tristate "Xen network device frontend driver"
        depends on XEN
index 652fc6b98039431832aaceda6f1b4a637720c126..b90738d13994318dcf2a06442cd7eba52629b9a7 100644 (file)
@@ -301,3 +301,4 @@ obj-$(CONFIG_CAIF) += caif/
 
 obj-$(CONFIG_OCTEON_MGMT_ETHERNET) += octeon/
 obj-$(CONFIG_PCH_GBE) += pch_gbe/
+obj-$(CONFIG_TILE_NET) += tile/
index 919080b2c3a50eb48bea7311ac0db4e8d3e8103e..1bf67200994827fd76250e718b3bdf4a67a609e8 100644 (file)
@@ -82,7 +82,7 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw)
        addr[0] = addr[1] = 0;
        AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data);
        if (atl1c_check_eeprom_exist(hw)) {
-               if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c_b) {
+               if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c) {
                        /* Enable OTP CLK */
                        if (!(otp_ctrl_data & OTP_CTRL_CLK_EN)) {
                                otp_ctrl_data |= OTP_CTRL_CLK_EN;
index 43489f89c142f7d10e25f0454287ef28939fd228..53eff9ba6e9500a3ea2327a55a42fcb9d9aeefea 100644 (file)
@@ -155,10 +155,10 @@ static void au1000_enable_mac(struct net_device *dev, int force_reset)
        spin_lock_irqsave(&aup->lock, flags);
 
        if (force_reset || (!aup->mac_enabled)) {
-               writel(MAC_EN_CLOCK_ENABLE, &aup->enable);
+               writel(MAC_EN_CLOCK_ENABLE, aup->enable);
                au_sync_delay(2);
                writel((MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2
-                               | MAC_EN_CLOCK_ENABLE), &aup->enable);
+                               | MAC_EN_CLOCK_ENABLE), aup->enable);
                au_sync_delay(2);
 
                aup->mac_enabled = 1;
@@ -503,9 +503,9 @@ static void au1000_reset_mac_unlocked(struct net_device *dev)
 
        au1000_hard_stop(dev);
 
-       writel(MAC_EN_CLOCK_ENABLE, &aup->enable);
+       writel(MAC_EN_CLOCK_ENABLE, aup->enable);
        au_sync_delay(2);
-       writel(0, &aup->enable);
+       writel(0, aup->enable);
        au_sync_delay(2);
 
        aup->tx_full = 0;
@@ -1119,7 +1119,7 @@ static int __devinit au1000_probe(struct platform_device *pdev)
        /* set a random MAC now in case platform_data doesn't provide one */
        random_ether_addr(dev->dev_addr);
 
-       writel(0, &aup->enable);
+       writel(0, aup->enable);
        aup->mac_enabled = 0;
 
        pd = pdev->dev.platform_data;
index c6e86315b3f8df37aa2ac1a767ac46fc1b5eba60..2e2b76258ab42cbc6b0dc73f70bd9547a5846857 100644 (file)
@@ -381,11 +381,11 @@ static void b44_set_flow_ctrl(struct b44 *bp, u32 local, u32 remote)
        __b44_set_flow_ctrl(bp, pause_enab);
 }
 
-#ifdef SSB_DRIVER_MIPS
-extern char *nvram_get(char *name);
+#ifdef CONFIG_BCM47XX
+#include <asm/mach-bcm47xx/nvram.h>
 static void b44_wap54g10_workaround(struct b44 *bp)
 {
-       const char *str;
+       char buf[20];
        u32 val;
        int err;
 
@@ -394,10 +394,9 @@ static void b44_wap54g10_workaround(struct b44 *bp)
         * see https://dev.openwrt.org/ticket/146
         * check and reset bit "isolate"
         */
-       str = nvram_get("boardnum");
-       if (!str)
+       if (nvram_getenv("boardnum", buf, sizeof(buf)) < 0)
                return;
-       if (simple_strtoul(str, NULL, 0) == 2) {
+       if (simple_strtoul(buf, NULL, 0) == 2) {
                err = __b44_readphy(bp, 0, MII_BMCR, &val);
                if (err)
                        goto error;
index 36eca1ce75d4e29a4c41bbf285931ce003a6a92a..e4465d222a7d019654c27c5f4d3db89067f89cf8 100644 (file)
@@ -1235,7 +1235,7 @@ int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id,
 
                i = 0;
                netdev_for_each_mc_addr(ha, netdev)
-                       memcpy(req->mac[i].byte, ha->addr, ETH_ALEN);
+                       memcpy(req->mac[i++].byte, ha->addr, ETH_ALEN);
        } else {
                req->promiscuous = 1;
        }
index c36cd2ffbadcaa41e15a043a937d1b1ad62c22b4..93354eee2cfd1e679929054c9cc28fe7b35dea51 100644 (file)
@@ -2458,6 +2458,12 @@ int be_load_fw(struct be_adapter *adapter, u8 *func)
        int status, i = 0, num_imgs = 0;
        const u8 *p;
 
+       if (!netif_running(adapter->netdev)) {
+               dev_err(&adapter->pdev->dev,
+                       "Firmware load not allowed (interface is down)\n");
+               return -EPERM;
+       }
+
        strcpy(fw_file, func);
 
        status = request_firmware(&fw, fw_file, &adapter->pdev->dev);
index 863e73a85fbe0ef4cd48ebac5cd5e95846397ebc..d255428122fc0b87d3e4ff2925410b5b2d5f6a47 100644 (file)
@@ -20,8 +20,8 @@
  * (you will need to reboot afterwards) */
 /* #define BNX2X_STOP_ON_ERROR */
 
-#define DRV_MODULE_VERSION      "1.60.00-4"
-#define DRV_MODULE_RELDATE      "2010/11/01"
+#define DRV_MODULE_VERSION      "1.60.01-0"
+#define DRV_MODULE_RELDATE      "2010/11/12"
 #define BNX2X_BC_VER            0x040200
 
 #define BNX2X_MULTI_QUEUE
index 94d5f59d5a6f0a1de6dd8cc5ad44fc2083649b98..0af361e4e3d16ab83d8c3067396f63c5d46d1cb1 100644 (file)
@@ -1782,15 +1782,15 @@ exit_lbl:
 }
 #endif
 
-static inline void bnx2x_set_pbd_gso_e2(struct sk_buff *skb,
-                                    struct eth_tx_parse_bd_e2 *pbd,
-                                    u32 xmit_type)
+static inline void bnx2x_set_pbd_gso_e2(struct sk_buff *skb, u32 *parsing_data,
+                                       u32 xmit_type)
 {
-       pbd->parsing_data |= cpu_to_le16(skb_shinfo(skb)->gso_size) <<
-               ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT;
+       *parsing_data |= (skb_shinfo(skb)->gso_size <<
+                             ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT) &
+                             ETH_TX_PARSE_BD_E2_LSO_MSS;
        if ((xmit_type & XMIT_GSO_V6) &&
            (ipv6_hdr(skb)->nexthdr == NEXTHDR_IPV6))
-               pbd->parsing_data |= ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR;
+               *parsing_data |= ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR;
 }
 
 /**
@@ -1835,15 +1835,15 @@ static inline void bnx2x_set_pbd_gso(struct sk_buff *skb,
  * @return header len
  */
 static inline  u8 bnx2x_set_pbd_csum_e2(struct bnx2x *bp, struct sk_buff *skb,
-       struct eth_tx_parse_bd_e2 *pbd,
-       u32 xmit_type)
+       u32 *parsing_data, u32 xmit_type)
 {
-       pbd->parsing_data |= cpu_to_le16(tcp_hdrlen(skb)/4) <<
-               ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT;
+       *parsing_data |= ((tcp_hdrlen(skb)/4) <<
+               ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT) &
+               ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW;
 
-       pbd->parsing_data |= cpu_to_le16(((unsigned char *)tcp_hdr(skb) -
-                                         skb->data) / 2) <<
-               ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT;
+       *parsing_data |= ((((u8 *)tcp_hdr(skb) - skb->data) / 2) <<
+               ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT) &
+               ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W;
 
        return skb_transport_header(skb) + tcp_hdrlen(skb) - skb->data;
 }
@@ -1912,6 +1912,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
        struct eth_tx_bd *tx_data_bd, *total_pkt_bd = NULL;
        struct eth_tx_parse_bd_e1x *pbd_e1x = NULL;
        struct eth_tx_parse_bd_e2 *pbd_e2 = NULL;
+       u32 pbd_e2_parsing_data = 0;
        u16 pkt_prod, bd_prod;
        int nbd, fp_index;
        dma_addr_t mapping;
@@ -2033,8 +2034,9 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
                memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2));
                /* Set PBD in checksum offload case */
                if (xmit_type & XMIT_CSUM)
-                       hlen = bnx2x_set_pbd_csum_e2(bp,
-                                                    skb, pbd_e2, xmit_type);
+                       hlen = bnx2x_set_pbd_csum_e2(bp, skb,
+                                                    &pbd_e2_parsing_data,
+                                                    xmit_type);
        } else {
                pbd_e1x = &fp->tx_desc_ring[bd_prod].parse_bd_e1x;
                memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x));
@@ -2076,10 +2078,18 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        bd_prod = bnx2x_tx_split(bp, fp, tx_buf, &tx_start_bd,
                                                 hlen, bd_prod, ++nbd);
                if (CHIP_IS_E2(bp))
-                       bnx2x_set_pbd_gso_e2(skb, pbd_e2, xmit_type);
+                       bnx2x_set_pbd_gso_e2(skb, &pbd_e2_parsing_data,
+                                            xmit_type);
                else
                        bnx2x_set_pbd_gso(skb, pbd_e1x, xmit_type);
        }
+
+       /* Set the PBD's parsing_data field if not zero
+        * (for the chips newer than 57711).
+        */
+       if (pbd_e2_parsing_data)
+               pbd_e2->parsing_data = cpu_to_le32(pbd_e2_parsing_data);
+
        tx_data_bd = (struct eth_tx_bd *)tx_start_bd;
 
        /* Handle fragmented skb */
index a306b0e46b613417c630e79398c5f8250204195d..66df29fcf7516e45b7794fee314d0122fca6d42b 100644 (file)
@@ -838,7 +838,7 @@ static void bnx2x_qm_init_ptr_table(struct bnx2x *bp, int qm_cid_count,
 /****************************************************************************
 * SRC initializations
 ****************************************************************************/
-
+#ifdef BCM_CNIC
 /* called during init func stage */
 static void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2,
                              dma_addr_t t2_mapping, int src_cid_count)
@@ -862,5 +862,5 @@ static void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2,
                    U64_HI((u64)t2_mapping +
                           (src_cid_count-1) * sizeof(struct src_ent)));
 }
-
+#endif
 #endif /* BNX2X_INIT_OPS_H */
index e9ad16f00b56755847eb887a898c999ef2c08c04..9709b8569666d56ff84fb263429eb6f27c244033 100644 (file)
@@ -9064,7 +9064,7 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
        default:
                pr_err("Unknown board_type (%ld), aborting\n",
                           ent->driver_data);
-               return ENODEV;
+               return -ENODEV;
        }
 
        cid_count += CNIC_CONTEXT_USE;
index bdb68a600382bdcfbe8a9e2cf70f8360821e2567..d0ea760ce419f0ae8040bf880cd80013c651a93a 100644 (file)
@@ -171,7 +171,7 @@ MODULE_PARM_DESC(resend_igmp, "Number of IGMP membership reports to send on link
 /*----------------------------- Global variables ----------------------------*/
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-cpumask_var_t netpoll_block_tx;
+atomic_t netpoll_block_tx = ATOMIC_INIT(0);
 #endif
 
 static const char * const version =
@@ -878,8 +878,10 @@ static void __bond_resend_igmp_join_requests(struct net_device *dev)
        rcu_read_lock();
        in_dev = __in_dev_get_rcu(dev);
        if (in_dev) {
+               read_lock(&in_dev->mc_list_lock);
                for (im = in_dev->mc_list; im; im = im->next)
                        ip_mc_rejoin_group(im);
+               read_unlock(&in_dev->mc_list_lock);
        }
 
        rcu_read_unlock();
@@ -1574,7 +1576,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 
        /* If this is the first slave, then we need to set the master's hardware
         * address to be the same as the slave's. */
-       if (bond->slave_cnt == 0)
+       if (is_zero_ether_addr(bond->dev->dev_addr))
                memcpy(bond->dev->dev_addr, slave_dev->dev_addr,
                       slave_dev->addr_len);
 
@@ -5297,13 +5299,6 @@ static int __init bonding_init(void)
        if (res)
                goto out;
 
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       if (!alloc_cpumask_var(&netpoll_block_tx, GFP_KERNEL)) {
-               res = -ENOMEM;
-               goto out;
-       }
-#endif
-
        res = register_pernet_subsys(&bond_net_ops);
        if (res)
                goto out;
@@ -5332,9 +5327,6 @@ err:
        rtnl_link_unregister(&bond_link_ops);
 err_link:
        unregister_pernet_subsys(&bond_net_ops);
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       free_cpumask_var(netpoll_block_tx);
-#endif
        goto out;
 
 }
@@ -5351,7 +5343,10 @@ static void __exit bonding_exit(void)
        unregister_pernet_subsys(&bond_net_ops);
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-       free_cpumask_var(netpoll_block_tx);
+       /*
+        * Make sure we don't have an imbalance on our netpoll blocking
+        */
+       WARN_ON(atomic_read(&netpoll_block_tx));
 #endif
 }
 
index 4eedb12df6caf2e4676cbe11e2134e97ec01def1..c2f081352a037894d6e8238ccb70c39e796c4a69 100644 (file)
 
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-extern cpumask_var_t netpoll_block_tx;
+extern atomic_t netpoll_block_tx;
 
 static inline void block_netpoll_tx(void)
 {
-       preempt_disable();
-       BUG_ON(cpumask_test_and_set_cpu(smp_processor_id(),
-                                       netpoll_block_tx));
+       atomic_inc(&netpoll_block_tx);
 }
 
 static inline void unblock_netpoll_tx(void)
 {
-       BUG_ON(!cpumask_test_and_clear_cpu(smp_processor_id(),
-                                          netpoll_block_tx));
-       preempt_enable();
+       atomic_dec(&netpoll_block_tx);
 }
 
 static inline int is_netpoll_tx_blocked(struct net_device *dev)
 {
        if (unlikely(dev->priv_flags & IFF_IN_NETPOLL))
-               return cpumask_test_cpu(smp_processor_id(), netpoll_block_tx);
+               return atomic_read(&netpoll_block_tx);
        return 0;
 }
 #else
index 1cd90da86f130ea588070634db35959a47ca7b87..32b1c6fb2de1a74e5b97254cdf075ca933464734 100644 (file)
@@ -5,7 +5,7 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ":" __func__ "():" fmt
+#define pr_fmt(fmt) KBUILD_MODNAME ":" fmt
 
 #include <linux/version.h>
 #include <linux/init.h>
index 19f9c065666745633752c3e59b312d2a4e9812c0..80511167f35bd4bcfb53cf424eb58ff4174a558b 100644 (file)
@@ -6,7 +6,7 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ":" __func__ "():" fmt
+#define pr_fmt(fmt) KBUILD_MODNAME ":" fmt
 
 #include <linux/spinlock.h>
 #include <linux/sched.h>
index 8b4cea57a6c5c47f585f5fcae935771e575dcd18..20da1996d354d563d8a2616276de477041b2368d 100644 (file)
@@ -635,8 +635,8 @@ int cfspi_spi_probe(struct platform_device *pdev)
 
        ndev = alloc_netdev(sizeof(struct cfspi),
                        "cfspi%d", cfspi_setup);
-       if (!dev)
-               return -ENODEV;
+       if (!ndev)
+               return -ENOMEM;
 
        cfspi = netdev_priv(ndev);
        netif_stop_queue(ndev);
index bb813d94aea8ef5ae11db63ce6ac795fd0a62c39..e97521c801ea6e4a90714bd2038d4c0610b8806a 100644 (file)
@@ -2408,7 +2408,7 @@ int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox,
                if (index < NEXACT_MAC)
                        ret++;
                else if (hash)
-                       *hash |= (1 << hash_mac_addr(addr[i]));
+                       *hash |= (1ULL << hash_mac_addr(addr[i]));
        }
        return ret;
 }
index c3449bbc585a682b57a39b306f251f9691e27e0b..6bf464afa90ed1a60cf06bb91f31964cf82a7e5d 100644 (file)
@@ -816,40 +816,48 @@ static struct net_device_stats *cxgb4vf_get_stats(struct net_device *dev)
 }
 
 /*
- * Collect up to maxaddrs worth of a netdevice's unicast addresses into an
- * array of addrss pointers and return the number collected.
+ * Collect up to maxaddrs worth of a netdevice's unicast addresses, starting
+ * at a specified offset within the list, into an array of addrss pointers and
+ * return the number collected.
  */
-static inline int collect_netdev_uc_list_addrs(const struct net_device *dev,
-                                              const u8 **addr,
-                                              unsigned int maxaddrs)
+static inline unsigned int collect_netdev_uc_list_addrs(const struct net_device *dev,
+                                                       const u8 **addr,
+                                                       unsigned int offset,
+                                                       unsigned int maxaddrs)
 {
+       unsigned int index = 0;
        unsigned int naddr = 0;
        const struct netdev_hw_addr *ha;
 
-       for_each_dev_addr(dev, ha) {
-               addr[naddr++] = ha->addr;
-               if (naddr >= maxaddrs)
-                       break;
-       }
+       for_each_dev_addr(dev, ha)
+               if (index++ >= offset) {
+                       addr[naddr++] = ha->addr;
+                       if (naddr >= maxaddrs)
+                               break;
+               }
        return naddr;
 }
 
 /*
- * Collect up to maxaddrs worth of a netdevice's multicast addresses into an
- * array of addrss pointers and return the number collected.
+ * Collect up to maxaddrs worth of a netdevice's multicast addresses, starting
+ * at a specified offset within the list, into an array of addrss pointers and
+ * return the number collected.
  */
-static inline int collect_netdev_mc_list_addrs(const struct net_device *dev,
-                                              const u8 **addr,
-                                              unsigned int maxaddrs)
+static inline unsigned int collect_netdev_mc_list_addrs(const struct net_device *dev,
+                                                       const u8 **addr,
+                                                       unsigned int offset,
+                                                       unsigned int maxaddrs)
 {
+       unsigned int index = 0;
        unsigned int naddr = 0;
        const struct netdev_hw_addr *ha;
 
-       netdev_for_each_mc_addr(ha, dev) {
-               addr[naddr++] = ha->addr;
-               if (naddr >= maxaddrs)
-                       break;
-       }
+       netdev_for_each_mc_addr(ha, dev)
+               if (index++ >= offset) {
+                       addr[naddr++] = ha->addr;
+                       if (naddr >= maxaddrs)
+                               break;
+               }
        return naddr;
 }
 
@@ -862,16 +870,20 @@ static int set_addr_filters(const struct net_device *dev, bool sleep)
        u64 mhash = 0;
        u64 uhash = 0;
        bool free = true;
-       u16 filt_idx[7];
+       unsigned int offset, naddr;
        const u8 *addr[7];
-       int ret, naddr = 0;
+       int ret;
        const struct port_info *pi = netdev_priv(dev);
 
        /* first do the secondary unicast addresses */
-       naddr = collect_netdev_uc_list_addrs(dev, addr, ARRAY_SIZE(addr));
-       if (naddr > 0) {
+       for (offset = 0; ; offset += naddr) {
+               naddr = collect_netdev_uc_list_addrs(dev, addr, offset,
+                                                    ARRAY_SIZE(addr));
+               if (naddr == 0)
+                       break;
+
                ret = t4vf_alloc_mac_filt(pi->adapter, pi->viid, free,
-                                         naddr, addr, filt_idx, &uhash, sleep);
+                                         naddr, addr, NULL, &uhash, sleep);
                if (ret < 0)
                        return ret;
 
@@ -879,12 +891,17 @@ static int set_addr_filters(const struct net_device *dev, bool sleep)
        }
 
        /* next set up the multicast addresses */
-       naddr = collect_netdev_mc_list_addrs(dev, addr, ARRAY_SIZE(addr));
-       if (naddr > 0) {
+       for (offset = 0; ; offset += naddr) {
+               naddr = collect_netdev_mc_list_addrs(dev, addr, offset,
+                                                    ARRAY_SIZE(addr));
+               if (naddr == 0)
+                       break;
+
                ret = t4vf_alloc_mac_filt(pi->adapter, pi->viid, free,
-                                         naddr, addr, filt_idx, &mhash, sleep);
+                                         naddr, addr, NULL, &mhash, sleep);
                if (ret < 0)
                        return ret;
+               free = false;
        }
 
        return t4vf_set_addr_hash(pi->adapter, pi->viid, uhash != 0,
@@ -2252,6 +2269,7 @@ static void __devinit cfg_queues(struct adapter *adapter)
 {
        struct sge *s = &adapter->sge;
        int q10g, n10g, qidx, pidx, qs;
+       size_t iqe_size;
 
        /*
         * We should not be called till we know how many Queue Sets we can
@@ -2295,6 +2313,13 @@ static void __devinit cfg_queues(struct adapter *adapter)
        }
        s->ethqsets = qidx;
 
+       /*
+        * The Ingress Queue Entry Size for our various Response Queues needs
+        * to be big enough to accommodate the largest message we can receive
+        * from the chip/firmware; which is 64 bytes ...
+        */
+       iqe_size = 64;
+
        /*
         * Set up default Queue Set parameters ...  Start off with the
         * shortest interrupt holdoff timer.
@@ -2303,7 +2328,7 @@ static void __devinit cfg_queues(struct adapter *adapter)
                struct sge_eth_rxq *rxq = &s->ethrxq[qs];
                struct sge_eth_txq *txq = &s->ethtxq[qs];
 
-               init_rspq(&rxq->rspq, 0, 0, 1024, L1_CACHE_BYTES);
+               init_rspq(&rxq->rspq, 0, 0, 1024, iqe_size);
                rxq->fl.size = 72;
                txq->q.size = 1024;
        }
@@ -2312,8 +2337,7 @@ static void __devinit cfg_queues(struct adapter *adapter)
         * The firmware event queue is used for link state changes and
         * notifications of TX DMA completions.
         */
-       init_rspq(&s->fw_evtq, SGE_TIMER_RSTRT_CNTR, 0, 512,
-                 L1_CACHE_BYTES);
+       init_rspq(&s->fw_evtq, SGE_TIMER_RSTRT_CNTR, 0, 512, iqe_size);
 
        /*
         * The forwarded interrupt queue is used when we're in MSI interrupt
@@ -2329,7 +2353,7 @@ static void __devinit cfg_queues(struct adapter *adapter)
         * any time ...
         */
        init_rspq(&s->intrq, SGE_TIMER_RSTRT_CNTR, 0, MSIX_ENTRIES + 1,
-                 L1_CACHE_BYTES);
+                 iqe_size);
 }
 
 /*
index e306c20dfaee3fd2c54a7d4e3497ddd8ba787d19..19520afe1a12d70dd06748bba1a27e7bf65af526 100644 (file)
@@ -1014,48 +1014,72 @@ int t4vf_alloc_mac_filt(struct adapter *adapter, unsigned int viid, bool free,
                        unsigned int naddr, const u8 **addr, u16 *idx,
                        u64 *hash, bool sleep_ok)
 {
-       int i, ret;
+       int offset, ret = 0;
+       unsigned nfilters = 0;
+       unsigned int rem = naddr;
        struct fw_vi_mac_cmd cmd, rpl;
-       struct fw_vi_mac_exact *p;
-       size_t len16;
 
-       if (naddr > ARRAY_SIZE(cmd.u.exact))
+       if (naddr > FW_CLS_TCAM_NUM_ENTRIES)
                return -EINVAL;
-       len16 = DIV_ROUND_UP(offsetof(struct fw_vi_mac_cmd,
-                                     u.exact[naddr]), 16);
 
-       memset(&cmd, 0, sizeof(cmd));
-       cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_MAC_CMD) |
-                                    FW_CMD_REQUEST |
-                                    FW_CMD_WRITE |
-                                    (free ? FW_CMD_EXEC : 0) |
-                                    FW_VI_MAC_CMD_VIID(viid));
-       cmd.freemacs_to_len16 = cpu_to_be32(FW_VI_MAC_CMD_FREEMACS(free) |
-                                           FW_CMD_LEN16(len16));
+       for (offset = 0; offset < naddr; /**/) {
+               unsigned int fw_naddr = (rem < ARRAY_SIZE(cmd.u.exact)
+                                        ? rem
+                                        : ARRAY_SIZE(cmd.u.exact));
+               size_t len16 = DIV_ROUND_UP(offsetof(struct fw_vi_mac_cmd,
+                                                    u.exact[fw_naddr]), 16);
+               struct fw_vi_mac_exact *p;
+               int i;
 
-       for (i = 0, p = cmd.u.exact; i < naddr; i++, p++) {
-               p->valid_to_idx =
-                       cpu_to_be16(FW_VI_MAC_CMD_VALID |
-                                   FW_VI_MAC_CMD_IDX(FW_VI_MAC_ADD_MAC));
-               memcpy(p->macaddr, addr[i], sizeof(p->macaddr));
-       }
+               memset(&cmd, 0, sizeof(cmd));
+               cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_MAC_CMD) |
+                                            FW_CMD_REQUEST |
+                                            FW_CMD_WRITE |
+                                            (free ? FW_CMD_EXEC : 0) |
+                                            FW_VI_MAC_CMD_VIID(viid));
+               cmd.freemacs_to_len16 =
+                       cpu_to_be32(FW_VI_MAC_CMD_FREEMACS(free) |
+                                   FW_CMD_LEN16(len16));
+
+               for (i = 0, p = cmd.u.exact; i < fw_naddr; i++, p++) {
+                       p->valid_to_idx = cpu_to_be16(
+                               FW_VI_MAC_CMD_VALID |
+                               FW_VI_MAC_CMD_IDX(FW_VI_MAC_ADD_MAC));
+                       memcpy(p->macaddr, addr[offset+i], sizeof(p->macaddr));
+               }
+
+
+               ret = t4vf_wr_mbox_core(adapter, &cmd, sizeof(cmd), &rpl,
+                                       sleep_ok);
+               if (ret && ret != -ENOMEM)
+                       break;
 
-       ret = t4vf_wr_mbox_core(adapter, &cmd, sizeof(cmd), &rpl, sleep_ok);
-       if (ret)
-               return ret;
-
-       for (i = 0, p = rpl.u.exact; i < naddr; i++, p++) {
-               u16 index = FW_VI_MAC_CMD_IDX_GET(be16_to_cpu(p->valid_to_idx));
-
-               if (idx)
-                       idx[i] = (index >= FW_CLS_TCAM_NUM_ENTRIES
-                                 ? 0xffff
-                                 : index);
-               if (index < FW_CLS_TCAM_NUM_ENTRIES)
-                       ret++;
-               else if (hash)
-                       *hash |= (1 << hash_mac_addr(addr[i]));
+               for (i = 0, p = rpl.u.exact; i < fw_naddr; i++, p++) {
+                       u16 index = FW_VI_MAC_CMD_IDX_GET(
+                               be16_to_cpu(p->valid_to_idx));
+
+                       if (idx)
+                               idx[offset+i] =
+                                       (index >= FW_CLS_TCAM_NUM_ENTRIES
+                                        ? 0xffff
+                                        : index);
+                       if (index < FW_CLS_TCAM_NUM_ENTRIES)
+                               nfilters++;
+                       else if (hash)
+                               *hash |= (1ULL << hash_mac_addr(addr[offset+i]));
+               }
+
+               free = false;
+               offset += fw_naddr;
+               rem -= fw_naddr;
        }
+
+       /*
+        * If there were no errors or we merely ran out of room in our MAC
+        * address arena, return the number of filters actually written.
+        */
+       if (ret == 0 || ret == -ENOMEM)
+               ret = nfilters;
        return ret;
 }
 
index 4686c3983fc3044f0e0af47cf75dee71b6dadb02..4d62f7bfa0367578471f2773f04a365fed7db972 100644 (file)
@@ -31,7 +31,7 @@
 
 char e1000_driver_name[] = "e1000";
 static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
-#define DRV_VERSION "7.3.21-k6-NAPI"
+#define DRV_VERSION "7.3.21-k8-NAPI"
 const char e1000_driver_version[] = DRV_VERSION;
 static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
 
@@ -485,9 +485,6 @@ void e1000_down(struct e1000_adapter *adapter)
        struct net_device *netdev = adapter->netdev;
        u32 rctl, tctl;
 
-       /* signal that we're down so the interrupt handler does not
-        * reschedule our watchdog timer */
-       set_bit(__E1000_DOWN, &adapter->flags);
 
        /* disable receives in the hardware */
        rctl = er32(RCTL);
@@ -508,6 +505,13 @@ void e1000_down(struct e1000_adapter *adapter)
 
        e1000_irq_disable(adapter);
 
+       /*
+        * Setting DOWN must be after irq_disable to prevent
+        * a screaming interrupt.  Setting DOWN also prevents
+        * timers and tasks from rescheduling.
+        */
+       set_bit(__E1000_DOWN, &adapter->flags);
+
        del_timer_sync(&adapter->tx_fifo_stall_timer);
        del_timer_sync(&adapter->watchdog_timer);
        del_timer_sync(&adapter->phy_info_timer);
index 75b099ce49c9b47e361adc66da99d148b58640f3..1f37ee6b2a2626282fd5a772cc21f821321b9379 100644 (file)
@@ -261,6 +261,13 @@ static void ehea_get_ethtool_stats(struct net_device *dev,
 
 }
 
+static int ehea_set_flags(struct net_device *dev, u32 data)
+{
+       return ethtool_op_set_flags(dev, data, ETH_FLAG_LRO
+                                       | ETH_FLAG_TXVLAN
+                                       | ETH_FLAG_RXVLAN);
+}
+
 const struct ethtool_ops ehea_ethtool_ops = {
        .get_settings = ehea_get_settings,
        .get_drvinfo = ehea_get_drvinfo,
@@ -273,6 +280,8 @@ const struct ethtool_ops ehea_ethtool_ops = {
        .get_ethtool_stats = ehea_get_ethtool_stats,
        .get_rx_csum = ehea_get_rx_csum,
        .set_settings = ehea_set_settings,
+       .get_flags = ethtool_op_get_flags,
+       .set_flags = ehea_set_flags,
        .nway_reset = ehea_nway_reset,          /* Restart autonegotiation */
 };
 
index 182b2a7be8dcd02673bd9512d2760cb61b86b884..b95f087cd5a9c4a51525718e90ba65b56cf81b99 100644 (file)
@@ -400,6 +400,7 @@ static void ehea_refill_rq1(struct ehea_port_res *pr, int index, int nr_of_wqes)
                        skb_arr_rq1[index] = netdev_alloc_skb(dev,
                                                              EHEA_L_PKT_SIZE);
                        if (!skb_arr_rq1[index]) {
+                               ehea_info("Unable to allocate enough skb in the array\n");
                                pr->rq1_skba.os_skbs = fill_wqes - i;
                                break;
                        }
@@ -422,13 +423,20 @@ static void ehea_init_fill_rq1(struct ehea_port_res *pr, int nr_rq1a)
        struct net_device *dev = pr->port->netdev;
        int i;
 
-       for (i = 0; i < pr->rq1_skba.len; i++) {
+       if (nr_rq1a > pr->rq1_skba.len) {
+               ehea_error("NR_RQ1A bigger than skb array len\n");
+               return;
+       }
+
+       for (i = 0; i < nr_rq1a; i++) {
                skb_arr_rq1[i] = netdev_alloc_skb(dev, EHEA_L_PKT_SIZE);
-               if (!skb_arr_rq1[i])
+               if (!skb_arr_rq1[i]) {
+                       ehea_info("No enough memory to allocate skb array\n");
                        break;
+               }
        }
        /* Ring doorbell */
-       ehea_update_rq1a(pr->qp, nr_rq1a);
+       ehea_update_rq1a(pr->qp, i);
 }
 
 static int ehea_refill_rq_def(struct ehea_port_res *pr,
@@ -675,7 +683,7 @@ static void ehea_proc_skb(struct ehea_port_res *pr, struct ehea_cqe *cqe,
        int vlan_extracted = ((cqe->status & EHEA_CQE_VLAN_TAG_XTRACT) &&
                              pr->port->vgrp);
 
-       if (use_lro) {
+       if (skb->dev->features & NETIF_F_LRO) {
                if (vlan_extracted)
                        lro_vlan_hwaccel_receive_skb(&pr->lro_mgr, skb,
                                                     pr->port->vgrp,
@@ -735,8 +743,10 @@ static int ehea_proc_rwqes(struct net_device *dev,
 
                                        skb = netdev_alloc_skb(dev,
                                                               EHEA_L_PKT_SIZE);
-                                       if (!skb)
+                                       if (!skb) {
+                                               ehea_info("Not enough memory to allocate skb\n");
                                                break;
+                                       }
                                }
                                skb_copy_to_linear_data(skb, ((char *)cqe) + 64,
                                                 cqe->num_bytes_transfered - 4);
@@ -777,7 +787,7 @@ static int ehea_proc_rwqes(struct net_device *dev,
                }
                cqe = ehea_poll_rq1(qp, &wqe_index);
        }
-       if (use_lro)
+       if (dev->features & NETIF_F_LRO)
                lro_flush_all(&pr->lro_mgr);
 
        pr->rx_packets += processed;
@@ -3268,6 +3278,9 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
                      | NETIF_F_LLTX;
        dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT;
 
+       if (use_lro)
+               dev->features |= NETIF_F_LRO;
+
        INIT_WORK(&port->reset_task, ehea_reset_port);
 
        ret = register_netdev(dev);
index a466ef91dd4351d58f37e4ed5b443395ce4725e6..aa28b270c045e1a32562be18f68a1ec0449f276f 100644 (file)
@@ -1962,7 +1962,8 @@ static void enic_poll_controller(struct net_device *netdev)
        case VNIC_DEV_INTR_MODE_MSIX:
                for (i = 0; i < enic->rq_count; i++) {
                        intr = enic_msix_rq_intr(enic, i);
-                       enic_isr_msix_rq(enic->msix_entry[intr].vector, enic);
+                       enic_isr_msix_rq(enic->msix_entry[intr].vector,
+                               &enic->napi[i]);
                }
                intr = enic_msix_wq_intr(enic, i);
                enic_isr_msix_wq(enic->msix_entry[intr].vector, enic);
index 49e4ce1246a75e01c30a623de0031707fe0273c9..d1bec6269173844cfb17786c99936beee8dfd197 100644 (file)
@@ -577,11 +577,10 @@ static int gfar_parse_group(struct device_node *np,
                        irq_of_parse_and_map(np, 1);
                priv->gfargrp[priv->num_grps].interruptError =
                        irq_of_parse_and_map(np,2);
-               if (priv->gfargrp[priv->num_grps].interruptTransmit < 0 ||
-                       priv->gfargrp[priv->num_grps].interruptReceive < 0 ||
-                       priv->gfargrp[priv->num_grps].interruptError < 0) {
+               if (priv->gfargrp[priv->num_grps].interruptTransmit == NO_IRQ ||
+                   priv->gfargrp[priv->num_grps].interruptReceive  == NO_IRQ ||
+                   priv->gfargrp[priv->num_grps].interruptError    == NO_IRQ)
                        return -EINVAL;
-               }
        }
 
        priv->gfargrp[priv->num_grps].grp_id = priv->num_grps;
index ab9f675c5b8b8b86473d07b60b3ad933523b3ab5..fe337bd121aa74d3eb60cf866e31b8f76fa84573 100644 (file)
@@ -104,6 +104,8 @@ static void ri_tasklet(unsigned long dev)
                        rcu_read_unlock();
                        dev_kfree_skb(skb);
                        stats->tx_dropped++;
+                       if (skb_queue_len(&dp->tq) != 0)
+                               goto resched;
                        break;
                }
                rcu_read_unlock();
index dc019809234352418978474531efa675a4e879a2..aa93655c3aa7c1da10f8aeda9eaf2a1535b06756 100644 (file)
@@ -88,16 +88,14 @@ static const char *ipg_brand_name[] = {
        "IC PLUS IP1000 1000/100/10 based NIC",
        "Sundance Technology ST2021 based NIC",
        "Tamarack Microelectronics TC9020/9021 based NIC",
-       "Tamarack Microelectronics TC9020/9021 based NIC",
        "D-Link NIC IP1000A"
 };
 
 static DEFINE_PCI_DEVICE_TABLE(ipg_pci_tbl) = {
        { PCI_VDEVICE(SUNDANCE, 0x1023), 0 },
        { PCI_VDEVICE(SUNDANCE, 0x2021), 1 },
-       { PCI_VDEVICE(SUNDANCE, 0x1021), 2 },
-       { PCI_VDEVICE(DLINK,    0x9021), 3 },
-       { PCI_VDEVICE(DLINK,    0x4020), 4 },
+       { PCI_VDEVICE(DLINK,    0x9021), 2 },
+       { PCI_VDEVICE(DLINK,    0x4020), 3 },
        { 0, }
 };
 
index 00b38bccd6d0fd51f19cfe383f71a1f5952d6a43..52a7c86af66347c388d24d29b043fe52e6a2ca5f 100644 (file)
@@ -258,7 +258,7 @@ static int sh_sir_set_baudrate(struct sh_sir_self *self, u32 baudrate)
 
        /* Baud Rate Error Correction x 10000 */
        u32 rate_err_array[] = {
-               0000, 0625, 1250, 1875,
+                  0,  625, 1250, 1875,
                2500, 3125, 3750, 4375,
                5000, 5625, 6250, 6875,
                7500, 8125, 8750, 9375,
index fbad4d819608f234d0eff25175bccf9a8545c20b..eee0b298bd3616558ca8d9f5cf44a02fe95c68e7 100644 (file)
@@ -4771,6 +4771,9 @@ void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter)
                adapter->rx_ring[i] = NULL;
        }
 
+       adapter->num_tx_queues = 0;
+       adapter->num_rx_queues = 0;
+
        ixgbe_free_q_vectors(adapter);
        ixgbe_reset_interrupt_capability(adapter);
 }
index b68eee2414c208765849d0136dfb7cb0065f52ba..7a7e18ba278a829bebc488e091fc615e8aed5825 100644 (file)
@@ -289,6 +289,10 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
                MLX4_GET(field, outbox, QUERY_DEV_CAP_LOG_BF_REG_SZ_OFFSET);
                dev_cap->bf_reg_size = 1 << (field & 0x1f);
                MLX4_GET(field, outbox, QUERY_DEV_CAP_LOG_MAX_BF_REGS_PER_PAGE_OFFSET);
+               if ((1 << (field & 0x3f)) > (PAGE_SIZE / dev_cap->bf_reg_size)) {
+                       mlx4_warn(dev, "firmware bug: log2 # of blue flame regs is invalid (%d), forcing 3\n", field & 0x1f);
+                       field = 3;
+               }
                dev_cap->bf_regs_per_page = 1 << (field & 0x3f);
                mlx4_dbg(dev, "BlueFlame available (reg size %d, regs/page %d)\n",
                         dev_cap->bf_reg_size, dev_cap->bf_regs_per_page);
index 472056b47440877f93c83a11d994fca16b99dd96..03a1d280105f72c93b99744b7e69690aff992946 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 1999 - 2010 Intel Corporation.
- * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ * Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD.
  *
  * This code was derived from the Intel e1000e Linux driver.
  *
@@ -2464,8 +2464,8 @@ static void __exit pch_gbe_exit_module(void)
 module_init(pch_gbe_init_module);
 module_exit(pch_gbe_exit_module);
 
-MODULE_DESCRIPTION("OKI semiconductor PCH Gigabit ethernet Driver");
-MODULE_AUTHOR("OKI semiconductor, <masa-korg@dsn.okisemi.com>");
+MODULE_DESCRIPTION("EG20T PCH Gigabit ethernet Driver");
+MODULE_AUTHOR("OKI SEMICONDUCTOR, <toshiharu-linux@dsn.okisemi.com>");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 MODULE_DEVICE_TABLE(pci, pch_gbe_pcidev_id);
index 2510146fc5607db7a26d9b54ad634f8941d65ae2..ef0996a0eaaaa9e39e84d183cbc074be9bff5080 100644 (file)
@@ -434,8 +434,8 @@ void pch_gbe_check_options(struct pch_gbe_adapter *adapter)
                        .err  = "using default of "
                                __MODULE_STRING(PCH_GBE_DEFAULT_TXD),
                        .def  = PCH_GBE_DEFAULT_TXD,
-                       .arg  = { .r = { .min = PCH_GBE_MIN_TXD } },
-                       .arg  = { .r = { .max = PCH_GBE_MAX_TXD } }
+                       .arg  = { .r = { .min = PCH_GBE_MIN_TXD,
+                                        .max = PCH_GBE_MAX_TXD } }
                };
                struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring;
                tx_ring->count = TxDescriptors;
@@ -450,8 +450,8 @@ void pch_gbe_check_options(struct pch_gbe_adapter *adapter)
                        .err  = "using default of "
                                __MODULE_STRING(PCH_GBE_DEFAULT_RXD),
                        .def  = PCH_GBE_DEFAULT_RXD,
-                       .arg  = { .r = { .min = PCH_GBE_MIN_RXD } },
-                       .arg  = { .r = { .max = PCH_GBE_MAX_RXD } }
+                       .arg  = { .r = { .min = PCH_GBE_MIN_RXD,
+                                        .max = PCH_GBE_MAX_RXD } }
                };
                struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring;
                rx_ring->count = RxDescriptors;
index cb3d13e4e074097a4b89b9f0315f3d64b6ad68ff..35fda5ac8120c056eb94d0f14bea376494d2d59c 100644 (file)
@@ -64,7 +64,7 @@ config BCM63XX_PHY
 config ICPLUS_PHY
        tristate "Drivers for ICPlus PHYs"
        ---help---
-         Currently supports the IP175C PHY.
+         Currently supports the IP175C and IP1001 PHYs.
 
 config REALTEK_PHY
        tristate "Drivers for Realtek PHYs"
index c1d2d251fe8bfcef7114fd57b1018c70697006f5..9a09e24c30bc2e222974b481f76d219ed6a22cd6 100644 (file)
@@ -30,7 +30,7 @@
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 
-MODULE_DESCRIPTION("ICPlus IP175C PHY driver");
+MODULE_DESCRIPTION("ICPlus IP175C/IC1001 PHY drivers");
 MODULE_AUTHOR("Michael Barkowski");
 MODULE_LICENSE("GPL");
 
@@ -89,6 +89,33 @@ static int ip175c_config_init(struct phy_device *phydev)
        return 0;
 }
 
+static int ip1001_config_init(struct phy_device *phydev)
+{
+       int err, value;
+
+       /* Software Reset PHY */
+       value = phy_read(phydev, MII_BMCR);
+       value |= BMCR_RESET;
+       err = phy_write(phydev, MII_BMCR, value);
+       if (err < 0)
+               return err;
+
+       do {
+               value = phy_read(phydev, MII_BMCR);
+       } while (value & BMCR_RESET);
+
+       /* Additional delay (2ns) used to adjust RX clock phase
+        * at GMII/ RGMII interface */
+       value = phy_read(phydev, 16);
+       value |= 0x3;
+
+       err = phy_write(phydev, 16, value);
+       if (err < 0)
+               return err;
+
+       return err;
+}
+
 static int ip175c_read_status(struct phy_device *phydev)
 {
        if (phydev->addr == 4) /* WAN port */
@@ -121,21 +148,43 @@ static struct phy_driver ip175c_driver = {
        .driver         = { .owner = THIS_MODULE,},
 };
 
-static int __init ip175c_init(void)
+static struct phy_driver ip1001_driver = {
+       .phy_id         = 0x02430d90,
+       .name           = "ICPlus IP1001",
+       .phy_id_mask    = 0x0ffffff0,
+       .features       = PHY_GBIT_FEATURES | SUPPORTED_Pause |
+                         SUPPORTED_Asym_Pause,
+       .config_init    = &ip1001_config_init,
+       .config_aneg    = &genphy_config_aneg,
+       .read_status    = &genphy_read_status,
+       .suspend        = genphy_suspend,
+       .resume         = genphy_resume,
+       .driver         = { .owner = THIS_MODULE,},
+};
+
+static int __init icplus_init(void)
 {
+       int ret = 0;
+
+       ret = phy_driver_register(&ip1001_driver);
+       if (ret < 0)
+               return -ENODEV;
+
        return phy_driver_register(&ip175c_driver);
 }
 
-static void __exit ip175c_exit(void)
+static void __exit icplus_exit(void)
 {
+       phy_driver_unregister(&ip1001_driver);
        phy_driver_unregister(&ip175c_driver);
 }
 
-module_init(ip175c_init);
-module_exit(ip175c_exit);
+module_init(icplus_init);
+module_exit(icplus_exit);
 
 static struct mdio_device_id __maybe_unused icplus_tbl[] = {
        { 0x02430d80, 0x0ffffff0 },
+       { 0x02430d90, 0x0ffffff0 },
        { }
 };
 
index f0bd1a1aba3ab3413a16eab296b4881d99ea1145..e8b9c53c304b63d2ba2b4a530504e5fafb08f6dc 100644 (file)
 #include <linux/ethtool.h>
 #include <linux/phy.h>
 #include <linux/marvell_phy.h>
+#include <linux/of.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 
+#define MII_MARVELL_PHY_PAGE           22
+
 #define MII_M1011_IEVENT               0x13
 #define MII_M1011_IEVENT_CLEAR         0x0000
 
@@ -80,7 +83,6 @@
 #define MII_88E1121_PHY_LED_CTRL       16
 #define MII_88E1121_PHY_LED_PAGE       3
 #define MII_88E1121_PHY_LED_DEF                0x0030
-#define MII_88E1121_PHY_PAGE           22
 
 #define MII_M1011_PHY_STATUS           0x11
 #define MII_M1011_PHY_STATUS_1000      0x8000
@@ -186,13 +188,94 @@ static int marvell_config_aneg(struct phy_device *phydev)
        return 0;
 }
 
+#ifdef CONFIG_OF_MDIO
+/*
+ * Set and/or override some configuration registers based on the
+ * marvell,reg-init property stored in the of_node for the phydev.
+ *
+ * marvell,reg-init = <reg-page reg mask value>,...;
+ *
+ * There may be one or more sets of <reg-page reg mask value>:
+ *
+ * reg-page: which register bank to use.
+ * reg: the register.
+ * mask: if non-zero, ANDed with existing register value.
+ * value: ORed with the masked value and written to the regiser.
+ *
+ */
+static int marvell_of_reg_init(struct phy_device *phydev)
+{
+       const __be32 *paddr;
+       int len, i, saved_page, current_page, page_changed, ret;
+
+       if (!phydev->dev.of_node)
+               return 0;
+
+       paddr = of_get_property(phydev->dev.of_node, "marvell,reg-init", &len);
+       if (!paddr || len < (4 * sizeof(*paddr)))
+               return 0;
+
+       saved_page = phy_read(phydev, MII_MARVELL_PHY_PAGE);
+       if (saved_page < 0)
+               return saved_page;
+       page_changed = 0;
+       current_page = saved_page;
+
+       ret = 0;
+       len /= sizeof(*paddr);
+       for (i = 0; i < len - 3; i += 4) {
+               u16 reg_page = be32_to_cpup(paddr + i);
+               u16 reg = be32_to_cpup(paddr + i + 1);
+               u16 mask = be32_to_cpup(paddr + i + 2);
+               u16 val_bits = be32_to_cpup(paddr + i + 3);
+               int val;
+
+               if (reg_page != current_page) {
+                       current_page = reg_page;
+                       page_changed = 1;
+                       ret = phy_write(phydev, MII_MARVELL_PHY_PAGE, reg_page);
+                       if (ret < 0)
+                               goto err;
+               }
+
+               val = 0;
+               if (mask) {
+                       val = phy_read(phydev, reg);
+                       if (val < 0) {
+                               ret = val;
+                               goto err;
+                       }
+                       val &= mask;
+               }
+               val |= val_bits;
+
+               ret = phy_write(phydev, reg, val);
+               if (ret < 0)
+                       goto err;
+
+       }
+err:
+       if (page_changed) {
+               i = phy_write(phydev, MII_MARVELL_PHY_PAGE, saved_page);
+               if (ret == 0)
+                       ret = i;
+       }
+       return ret;
+}
+#else
+static int marvell_of_reg_init(struct phy_device *phydev)
+{
+       return 0;
+}
+#endif /* CONFIG_OF_MDIO */
+
 static int m88e1121_config_aneg(struct phy_device *phydev)
 {
        int err, oldpage, mscr;
 
-       oldpage = phy_read(phydev, MII_88E1121_PHY_PAGE);
+       oldpage = phy_read(phydev, MII_MARVELL_PHY_PAGE);
 
-       err = phy_write(phydev, MII_88E1121_PHY_PAGE,
+       err = phy_write(phydev, MII_MARVELL_PHY_PAGE,
                        MII_88E1121_PHY_MSCR_PAGE);
        if (err < 0)
                return err;
@@ -218,7 +301,7 @@ static int m88e1121_config_aneg(struct phy_device *phydev)
                        return err;
        }
 
-       phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage);
+       phy_write(phydev, MII_MARVELL_PHY_PAGE, oldpage);
 
        err = phy_write(phydev, MII_BMCR, BMCR_RESET);
        if (err < 0)
@@ -229,11 +312,11 @@ static int m88e1121_config_aneg(struct phy_device *phydev)
        if (err < 0)
                return err;
 
-       oldpage = phy_read(phydev, MII_88E1121_PHY_PAGE);
+       oldpage = phy_read(phydev, MII_MARVELL_PHY_PAGE);
 
-       phy_write(phydev, MII_88E1121_PHY_PAGE, MII_88E1121_PHY_LED_PAGE);
+       phy_write(phydev, MII_MARVELL_PHY_PAGE, MII_88E1121_PHY_LED_PAGE);
        phy_write(phydev, MII_88E1121_PHY_LED_CTRL, MII_88E1121_PHY_LED_DEF);
-       phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage);
+       phy_write(phydev, MII_MARVELL_PHY_PAGE, oldpage);
 
        err = genphy_config_aneg(phydev);
 
@@ -244,9 +327,9 @@ static int m88e1318_config_aneg(struct phy_device *phydev)
 {
        int err, oldpage, mscr;
 
-       oldpage = phy_read(phydev, MII_88E1121_PHY_PAGE);
+       oldpage = phy_read(phydev, MII_MARVELL_PHY_PAGE);
 
-       err = phy_write(phydev, MII_88E1121_PHY_PAGE,
+       err = phy_write(phydev, MII_MARVELL_PHY_PAGE,
                        MII_88E1121_PHY_MSCR_PAGE);
        if (err < 0)
                return err;
@@ -258,7 +341,7 @@ static int m88e1318_config_aneg(struct phy_device *phydev)
        if (err < 0)
                return err;
 
-       err = phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage);
+       err = phy_write(phydev, MII_MARVELL_PHY_PAGE, oldpage);
        if (err < 0)
                return err;
 
@@ -368,6 +451,9 @@ static int m88e1111_config_init(struct phy_device *phydev)
                        return err;
        }
 
+       err = marvell_of_reg_init(phydev);
+       if (err < 0)
+               return err;
 
        err = phy_write(phydev, MII_BMCR, BMCR_RESET);
        if (err < 0)
@@ -398,7 +484,7 @@ static int m88e1118_config_init(struct phy_device *phydev)
        int err;
 
        /* Change address */
-       err = phy_write(phydev, 0x16, 0x0002);
+       err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0002);
        if (err < 0)
                return err;
 
@@ -408,7 +494,7 @@ static int m88e1118_config_init(struct phy_device *phydev)
                return err;
 
        /* Change address */
-       err = phy_write(phydev, 0x16, 0x0003);
+       err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0003);
        if (err < 0)
                return err;
 
@@ -420,8 +506,42 @@ static int m88e1118_config_init(struct phy_device *phydev)
        if (err < 0)
                return err;
 
+       err = marvell_of_reg_init(phydev);
+       if (err < 0)
+               return err;
+
        /* Reset address */
-       err = phy_write(phydev, 0x16, 0x0);
+       err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0);
+       if (err < 0)
+               return err;
+
+       err = phy_write(phydev, MII_BMCR, BMCR_RESET);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int m88e1149_config_init(struct phy_device *phydev)
+{
+       int err;
+
+       /* Change address */
+       err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0002);
+       if (err < 0)
+               return err;
+
+       /* Enable 1000 Mbit */
+       err = phy_write(phydev, 0x15, 0x1048);
+       if (err < 0)
+               return err;
+
+       err = marvell_of_reg_init(phydev);
+       if (err < 0)
+               return err;
+
+       /* Reset address */
+       err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0);
        if (err < 0)
                return err;
 
@@ -491,6 +611,10 @@ static int m88e1145_config_init(struct phy_device *phydev)
                }
        }
 
+       err = marvell_of_reg_init(phydev);
+       if (err < 0)
+               return err;
+
        return 0;
 }
 
@@ -684,6 +808,19 @@ static struct phy_driver marvell_drivers[] = {
                .config_intr = &marvell_config_intr,
                .driver = { .owner = THIS_MODULE },
        },
+       {
+               .phy_id = MARVELL_PHY_ID_88E1149R,
+               .phy_id_mask = MARVELL_PHY_ID_MASK,
+               .name = "Marvell 88E1149R",
+               .features = PHY_GBIT_FEATURES,
+               .flags = PHY_HAS_INTERRUPT,
+               .config_init = &m88e1149_config_init,
+               .config_aneg = &m88e1118_config_aneg,
+               .read_status = &genphy_read_status,
+               .ack_interrupt = &marvell_ack_interrupt,
+               .config_intr = &marvell_config_intr,
+               .driver = { .owner = THIS_MODULE },
+       },
        {
                .phy_id = MARVELL_PHY_ID_88E1240,
                .phy_id_mask = MARVELL_PHY_ID_MASK,
@@ -735,6 +872,7 @@ static struct mdio_device_id __maybe_unused marvell_tbl[] = {
        { 0x01410e10, 0xfffffff0 },
        { 0x01410cb0, 0xfffffff0 },
        { 0x01410cd0, 0xfffffff0 },
+       { 0x01410e50, 0xfffffff0 },
        { 0x01410e30, 0xfffffff0 },
        { 0x01410e90, 0xfffffff0 },
        { }
index 09cf56d0416a8c24c78780c7eb374fcebf01cffc..39659976a1acfb1589834368aab20080c894d6eb 100644 (file)
@@ -2584,16 +2584,16 @@ ppp_create_interface(struct net *net, int unit, int *retp)
         */
        dev_net_set(dev, net);
 
-       ret = -EEXIST;
        mutex_lock(&pn->all_ppp_mutex);
 
        if (unit < 0) {
                unit = unit_get(&pn->units_idr, ppp);
                if (unit < 0) {
-                       *retp = unit;
+                       ret = unit;
                        goto out2;
                }
        } else {
+               ret = -EEXIST;
                if (unit_find(&pn->units_idr, unit))
                        goto out2; /* unit already exists */
                /*
@@ -2668,10 +2668,10 @@ static void ppp_shutdown_interface(struct ppp *ppp)
                ppp->closing = 1;
                ppp_unlock(ppp);
                unregister_netdev(ppp->dev);
+               unit_put(&pn->units_idr, ppp->file.index);
        } else
                ppp_unlock(ppp);
 
-       unit_put(&pn->units_idr, ppp->file.index);
        ppp->file.dead = 1;
        ppp->owner = NULL;
        wake_up_interruptible(&ppp->file.rwait);
@@ -2859,8 +2859,7 @@ static void __exit ppp_cleanup(void)
  * by holding all_ppp_mutex
  */
 
-/* associate pointer with specified number */
-static int unit_set(struct idr *p, void *ptr, int n)
+static int __unit_alloc(struct idr *p, void *ptr, int n)
 {
        int unit, err;
 
@@ -2871,10 +2870,24 @@ again:
        }
 
        err = idr_get_new_above(p, ptr, n, &unit);
-       if (err == -EAGAIN)
-               goto again;
+       if (err < 0) {
+               if (err == -EAGAIN)
+                       goto again;
+               return err;
+       }
+
+       return unit;
+}
+
+/* associate pointer with specified number */
+static int unit_set(struct idr *p, void *ptr, int n)
+{
+       int unit;
 
-       if (unit != n) {
+       unit = __unit_alloc(p, ptr, n);
+       if (unit < 0)
+               return unit;
+       else if (unit != n) {
                idr_remove(p, unit);
                return -EINVAL;
        }
@@ -2885,19 +2898,7 @@ again:
 /* get new free unit number and associate pointer with it */
 static int unit_get(struct idr *p, void *ptr)
 {
-       int unit, err;
-
-again:
-       if (!idr_pre_get(p, GFP_KERNEL)) {
-               printk(KERN_ERR "PPP: No free memory for idr\n");
-               return -ENOMEM;
-       }
-
-       err = idr_get_new_above(p, ptr, 0, &unit);
-       if (err == -EAGAIN)
-               goto again;
-
-       return unit;
+       return __unit_alloc(p, ptr, 0);
 }
 
 /* put unit number back to a pool */
index d72fb0519a2aa674a8757f5146b0df19655d9749..78c0e3c9b2b5fcb8d42fb910ab2416e4db787dc7 100644 (file)
@@ -948,7 +948,7 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
 
 abort:
        kfree_skb(skb);
-       return 0;
+       return 1;
 }
 
 /************************************************************************
index 22821398fc63765054eff056ab2529beedfb30fc..9787dff90d3fa18a3e70cbdac43fa73062202b33 100644 (file)
@@ -2083,6 +2083,7 @@ struct ql_adapter {
        u32 mailbox_in;
        u32 mailbox_out;
        struct mbox_params idc_mbc;
+       struct mutex    mpi_mutex;
 
        int tx_ring_size;
        int rx_ring_size;
index c30e0fe55a314858828c2caa4d464b0c2301fe81..2555b1d34f346d691f904bb3f8593a3933f2b6fc 100644 (file)
@@ -62,15 +62,15 @@ static const u32 default_msg =
 /* NETIF_MSG_PKTDATA | */
     NETIF_MSG_HW | NETIF_MSG_WOL | 0;
 
-static int debug = 0x00007fff; /* defaults above */
-module_param(debug, int, 0);
+static int debug = -1; /* defaults above */
+module_param(debug, int, 0664);
 MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
 
 #define MSIX_IRQ 0
 #define MSI_IRQ 1
 #define LEG_IRQ 2
 static int qlge_irq_type = MSIX_IRQ;
-module_param(qlge_irq_type, int, MSIX_IRQ);
+module_param(qlge_irq_type, int, 0664);
 MODULE_PARM_DESC(qlge_irq_type, "0 = MSI-X, 1 = MSI, 2 = Legacy.");
 
 static int qlge_mpi_coredump;
@@ -4629,6 +4629,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
        INIT_DELAYED_WORK(&qdev->mpi_idc_work, ql_mpi_idc_work);
        INIT_DELAYED_WORK(&qdev->mpi_core_to_log, ql_mpi_core_to_log);
        init_completion(&qdev->ide_completion);
+       mutex_init(&qdev->mpi_mutex);
 
        if (!cards_found) {
                dev_info(&pdev->dev, "%s\n", DRV_STRING);
index 0e7c7c7ee1647006baf561ffd90308290fbd2399..a2e919bcb3c6b616250eeafb4e76ae7a5921f50e 100644 (file)
@@ -534,6 +534,7 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp)
        int status;
        unsigned long count;
 
+       mutex_lock(&qdev->mpi_mutex);
 
        /* Begin polled mode for MPI */
        ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16));
@@ -603,6 +604,7 @@ done:
 end:
        /* End polled mode for MPI */
        ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI);
+       mutex_unlock(&qdev->mpi_mutex);
        return status;
 }
 
@@ -1099,9 +1101,7 @@ int ql_wait_fifo_empty(struct ql_adapter *qdev)
 static int ql_set_port_cfg(struct ql_adapter *qdev)
 {
        int status;
-       rtnl_lock();
        status = ql_mb_set_port_cfg(qdev);
-       rtnl_unlock();
        if (status)
                return status;
        status = ql_idc_wait(qdev);
@@ -1122,9 +1122,7 @@ void ql_mpi_port_cfg_work(struct work_struct *work)
            container_of(work, struct ql_adapter, mpi_port_cfg_work.work);
        int status;
 
-       rtnl_lock();
        status = ql_mb_get_port_cfg(qdev);
-       rtnl_unlock();
        if (status) {
                netif_err(qdev, drv, qdev->ndev,
                          "Bug: Failed to get port config data.\n");
@@ -1167,7 +1165,6 @@ void ql_mpi_idc_work(struct work_struct *work)
        u32 aen;
        int timeout;
 
-       rtnl_lock();
        aen = mbcp->mbox_out[1] >> 16;
        timeout = (mbcp->mbox_out[1] >> 8) & 0xf;
 
@@ -1231,7 +1228,6 @@ void ql_mpi_idc_work(struct work_struct *work)
                }
                break;
        }
-       rtnl_unlock();
 }
 
 void ql_mpi_work(struct work_struct *work)
@@ -1242,7 +1238,7 @@ void ql_mpi_work(struct work_struct *work)
        struct mbox_params *mbcp = &mbc;
        int err = 0;
 
-       rtnl_lock();
+       mutex_lock(&qdev->mpi_mutex);
        /* Begin polled mode for MPI */
        ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16));
 
@@ -1259,7 +1255,7 @@ void ql_mpi_work(struct work_struct *work)
 
        /* End polled mode for MPI */
        ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI);
-       rtnl_unlock();
+       mutex_unlock(&qdev->mpi_mutex);
        ql_enable_completion_interrupt(qdev, 0);
 }
 
index 4c4d16905efb7253a055978e736edc93381cdd69..53b13deade9528539ea2dcaf5fe268b0e1ceabda 100644 (file)
@@ -744,26 +744,36 @@ static void rtl8169_xmii_reset_enable(void __iomem *ioaddr)
        mdio_write(ioaddr, MII_BMCR, val & 0xffff);
 }
 
-static void rtl8169_check_link_status(struct net_device *dev,
+static void __rtl8169_check_link_status(struct net_device *dev,
                                      struct rtl8169_private *tp,
-                                     void __iomem *ioaddr)
+                                     void __iomem *ioaddr,
+                                     bool pm)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&tp->lock, flags);
        if (tp->link_ok(ioaddr)) {
                /* This is to cancel a scheduled suspend if there's one. */
-               pm_request_resume(&tp->pci_dev->dev);
+               if (pm)
+                       pm_request_resume(&tp->pci_dev->dev);
                netif_carrier_on(dev);
                netif_info(tp, ifup, dev, "link up\n");
        } else {
                netif_carrier_off(dev);
                netif_info(tp, ifdown, dev, "link down\n");
-               pm_schedule_suspend(&tp->pci_dev->dev, 100);
+               if (pm)
+                       pm_schedule_suspend(&tp->pci_dev->dev, 100);
        }
        spin_unlock_irqrestore(&tp->lock, flags);
 }
 
+static void rtl8169_check_link_status(struct net_device *dev,
+                                     struct rtl8169_private *tp,
+                                     void __iomem *ioaddr)
+{
+       __rtl8169_check_link_status(dev, tp, ioaddr, false);
+}
+
 #define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
 
 static u32 __rtl8169_get_wol(struct rtl8169_private *tp)
@@ -4440,8 +4450,7 @@ static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1)
        u32 status = opts1 & RxProtoMask;
 
        if (((status == RxProtoTCP) && !(opts1 & TCPFail)) ||
-           ((status == RxProtoUDP) && !(opts1 & UDPFail)) ||
-           ((status == RxProtoIP) && !(opts1 & IPFail)))
+           ((status == RxProtoUDP) && !(opts1 & UDPFail)))
                skb->ip_summed = CHECKSUM_UNNECESSARY;
        else
                skb_checksum_none_assert(skb);
@@ -4601,7 +4610,7 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
                }
 
                if (status & LinkChg)
-                       rtl8169_check_link_status(dev, tp, ioaddr);
+                       __rtl8169_check_link_status(dev, tp, ioaddr, true);
 
                /* We need to see the lastest version of tp->intr_mask to
                 * avoid ignoring an MSI interrupt and having to wait for
@@ -4891,11 +4900,7 @@ static int rtl8169_runtime_idle(struct device *device)
        struct net_device *dev = pci_get_drvdata(pdev);
        struct rtl8169_private *tp = netdev_priv(dev);
 
-       if (!tp->TxDescArray)
-               return 0;
-
-       rtl8169_check_link_status(dev, tp, tp->mmio_addr);
-       return -EBUSY;
+       return tp->TxDescArray ? -EBUSY : 0;
 }
 
 static const struct dev_pm_ops rtl8169_pm_ops = {
index 05df20e47976cb3965c59c5b227e67877bd2d0c4..fb83cdd946436561dbe645f5d742317fea8cfe91 100644 (file)
@@ -197,7 +197,9 @@ MODULE_PARM_DESC(debug, "Bitmapped debugging message enable value");
 
 static void efx_remove_channels(struct efx_nic *efx);
 static void efx_remove_port(struct efx_nic *efx);
+static void efx_init_napi(struct efx_nic *efx);
 static void efx_fini_napi(struct efx_nic *efx);
+static void efx_fini_napi_channel(struct efx_channel *channel);
 static void efx_fini_struct(struct efx_nic *efx);
 static void efx_start_all(struct efx_nic *efx);
 static void efx_stop_all(struct efx_nic *efx);
@@ -335,8 +337,10 @@ void efx_process_channel_now(struct efx_channel *channel)
 
        /* Disable interrupts and wait for ISRs to complete */
        efx_nic_disable_interrupts(efx);
-       if (efx->legacy_irq)
+       if (efx->legacy_irq) {
                synchronize_irq(efx->legacy_irq);
+               efx->legacy_irq_enabled = false;
+       }
        if (channel->irq)
                synchronize_irq(channel->irq);
 
@@ -351,6 +355,8 @@ void efx_process_channel_now(struct efx_channel *channel)
        efx_channel_processed(channel);
 
        napi_enable(&channel->napi_str);
+       if (efx->legacy_irq)
+               efx->legacy_irq_enabled = true;
        efx_nic_enable_interrupts(efx);
 }
 
@@ -426,6 +432,7 @@ efx_alloc_channel(struct efx_nic *efx, int i, struct efx_channel *old_channel)
 
                *channel = *old_channel;
 
+               channel->napi_dev = NULL;
                memset(&channel->eventq, 0, sizeof(channel->eventq));
 
                rx_queue = &channel->rx_queue;
@@ -736,9 +743,13 @@ efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries)
        if (rc)
                goto rollback;
 
+       efx_init_napi(efx);
+
        /* Destroy old channels */
-       for (i = 0; i < efx->n_channels; i++)
+       for (i = 0; i < efx->n_channels; i++) {
+               efx_fini_napi_channel(other_channel[i]);
                efx_remove_channel(other_channel[i]);
+       }
 out:
        /* Free unused channel structures */
        for (i = 0; i < efx->n_channels; i++)
@@ -1400,6 +1411,8 @@ static void efx_start_all(struct efx_nic *efx)
                efx_start_channel(channel);
        }
 
+       if (efx->legacy_irq)
+               efx->legacy_irq_enabled = true;
        efx_nic_enable_interrupts(efx);
 
        /* Switch to event based MCDI completions after enabling interrupts.
@@ -1460,8 +1473,10 @@ static void efx_stop_all(struct efx_nic *efx)
 
        /* Disable interrupts and wait for ISR to complete */
        efx_nic_disable_interrupts(efx);
-       if (efx->legacy_irq)
+       if (efx->legacy_irq) {
                synchronize_irq(efx->legacy_irq);
+               efx->legacy_irq_enabled = false;
+       }
        efx_for_each_channel(channel, efx) {
                if (channel->irq)
                        synchronize_irq(channel->irq);
@@ -1593,7 +1608,7 @@ static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
  *
  **************************************************************************/
 
-static int efx_init_napi(struct efx_nic *efx)
+static void efx_init_napi(struct efx_nic *efx)
 {
        struct efx_channel *channel;
 
@@ -1602,18 +1617,21 @@ static int efx_init_napi(struct efx_nic *efx)
                netif_napi_add(channel->napi_dev, &channel->napi_str,
                               efx_poll, napi_weight);
        }
-       return 0;
+}
+
+static void efx_fini_napi_channel(struct efx_channel *channel)
+{
+       if (channel->napi_dev)
+               netif_napi_del(&channel->napi_str);
+       channel->napi_dev = NULL;
 }
 
 static void efx_fini_napi(struct efx_nic *efx)
 {
        struct efx_channel *channel;
 
-       efx_for_each_channel(channel, efx) {
-               if (channel->napi_dev)
-                       netif_napi_del(&channel->napi_str);
-               channel->napi_dev = NULL;
-       }
+       efx_for_each_channel(channel, efx)
+               efx_fini_napi_channel(channel);
 }
 
 /**************************************************************************
@@ -2335,9 +2353,7 @@ static int efx_pci_probe_main(struct efx_nic *efx)
        if (rc)
                goto fail1;
 
-       rc = efx_init_napi(efx);
-       if (rc)
-               goto fail2;
+       efx_init_napi(efx);
 
        rc = efx->type->init(efx);
        if (rc) {
@@ -2368,7 +2384,6 @@ static int efx_pci_probe_main(struct efx_nic *efx)
        efx->type->fini(efx);
  fail3:
        efx_fini_napi(efx);
- fail2:
        efx_remove_all(efx);
  fail1:
        return rc;
index 0a7e26d73b525b13aba1fc9e234d38a699322f2a..b137c889152b14be6486fe9271f00658f81df031 100644 (file)
@@ -621,6 +621,7 @@ struct efx_filter_state;
  * @pci_dev: The PCI device
  * @type: Controller type attributes
  * @legacy_irq: IRQ number
+ * @legacy_irq_enabled: Are IRQs enabled on NIC (INT_EN_KER register)?
  * @workqueue: Workqueue for port reconfigures and the HW monitor.
  *     Work items do not hold and must not acquire RTNL.
  * @workqueue_name: Name of workqueue
@@ -709,6 +710,7 @@ struct efx_nic {
        struct pci_dev *pci_dev;
        const struct efx_nic_type *type;
        int legacy_irq;
+       bool legacy_irq_enabled;
        struct workqueue_struct *workqueue;
        char workqueue_name[16];
        struct work_struct reset_work;
index 41c36b9a4244b907907936b0a6abeaf8f2a301d1..67cb0c96838caeee1bc0497266ef51dd8e9bb407 100644 (file)
@@ -1418,6 +1418,12 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id)
        u32 queues;
        int syserr;
 
+       /* Could this be ours?  If interrupts are disabled then the
+        * channel state may not be valid.
+        */
+       if (!efx->legacy_irq_enabled)
+               return result;
+
        /* Read the ISR which also ACKs the interrupts */
        efx_readd(efx, &reg, FR_BZ_INT_ISR0);
        queues = EFX_EXTRACT_DWORD(reg, 0, 31);
index 06bc6034ce810f49a67a698af524bec91e1eee5f..2114837809e76707e69f41cde38b0a0856ee745a 100644 (file)
@@ -1509,6 +1509,8 @@ static int stmmac_probe(struct net_device *dev)
                pr_warning("\tno valid MAC address;"
                        "please, use ifconfig or nwhwconfig!\n");
 
+       spin_lock_init(&priv->lock);
+
        ret = register_netdev(dev);
        if (ret) {
                pr_err("%s: ERROR %i registering the device\n",
@@ -1520,8 +1522,6 @@ static int stmmac_probe(struct net_device *dev)
            dev->name, (dev->features & NETIF_F_SG) ? "on" : "off",
            (dev->features & NETIF_F_HW_CSUM) ? "on" : "off");
 
-       spin_lock_init(&priv->lock);
-
        return ret;
 }
 
diff --git a/drivers/net/tile/Makefile b/drivers/net/tile/Makefile
new file mode 100644 (file)
index 0000000..f634f14
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Makefile for the TILE on-chip networking support.
+#
+
+obj-$(CONFIG_TILE_NET) += tile_net.o
+ifdef CONFIG_TILEGX
+tile_net-objs := tilegx.o mpipe.o iorpc_mpipe.o dma_queue.o
+else
+tile_net-objs := tilepro.o
+endif
diff --git a/drivers/net/tile/tilepro.c b/drivers/net/tile/tilepro.c
new file mode 100644 (file)
index 0000000..0e6bac5
--- /dev/null
@@ -0,0 +1,2406 @@
+/*
+ * Copyright 2010 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is 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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>      /* printk() */
+#include <linux/slab.h>        /* kmalloc() */
+#include <linux/errno.h>       /* error codes */
+#include <linux/types.h>       /* size_t */
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/netdevice.h>   /* struct device, and other headers */
+#include <linux/etherdevice.h> /* eth_type_trans */
+#include <linux/skbuff.h>
+#include <linux/ioctl.h>
+#include <linux/cdev.h>
+#include <linux/hugetlb.h>
+#include <linux/in6.h>
+#include <linux/timer.h>
+#include <linux/io.h>
+#include <asm/checksum.h>
+#include <asm/homecache.h>
+
+#include <hv/drv_xgbe_intf.h>
+#include <hv/drv_xgbe_impl.h>
+#include <hv/hypervisor.h>
+#include <hv/netio_intf.h>
+
+/* For TSO */
+#include <linux/ip.h>
+#include <linux/tcp.h>
+
+
+/* There is no singlethread_cpu, so schedule work on the current cpu. */
+#define singlethread_cpu -1
+
+
+/*
+ * First, "tile_net_init_module()" initializes all four "devices" which
+ * can be used by linux.
+ *
+ * Then, "ifconfig DEVICE up" calls "tile_net_open()", which analyzes
+ * the network cpus, then uses "tile_net_open_aux()" to initialize
+ * LIPP/LEPP, and then uses "tile_net_open_inner()" to register all
+ * the tiles, provide buffers to LIPP, allow ingress to start, and
+ * turn on hypervisor interrupt handling (and NAPI) on all tiles.
+ *
+ * If registration fails due to the link being down, then "retry_work"
+ * is used to keep calling "tile_net_open_inner()" until it succeeds.
+ *
+ * If "ifconfig DEVICE down" is called, it uses "tile_net_stop()" to
+ * stop egress, drain the LIPP buffers, unregister all the tiles, stop
+ * LIPP/LEPP, and wipe the LEPP queue.
+ *
+ * We start out with the ingress interrupt enabled on each CPU.  When
+ * this interrupt fires, we disable it, and call "napi_schedule()".
+ * This will cause "tile_net_poll()" to be called, which will pull
+ * packets from the netio queue, filtering them out, or passing them
+ * to "netif_receive_skb()".  If our budget is exhausted, we will
+ * return, knowing we will be called again later.  Otherwise, we
+ * reenable the ingress interrupt, and call "napi_complete()".
+ *
+ *
+ * NOTE: The use of "native_driver" ensures that EPP exists, and that
+ * "epp_sendv" is legal, and that "LIPP" is being used.
+ *
+ * NOTE: Failing to free completions for an arbitrarily long time
+ * (which is defined to be illegal) does in fact cause bizarre
+ * problems.  The "egress_timer" helps prevent this from happening.
+ *
+ * NOTE: The egress code can be interrupted by the interrupt handler.
+ */
+
+
+/* HACK: Allow use of "jumbo" packets. */
+/* This should be 1500 if "jumbo" is not set in LIPP. */
+/* This should be at most 10226 (10240 - 14) if "jumbo" is set in LIPP. */
+/* ISSUE: This has not been thoroughly tested (except at 1500). */
+#define TILE_NET_MTU 1500
+
+/* HACK: Define to support GSO. */
+/* ISSUE: This may actually hurt performance of the TCP blaster. */
+/* #define TILE_NET_GSO */
+
+/* Define this to collapse "duplicate" acks. */
+/* #define IGNORE_DUP_ACKS */
+
+/* HACK: Define this to verify incoming packets. */
+/* #define TILE_NET_VERIFY_INGRESS */
+
+/* Use 3000 to enable the Linux Traffic Control (QoS) layer, else 0. */
+#define TILE_NET_TX_QUEUE_LEN 0
+
+/* Define to dump packets (prints out the whole packet on tx and rx). */
+/* #define TILE_NET_DUMP_PACKETS */
+
+/* Define to enable debug spew (all PDEBUG's are enabled). */
+/* #define TILE_NET_DEBUG */
+
+
+/* Define to activate paranoia checks. */
+/* #define TILE_NET_PARANOIA */
+
+/* Default transmit lockup timeout period, in jiffies. */
+#define TILE_NET_TIMEOUT (5 * HZ)
+
+/* Default retry interval for bringing up the NetIO interface, in jiffies. */
+#define TILE_NET_RETRY_INTERVAL (5 * HZ)
+
+/* Number of ports (xgbe0, xgbe1, gbe0, gbe1). */
+#define TILE_NET_DEVS 4
+
+
+
+/* Paranoia. */
+#if NET_IP_ALIGN != LIPP_PACKET_PADDING
+#error "NET_IP_ALIGN must match LIPP_PACKET_PADDING."
+#endif
+
+
+/* Debug print. */
+#ifdef TILE_NET_DEBUG
+#define PDEBUG(fmt, args...) net_printk(fmt, ## args)
+#else
+#define PDEBUG(fmt, args...)
+#endif
+
+
+MODULE_AUTHOR("Tilera");
+MODULE_LICENSE("GPL");
+
+
+#define IS_MULTICAST(mac_addr) \
+       (((u8 *)(mac_addr))[0] & 0x01)
+
+#define IS_BROADCAST(mac_addr) \
+       (((u16 *)(mac_addr))[0] == 0xffff)
+
+
+/*
+ * Queue of incoming packets for a specific cpu and device.
+ *
+ * Includes a pointer to the "system" data, and the actual "user" data.
+ */
+struct tile_netio_queue {
+       netio_queue_impl_t *__system_part;
+       netio_queue_user_impl_t __user_part;
+
+};
+
+
+/*
+ * Statistics counters for a specific cpu and device.
+ */
+struct tile_net_stats_t {
+       u32 rx_packets;
+       u32 rx_bytes;
+       u32 tx_packets;
+       u32 tx_bytes;
+};
+
+
+/*
+ * Info for a specific cpu and device.
+ *
+ * ISSUE: There is a "dev" pointer in "napi" as well.
+ */
+struct tile_net_cpu {
+       /* The NAPI struct. */
+       struct napi_struct napi;
+       /* Packet queue. */
+       struct tile_netio_queue queue;
+       /* Statistics. */
+       struct tile_net_stats_t stats;
+       /* ISSUE: Is this needed? */
+       bool napi_enabled;
+       /* True if this tile has succcessfully registered with the IPP. */
+       bool registered;
+       /* True if the link was down last time we tried to register. */
+       bool link_down;
+       /* True if "egress_timer" is scheduled. */
+       bool egress_timer_scheduled;
+       /* Number of small sk_buffs which must still be provided. */
+       unsigned int num_needed_small_buffers;
+       /* Number of large sk_buffs which must still be provided. */
+       unsigned int num_needed_large_buffers;
+       /* A timer for handling egress completions. */
+       struct timer_list egress_timer;
+};
+
+
+/*
+ * Info for a specific device.
+ */
+struct tile_net_priv {
+       /* Our network device. */
+       struct net_device *dev;
+       /* The actual egress queue. */
+       lepp_queue_t *epp_queue;
+       /* Protects "epp_queue->cmd_tail" and "epp_queue->comp_tail" */
+       spinlock_t cmd_lock;
+       /* Protects "epp_queue->comp_head". */
+       spinlock_t comp_lock;
+       /* The hypervisor handle for this interface. */
+       int hv_devhdl;
+       /* The intr bit mask that IDs this device. */
+       u32 intr_id;
+       /* True iff "tile_net_open_aux()" has succeeded. */
+       int partly_opened;
+       /* True iff "tile_net_open_inner()" has succeeded. */
+       int fully_opened;
+       /* Effective network cpus. */
+       struct cpumask network_cpus_map;
+       /* Number of network cpus. */
+       int network_cpus_count;
+       /* Credits per network cpu. */
+       int network_cpus_credits;
+       /* Network stats. */
+       struct net_device_stats stats;
+       /* For NetIO bringup retries. */
+       struct delayed_work retry_work;
+       /* Quick access to per cpu data. */
+       struct tile_net_cpu *cpu[NR_CPUS];
+};
+
+
+/*
+ * The actual devices (xgbe0, xgbe1, gbe0, gbe1).
+ */
+static struct net_device *tile_net_devs[TILE_NET_DEVS];
+
+/*
+ * The "tile_net_cpu" structures for each device.
+ */
+static DEFINE_PER_CPU(struct tile_net_cpu, hv_xgbe0);
+static DEFINE_PER_CPU(struct tile_net_cpu, hv_xgbe1);
+static DEFINE_PER_CPU(struct tile_net_cpu, hv_gbe0);
+static DEFINE_PER_CPU(struct tile_net_cpu, hv_gbe1);
+
+
+/*
+ * True if "network_cpus" was specified.
+ */
+static bool network_cpus_used;
+
+/*
+ * The actual cpus in "network_cpus".
+ */
+static struct cpumask network_cpus_map;
+
+
+
+#ifdef TILE_NET_DEBUG
+/*
+ * printk with extra stuff.
+ *
+ * We print the CPU we're running in brackets.
+ */
+static void net_printk(char *fmt, ...)
+{
+       int i;
+       int len;
+       va_list args;
+       static char buf[256];
+
+       len = sprintf(buf, "tile_net[%2.2d]: ", smp_processor_id());
+       va_start(args, fmt);
+       i = vscnprintf(buf + len, sizeof(buf) - len - 1, fmt, args);
+       va_end(args);
+       buf[255] = '\0';
+       pr_notice(buf);
+}
+#endif
+
+
+#ifdef TILE_NET_DUMP_PACKETS
+/*
+ * Dump a packet.
+ */
+static void dump_packet(unsigned char *data, unsigned long length, char *s)
+{
+       unsigned long i;
+       static unsigned int count;
+
+       pr_info("dump_packet(data %p, length 0x%lx s %s count 0x%x)\n",
+              data, length, s, count++);
+
+       pr_info("\n");
+
+       for (i = 0; i < length; i++) {
+               if ((i & 0xf) == 0)
+                       sprintf(buf, "%8.8lx:", i);
+               sprintf(buf + strlen(buf), " %2.2x", data[i]);
+               if ((i & 0xf) == 0xf || i == length - 1)
+                       pr_info("%s\n", buf);
+       }
+}
+#endif
+
+
+/*
+ * Provide support for the __netio_fastio1() swint
+ * (see <hv/drv_xgbe_intf.h> for how it is used).
+ *
+ * The fastio swint2 call may clobber all the caller-saved registers.
+ * It rarely clobbers memory, but we allow for the possibility in
+ * the signature just to be on the safe side.
+ *
+ * Also, gcc doesn't seem to allow an input operand to be
+ * clobbered, so we fake it with dummy outputs.
+ *
+ * This function can't be static because of the way it is declared
+ * in the netio header.
+ */
+inline int __netio_fastio1(u32 fastio_index, u32 arg0)
+{
+       long result, clobber_r1, clobber_r10;
+       asm volatile("swint2"
+                    : "=R00" (result),
+                      "=R01" (clobber_r1), "=R10" (clobber_r10)
+                    : "R10" (fastio_index), "R01" (arg0)
+                    : "memory", "r2", "r3", "r4",
+                      "r5", "r6", "r7", "r8", "r9",
+                      "r11", "r12", "r13", "r14",
+                      "r15", "r16", "r17", "r18", "r19",
+                      "r20", "r21", "r22", "r23", "r24",
+                      "r25", "r26", "r27", "r28", "r29");
+       return result;
+}
+
+
+/*
+ * Provide a linux buffer to LIPP.
+ */
+static void tile_net_provide_linux_buffer(struct tile_net_cpu *info,
+                                         void *va, bool small)
+{
+       struct tile_netio_queue *queue = &info->queue;
+
+       /* Convert "va" and "small" to "linux_buffer_t". */
+       unsigned int buffer = ((unsigned int)(__pa(va) >> 7) << 1) + small;
+
+       __netio_fastio_free_buffer(queue->__user_part.__fastio_index, buffer);
+}
+
+
+/*
+ * Provide a linux buffer for LIPP.
+ */
+static bool tile_net_provide_needed_buffer(struct tile_net_cpu *info,
+                                          bool small)
+{
+       /* ISSUE: What should we use here? */
+       unsigned int large_size = NET_IP_ALIGN + TILE_NET_MTU + 100;
+
+       /* Round up to ensure to avoid "false sharing" with last cache line. */
+       unsigned int buffer_size =
+                (((small ? LIPP_SMALL_PACKET_SIZE : large_size) +
+                  CHIP_L2_LINE_SIZE() - 1) & -CHIP_L2_LINE_SIZE());
+
+       /*
+        * ISSUE: Since CPAs are 38 bits, and we can only encode the
+        * high 31 bits in a "linux_buffer_t", the low 7 bits must be
+        * zero, and thus, we must align the actual "va" mod 128.
+        */
+       const unsigned long align = 128;
+
+       struct sk_buff *skb;
+       void *va;
+
+       struct sk_buff **skb_ptr;
+
+       /* Note that "dev_alloc_skb()" adds NET_SKB_PAD more bytes, */
+       /* and also "reserves" that many bytes. */
+       /* ISSUE: Can we "share" the NET_SKB_PAD bytes with "skb_ptr"? */
+       int len = sizeof(*skb_ptr) + align + buffer_size;
+
+       while (1) {
+
+               /* Allocate (or fail). */
+               skb = dev_alloc_skb(len);
+               if (skb == NULL)
+                       return false;
+
+               /* Make room for a back-pointer to 'skb'. */
+               skb_reserve(skb, sizeof(*skb_ptr));
+
+               /* Make sure we are aligned. */
+               skb_reserve(skb, -(long)skb->data & (align - 1));
+
+               /* This address is given to IPP. */
+               va = skb->data;
+
+               if (small)
+                       break;
+
+               /* ISSUE: This has never been observed! */
+               /* Large buffers must not span a huge page. */
+               if (((((long)va & ~HPAGE_MASK) + 1535) & HPAGE_MASK) == 0)
+                       break;
+               pr_err("Leaking unaligned linux buffer at %p.\n", va);
+       }
+
+       /* Skip two bytes to satisfy LIPP assumptions. */
+       /* Note that this aligns IP on a 16 byte boundary. */
+       /* ISSUE: Do this when the packet arrives? */
+       skb_reserve(skb, NET_IP_ALIGN);
+
+       /* Save a back-pointer to 'skb'. */
+       skb_ptr = va - sizeof(*skb_ptr);
+       *skb_ptr = skb;
+
+       /* Invalidate the packet buffer. */
+       if (!hash_default)
+               __inv_buffer(skb->data, buffer_size);
+
+       /* Make sure "skb_ptr" has been flushed. */
+       __insn_mf();
+
+#ifdef TILE_NET_PARANOIA
+#if CHIP_HAS_CBOX_HOME_MAP()
+       if (hash_default) {
+               HV_PTE pte = *virt_to_pte(current->mm, (unsigned long)va);
+               if (hv_pte_get_mode(pte) != HV_PTE_MODE_CACHE_HASH_L3)
+                       panic("Non-coherent ingress buffer!");
+       }
+#endif
+#endif
+
+       /* Provide the new buffer. */
+       tile_net_provide_linux_buffer(info, va, small);
+
+       return true;
+}
+
+
+/*
+ * Provide linux buffers for LIPP.
+ */
+static void tile_net_provide_needed_buffers(struct tile_net_cpu *info)
+{
+       while (info->num_needed_small_buffers != 0) {
+               if (!tile_net_provide_needed_buffer(info, true))
+                       goto oops;
+               info->num_needed_small_buffers--;
+       }
+
+       while (info->num_needed_large_buffers != 0) {
+               if (!tile_net_provide_needed_buffer(info, false))
+                       goto oops;
+               info->num_needed_large_buffers--;
+       }
+
+       return;
+
+oops:
+
+       /* Add a description to the page allocation failure dump. */
+       pr_notice("Could not provide a linux buffer to LIPP.\n");
+}
+
+
+/*
+ * Grab some LEPP completions, and store them in "comps", of size
+ * "comps_size", and return the number of completions which were
+ * stored, so the caller can free them.
+ *
+ * If "pending" is not NULL, it will be set to true if there might
+ * still be some pending completions caused by this tile, else false.
+ */
+static unsigned int tile_net_lepp_grab_comps(struct net_device *dev,
+                                            struct sk_buff *comps[],
+                                            unsigned int comps_size,
+                                            bool *pending)
+{
+       struct tile_net_priv *priv = netdev_priv(dev);
+
+       lepp_queue_t *eq = priv->epp_queue;
+
+       unsigned int n = 0;
+
+       unsigned int comp_head;
+       unsigned int comp_busy;
+       unsigned int comp_tail;
+
+       spin_lock(&priv->comp_lock);
+
+       comp_head = eq->comp_head;
+       comp_busy = eq->comp_busy;
+       comp_tail = eq->comp_tail;
+
+       while (comp_head != comp_busy && n < comps_size) {
+               comps[n++] = eq->comps[comp_head];
+               LEPP_QINC(comp_head);
+       }
+
+       if (pending != NULL)
+               *pending = (comp_head != comp_tail);
+
+       eq->comp_head = comp_head;
+
+       spin_unlock(&priv->comp_lock);
+
+       return n;
+}
+
+
+/*
+ * Make sure the egress timer is scheduled.
+ *
+ * Note that we use "schedule if not scheduled" logic instead of the more
+ * obvious "reschedule" logic, because "reschedule" is fairly expensive.
+ */
+static void tile_net_schedule_egress_timer(struct tile_net_cpu *info)
+{
+       if (!info->egress_timer_scheduled) {
+               mod_timer_pinned(&info->egress_timer, jiffies + 1);
+               info->egress_timer_scheduled = true;
+       }
+}
+
+
+/*
+ * The "function" for "info->egress_timer".
+ *
+ * This timer will reschedule itself as long as there are any pending
+ * completions expected (on behalf of any tile).
+ *
+ * ISSUE: Realistically, will the timer ever stop scheduling itself?
+ *
+ * ISSUE: This timer is almost never actually needed, so just use a global
+ * timer that can run on any tile.
+ *
+ * ISSUE: Maybe instead track number of expected completions, and free
+ * only that many, resetting to zero if "pending" is ever false.
+ */
+static void tile_net_handle_egress_timer(unsigned long arg)
+{
+       struct tile_net_cpu *info = (struct tile_net_cpu *)arg;
+       struct net_device *dev = info->napi.dev;
+
+       struct sk_buff *olds[32];
+       unsigned int wanted = 32;
+       unsigned int i, nolds = 0;
+       bool pending;
+
+       /* The timer is no longer scheduled. */
+       info->egress_timer_scheduled = false;
+
+       nolds = tile_net_lepp_grab_comps(dev, olds, wanted, &pending);
+
+       for (i = 0; i < nolds; i++)
+               kfree_skb(olds[i]);
+
+       /* Reschedule timer if needed. */
+       if (pending)
+               tile_net_schedule_egress_timer(info);
+}
+
+
+#ifdef IGNORE_DUP_ACKS
+
+/*
+ * Help detect "duplicate" ACKs.  These are sequential packets (for a
+ * given flow) which are exactly 66 bytes long, sharing everything but
+ * ID=2@0x12, Hsum=2@0x18, Ack=4@0x2a, WinSize=2@0x30, Csum=2@0x32,
+ * Tstamps=10@0x38.  The ID's are +1, the Hsum's are -1, the Ack's are
+ * +N, and the Tstamps are usually identical.
+ *
+ * NOTE: Apparently truly duplicate acks (with identical "ack" values),
+ * should not be collapsed, as they are used for some kind of flow control.
+ */
+static bool is_dup_ack(char *s1, char *s2, unsigned int len)
+{
+       int i;
+
+       unsigned long long ignorable = 0;
+
+       /* Identification. */
+       ignorable |= (1ULL << 0x12);
+       ignorable |= (1ULL << 0x13);
+
+       /* Header checksum. */
+       ignorable |= (1ULL << 0x18);
+       ignorable |= (1ULL << 0x19);
+
+       /* ACK. */
+       ignorable |= (1ULL << 0x2a);
+       ignorable |= (1ULL << 0x2b);
+       ignorable |= (1ULL << 0x2c);
+       ignorable |= (1ULL << 0x2d);
+
+       /* WinSize. */
+       ignorable |= (1ULL << 0x30);
+       ignorable |= (1ULL << 0x31);
+
+       /* Checksum. */
+       ignorable |= (1ULL << 0x32);
+       ignorable |= (1ULL << 0x33);
+
+       for (i = 0; i < len; i++, ignorable >>= 1) {
+
+               if ((ignorable & 1) || (s1[i] == s2[i]))
+                       continue;
+
+#ifdef TILE_NET_DEBUG
+               /* HACK: Mention non-timestamp diffs. */
+               if (i < 0x38 && i != 0x2f &&
+                   net_ratelimit())
+                       pr_info("Diff at 0x%x\n", i);
+#endif
+
+               return false;
+       }
+
+#ifdef TILE_NET_NO_SUPPRESS_DUP_ACKS
+       /* HACK: Do not suppress truly duplicate ACKs. */
+       /* ISSUE: Is this actually necessary or helpful? */
+       if (s1[0x2a] == s2[0x2a] &&
+           s1[0x2b] == s2[0x2b] &&
+           s1[0x2c] == s2[0x2c] &&
+           s1[0x2d] == s2[0x2d]) {
+               return false;
+       }
+#endif
+
+       return true;
+}
+
+#endif
+
+
+
+/*
+ * Like "tile_net_handle_packets()", but just discard packets.
+ */
+static void tile_net_discard_packets(struct net_device *dev)
+{
+       struct tile_net_priv *priv = netdev_priv(dev);
+       int my_cpu = smp_processor_id();
+       struct tile_net_cpu *info = priv->cpu[my_cpu];
+       struct tile_netio_queue *queue = &info->queue;
+       netio_queue_impl_t *qsp = queue->__system_part;
+       netio_queue_user_impl_t *qup = &queue->__user_part;
+
+       while (qup->__packet_receive_read !=
+              qsp->__packet_receive_queue.__packet_write) {
+
+               int index = qup->__packet_receive_read;
+
+               int index2_aux = index + sizeof(netio_pkt_t);
+               int index2 =
+                       ((index2_aux ==
+                         qsp->__packet_receive_queue.__last_packet_plus_one) ?
+                        0 : index2_aux);
+
+               netio_pkt_t *pkt = (netio_pkt_t *)
+                       ((unsigned long) &qsp[1] + index);
+
+               /* Extract the "linux_buffer_t". */
+               unsigned int buffer = pkt->__packet.word;
+
+               /* Convert "linux_buffer_t" to "va". */
+               void *va = __va((phys_addr_t)(buffer >> 1) << 7);
+
+               /* Acquire the associated "skb". */
+               struct sk_buff **skb_ptr = va - sizeof(*skb_ptr);
+               struct sk_buff *skb = *skb_ptr;
+
+               kfree_skb(skb);
+
+               /* Consume this packet. */
+               qup->__packet_receive_read = index2;
+       }
+}
+
+
+/*
+ * Handle the next packet.  Return true if "processed", false if "filtered".
+ */
+static bool tile_net_poll_aux(struct tile_net_cpu *info, int index)
+{
+       struct net_device *dev = info->napi.dev;
+
+       struct tile_netio_queue *queue = &info->queue;
+       netio_queue_impl_t *qsp = queue->__system_part;
+       netio_queue_user_impl_t *qup = &queue->__user_part;
+       struct tile_net_stats_t *stats = &info->stats;
+
+       int filter;
+
+       int index2_aux = index + sizeof(netio_pkt_t);
+       int index2 =
+               ((index2_aux ==
+                 qsp->__packet_receive_queue.__last_packet_plus_one) ?
+                0 : index2_aux);
+
+       netio_pkt_t *pkt = (netio_pkt_t *)((unsigned long) &qsp[1] + index);
+
+       netio_pkt_metadata_t *metadata = NETIO_PKT_METADATA(pkt);
+
+       /* Extract the packet size. */
+       unsigned long len =
+               (NETIO_PKT_CUSTOM_LENGTH(pkt) +
+                NET_IP_ALIGN - NETIO_PACKET_PADDING);
+
+       /* Extract the "linux_buffer_t". */
+       unsigned int buffer = pkt->__packet.word;
+
+       /* Extract "small" (vs "large"). */
+       bool small = ((buffer & 1) != 0);
+
+       /* Convert "linux_buffer_t" to "va". */
+       void *va = __va((phys_addr_t)(buffer >> 1) << 7);
+
+       /* Extract the packet data pointer. */
+       /* Compare to "NETIO_PKT_CUSTOM_DATA(pkt)". */
+       unsigned char *buf = va + NET_IP_ALIGN;
+
+#ifdef IGNORE_DUP_ACKS
+
+       static int other;
+       static int final;
+       static int keep;
+       static int skip;
+
+#endif
+
+       /* Invalidate the packet buffer. */
+       if (!hash_default)
+               __inv_buffer(buf, len);
+
+       /* ISSUE: Is this needed? */
+       dev->last_rx = jiffies;
+
+#ifdef TILE_NET_DUMP_PACKETS
+       dump_packet(buf, len, "rx");
+#endif /* TILE_NET_DUMP_PACKETS */
+
+#ifdef TILE_NET_VERIFY_INGRESS
+       if (!NETIO_PKT_L4_CSUM_CORRECT_M(metadata, pkt) &&
+           NETIO_PKT_L4_CSUM_CALCULATED_M(metadata, pkt)) {
+               /*
+                * FIXME: This complains about UDP packets
+                * with a "zero" checksum (bug 6624).
+                */
+#ifdef TILE_NET_PANIC_ON_BAD
+               dump_packet(buf, len, "rx");
+               panic("Bad L4 checksum.");
+#else
+               pr_warning("Bad L4 checksum on %d byte packet.\n", len);
+#endif
+       }
+       if (!NETIO_PKT_L3_CSUM_CORRECT_M(metadata, pkt) &&
+           NETIO_PKT_L3_CSUM_CALCULATED_M(metadata, pkt)) {
+               dump_packet(buf, len, "rx");
+               panic("Bad L3 checksum.");
+       }
+       switch (NETIO_PKT_STATUS_M(metadata, pkt)) {
+       case NETIO_PKT_STATUS_OVERSIZE:
+               if (len >= 64) {
+                       dump_packet(buf, len, "rx");
+                       panic("Unexpected OVERSIZE.");
+               }
+               break;
+       case NETIO_PKT_STATUS_BAD:
+#ifdef TILE_NET_PANIC_ON_BAD
+               dump_packet(buf, len, "rx");
+               panic("Unexpected BAD packet.");
+#else
+               pr_warning("Unexpected BAD %d byte packet.\n", len);
+#endif
+       }
+#endif
+
+       filter = 0;
+
+       if (!(dev->flags & IFF_UP)) {
+               /* Filter packets received before we're up. */
+               filter = 1;
+       } else if (!(dev->flags & IFF_PROMISC)) {
+               /*
+                * FIXME: Implement HW multicast filter.
+                */
+               if (!IS_MULTICAST(buf) && !IS_BROADCAST(buf)) {
+                       /* Filter packets not for our address. */
+                       const u8 *mine = dev->dev_addr;
+                       filter = compare_ether_addr(mine, buf);
+               }
+       }
+
+#ifdef IGNORE_DUP_ACKS
+
+       if (len != 66) {
+               /* FIXME: Must check "is_tcp_ack(buf, len)" somehow. */
+
+               other++;
+
+       } else if (index2 ==
+                  qsp->__packet_receive_queue.__packet_write) {
+
+               final++;
+
+       } else {
+
+               netio_pkt_t *pkt2 = (netio_pkt_t *)
+                       ((unsigned long) &qsp[1] + index2);
+
+               netio_pkt_metadata_t *metadata2 =
+                       NETIO_PKT_METADATA(pkt2);
+
+               /* Extract the packet size. */
+               unsigned long len2 =
+                       (NETIO_PKT_CUSTOM_LENGTH(pkt2) +
+                        NET_IP_ALIGN - NETIO_PACKET_PADDING);
+
+               if (len2 == 66 &&
+                   NETIO_PKT_FLOW_HASH_M(metadata, pkt) ==
+                   NETIO_PKT_FLOW_HASH_M(metadata2, pkt2)) {
+
+                       /* Extract the "linux_buffer_t". */
+                       unsigned int buffer2 = pkt2->__packet.word;
+
+                       /* Convert "linux_buffer_t" to "va". */
+                       void *va2 =
+                               __va((phys_addr_t)(buffer2 >> 1) << 7);
+
+                       /* Extract the packet data pointer. */
+                       /* Compare to "NETIO_PKT_CUSTOM_DATA(pkt)". */
+                       unsigned char *buf2 = va2 + NET_IP_ALIGN;
+
+                       /* Invalidate the packet buffer. */
+                       if (!hash_default)
+                               __inv_buffer(buf2, len2);
+
+                       if (is_dup_ack(buf, buf2, len)) {
+                               skip++;
+                               filter = 1;
+                       } else {
+                               keep++;
+                       }
+               }
+       }
+
+       if (net_ratelimit())
+               pr_info("Other %d Final %d Keep %d Skip %d.\n",
+                       other, final, keep, skip);
+
+#endif
+
+       if (filter) {
+
+               /* ISSUE: Update "drop" statistics? */
+
+               tile_net_provide_linux_buffer(info, va, small);
+
+       } else {
+
+               /* Acquire the associated "skb". */
+               struct sk_buff **skb_ptr = va - sizeof(*skb_ptr);
+               struct sk_buff *skb = *skb_ptr;
+
+               /* Paranoia. */
+               if (skb->data != buf)
+                       panic("Corrupt linux buffer from LIPP! "
+                             "VA=%p, skb=%p, skb->data=%p\n",
+                             va, skb, skb->data);
+
+               /* Encode the actual packet length. */
+               skb_put(skb, len);
+
+               /* NOTE: This call also sets "skb->dev = dev". */
+               skb->protocol = eth_type_trans(skb, dev);
+
+               /* ISSUE: Discard corrupt packets? */
+               /* ISSUE: Discard packets with bad checksums? */
+
+               /* Avoid recomputing TCP/UDP checksums. */
+               if (NETIO_PKT_L4_CSUM_CORRECT_M(metadata, pkt))
+                       skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+               netif_receive_skb(skb);
+
+               stats->rx_packets++;
+               stats->rx_bytes += len;
+
+               if (small)
+                       info->num_needed_small_buffers++;
+               else
+                       info->num_needed_large_buffers++;
+       }
+
+       /* Return four credits after every fourth packet. */
+       if (--qup->__receive_credit_remaining == 0) {
+               u32 interval = qup->__receive_credit_interval;
+               qup->__receive_credit_remaining = interval;
+               __netio_fastio_return_credits(qup->__fastio_index, interval);
+       }
+
+       /* Consume this packet. */
+       qup->__packet_receive_read = index2;
+
+       return !filter;
+}
+
+
+/*
+ * Handle some packets for the given device on the current CPU.
+ *
+ * ISSUE: The "rotting packet" race condition occurs if a packet
+ * arrives after the queue appears to be empty, and before the
+ * hypervisor interrupt is re-enabled.
+ */
+static int tile_net_poll(struct napi_struct *napi, int budget)
+{
+       struct net_device *dev = napi->dev;
+       struct tile_net_priv *priv = netdev_priv(dev);
+       int my_cpu = smp_processor_id();
+       struct tile_net_cpu *info = priv->cpu[my_cpu];
+       struct tile_netio_queue *queue = &info->queue;
+       netio_queue_impl_t *qsp = queue->__system_part;
+       netio_queue_user_impl_t *qup = &queue->__user_part;
+
+       unsigned int work = 0;
+
+       while (1) {
+               int index = qup->__packet_receive_read;
+               if (index == qsp->__packet_receive_queue.__packet_write)
+                       break;
+
+               if (tile_net_poll_aux(info, index)) {
+                       if (++work >= budget)
+                               goto done;
+               }
+       }
+
+       napi_complete(&info->napi);
+
+       /* Re-enable hypervisor interrupts. */
+       enable_percpu_irq(priv->intr_id);
+
+       /* HACK: Avoid the "rotting packet" problem. */
+       if (qup->__packet_receive_read !=
+           qsp->__packet_receive_queue.__packet_write)
+               napi_schedule(&info->napi);
+
+       /* ISSUE: Handle completions? */
+
+done:
+
+       tile_net_provide_needed_buffers(info);
+
+       return work;
+}
+
+
+/*
+ * Handle an ingress interrupt for the given device on the current cpu.
+ */
+static irqreturn_t tile_net_handle_ingress_interrupt(int irq, void *dev_ptr)
+{
+       struct net_device *dev = (struct net_device *)dev_ptr;
+       struct tile_net_priv *priv = netdev_priv(dev);
+       int my_cpu = smp_processor_id();
+       struct tile_net_cpu *info = priv->cpu[my_cpu];
+
+       /* Disable hypervisor interrupt. */
+       disable_percpu_irq(priv->intr_id);
+
+       napi_schedule(&info->napi);
+
+       return IRQ_HANDLED;
+}
+
+
+/*
+ * One time initialization per interface.
+ */
+static int tile_net_open_aux(struct net_device *dev)
+{
+       struct tile_net_priv *priv = netdev_priv(dev);
+
+       int ret;
+       int dummy;
+       unsigned int epp_lotar;
+
+       /*
+        * Find out where EPP memory should be homed.
+        */
+       ret = hv_dev_pread(priv->hv_devhdl, 0,
+                          (HV_VirtAddr)&epp_lotar, sizeof(epp_lotar),
+                          NETIO_EPP_SHM_OFF);
+       if (ret < 0) {
+               pr_err("could not read epp_shm_queue lotar.\n");
+               return -EIO;
+       }
+
+       /*
+        * Home the page on the EPP.
+        */
+       {
+               int epp_home = hv_lotar_to_cpu(epp_lotar);
+               struct page *page = virt_to_page(priv->epp_queue);
+               homecache_change_page_home(page, 0, epp_home);
+       }
+
+       /*
+        * Register the EPP shared memory queue.
+        */
+       {
+               netio_ipp_address_t ea = {
+                       .va = 0,
+                       .pa = __pa(priv->epp_queue),
+                       .pte = hv_pte(0),
+                       .size = PAGE_SIZE,
+               };
+               ea.pte = hv_pte_set_lotar(ea.pte, epp_lotar);
+               ea.pte = hv_pte_set_mode(ea.pte, HV_PTE_MODE_CACHE_TILE_L3);
+               ret = hv_dev_pwrite(priv->hv_devhdl, 0,
+                                   (HV_VirtAddr)&ea,
+                                   sizeof(ea),
+                                   NETIO_EPP_SHM_OFF);
+               if (ret < 0)
+                       return -EIO;
+       }
+
+       /*
+        * Start LIPP/LEPP.
+        */
+       if (hv_dev_pwrite(priv->hv_devhdl, 0, (HV_VirtAddr)&dummy,
+                         sizeof(dummy), NETIO_IPP_START_SHIM_OFF) < 0) {
+               pr_warning("Failed to start LIPP/LEPP.\n");
+               return -EIO;
+       }
+
+       return 0;
+}
+
+
+/*
+ * Register with hypervisor on each CPU.
+ *
+ * Strangely, this function does important things even if it "fails",
+ * which is especially common if the link is not up yet.  Hopefully
+ * these things are all "harmless" if done twice!
+ */
+static void tile_net_register(void *dev_ptr)
+{
+       struct net_device *dev = (struct net_device *)dev_ptr;
+       struct tile_net_priv *priv = netdev_priv(dev);
+       int my_cpu = smp_processor_id();
+       struct tile_net_cpu *info;
+
+       struct tile_netio_queue *queue;
+
+       /* Only network cpus can receive packets. */
+       int queue_id =
+               cpumask_test_cpu(my_cpu, &priv->network_cpus_map) ? 0 : 255;
+
+       netio_input_config_t config = {
+               .flags = 0,
+               .num_receive_packets = priv->network_cpus_credits,
+               .queue_id = queue_id
+       };
+
+       int ret = 0;
+       netio_queue_impl_t *queuep;
+
+       PDEBUG("tile_net_register(queue_id %d)\n", queue_id);
+
+       if (!strcmp(dev->name, "xgbe0"))
+               info = &__get_cpu_var(hv_xgbe0);
+       else if (!strcmp(dev->name, "xgbe1"))
+               info = &__get_cpu_var(hv_xgbe1);
+       else if (!strcmp(dev->name, "gbe0"))
+               info = &__get_cpu_var(hv_gbe0);
+       else if (!strcmp(dev->name, "gbe1"))
+               info = &__get_cpu_var(hv_gbe1);
+       else
+               BUG();
+
+       /* Initialize the egress timer. */
+       init_timer(&info->egress_timer);
+       info->egress_timer.data = (long)info;
+       info->egress_timer.function = tile_net_handle_egress_timer;
+
+       priv->cpu[my_cpu] = info;
+
+       /*
+        * Register ourselves with the IPP.
+        */
+       ret = hv_dev_pwrite(priv->hv_devhdl, 0,
+                           (HV_VirtAddr)&config,
+                           sizeof(netio_input_config_t),
+                           NETIO_IPP_INPUT_REGISTER_OFF);
+       PDEBUG("hv_dev_pwrite(NETIO_IPP_INPUT_REGISTER_OFF) returned %d\n",
+              ret);
+       if (ret < 0) {
+               printk(KERN_DEBUG "hv_dev_pwrite NETIO_IPP_INPUT_REGISTER_OFF"
+                      " failure %d\n", ret);
+               info->link_down = (ret == NETIO_LINK_DOWN);
+               return;
+       }
+
+       /*
+        * Get the pointer to our queue's system part.
+        */
+
+       ret = hv_dev_pread(priv->hv_devhdl, 0,
+                          (HV_VirtAddr)&queuep,
+                          sizeof(netio_queue_impl_t *),
+                          NETIO_IPP_INPUT_REGISTER_OFF);
+       PDEBUG("hv_dev_pread(NETIO_IPP_INPUT_REGISTER_OFF) returned %d\n",
+              ret);
+       PDEBUG("queuep %p\n", queuep);
+       if (ret <= 0) {
+               /* ISSUE: Shouldn't this be a fatal error? */
+               pr_err("hv_dev_pread NETIO_IPP_INPUT_REGISTER_OFF failure\n");
+               return;
+       }
+
+       queue = &info->queue;
+
+       queue->__system_part = queuep;
+
+       memset(&queue->__user_part, 0, sizeof(netio_queue_user_impl_t));
+
+       /* This is traditionally "config.num_receive_packets / 2". */
+       queue->__user_part.__receive_credit_interval = 4;
+       queue->__user_part.__receive_credit_remaining =
+               queue->__user_part.__receive_credit_interval;
+
+       /*
+        * Get a fastio index from the hypervisor.
+        * ISSUE: Shouldn't this check the result?
+        */
+       ret = hv_dev_pread(priv->hv_devhdl, 0,
+                          (HV_VirtAddr)&queue->__user_part.__fastio_index,
+                          sizeof(queue->__user_part.__fastio_index),
+                          NETIO_IPP_GET_FASTIO_OFF);
+       PDEBUG("hv_dev_pread(NETIO_IPP_GET_FASTIO_OFF) returned %d\n", ret);
+
+       netif_napi_add(dev, &info->napi, tile_net_poll, 64);
+
+       /* Now we are registered. */
+       info->registered = true;
+}
+
+
+/*
+ * Unregister with hypervisor on each CPU.
+ */
+static void tile_net_unregister(void *dev_ptr)
+{
+       struct net_device *dev = (struct net_device *)dev_ptr;
+       struct tile_net_priv *priv = netdev_priv(dev);
+       int my_cpu = smp_processor_id();
+       struct tile_net_cpu *info = priv->cpu[my_cpu];
+
+       int ret = 0;
+       int dummy = 0;
+
+       /* Do nothing if never registered. */
+       if (info == NULL)
+               return;
+
+       /* Do nothing if already unregistered. */
+       if (!info->registered)
+               return;
+
+       /*
+        * Unregister ourselves with LIPP.
+        */
+       ret = hv_dev_pwrite(priv->hv_devhdl, 0, (HV_VirtAddr)&dummy,
+                           sizeof(dummy), NETIO_IPP_INPUT_UNREGISTER_OFF);
+       PDEBUG("hv_dev_pwrite(NETIO_IPP_INPUT_UNREGISTER_OFF) returned %d\n",
+              ret);
+       if (ret < 0) {
+               /* FIXME: Just panic? */
+               pr_err("hv_dev_pwrite NETIO_IPP_INPUT_UNREGISTER_OFF"
+                      " failure %d\n", ret);
+       }
+
+       /*
+        * Discard all packets still in our NetIO queue.  Hopefully,
+        * once the unregister call is complete, there will be no
+        * packets still in flight on the IDN.
+        */
+       tile_net_discard_packets(dev);
+
+       /* Reset state. */
+       info->num_needed_small_buffers = 0;
+       info->num_needed_large_buffers = 0;
+
+       /* Cancel egress timer. */
+       del_timer(&info->egress_timer);
+       info->egress_timer_scheduled = false;
+
+       netif_napi_del(&info->napi);
+
+       /* Now we are unregistered. */
+       info->registered = false;
+}
+
+
+/*
+ * Helper function for "tile_net_stop()".
+ *
+ * Also used to handle registration failure in "tile_net_open_inner()",
+ * when "fully_opened" is known to be false, and the various extra
+ * steps in "tile_net_stop()" are not necessary.  ISSUE: It might be
+ * simpler if we could just call "tile_net_stop()" anyway.
+ */
+static void tile_net_stop_aux(struct net_device *dev)
+{
+       struct tile_net_priv *priv = netdev_priv(dev);
+
+       int dummy = 0;
+
+       /* Unregister all tiles, so LIPP will stop delivering packets. */
+       on_each_cpu(tile_net_unregister, (void *)dev, 1);
+
+       /* Stop LIPP/LEPP. */
+       if (hv_dev_pwrite(priv->hv_devhdl, 0, (HV_VirtAddr)&dummy,
+                         sizeof(dummy), NETIO_IPP_STOP_SHIM_OFF) < 0)
+               panic("Failed to stop LIPP/LEPP!\n");
+
+       priv->partly_opened = 0;
+}
+
+
+/*
+ * Disable ingress interrupts for the given device on the current cpu.
+ */
+static void tile_net_disable_intr(void *dev_ptr)
+{
+       struct net_device *dev = (struct net_device *)dev_ptr;
+       struct tile_net_priv *priv = netdev_priv(dev);
+       int my_cpu = smp_processor_id();
+       struct tile_net_cpu *info = priv->cpu[my_cpu];
+
+       /* Disable hypervisor interrupt. */
+       disable_percpu_irq(priv->intr_id);
+
+       /* Disable NAPI if needed. */
+       if (info != NULL && info->napi_enabled) {
+               napi_disable(&info->napi);
+               info->napi_enabled = false;
+       }
+}
+
+
+/*
+ * Enable ingress interrupts for the given device on the current cpu.
+ */
+static void tile_net_enable_intr(void *dev_ptr)
+{
+       struct net_device *dev = (struct net_device *)dev_ptr;
+       struct tile_net_priv *priv = netdev_priv(dev);
+       int my_cpu = smp_processor_id();
+       struct tile_net_cpu *info = priv->cpu[my_cpu];
+
+       /* Enable hypervisor interrupt. */
+       enable_percpu_irq(priv->intr_id);
+
+       /* Enable NAPI. */
+       napi_enable(&info->napi);
+       info->napi_enabled = true;
+}
+
+
+/*
+ * tile_net_open_inner does most of the work of bringing up the interface.
+ * It's called from tile_net_open(), and also from tile_net_retry_open().
+ * The return value is 0 if the interface was brought up, < 0 if
+ * tile_net_open() should return the return value as an error, and > 0 if
+ * tile_net_open() should return success and schedule a work item to
+ * periodically retry the bringup.
+ */
+static int tile_net_open_inner(struct net_device *dev)
+{
+       struct tile_net_priv *priv = netdev_priv(dev);
+       int my_cpu = smp_processor_id();
+       struct tile_net_cpu *info;
+       struct tile_netio_queue *queue;
+       unsigned int irq;
+       int i;
+
+       /*
+        * First try to register just on the local CPU, and handle any
+        * semi-expected "link down" failure specially.  Note that we
+        * do NOT call "tile_net_stop_aux()", unlike below.
+        */
+       tile_net_register(dev);
+       info = priv->cpu[my_cpu];
+       if (!info->registered) {
+               if (info->link_down)
+                       return 1;
+               return -EAGAIN;
+       }
+
+       /*
+        * Now register everywhere else.  If any registration fails,
+        * even for "link down" (which might not be possible), we
+        * clean up using "tile_net_stop_aux()".
+        */
+       smp_call_function(tile_net_register, (void *)dev, 1);
+       for_each_online_cpu(i) {
+               if (!priv->cpu[i]->registered) {
+                       tile_net_stop_aux(dev);
+                       return -EAGAIN;
+               }
+       }
+
+       queue = &info->queue;
+
+       /*
+        * Set the device intr bit mask.
+        * The tile_net_register above sets per tile __intr_id.
+        */
+       priv->intr_id = queue->__system_part->__intr_id;
+       BUG_ON(!priv->intr_id);
+
+       /*
+        * Register the device interrupt handler.
+        * The __ffs() function returns the index into the interrupt handler
+        * table from the interrupt bit mask which should have one bit
+        * and one bit only set.
+        */
+       irq = __ffs(priv->intr_id);
+       tile_irq_activate(irq, TILE_IRQ_PERCPU);
+       BUG_ON(request_irq(irq, tile_net_handle_ingress_interrupt,
+                          0, dev->name, (void *)dev) != 0);
+
+       /* ISSUE: How could "priv->fully_opened" ever be "true" here? */
+
+       if (!priv->fully_opened) {
+
+               int dummy = 0;
+
+               /* Allocate initial buffers. */
+
+               int max_buffers =
+                       priv->network_cpus_count * priv->network_cpus_credits;
+
+               info->num_needed_small_buffers =
+                       min(LIPP_SMALL_BUFFERS, max_buffers);
+
+               info->num_needed_large_buffers =
+                       min(LIPP_LARGE_BUFFERS, max_buffers);
+
+               tile_net_provide_needed_buffers(info);
+
+               if (info->num_needed_small_buffers != 0 ||
+                   info->num_needed_large_buffers != 0)
+                       panic("Insufficient memory for buffer stack!");
+
+               /* Start LIPP/LEPP and activate "ingress" at the shim. */
+               if (hv_dev_pwrite(priv->hv_devhdl, 0, (HV_VirtAddr)&dummy,
+                                 sizeof(dummy), NETIO_IPP_INPUT_INIT_OFF) < 0)
+                       panic("Failed to activate the LIPP Shim!\n");
+
+               priv->fully_opened = 1;
+       }
+
+       /* On each tile, enable the hypervisor to trigger interrupts. */
+       /* ISSUE: Do this before starting LIPP/LEPP? */
+       on_each_cpu(tile_net_enable_intr, (void *)dev, 1);
+
+       /* Start our transmit queue. */
+       netif_start_queue(dev);
+
+       return 0;
+}
+
+
+/*
+ * Called periodically to retry bringing up the NetIO interface,
+ * if it doesn't come up cleanly during tile_net_open().
+ */
+static void tile_net_open_retry(struct work_struct *w)
+{
+       struct delayed_work *dw =
+               container_of(w, struct delayed_work, work);
+
+       struct tile_net_priv *priv =
+               container_of(dw, struct tile_net_priv, retry_work);
+
+       /*
+        * Try to bring the NetIO interface up.  If it fails, reschedule
+        * ourselves to try again later; otherwise, tell Linux we now have
+        * a working link.  ISSUE: What if the return value is negative?
+        */
+       if (tile_net_open_inner(priv->dev))
+               schedule_delayed_work_on(singlethread_cpu, &priv->retry_work,
+                                        TILE_NET_RETRY_INTERVAL);
+       else
+               netif_carrier_on(priv->dev);
+}
+
+
+/*
+ * Called when a network interface is made active.
+ *
+ * Returns 0 on success, negative value on failure.
+ *
+ * The open entry point is called when a network interface is made
+ * active by the system (IFF_UP).  At this point all resources needed
+ * for transmit and receive operations are allocated, the interrupt
+ * handler is registered with the OS, the watchdog timer is started,
+ * and the stack is notified that the interface is ready.
+ *
+ * If the actual link is not available yet, then we tell Linux that
+ * we have no carrier, and we keep checking until the link comes up.
+ */
+static int tile_net_open(struct net_device *dev)
+{
+       int ret = 0;
+       struct tile_net_priv *priv = netdev_priv(dev);
+
+       /*
+        * We rely on priv->partly_opened to tell us if this is the
+        * first time this interface is being brought up. If it is
+        * set, the IPP was already initialized and should not be
+        * initialized again.
+        */
+       if (!priv->partly_opened) {
+
+               int count;
+               int credits;
+
+               /* Initialize LIPP/LEPP, and start the Shim. */
+               ret = tile_net_open_aux(dev);
+               if (ret < 0) {
+                       pr_err("tile_net_open_aux failed: %d\n", ret);
+                       return ret;
+               }
+
+               /* Analyze the network cpus. */
+
+               if (network_cpus_used)
+                       cpumask_copy(&priv->network_cpus_map,
+                                    &network_cpus_map);
+               else
+                       cpumask_copy(&priv->network_cpus_map, cpu_online_mask);
+
+
+               count = cpumask_weight(&priv->network_cpus_map);
+
+               /* Limit credits to available buffers, and apply min. */
+               credits = max(16, (LIPP_LARGE_BUFFERS / count) & ~1);
+
+               /* Apply "GBE" max limit. */
+               /* ISSUE: Use higher limit for XGBE? */
+               credits = min(NETIO_MAX_RECEIVE_PKTS, credits);
+
+               priv->network_cpus_count = count;
+               priv->network_cpus_credits = credits;
+
+#ifdef TILE_NET_DEBUG
+               pr_info("Using %d network cpus, with %d credits each\n",
+                      priv->network_cpus_count, priv->network_cpus_credits);
+#endif
+
+               priv->partly_opened = 1;
+       }
+
+       /*
+        * Attempt to bring up the link.
+        */
+       ret = tile_net_open_inner(dev);
+       if (ret <= 0) {
+               if (ret == 0)
+                       netif_carrier_on(dev);
+               return ret;
+       }
+
+       /*
+        * We were unable to bring up the NetIO interface, but we want to
+        * try again in a little bit.  Tell Linux that we have no carrier
+        * so it doesn't try to use the interface before the link comes up
+        * and then remember to try again later.
+        */
+       netif_carrier_off(dev);
+       schedule_delayed_work_on(singlethread_cpu, &priv->retry_work,
+                                TILE_NET_RETRY_INTERVAL);
+
+       return 0;
+}
+
+
+/*
+ * Disables a network interface.
+ *
+ * Returns 0, this is not allowed to fail.
+ *
+ * The close entry point is called when an interface is de-activated
+ * by the OS.  The hardware is still under the drivers control, but
+ * needs to be disabled.  A global MAC reset is issued to stop the
+ * hardware, and all transmit and receive resources are freed.
+ *
+ * ISSUE: Can this can be called while "tile_net_poll()" is running?
+ */
+static int tile_net_stop(struct net_device *dev)
+{
+       struct tile_net_priv *priv = netdev_priv(dev);
+
+       bool pending = true;
+
+       PDEBUG("tile_net_stop()\n");
+
+       /* ISSUE: Only needed if not yet fully open. */
+       cancel_delayed_work_sync(&priv->retry_work);
+
+       /* Can't transmit any more. */
+       netif_stop_queue(dev);
+
+       /*
+        * Disable hypervisor interrupts on each tile.
+        */
+       on_each_cpu(tile_net_disable_intr, (void *)dev, 1);
+
+       /*
+        * Unregister the interrupt handler.
+        * The __ffs() function returns the index into the interrupt handler
+        * table from the interrupt bit mask which should have one bit
+        * and one bit only set.
+        */
+       if (priv->intr_id)
+               free_irq(__ffs(priv->intr_id), dev);
+
+       /*
+        * Drain all the LIPP buffers.
+        */
+
+       while (true) {
+               int buffer;
+
+               /* NOTE: This should never fail. */
+               if (hv_dev_pread(priv->hv_devhdl, 0, (HV_VirtAddr)&buffer,
+                                sizeof(buffer), NETIO_IPP_DRAIN_OFF) < 0)
+                       break;
+
+               /* Stop when done. */
+               if (buffer == 0)
+                       break;
+
+               {
+                       /* Convert "linux_buffer_t" to "va". */
+                       void *va = __va((phys_addr_t)(buffer >> 1) << 7);
+
+                       /* Acquire the associated "skb". */
+                       struct sk_buff **skb_ptr = va - sizeof(*skb_ptr);
+                       struct sk_buff *skb = *skb_ptr;
+
+                       kfree_skb(skb);
+               }
+       }
+
+       /* Stop LIPP/LEPP. */
+       tile_net_stop_aux(dev);
+
+
+       priv->fully_opened = 0;
+
+
+       /*
+        * XXX: ISSUE: It appears that, in practice anyway, by the
+        * time we get here, there are no pending completions.
+        */
+       while (pending) {
+
+               struct sk_buff *olds[32];
+               unsigned int wanted = 32;
+               unsigned int i, nolds = 0;
+
+               nolds = tile_net_lepp_grab_comps(dev, olds,
+                                                wanted, &pending);
+
+               /* ISSUE: We have never actually seen this debug spew. */
+               if (nolds != 0)
+                       pr_info("During tile_net_stop(), grabbed %d comps.\n",
+                              nolds);
+
+               for (i = 0; i < nolds; i++)
+                       kfree_skb(olds[i]);
+       }
+
+
+       /* Wipe the EPP queue. */
+       memset(priv->epp_queue, 0, sizeof(lepp_queue_t));
+
+       /* Evict the EPP queue. */
+       finv_buffer(priv->epp_queue, PAGE_SIZE);
+
+       return 0;
+}
+
+
+/*
+ * Prepare the "frags" info for the resulting LEPP command.
+ *
+ * If needed, flush the memory used by the frags.
+ */
+static unsigned int tile_net_tx_frags(lepp_frag_t *frags,
+                                     struct sk_buff *skb,
+                                     void *b_data, unsigned int b_len)
+{
+       unsigned int i, n = 0;
+
+       struct skb_shared_info *sh = skb_shinfo(skb);
+
+       phys_addr_t cpa;
+
+       if (b_len != 0) {
+
+               if (!hash_default)
+                       finv_buffer_remote(b_data, b_len);
+
+               cpa = __pa(b_data);
+               frags[n].cpa_lo = cpa;
+               frags[n].cpa_hi = cpa >> 32;
+               frags[n].length = b_len;
+               frags[n].hash_for_home = hash_default;
+               n++;
+       }
+
+       for (i = 0; i < sh->nr_frags; i++) {
+
+               skb_frag_t *f = &sh->frags[i];
+               unsigned long pfn = page_to_pfn(f->page);
+
+               /* FIXME: Compute "hash_for_home" properly. */
+               /* ISSUE: The hypervisor checks CHIP_HAS_REV1_DMA_PACKETS(). */
+               int hash_for_home = hash_default;
+
+               /* FIXME: Hmmm. */
+               if (!hash_default) {
+                       void *va = pfn_to_kaddr(pfn) + f->page_offset;
+                       BUG_ON(PageHighMem(f->page));
+                       finv_buffer_remote(va, f->size);
+               }
+
+               cpa = ((phys_addr_t)pfn << PAGE_SHIFT) + f->page_offset;
+               frags[n].cpa_lo = cpa;
+               frags[n].cpa_hi = cpa >> 32;
+               frags[n].length = f->size;
+               frags[n].hash_for_home = hash_for_home;
+               n++;
+       }
+
+       return n;
+}
+
+
+/*
+ * This function takes "skb", consisting of a header template and a
+ * payload, and hands it to LEPP, to emit as one or more segments,
+ * each consisting of a possibly modified header, plus a piece of the
+ * payload, via a process known as "tcp segmentation offload".
+ *
+ * Usually, "data" will contain the header template, of size "sh_len",
+ * and "sh->frags" will contain "skb->data_len" bytes of payload, and
+ * there will be "sh->gso_segs" segments.
+ *
+ * Sometimes, if "sendfile()" requires copying, we will be called with
+ * "data" containing the header and payload, with "frags" being empty.
+ *
+ * In theory, "sh->nr_frags" could be 3, but in practice, it seems
+ * that this will never actually happen.
+ *
+ * See "emulate_large_send_offload()" for some reference code, which
+ * does not handle checksumming.
+ *
+ * ISSUE: How do we make sure that high memory DMA does not migrate?
+ */
+static int tile_net_tx_tso(struct sk_buff *skb, struct net_device *dev)
+{
+       struct tile_net_priv *priv = netdev_priv(dev);
+       int my_cpu = smp_processor_id();
+       struct tile_net_cpu *info = priv->cpu[my_cpu];
+       struct tile_net_stats_t *stats = &info->stats;
+
+       struct skb_shared_info *sh = skb_shinfo(skb);
+
+       unsigned char *data = skb->data;
+
+       /* The ip header follows the ethernet header. */
+       struct iphdr *ih = ip_hdr(skb);
+       unsigned int ih_len = ih->ihl * 4;
+
+       /* Note that "nh == ih", by definition. */
+       unsigned char *nh = skb_network_header(skb);
+       unsigned int eh_len = nh - data;
+
+       /* The tcp header follows the ip header. */
+       struct tcphdr *th = (struct tcphdr *)(nh + ih_len);
+       unsigned int th_len = th->doff * 4;
+
+       /* The total number of header bytes. */
+       /* NOTE: This may be less than skb_headlen(skb). */
+       unsigned int sh_len = eh_len + ih_len + th_len;
+
+       /* The number of payload bytes at "skb->data + sh_len". */
+       /* This is non-zero for sendfile() without HIGHDMA. */
+       unsigned int b_len = skb_headlen(skb) - sh_len;
+
+       /* The total number of payload bytes. */
+       unsigned int d_len = b_len + skb->data_len;
+
+       /* The maximum payload size. */
+       unsigned int p_len = sh->gso_size;
+
+       /* The total number of segments. */
+       unsigned int num_segs = sh->gso_segs;
+
+       /* The temporary copy of the command. */
+       u32 cmd_body[(LEPP_MAX_CMD_SIZE + 3) / 4];
+       lepp_tso_cmd_t *cmd = (lepp_tso_cmd_t *)cmd_body;
+
+       /* Analyze the "frags". */
+       unsigned int num_frags =
+               tile_net_tx_frags(cmd->frags, skb, data + sh_len, b_len);
+
+       /* The size of the command, including frags and header. */
+       size_t cmd_size = LEPP_TSO_CMD_SIZE(num_frags, sh_len);
+
+       /* The command header. */
+       lepp_tso_cmd_t cmd_init = {
+               .tso = true,
+               .header_size = sh_len,
+               .ip_offset = eh_len,
+               .tcp_offset = eh_len + ih_len,
+               .payload_size = p_len,
+               .num_frags = num_frags,
+       };
+
+       unsigned long irqflags;
+
+       lepp_queue_t *eq = priv->epp_queue;
+
+       struct sk_buff *olds[4];
+       unsigned int wanted = 4;
+       unsigned int i, nolds = 0;
+
+       unsigned int cmd_head, cmd_tail, cmd_next;
+       unsigned int comp_tail;
+
+       unsigned int free_slots;
+
+
+       /* Paranoia. */
+       BUG_ON(skb->protocol != htons(ETH_P_IP));
+       BUG_ON(ih->protocol != IPPROTO_TCP);
+       BUG_ON(skb->ip_summed != CHECKSUM_PARTIAL);
+       BUG_ON(num_frags > LEPP_MAX_FRAGS);
+       /*--BUG_ON(num_segs != (d_len + (p_len - 1)) / p_len); */
+       BUG_ON(num_segs <= 1);
+
+
+       /* Finish preparing the command. */
+
+       /* Copy the command header. */
+       *cmd = cmd_init;
+
+       /* Copy the "header". */
+       memcpy(&cmd->frags[num_frags], data, sh_len);
+
+
+       /* Prefetch and wait, to minimize time spent holding the spinlock. */
+       prefetch_L1(&eq->comp_tail);
+       prefetch_L1(&eq->cmd_tail);
+       mb();
+
+
+       /* Enqueue the command. */
+
+       spin_lock_irqsave(&priv->cmd_lock, irqflags);
+
+       /*
+        * Handle completions if needed to make room.
+        * HACK: Spin until there is sufficient room.
+        */
+       free_slots = lepp_num_free_comp_slots(eq);
+       if (free_slots < 1) {
+spin:
+               nolds += tile_net_lepp_grab_comps(dev, olds + nolds,
+                                                 wanted - nolds, NULL);
+               if (lepp_num_free_comp_slots(eq) < 1)
+                       goto spin;
+       }
+
+       cmd_head = eq->cmd_head;
+       cmd_tail = eq->cmd_tail;
+
+       /* NOTE: The "gotos" below are untested. */
+
+       /* Prepare to advance, detecting full queue. */
+       cmd_next = cmd_tail + cmd_size;
+       if (cmd_tail < cmd_head && cmd_next >= cmd_head)
+               goto spin;
+       if (cmd_next > LEPP_CMD_LIMIT) {
+               cmd_next = 0;
+               if (cmd_next == cmd_head)
+                       goto spin;
+       }
+
+       /* Copy the command. */
+       memcpy(&eq->cmds[cmd_tail], cmd, cmd_size);
+
+       /* Advance. */
+       cmd_tail = cmd_next;
+
+       /* Record "skb" for eventual freeing. */
+       comp_tail = eq->comp_tail;
+       eq->comps[comp_tail] = skb;
+       LEPP_QINC(comp_tail);
+       eq->comp_tail = comp_tail;
+
+       /* Flush before allowing LEPP to handle the command. */
+       __insn_mf();
+
+       eq->cmd_tail = cmd_tail;
+
+       spin_unlock_irqrestore(&priv->cmd_lock, irqflags);
+
+       if (nolds == 0)
+               nolds = tile_net_lepp_grab_comps(dev, olds, wanted, NULL);
+
+       /* Handle completions. */
+       for (i = 0; i < nolds; i++)
+               kfree_skb(olds[i]);
+
+       /* Update stats. */
+       stats->tx_packets += num_segs;
+       stats->tx_bytes += (num_segs * sh_len) + d_len;
+
+       /* Make sure the egress timer is scheduled. */
+       tile_net_schedule_egress_timer(info);
+
+       return NETDEV_TX_OK;
+}
+
+
+/*
+ * Transmit a packet (called by the kernel via "hard_start_xmit" hook).
+ */
+static int tile_net_tx(struct sk_buff *skb, struct net_device *dev)
+{
+       struct tile_net_priv *priv = netdev_priv(dev);
+       int my_cpu = smp_processor_id();
+       struct tile_net_cpu *info = priv->cpu[my_cpu];
+       struct tile_net_stats_t *stats = &info->stats;
+
+       unsigned long irqflags;
+
+       struct skb_shared_info *sh = skb_shinfo(skb);
+
+       unsigned int len = skb->len;
+       unsigned char *data = skb->data;
+
+       unsigned int csum_start = skb->csum_start - skb_headroom(skb);
+
+       lepp_frag_t frags[LEPP_MAX_FRAGS];
+
+       unsigned int num_frags;
+
+       lepp_queue_t *eq = priv->epp_queue;
+
+       struct sk_buff *olds[4];
+       unsigned int wanted = 4;
+       unsigned int i, nolds = 0;
+
+       unsigned int cmd_size = sizeof(lepp_cmd_t);
+
+       unsigned int cmd_head, cmd_tail, cmd_next;
+       unsigned int comp_tail;
+
+       lepp_cmd_t cmds[LEPP_MAX_FRAGS];
+
+       unsigned int free_slots;
+
+
+       /*
+        * This is paranoia, since we think that if the link doesn't come
+        * up, telling Linux we have no carrier will keep it from trying
+        * to transmit.  If it does, though, we can't execute this routine,
+        * since data structures we depend on aren't set up yet.
+        */
+       if (!info->registered)
+               return NETDEV_TX_BUSY;
+
+
+       /* Save the timestamp. */
+       dev->trans_start = jiffies;
+
+
+#ifdef TILE_NET_PARANOIA
+#if CHIP_HAS_CBOX_HOME_MAP()
+       if (hash_default) {
+               HV_PTE pte = *virt_to_pte(current->mm, (unsigned long)data);
+               if (hv_pte_get_mode(pte) != HV_PTE_MODE_CACHE_HASH_L3)
+                       panic("Non-coherent egress buffer!");
+       }
+#endif
+#endif
+
+
+#ifdef TILE_NET_DUMP_PACKETS
+       /* ISSUE: Does not dump the "frags". */
+       dump_packet(data, skb_headlen(skb), "tx");
+#endif /* TILE_NET_DUMP_PACKETS */
+
+
+       if (sh->gso_size != 0)
+               return tile_net_tx_tso(skb, dev);
+
+
+       /* Prepare the commands. */
+
+       num_frags = tile_net_tx_frags(frags, skb, data, skb_headlen(skb));
+
+       for (i = 0; i < num_frags; i++) {
+
+               bool final = (i == num_frags - 1);
+
+               lepp_cmd_t cmd = {
+                       .cpa_lo = frags[i].cpa_lo,
+                       .cpa_hi = frags[i].cpa_hi,
+                       .length = frags[i].length,
+                       .hash_for_home = frags[i].hash_for_home,
+                       .send_completion = final,
+                       .end_of_packet = final
+               };
+
+               if (i == 0 && skb->ip_summed == CHECKSUM_PARTIAL) {
+                       cmd.compute_checksum = 1;
+                       cmd.checksum_data.bits.start_byte = csum_start;
+                       cmd.checksum_data.bits.count = len - csum_start;
+                       cmd.checksum_data.bits.destination_byte =
+                               csum_start + skb->csum_offset;
+               }
+
+               cmds[i] = cmd;
+       }
+
+
+       /* Prefetch and wait, to minimize time spent holding the spinlock. */
+       prefetch_L1(&eq->comp_tail);
+       prefetch_L1(&eq->cmd_tail);
+       mb();
+
+
+       /* Enqueue the commands. */
+
+       spin_lock_irqsave(&priv->cmd_lock, irqflags);
+
+       /*
+        * Handle completions if needed to make room.
+        * HACK: Spin until there is sufficient room.
+        */
+       free_slots = lepp_num_free_comp_slots(eq);
+       if (free_slots < 1) {
+spin:
+               nolds += tile_net_lepp_grab_comps(dev, olds + nolds,
+                                                 wanted - nolds, NULL);
+               if (lepp_num_free_comp_slots(eq) < 1)
+                       goto spin;
+       }
+
+       cmd_head = eq->cmd_head;
+       cmd_tail = eq->cmd_tail;
+
+       /* NOTE: The "gotos" below are untested. */
+
+       /* Copy the commands, or fail. */
+       for (i = 0; i < num_frags; i++) {
+
+               /* Prepare to advance, detecting full queue. */
+               cmd_next = cmd_tail + cmd_size;
+               if (cmd_tail < cmd_head && cmd_next >= cmd_head)
+                       goto spin;
+               if (cmd_next > LEPP_CMD_LIMIT) {
+                       cmd_next = 0;
+                       if (cmd_next == cmd_head)
+                               goto spin;
+               }
+
+               /* Copy the command. */
+               *(lepp_cmd_t *)&eq->cmds[cmd_tail] = cmds[i];
+
+               /* Advance. */
+               cmd_tail = cmd_next;
+       }
+
+       /* Record "skb" for eventual freeing. */
+       comp_tail = eq->comp_tail;
+       eq->comps[comp_tail] = skb;
+       LEPP_QINC(comp_tail);
+       eq->comp_tail = comp_tail;
+
+       /* Flush before allowing LEPP to handle the command. */
+       __insn_mf();
+
+       eq->cmd_tail = cmd_tail;
+
+       spin_unlock_irqrestore(&priv->cmd_lock, irqflags);
+
+       if (nolds == 0)
+               nolds = tile_net_lepp_grab_comps(dev, olds, wanted, NULL);
+
+       /* Handle completions. */
+       for (i = 0; i < nolds; i++)
+               kfree_skb(olds[i]);
+
+       /* HACK: Track "expanded" size for short packets (e.g. 42 < 60). */
+       stats->tx_packets++;
+       stats->tx_bytes += ((len >= ETH_ZLEN) ? len : ETH_ZLEN);
+
+       /* Make sure the egress timer is scheduled. */
+       tile_net_schedule_egress_timer(info);
+
+       return NETDEV_TX_OK;
+}
+
+
+/*
+ * Deal with a transmit timeout.
+ */
+static void tile_net_tx_timeout(struct net_device *dev)
+{
+       PDEBUG("tile_net_tx_timeout()\n");
+       PDEBUG("Transmit timeout at %ld, latency %ld\n", jiffies,
+              jiffies - dev->trans_start);
+
+       /* XXX: ISSUE: This doesn't seem useful for us. */
+       netif_wake_queue(dev);
+}
+
+
+/*
+ * Ioctl commands.
+ */
+static int tile_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+       return -EOPNOTSUPP;
+}
+
+
+/*
+ * Get System Network Statistics.
+ *
+ * Returns the address of the device statistics structure.
+ */
+static struct net_device_stats *tile_net_get_stats(struct net_device *dev)
+{
+       struct tile_net_priv *priv = netdev_priv(dev);
+       u32 rx_packets = 0;
+       u32 tx_packets = 0;
+       u32 rx_bytes = 0;
+       u32 tx_bytes = 0;
+       int i;
+
+       for_each_online_cpu(i) {
+               if (priv->cpu[i]) {
+                       rx_packets += priv->cpu[i]->stats.rx_packets;
+                       rx_bytes += priv->cpu[i]->stats.rx_bytes;
+                       tx_packets += priv->cpu[i]->stats.tx_packets;
+                       tx_bytes += priv->cpu[i]->stats.tx_bytes;
+               }
+       }
+
+       priv->stats.rx_packets = rx_packets;
+       priv->stats.rx_bytes = rx_bytes;
+       priv->stats.tx_packets = tx_packets;
+       priv->stats.tx_bytes = tx_bytes;
+
+       return &priv->stats;
+}
+
+
+/*
+ * Change the "mtu".
+ *
+ * The "change_mtu" method is usually not needed.
+ * If you need it, it must be like this.
+ */
+static int tile_net_change_mtu(struct net_device *dev, int new_mtu)
+{
+       PDEBUG("tile_net_change_mtu()\n");
+
+       /* Check ranges. */
+       if ((new_mtu < 68) || (new_mtu > 1500))
+               return -EINVAL;
+
+       /* Accept the value. */
+       dev->mtu = new_mtu;
+
+       return 0;
+}
+
+
+/*
+ * Change the Ethernet Address of the NIC.
+ *
+ * The hypervisor driver does not support changing MAC address.  However,
+ * the IPP does not do anything with the MAC address, so the address which
+ * gets used on outgoing packets, and which is accepted on incoming packets,
+ * is completely up to the NetIO program or kernel driver which is actually
+ * handling them.
+ *
+ * Returns 0 on success, negative on failure.
+ */
+static int tile_net_set_mac_address(struct net_device *dev, void *p)
+{
+       struct sockaddr *addr = p;
+
+       if (!is_valid_ether_addr(addr->sa_data))
+               return -EINVAL;
+
+       /* ISSUE: Note that "dev_addr" is now a pointer. */
+       memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+       return 0;
+}
+
+
+/*
+ * Obtain the MAC address from the hypervisor.
+ * This must be done before opening the device.
+ */
+static int tile_net_get_mac(struct net_device *dev)
+{
+       struct tile_net_priv *priv = netdev_priv(dev);
+
+       char hv_dev_name[32];
+       int len;
+
+       __netio_getset_offset_t offset = { .word = NETIO_IPP_PARAM_OFF };
+
+       int ret;
+
+       /* For example, "xgbe0". */
+       strcpy(hv_dev_name, dev->name);
+       len = strlen(hv_dev_name);
+
+       /* For example, "xgbe/0". */
+       hv_dev_name[len] = hv_dev_name[len - 1];
+       hv_dev_name[len - 1] = '/';
+       len++;
+
+       /* For example, "xgbe/0/native_hash". */
+       strcpy(hv_dev_name + len, hash_default ? "/native_hash" : "/native");
+
+       /* Get the hypervisor handle for this device. */
+       priv->hv_devhdl = hv_dev_open((HV_VirtAddr)hv_dev_name, 0);
+       PDEBUG("hv_dev_open(%s) returned %d %p\n",
+              hv_dev_name, priv->hv_devhdl, &priv->hv_devhdl);
+       if (priv->hv_devhdl < 0) {
+               if (priv->hv_devhdl == HV_ENODEV)
+                       printk(KERN_DEBUG "Ignoring unconfigured device %s\n",
+                                hv_dev_name);
+               else
+                       printk(KERN_DEBUG "hv_dev_open(%s) returned %d\n",
+                                hv_dev_name, priv->hv_devhdl);
+               return -1;
+       }
+
+       /*
+        * Read the hardware address from the hypervisor.
+        * ISSUE: Note that "dev_addr" is now a pointer.
+        */
+       offset.bits.class = NETIO_PARAM;
+       offset.bits.addr = NETIO_PARAM_MAC;
+       ret = hv_dev_pread(priv->hv_devhdl, 0,
+                          (HV_VirtAddr)dev->dev_addr, dev->addr_len,
+                          offset.word);
+       PDEBUG("hv_dev_pread(NETIO_PARAM_MAC) returned %d\n", ret);
+       if (ret <= 0) {
+               printk(KERN_DEBUG "hv_dev_pread(NETIO_PARAM_MAC) %s failed\n",
+                      dev->name);
+               /*
+                * Since the device is configured by the hypervisor but we
+                * can't get its MAC address, we are most likely running
+                * the simulator, so let's generate a random MAC address.
+                */
+               random_ether_addr(dev->dev_addr);
+       }
+
+       return 0;
+}
+
+
+static struct net_device_ops tile_net_ops = {
+       .ndo_open = tile_net_open,
+       .ndo_stop = tile_net_stop,
+       .ndo_start_xmit = tile_net_tx,
+       .ndo_do_ioctl = tile_net_ioctl,
+       .ndo_get_stats = tile_net_get_stats,
+       .ndo_change_mtu = tile_net_change_mtu,
+       .ndo_tx_timeout = tile_net_tx_timeout,
+       .ndo_set_mac_address = tile_net_set_mac_address
+};
+
+
+/*
+ * The setup function.
+ *
+ * This uses ether_setup() to assign various fields in dev, including
+ * setting IFF_BROADCAST and IFF_MULTICAST, then sets some extra fields.
+ */
+static void tile_net_setup(struct net_device *dev)
+{
+       PDEBUG("tile_net_setup()\n");
+
+       ether_setup(dev);
+
+       dev->netdev_ops = &tile_net_ops;
+
+       dev->watchdog_timeo = TILE_NET_TIMEOUT;
+
+       /* We want lockless xmit. */
+       dev->features |= NETIF_F_LLTX;
+
+       /* We support hardware tx checksums. */
+       dev->features |= NETIF_F_HW_CSUM;
+
+       /* We support scatter/gather. */
+       dev->features |= NETIF_F_SG;
+
+       /* We support TSO. */
+       dev->features |= NETIF_F_TSO;
+
+#ifdef TILE_NET_GSO
+       /* We support GSO. */
+       dev->features |= NETIF_F_GSO;
+#endif
+
+       if (hash_default)
+               dev->features |= NETIF_F_HIGHDMA;
+
+       /* ISSUE: We should support NETIF_F_UFO. */
+
+       dev->tx_queue_len = TILE_NET_TX_QUEUE_LEN;
+
+       dev->mtu = TILE_NET_MTU;
+}
+
+
+/*
+ * Allocate the device structure, register the device, and obtain the
+ * MAC address from the hypervisor.
+ */
+static struct net_device *tile_net_dev_init(const char *name)
+{
+       int ret;
+       struct net_device *dev;
+       struct tile_net_priv *priv;
+       struct page *page;
+
+       /*
+        * Allocate the device structure.  This allocates "priv", calls
+        * tile_net_setup(), and saves "name".  Normally, "name" is a
+        * template, instantiated by register_netdev(), but not for us.
+        */
+       dev = alloc_netdev(sizeof(*priv), name, tile_net_setup);
+       if (!dev) {
+               pr_err("alloc_netdev(%s) failed\n", name);
+               return NULL;
+       }
+
+       priv = netdev_priv(dev);
+
+       /* Initialize "priv". */
+
+       memset(priv, 0, sizeof(*priv));
+
+       /* Save "dev" for "tile_net_open_retry()". */
+       priv->dev = dev;
+
+       INIT_DELAYED_WORK(&priv->retry_work, tile_net_open_retry);
+
+       spin_lock_init(&priv->cmd_lock);
+       spin_lock_init(&priv->comp_lock);
+
+       /* Allocate "epp_queue". */
+       BUG_ON(get_order(sizeof(lepp_queue_t)) != 0);
+       page = alloc_pages(GFP_KERNEL | __GFP_ZERO, 0);
+       if (!page) {
+               free_netdev(dev);
+               return NULL;
+       }
+       priv->epp_queue = page_address(page);
+
+       /* Register the network device. */
+       ret = register_netdev(dev);
+       if (ret) {
+               pr_err("register_netdev %s failed %d\n", dev->name, ret);
+               free_page((unsigned long)priv->epp_queue);
+               free_netdev(dev);
+               return NULL;
+       }
+
+       /* Get the MAC address. */
+       ret = tile_net_get_mac(dev);
+       if (ret < 0) {
+               unregister_netdev(dev);
+               free_page((unsigned long)priv->epp_queue);
+               free_netdev(dev);
+               return NULL;
+       }
+
+       return dev;
+}
+
+
+/*
+ * Module cleanup.
+ */
+static void tile_net_cleanup(void)
+{
+       int i;
+
+       for (i = 0; i < TILE_NET_DEVS; i++) {
+               if (tile_net_devs[i]) {
+                       struct net_device *dev = tile_net_devs[i];
+                       struct tile_net_priv *priv = netdev_priv(dev);
+                       unregister_netdev(dev);
+                       finv_buffer(priv->epp_queue, PAGE_SIZE);
+                       free_page((unsigned long)priv->epp_queue);
+                       free_netdev(dev);
+               }
+       }
+}
+
+
+/*
+ * Module initialization.
+ */
+static int tile_net_init_module(void)
+{
+       pr_info("Tilera IPP Net Driver\n");
+
+       tile_net_devs[0] = tile_net_dev_init("xgbe0");
+       tile_net_devs[1] = tile_net_dev_init("xgbe1");
+       tile_net_devs[2] = tile_net_dev_init("gbe0");
+       tile_net_devs[3] = tile_net_dev_init("gbe1");
+
+       return 0;
+}
+
+
+#ifndef MODULE
+/*
+ * The "network_cpus" boot argument specifies the cpus that are dedicated
+ * to handle ingress packets.
+ *
+ * The parameter should be in the form "network_cpus=m-n[,x-y]", where
+ * m, n, x, y are integer numbers that represent the cpus that can be
+ * neither a dedicated cpu nor a dataplane cpu.
+ */
+static int __init network_cpus_setup(char *str)
+{
+       int rc = cpulist_parse_crop(str, &network_cpus_map);
+       if (rc != 0) {
+               pr_warning("network_cpus=%s: malformed cpu list\n",
+                      str);
+       } else {
+
+               /* Remove dedicated cpus. */
+               cpumask_and(&network_cpus_map, &network_cpus_map,
+                           cpu_possible_mask);
+
+
+               if (cpumask_empty(&network_cpus_map)) {
+                       pr_warning("Ignoring network_cpus='%s'.\n",
+                              str);
+               } else {
+                       char buf[1024];
+                       cpulist_scnprintf(buf, sizeof(buf), &network_cpus_map);
+                       pr_info("Linux network CPUs: %s\n", buf);
+                       network_cpus_used = true;
+               }
+       }
+
+       return 0;
+}
+__setup("network_cpus=", network_cpus_setup);
+#endif
+
+
+module_init(tile_net_init_module);
+module_exit(tile_net_cleanup);
index a9f7d5d1a2695f95a968001a93c1449b9ac998be..7064e035757a16b927d35aa61991268089275744 100644 (file)
@@ -688,9 +688,6 @@ static netdev_tx_t dmfe_start_xmit(struct sk_buff *skb,
 
        DMFE_DBUG(0, "dmfe_start_xmit", 0);
 
-       /* Resource flag check */
-       netif_stop_queue(dev);
-
        /* Too large packet check */
        if (skb->len > MAX_PACKET_SIZE) {
                pr_err("big packet = %d\n", (u16)skb->len);
@@ -698,6 +695,9 @@ static netdev_tx_t dmfe_start_xmit(struct sk_buff *skb,
                return NETDEV_TX_OK;
        }
 
+       /* Resource flag check */
+       netif_stop_queue(dev);
+
        spin_lock_irqsave(&db->lock, flags);
 
        /* No Tx resource check, it never happen nromally */
index 05a95586f3c52f76ead1b26bb6545b3a18b1a076..055b87ab4f075b66afb7cc4d33c58b440d4f83be 100644 (file)
@@ -899,7 +899,8 @@ struct ucc_geth_hardware_statistics {
 #define UCC_GETH_UTFS_INIT                      512    /* Tx virtual FIFO size
                                                         */
 #define UCC_GETH_UTFET_INIT                     256    /* 1/2 utfs */
-#define UCC_GETH_UTFTT_INIT                     512
+#define UCC_GETH_UTFTT_INIT                     256    /* 1/2 utfs
+                                                          due to errata */
 /* Gigabit Ethernet (1000 Mbps) */
 #define UCC_GETH_URFS_GIGA_INIT                 4096/*2048*/   /* Rx virtual
                                                                   FIFO size */
index b154a94de03e61927cdc063c8671867108cf7b89..812edf85d6d32b017454f449f4d03e300ed4ec50 100644 (file)
@@ -958,10 +958,6 @@ static void packetizeRx(struct hso_net *odev, unsigned char *ip_pkt,
                                /* Packet is complete. Inject into stack. */
                                /* We have IP packet here */
                                odev->skb_rx_buf->protocol = cpu_to_be16(ETH_P_IP);
-                               /* don't check it */
-                               odev->skb_rx_buf->ip_summed =
-                                       CHECKSUM_UNNECESSARY;
-
                                skb_reset_mac_header(odev->skb_rx_buf);
 
                                /* Ship it off to the kernel */
@@ -2994,12 +2990,14 @@ static int hso_probe(struct usb_interface *interface,
 
        case HSO_INTF_BULK:
                /* It's a regular bulk interface */
-               if (((port_spec & HSO_PORT_MASK) == HSO_PORT_NETWORK) &&
-                   !disable_net)
-                       hso_dev = hso_create_net_device(interface, port_spec);
-               else
+               if ((port_spec & HSO_PORT_MASK) == HSO_PORT_NETWORK) {
+                       if (!disable_net)
+                               hso_dev =
+                                   hso_create_net_device(interface, port_spec);
+               } else {
                        hso_dev =
                            hso_create_bulk_serial_device(interface, port_spec);
+               }
                if (!hso_dev)
                        goto exit;
                break;
index ea476cbd38b511039c8cb21ecdba7c61c1071ff1..e305274f83fba70c4967b2af57934ec5347a7eea 100644 (file)
@@ -293,6 +293,7 @@ static inline void sca_tx_done(port_t *port)
        struct net_device *dev = port->netdev;
        card_t* card = port->card;
        u8 stat;
+       unsigned count = 0;
 
        spin_lock(&port->lock);
 
@@ -316,10 +317,12 @@ static inline void sca_tx_done(port_t *port)
                        dev->stats.tx_bytes += readw(&desc->len);
                }
                writeb(0, &desc->stat); /* Free descriptor */
+               count++;
                port->txlast = (port->txlast + 1) % card->tx_ring_buffers;
        }
 
-       netif_wake_queue(dev);
+       if (count)
+               netif_wake_queue(dev);
        spin_unlock(&port->lock);
 }
 
index d81ad83978855ac4929a93f082139afd63f8cc41..24297b274cd475ac855114394784c7eeaab2bcd0 100644 (file)
@@ -498,7 +498,6 @@ norbuff:
 static int x25_asy_close(struct net_device *dev)
 {
        struct x25_asy *sl = netdev_priv(dev);
-       int err;
 
        spin_lock(&sl->lock);
        if (sl->tty)
@@ -507,10 +506,6 @@ static int x25_asy_close(struct net_device *dev)
        netif_stop_queue(dev);
        sl->rcount = 0;
        sl->xleft  = 0;
-       err = lapb_unregister(dev);
-       if (err != LAPB_OK)
-               printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",
-                       err);
        spin_unlock(&sl->lock);
        return 0;
 }
@@ -582,7 +577,7 @@ static int x25_asy_open_tty(struct tty_struct *tty)
        if (err)
                return err;
        /* Done.  We have linked the TTY line to a channel. */
-       return sl->dev->base_addr;
+       return 0;
 }
 
 
@@ -595,6 +590,7 @@ static int x25_asy_open_tty(struct tty_struct *tty)
 static void x25_asy_close_tty(struct tty_struct *tty)
 {
        struct x25_asy *sl = tty->disc_data;
+       int err;
 
        /* First make sure we're connected. */
        if (!sl || sl->magic != X25_ASY_MAGIC)
@@ -605,6 +601,11 @@ static void x25_asy_close_tty(struct tty_struct *tty)
                dev_close(sl->dev);
        rtnl_unlock();
 
+       err = lapb_unregister(sl->dev);
+       if (err != LAPB_OK)
+               printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",
+                       err);
+
        tty->disc_data = NULL;
        sl->tty = NULL;
        x25_asy_free(sl);
index 8251946842e6186bddcd1cac303dbaea74664410..42ed923cdb1aad9479be7ed5f68a2b40c665ffcb 100644 (file)
@@ -1917,7 +1917,8 @@ ath5k_beacon_send(struct ath5k_softc *sc)
                sc->bmisscount = 0;
        }
 
-       if (sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) {
+       if ((sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) ||
+                       sc->opmode == NL80211_IFTYPE_MESH_POINT) {
                u64 tsf = ath5k_hw_get_tsf64(ah);
                u32 tsftu = TSF_TO_TU(tsf);
                int slot = ((tsftu % sc->bintval) * ATH_BCBUF) / sc->bintval;
@@ -1949,8 +1950,9 @@ ath5k_beacon_send(struct ath5k_softc *sc)
                /* NB: hw still stops DMA, so proceed */
        }
 
-       /* refresh the beacon for AP mode */
-       if (sc->opmode == NL80211_IFTYPE_AP)
+       /* refresh the beacon for AP or MESH mode */
+       if (sc->opmode == NL80211_IFTYPE_AP ||
+                       sc->opmode == NL80211_IFTYPE_MESH_POINT)
                ath5k_beacon_update(sc->hw, vif);
 
        ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr);
@@ -2851,7 +2853,8 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
 
        /* Assign the vap/adhoc to a beacon xmit slot. */
        if ((avf->opmode == NL80211_IFTYPE_AP) ||
-           (avf->opmode == NL80211_IFTYPE_ADHOC)) {
+           (avf->opmode == NL80211_IFTYPE_ADHOC) ||
+           (avf->opmode == NL80211_IFTYPE_MESH_POINT)) {
                int slot;
 
                WARN_ON(list_empty(&sc->bcbuf));
@@ -2870,7 +2873,7 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
                sc->bslot[avf->bslot] = vif;
                if (avf->opmode == NL80211_IFTYPE_AP)
                        sc->num_ap_vifs++;
-               else
+               else if (avf->opmode == NL80211_IFTYPE_ADHOC)
                        sc->num_adhoc_vifs++;
        }
 
index c4182359bee46603cffc46e9781750087f2a5f0f..a7b82f0085d2e899da46f6139dcac2185b42f924 100644 (file)
@@ -55,6 +55,8 @@
 #define SUB_NUM_CTL_MODES_AT_5G_40 2    /* excluding HT40, EXT-OFDM */
 #define SUB_NUM_CTL_MODES_AT_2G_40 3    /* excluding HT40, EXT-OFDM, EXT-CCK */
 
+#define CTL(_tpower, _flag) ((_tpower) | ((_flag) << 6))
+
 static const struct ar9300_eeprom ar9300_default = {
        .eepromVersion = 2,
        .templateVersion = 2,
@@ -290,20 +292,21 @@ static const struct ar9300_eeprom ar9300_default = {
                }
         },
        .ctlPowerData_2G = {
-                { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
-                { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
-                { { {60, 1}, {60, 0}, {60, 0}, {60, 1} } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
 
-                { { {60, 1}, {60, 0}, {0, 0}, {0, 0} } },
-                { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
-                { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
+                { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
 
-                { { {60, 0}, {60, 1}, {60, 1}, {60, 0} } },
-                { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
-                { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
 
-                { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
-                { { {60, 0}, {60, 1}, {60, 1}, {60, 1} } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
         },
        .modalHeader5G = {
                /* 4 idle,t1,t2,b (4 bits per setting) */
@@ -568,56 +571,56 @@ static const struct ar9300_eeprom ar9300_default = {
        .ctlPowerData_5G = {
                {
                        {
-                               {60, 1}, {60, 1}, {60, 1}, {60, 1},
-                               {60, 1}, {60, 1}, {60, 1}, {60, 0},
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
                        }
                },
                {
                        {
-                               {60, 1}, {60, 1}, {60, 1}, {60, 1},
-                               {60, 1}, {60, 1}, {60, 1}, {60, 0},
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
                        }
                },
                {
                        {
-                               {60, 0}, {60, 1}, {60, 0}, {60, 1},
-                               {60, 1}, {60, 1}, {60, 1}, {60, 1},
+                               CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
                        }
                },
                {
                        {
-                               {60, 0}, {60, 1}, {60, 1}, {60, 0},
-                               {60, 1}, {60, 0}, {60, 0}, {60, 0},
+                               CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                               CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
                        }
                },
                {
                        {
-                               {60, 1}, {60, 1}, {60, 1}, {60, 0},
-                               {60, 0}, {60, 0}, {60, 0}, {60, 0},
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                               CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0),
                        }
                },
                {
                        {
-                               {60, 1}, {60, 1}, {60, 1}, {60, 1},
-                               {60, 1}, {60, 0}, {60, 0}, {60, 0},
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
                        }
                },
                {
                        {
-                               {60, 1}, {60, 1}, {60, 1}, {60, 1},
-                               {60, 1}, {60, 1}, {60, 1}, {60, 1},
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
                        }
                },
                {
                        {
-                               {60, 1}, {60, 1}, {60, 0}, {60, 1},
-                               {60, 1}, {60, 1}, {60, 1}, {60, 0},
+                               CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
                        }
                },
                {
                        {
-                               {60, 1}, {60, 0}, {60, 1}, {60, 1},
-                               {60, 1}, {60, 1}, {60, 0}, {60, 1},
+                               CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
                        }
                },
         }
@@ -1827,9 +1830,9 @@ static u16 ar9003_hw_get_direct_edge_power(struct ar9300_eeprom *eep,
        struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G;
 
        if (is2GHz)
-               return ctl_2g[idx].ctlEdges[edge].tPower;
+               return CTL_EDGE_TPOWER(ctl_2g[idx].ctlEdges[edge]);
        else
-               return ctl_5g[idx].ctlEdges[edge].tPower;
+               return CTL_EDGE_TPOWER(ctl_5g[idx].ctlEdges[edge]);
 }
 
 static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep,
@@ -1847,12 +1850,12 @@ static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep,
 
        if (is2GHz) {
                if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 1) < freq &&
-                   ctl_2g[idx].ctlEdges[edge - 1].flag)
-                       return ctl_2g[idx].ctlEdges[edge - 1].tPower;
+                   CTL_EDGE_FLAGS(ctl_2g[idx].ctlEdges[edge - 1]))
+                       return CTL_EDGE_TPOWER(ctl_2g[idx].ctlEdges[edge - 1]);
        } else {
                if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 0) < freq &&
-                   ctl_5g[idx].ctlEdges[edge - 1].flag)
-                       return ctl_5g[idx].ctlEdges[edge - 1].tPower;
+                   CTL_EDGE_FLAGS(ctl_5g[idx].ctlEdges[edge - 1]))
+                       return CTL_EDGE_TPOWER(ctl_5g[idx].ctlEdges[edge - 1]);
        }
 
        return AR9300_MAX_RATE_POWER;
index 3c533bb983c72859c9fbea4563070f387747506e..655b3033396c7f89ce1585479afb918102f993ae 100644 (file)
@@ -261,17 +261,12 @@ struct cal_tgt_pow_ht {
        u8 tPow2x[14];
 } __packed;
 
-struct cal_ctl_edge_pwr {
-       u8 tPower:6,
-          flag:2;
-} __packed;
-
 struct cal_ctl_data_2g {
-       struct cal_ctl_edge_pwr ctlEdges[AR9300_NUM_BAND_EDGES_2G];
+       u8 ctlEdges[AR9300_NUM_BAND_EDGES_2G];
 } __packed;
 
 struct cal_ctl_data_5g {
-       struct cal_ctl_edge_pwr ctlEdges[AR9300_NUM_BAND_EDGES_5G];
+       u8 ctlEdges[AR9300_NUM_BAND_EDGES_5G];
 } __packed;
 
 struct ar9300_eeprom {
index 170d44a35ccbd2ca06886be2be2ed8c1cd5dcf25..0963071e8f908c15ebec8131c84b792d931e56d9 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/device.h>
 #include <linux/leds.h>
 #include <linux/completion.h>
+#include <linux/pm_qos_params.h>
 
 #include "debug.h"
 #include "common.h"
@@ -328,7 +329,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp);
 struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
 void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
 int ath_tx_setup(struct ath_softc *sc, int haltype);
-void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
+bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
 void ath_draintxq(struct ath_softc *sc,
                     struct ath_txq *txq, bool retry_tx);
 void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
@@ -646,6 +647,8 @@ struct ath_softc {
        struct ath_descdma txsdma;
 
        struct ath_ant_comb ant_comb;
+
+       struct pm_qos_request_list pm_qos_req;
 };
 
 struct ath_wiphy {
@@ -675,7 +678,6 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz)
 }
 
 extern struct ieee80211_ops ath9k_ops;
-extern struct pm_qos_request_list ath9k_pm_qos_req;
 extern int modparam_nohwcrypt;
 extern int led_blink;
 
index 1266333f586d8f574cf8fcda7086f036f3d56403..2bbf94d0191edb0ddc84084a37b07172203f2485 100644 (file)
@@ -240,16 +240,16 @@ u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower,
        for (i = 0; (i < num_band_edges) &&
                     (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
                if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) {
-                       twiceMaxEdgePower = pRdEdgesPower[i].tPower;
+                       twiceMaxEdgePower = CTL_EDGE_TPOWER(pRdEdgesPower[i].ctl);
                        break;
                } else if ((i > 0) &&
                           (freq < ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel,
                                                      is2GHz))) {
                        if (ath9k_hw_fbin2freq(pRdEdgesPower[i - 1].bChannel,
                                               is2GHz) < freq &&
-                           pRdEdgesPower[i - 1].flag) {
+                           CTL_EDGE_FLAGS(pRdEdgesPower[i - 1].ctl)) {
                                twiceMaxEdgePower =
-                                       pRdEdgesPower[i - 1].tPower;
+                                       CTL_EDGE_TPOWER(pRdEdgesPower[i - 1].ctl);
                        }
                        break;
                }
index dacb45e1b9063b620736475b6116975fcb60cf4d..dd59f09441a3cdf00cbc805a36e4734d58a04253 100644 (file)
 
 #define AR9287_CHECKSUM_LOCATION (AR9287_EEP_START_LOC + 1)
 
+#define CTL_EDGE_TPOWER(_ctl) ((_ctl) & 0x3f)
+#define CTL_EDGE_FLAGS(_ctl) (((_ctl) >> 6) & 0x03)
+
+#define LNA_CTL_BUF_MODE       BIT(0)
+#define LNA_CTL_ISEL_LO                BIT(1)
+#define LNA_CTL_ISEL_HI                BIT(2)
+#define LNA_CTL_BUF_IN         BIT(3)
+#define LNA_CTL_FEM_BAND       BIT(4)
+#define LNA_CTL_LOCAL_BIAS     BIT(5)
+#define LNA_CTL_FORCE_XPA      BIT(6)
+#define LNA_CTL_USE_ANT1       BIT(7)
+
 enum eeprom_param {
        EEP_NFTHRESH_5,
        EEP_NFTHRESH_2,
@@ -378,10 +390,7 @@ struct modal_eep_header {
        u8 xatten2Margin[AR5416_MAX_CHAINS];
        u8 ob_ch1;
        u8 db_ch1;
-       u8 useAnt1:1,
-           force_xpaon:1,
-           local_bias:1,
-           femBandSelectUsed:1, xlnabufin:1, xlnaisel:2, xlnabufmode:1;
+       u8 lna_ctl;
        u8 miscBits;
        u16 xpaBiasLvlFreq[3];
        u8 futureModal[6];
@@ -535,18 +544,10 @@ struct cal_target_power_ht {
        u8 tPow2x[8];
 } __packed;
 
-
-#ifdef __BIG_ENDIAN_BITFIELD
-struct cal_ctl_edges {
-       u8 bChannel;
-       u8 flag:2, tPower:6;
-} __packed;
-#else
 struct cal_ctl_edges {
        u8 bChannel;
-       u8 tPower:6, flag:2;
+       u8 ctl;
 } __packed;
-#endif
 
 struct cal_data_op_loop_ar9287 {
        u8 pwrPdg[2][5];
index 966b9496a9dd4b51cf5c1f850fc987ea4b6ffff2..195406db3bd899b28f96c7b8214428822c3735db 100644 (file)
@@ -37,7 +37,7 @@ static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
        int addr, eep_start_loc;
        eep_data = (u16 *)eep;
 
-       if (ah->hw_version.devid == 0x7015)
+       if (AR9287_HTC_DEVID(ah))
                eep_start_loc = AR9287_HTC_EEP_START_LOC;
        else
                eep_start_loc = AR9287_EEP_START_LOC;
index 76b4d65472dd2b37dbf98ff69b57646e53443c61..a3ccb1b9638d7b8b44f32ba651d519d042b806ec 100644 (file)
@@ -451,9 +451,10 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
                ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
                                          AR_AN_TOP2_LOCALBIAS,
                                          AR_AN_TOP2_LOCALBIAS_S,
-                                         pModal->local_bias);
+                                         !!(pModal->lna_ctl &
+                                            LNA_CTL_LOCAL_BIAS));
                REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG,
-                             pModal->force_xpaon);
+                             !!(pModal->lna_ctl & LNA_CTL_FORCE_XPA));
        }
 
        REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
@@ -1062,15 +1063,19 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
        case 1:
                break;
        case 2:
-               scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
+               if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN)
+                       scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
+               else
+                       scaledPower = 0;
                break;
        case 3:
-               scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
+               if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN)
+                       scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
+               else
+                       scaledPower = 0;
                break;
        }
 
-       scaledPower = max((u16)0, scaledPower);
-
        if (IS_CHAN_2GHZ(chan)) {
                numCtlModes = ARRAY_SIZE(ctlModesFor11g) -
                        SUB_NUM_CTL_MODES_AT_2G_40;
@@ -1428,9 +1433,9 @@ static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah,
 
        num_ant_config = 1;
 
-       if (pBase->version >= 0x0E0D)
-               if (pModal->useAnt1)
-                       num_ant_config += 1;
+       if (pBase->version >= 0x0E0D &&
+           (pModal->lna_ctl & LNA_CTL_USE_ANT1))
+               num_ant_config += 1;
 
        return num_ant_config;
 }
index f7ec31b4ddd3a9af801dcb8211763f21e6ab7e09..0de3c3d3c245c2ad5f71f0a419a7ba4fab96e60c 100644 (file)
@@ -36,8 +36,13 @@ static struct usb_device_id ath9k_hif_usb_ids[] = {
        { USB_DEVICE(0x13D3, 0x3327) }, /* Azurewave */
        { USB_DEVICE(0x13D3, 0x3328) }, /* Azurewave */
        { USB_DEVICE(0x13D3, 0x3346) }, /* IMC Networks */
+       { USB_DEVICE(0x13D3, 0x3348) }, /* Azurewave */
+       { USB_DEVICE(0x13D3, 0x3349) }, /* Azurewave */
+       { USB_DEVICE(0x13D3, 0x3350) }, /* Azurewave */
        { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */
        { USB_DEVICE(0x083A, 0xA704) }, /* SMC Networks */
+       { USB_DEVICE(0x040D, 0x3801) }, /* VIA */
+       { USB_DEVICE(0x1668, 0x1200) }, /* Verizon */
        { },
 };
 
@@ -806,6 +811,8 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev)
        case 0x7010:
        case 0x7015:
        case 0x9018:
+       case 0xA704:
+       case 0x1200:
                firm_offset = AR7010_FIRMWARE_TEXT;
                break;
        default:
@@ -928,6 +935,8 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
        case 0x7010:
        case 0x7015:
        case 0x9018:
+       case 0xA704:
+       case 0x1200:
                if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x0202)
                        hif_dev->fw_name = FIRMWARE_AR7010_1_1;
                else
@@ -1015,6 +1024,13 @@ static int ath9k_hif_usb_suspend(struct usb_interface *interface,
        struct hif_device_usb *hif_dev =
                (struct hif_device_usb *) usb_get_intfdata(interface);
 
+       /*
+        * The device has to be set to FULLSLEEP mode in case no
+        * interface is up.
+        */
+       if (!(hif_dev->flags & HIF_USB_START))
+               ath9k_htc_suspend(hif_dev->htc_handle);
+
        ath9k_hif_usb_dealloc_urbs(hif_dev);
 
        return 0;
index 75ecf6a30d25c6ac68d346c5ac862a0255ba4be1..c3b561daa6c1035a68f4b27da92914ba4e601399 100644 (file)
@@ -455,6 +455,8 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv);
 void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv);
 void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv);
 void ath9k_ps_work(struct work_struct *work);
+bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
+                       enum ath9k_power_mode mode);
 
 void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv);
 void ath9k_init_leds(struct ath9k_htc_priv *priv);
@@ -464,6 +466,7 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
                           u16 devid, char *product);
 void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug);
 #ifdef CONFIG_PM
+void ath9k_htc_suspend(struct htc_target *htc_handle);
 int ath9k_htc_resume(struct htc_target *htc_handle);
 #endif
 #ifdef CONFIG_ATH9K_HTC_DEBUGFS
index 3d7b97f1b3aeebe5840c438b5ccf631de702d6c2..8776f49ffd41bf2a40f080798fe6c5173b80c9b4 100644 (file)
@@ -249,6 +249,8 @@ static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid)
        case 0x7010:
        case 0x7015:
        case 0x9018:
+       case 0xA704:
+       case 0x1200:
                priv->htc->credits = 45;
                break;
        default:
@@ -889,6 +891,12 @@ void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)
 }
 
 #ifdef CONFIG_PM
+
+void ath9k_htc_suspend(struct htc_target *htc_handle)
+{
+       ath9k_htc_setpower(htc_handle->drv_priv, ATH9K_PM_FULL_SLEEP);
+}
+
 int ath9k_htc_resume(struct htc_target *htc_handle)
 {
        int ret;
index 9a3be8da755d2f7181ada323e5ec9054b58a0a9e..51977caca47fd6d456e521cff4511e1079f2e09a 100644 (file)
@@ -63,8 +63,8 @@ static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv,
        return mode;
 }
 
-static bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
-                              enum ath9k_power_mode mode)
+bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
+                       enum ath9k_power_mode mode)
 {
        bool ret;
 
index 3d19b5bc937f9c1c285e23645fcbf6a929037b21..29d80ca783933684b7c5c531cbb970ee7e006cda 100644 (file)
@@ -121,7 +121,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb)
                        tx_hdr.data_type = ATH9K_HTC_NORMAL;
                }
 
-               if (ieee80211_is_data(fc)) {
+               if (ieee80211_is_data_qos(fc)) {
                        qc = ieee80211_get_qos_ctl(hdr);
                        tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
                }
index 6ebc68bca91f0a999614572b38f69452df49645d..c7fbe25cc12827cf29f68729fe636b07ef75ebfa 100644 (file)
@@ -2044,7 +2044,8 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio)
                val = REG_READ(ah, AR7010_GPIO_IN);
                return (MS(val, AR7010_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) == 0;
        } else if (AR_SREV_9300_20_OR_LATER(ah))
-               return MS_REG_READ(AR9300, gpio) != 0;
+               return (MS(REG_READ(ah, AR_GPIO_IN), AR9300_GPIO_IN_VAL) &
+                       AR_GPIO_BIT(gpio)) != 0;
        else if (AR_SREV_9271(ah))
                return MS_REG_READ(AR9271, gpio) != 0;
        else if (AR_SREV_9287_11_OR_LATER(ah))
index 6a0d99eff404b77417856c7f1b7c035eb079359e..14b8ab386daff8823bcc3301fa52d467ce6cb01b 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/slab.h>
-#include <linux/pm_qos_params.h>
 
 #include "ath9k.h"
 
@@ -180,8 +179,6 @@ static const struct ath_ops ath9k_common_ops = {
        .write = ath9k_iowrite32,
 };
 
-struct pm_qos_request_list ath9k_pm_qos_req;
-
 /**************************/
 /*     Initialization     */
 /**************************/
@@ -664,6 +661,8 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
                hw->flags |= IEEE80211_HW_MFP_CAPABLE;
 
        hw->wiphy->interface_modes =
+               BIT(NL80211_IFTYPE_P2P_GO) |
+               BIT(NL80211_IFTYPE_P2P_CLIENT) |
                BIT(NL80211_IFTYPE_AP) |
                BIT(NL80211_IFTYPE_WDS) |
                BIT(NL80211_IFTYPE_STATION) |
@@ -759,7 +758,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
        ath_init_leds(sc);
        ath_start_rfkill_poll(sc);
 
-       pm_qos_add_request(&ath9k_pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
+       pm_qos_add_request(&sc->pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
                           PM_QOS_DEFAULT_VALUE);
 
        return 0;
@@ -817,8 +816,6 @@ void ath9k_deinit_device(struct ath_softc *sc)
 
        ath9k_ps_wakeup(sc);
 
-       pm_qos_remove_request(&ath9k_pm_qos_req);
-
        wiphy_rfkill_stop_polling(sc->hw->wiphy);
        ath_deinit_leds(sc);
 
@@ -832,6 +829,7 @@ void ath9k_deinit_device(struct ath_softc *sc)
        }
 
        ieee80211_unregister_hw(hw);
+       pm_qos_remove_request(&sc->pm_qos_req);
        ath_rx_cleanup(sc);
        ath_tx_cleanup(sc);
        ath9k_deinit_softc(sc);
index 8c13479b17cd9d418f7d7f496b01dbf7445ba202..c996963ab33927c027f3fb019200261c0ac07d18 100644 (file)
@@ -703,8 +703,7 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
                        rs->rs_phyerr = phyerr;
                } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
                        rs->rs_status |= ATH9K_RXERR_DECRYPT;
-               else if ((ads.ds_rxstatus8 & AR_MichaelErr) &&
-                        rs->rs_keyix != ATH9K_RXKEYIX_INVALID)
+               else if (ads.ds_rxstatus8 & AR_MichaelErr)
                        rs->rs_status |= ATH9K_RXERR_MIC;
                else if (ads.ds_rxstatus8 & AR_KeyMiss)
                        rs->rs_status |= ATH9K_RXERR_DECRYPT;
index 25d3ef4c338e1eb45800b45fec112fc064c095af..c0c3464d3a861162e1142a0e2931a73aedae1fab 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/nl80211.h>
-#include <linux/pm_qos_params.h>
 #include "ath9k.h"
 #include "btcoex.h"
 
@@ -245,11 +244,12 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
         * the relevant bits of the h/w.
         */
        ath9k_hw_set_interrupts(ah, 0);
-       ath_drain_all_txq(sc, false);
+       stopped = ath_drain_all_txq(sc, false);
 
        spin_lock_bh(&sc->rx.pcu_lock);
 
-       stopped = ath_stoprecv(sc);
+       if (!ath_stoprecv(sc))
+               stopped = false;
 
        /* XXX: do not flush receive queue here. We don't want
         * to flush data frames already in queue because of
@@ -1244,7 +1244,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
                        ath9k_btcoex_timer_resume(sc);
        }
 
-       pm_qos_update_request(&ath9k_pm_qos_req, 55);
+       pm_qos_update_request(&sc->pm_qos_req, 55);
 
 mutex_unlock:
        mutex_unlock(&sc->mutex);
@@ -1423,7 +1423,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
 
        sc->sc_flags |= SC_OP_INVALID;
 
-       pm_qos_update_request(&ath9k_pm_qos_req, PM_QOS_DEFAULT_VALUE);
+       pm_qos_update_request(&sc->pm_qos_req, PM_QOS_DEFAULT_VALUE);
 
        mutex_unlock(&sc->mutex);
 
@@ -1520,7 +1520,6 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
        struct ath_softc *sc = aphy->sc;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        struct ath_vif *avp = (void *)vif->drv_priv;
-       int i;
 
        ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n");
 
@@ -1534,21 +1533,24 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
        if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
            (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
            (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) {
+               /* Disable SWBA interrupt */
+               sc->sc_ah->imask &= ~ATH9K_INT_SWBA;
                ath9k_ps_wakeup(sc);
+               ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
                ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
                ath9k_ps_restore(sc);
+               tasklet_kill(&sc->bcon_tasklet);
        }
 
        ath_beacon_return(sc, avp);
        sc->sc_flags &= ~SC_OP_BEACONS;
 
-       for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
-               if (sc->beacon.bslot[i] == vif) {
-                       printk(KERN_DEBUG "%s: vif had allocated beacon "
-                              "slot\n", __func__);
-                       sc->beacon.bslot[i] = NULL;
-                       sc->beacon.bslot_aphy[i] = NULL;
-               }
+       if (sc->nbcnvifs) {
+               /* Re-enable SWBA interrupt */
+               sc->sc_ah->imask |= ATH9K_INT_SWBA;
+               ath9k_ps_wakeup(sc);
+               ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
+               ath9k_ps_restore(sc);
        }
 
        sc->nvifs--;
index c76ea53c20ce7dbe41863c00930853a59ccc6cf8..fdc2ec52b42fcd5647df2c967598e94bcfc13c9a 100644 (file)
@@ -518,7 +518,7 @@ bool ath_stoprecv(struct ath_softc *sc)
        bool stopped;
 
        spin_lock_bh(&sc->rx.rxbuflock);
-       ath9k_hw_stoppcurecv(ah);
+       ath9k_hw_abortpcurecv(ah);
        ath9k_hw_setrxfilter(ah, 0);
        stopped = ath9k_hw_stopdmarecv(ah);
 
@@ -838,6 +838,10 @@ static bool ath9k_rx_accept(struct ath_common *common,
                            struct ath_rx_status *rx_stats,
                            bool *decrypt_error)
 {
+#define is_mc_or_valid_tkip_keyix ((is_mc ||                   \
+               (rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID && \
+               test_bit(rx_stats->rs_keyix, common->tkip_keymap))))
+
        struct ath_hw *ah = common->ah;
        __le16 fc;
        u8 rx_status_len = ah->caps.rx_status_len;
@@ -879,15 +883,18 @@ static bool ath9k_rx_accept(struct ath_common *common,
                if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
                        *decrypt_error = true;
                } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) {
+                       bool is_mc;
                        /*
                         * The MIC error bit is only valid if the frame
                         * is not a control frame or fragment, and it was
                         * decrypted using a valid TKIP key.
                         */
+                       is_mc = !!is_multicast_ether_addr(hdr->addr1);
+
                        if (!ieee80211_is_ctl(fc) &&
                            !ieee80211_has_morefrags(fc) &&
                            !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
-                           test_bit(rx_stats->rs_keyix, common->tkip_keymap))
+                           is_mc_or_valid_tkip_keyix)
                                rxs->flag |= RX_FLAG_MMIC_ERROR;
                        else
                                rx_stats->rs_status &= ~ATH9K_RXERR_MIC;
index fa05b711e5cdfb7657f94ac420bc87a3f443c1ef..2c6a22fbb0f0cf76fb5ac5cfd22b530402e9f693 100644 (file)
 #define AR_DEVID_7010(_ah) \
        (((_ah)->hw_version.devid == 0x7010) || \
         ((_ah)->hw_version.devid == 0x7015) || \
-        ((_ah)->hw_version.devid == 0x9018))
+        ((_ah)->hw_version.devid == 0x9018) || \
+        ((_ah)->hw_version.devid == 0xA704) || \
+        ((_ah)->hw_version.devid == 0x1200))
+
+#define AR9287_HTC_DEVID(_ah) \
+       (((_ah)->hw_version.devid == 0x7015) || \
+        ((_ah)->hw_version.devid == 0x1200))
 
 #define AR_RADIO_SREV_MAJOR                   0xf0
 #define AR_RAD5133_SREV_MAJOR                 0xc0
@@ -978,11 +984,13 @@ enum {
 #define AR9287_GPIO_IN_VAL_S                     11
 #define AR9271_GPIO_IN_VAL                       0xFFFF0000
 #define AR9271_GPIO_IN_VAL_S                     16
-#define AR9300_GPIO_IN_VAL                       0x0001FFFF
-#define AR9300_GPIO_IN_VAL_S                     0
 #define AR7010_GPIO_IN_VAL                       0x0000FFFF
 #define AR7010_GPIO_IN_VAL_S                     0
 
+#define AR_GPIO_IN                              0x404c
+#define AR9300_GPIO_IN_VAL                       0x0001FFFF
+#define AR9300_GPIO_IN_VAL_S                     0
+
 #define AR_GPIO_OE_OUT                           (AR_SREV_9300_20_OR_LATER(ah) ? 0x4050 : 0x404c)
 #define AR_GPIO_OE_OUT_DRV                       0x3
 #define AR_GPIO_OE_OUT_DRV_NO                    0x0
index f2ade2402ce27709e1da385941b9adbaece96b1e..aff04789f794ee805bf50f1f13d28783f79851d3 100644 (file)
@@ -1120,7 +1120,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
        }
 }
 
-void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
+bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
 {
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@@ -1128,7 +1128,7 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
        int i, npend = 0;
 
        if (sc->sc_flags & SC_OP_INVALID)
-               return;
+               return true;
 
        /* Stop beacon queue */
        ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
@@ -1142,25 +1142,15 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
                }
        }
 
-       if (npend) {
-               int r;
-
-               ath_print(common, ATH_DBG_FATAL,
-                         "Failed to stop TX DMA. Resetting hardware!\n");
-
-               spin_lock_bh(&sc->sc_resetlock);
-               r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
-               if (r)
-                       ath_print(common, ATH_DBG_FATAL,
-                                 "Unable to reset hardware; reset status %d\n",
-                                 r);
-               spin_unlock_bh(&sc->sc_resetlock);
-       }
+       if (npend)
+               ath_print(common, ATH_DBG_FATAL, "Failed to stop TX DMA!\n");
 
        for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
                if (ATH_TXQ_SETUP(sc, i))
                        ath_draintxq(sc, &sc->tx.txq[i], retry_tx);
        }
+
+       return !npend;
 }
 
 void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
index ae6c006bbc56c03bd76f0e1cc56c46a927db1db9..546b4e4ec5ea090aaf6ed0ce7b77ed024e3c8fd6 100644 (file)
@@ -291,7 +291,8 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
 
                if (SUPP(CARL9170FW_WLANTX_CAB)) {
                        ar->hw->wiphy->interface_modes |=
-                               BIT(NL80211_IFTYPE_AP);
+                               BIT(NL80211_IFTYPE_AP) |
+                               BIT(NL80211_IFTYPE_P2P_GO);
                }
        }
 
index 980ae70ea424f6dc50a93734446536588bea9734..dc7b30b170d037de1dc9b38b058458a98f8efb43 100644 (file)
@@ -647,7 +647,7 @@ init:
        }
 
 unlock:
-       if (err && (vif_id != -1)) {
+       if (err && (vif_id >= 0)) {
                vif_priv->active = false;
                bitmap_release_region(&ar->vif_bitmap, vif_id, 0);
                ar->vifs--;
@@ -1631,7 +1631,8 @@ void *carl9170_alloc(size_t priv_size)
         * supports these modes. The code which will add the
         * additional interface_modes is in fw.c.
         */
-       hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+       hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+                                    BIT(NL80211_IFTYPE_P2P_CLIENT);
 
        hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS |
                     IEEE80211_HW_REPORTS_TX_ACK_STATUS |
index b575c865142d64f82f8e072518c0de44e46039cc..7e6506a77bbb625a28ad0e6b41f7984607fe5f80 100644 (file)
@@ -810,7 +810,7 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
 
        mac_tmp = cpu_to_le16(AR9170_TX_MAC_HW_DURATION |
                              AR9170_TX_MAC_BACKOFF);
-       mac_tmp |= cpu_to_le16((hw_queue << AR9170_TX_MAC_QOS_S) &&
+       mac_tmp |= cpu_to_le16((hw_queue << AR9170_TX_MAC_QOS_S) &
                               AR9170_TX_MAC_QOS);
 
        no_ack = !!(info->flags & IEEE80211_TX_CTL_NO_ACK);
index 3317039cd28fe5ae6b1e38ff0029bf345fd78d50..7504ed14c72575a7befb91b0c0d9dd2684660af9 100644 (file)
@@ -553,12 +553,12 @@ static int carl9170_usb_flush(struct ar9170 *ar)
                usb_free_urb(urb);
        }
 
-       ret = usb_wait_anchor_empty_timeout(&ar->tx_cmd, HZ);
+       ret = usb_wait_anchor_empty_timeout(&ar->tx_cmd, 1000);
        if (ret == 0)
                err = -ETIMEDOUT;
 
        /* lets wait a while until the tx - queues are dried out */
-       ret = usb_wait_anchor_empty_timeout(&ar->tx_anch, HZ);
+       ret = usb_wait_anchor_empty_timeout(&ar->tx_anch, 1000);
        if (ret == 0)
                err = -ETIMEDOUT;
 
index 9a55338d957f1768aed1121b393cca2ef862d640..09e2dfd7b175a74534de12fe240761f7a3138302 100644 (file)
@@ -163,6 +163,7 @@ static int b43_sdio_probe(struct sdio_func *func,
 err_free_ssb:
        kfree(sdio);
 err_disable_func:
+       sdio_claim_host(func);
        sdio_disable_func(func);
 err_release_host:
        sdio_release_host(func);
index e5685dc317a80423a7acb6a68694bba4043d3897..b4de0ca10feb8f9ef18b826e00f82a240fb40e91 100644 (file)
@@ -1170,7 +1170,6 @@ static void if_sdio_remove(struct sdio_func *func)
        lbs_deb_sdio("call remove card\n");
        lbs_stop_card(card->priv);
        lbs_remove_card(card->priv);
-       card->priv->surpriseremoved = 1;
 
        flush_workqueue(card->workqueue);
        destroy_workqueue(card->workqueue);
index 79bcb4e5d2ca03c7ccb82621576296a6ea68b5d0..ecd4d04b2c3cea67aebd6d62c9446a3318a2840c 100644 (file)
@@ -1055,7 +1055,6 @@ static int __devexit libertas_spi_remove(struct spi_device *spi)
        lbs_stop_card(priv);
        lbs_remove_card(priv); /* will call free_netdev */
 
-       priv->surpriseremoved = 1;
        free_irq(spi->irq, card);
        if_spi_terminate_spi_thread(card);
        if (card->pdata->teardown)
index 46b88b118c992c12764084233f8633a62a01a629..fcd1bbfc632d527364b8f1fc91abd70ba3242225 100644 (file)
@@ -915,8 +915,6 @@ void lbs_remove_card(struct lbs_private *priv)
 
        lbs_free_adapter(priv);
        lbs_cfg_free(priv);
-
-       priv->dev = NULL;
        free_netdev(dev);
 
        lbs_deb_leave(LBS_DEB_MAIN);
index e8e2d0f4763db4f33e899ad712595d9af5173333..f3d396e7544b9d1d0f7848bc1cabb74bce75b8de 100644 (file)
@@ -1392,10 +1392,9 @@ static void orinoco_process_scan_results(struct work_struct *work)
                                orinoco_add_hostscan_results(priv, buf, len);
 
                        kfree(buf);
-               } else if (priv->scan_request) {
+               } else {
                        /* Either abort or complete the scan */
-                       cfg80211_scan_done(priv->scan_request, (len < 0));
-                       priv->scan_request = NULL;
+                       orinoco_scan_done(priv, (len < 0));
                }
 
                spin_lock_irqsave(&priv->scan_lock, flags);
@@ -1684,6 +1683,8 @@ static int __orinoco_down(struct orinoco_private *priv)
                hermes_write_regn(hw, EVACK, 0xffff);
        }
 
+       orinoco_scan_done(priv, true);
+
        /* firmware will have to reassociate */
        netif_carrier_off(dev);
        priv->last_linkstatus = 0xffff;
@@ -1762,10 +1763,7 @@ void orinoco_reset(struct work_struct *work)
        orinoco_unlock(priv, &flags);
 
        /* Scanning support: Notify scan cancellation */
-       if (priv->scan_request) {
-               cfg80211_scan_done(priv->scan_request, 1);
-               priv->scan_request = NULL;
-       }
+       orinoco_scan_done(priv, true);
 
        if (priv->hard_reset) {
                err = (*priv->hard_reset)(priv);
@@ -1813,6 +1811,12 @@ static int __orinoco_commit(struct orinoco_private *priv)
        struct net_device *dev = priv->ndev;
        int err = 0;
 
+       /* If we've called commit, we are reconfiguring or bringing the
+        * interface up. Maintaining countermeasures across this would
+        * be confusing, so note that we've disabled them. The port will
+        * be enabled later in orinoco_commit or __orinoco_up. */
+       priv->tkip_cm_active = 0;
+
        err = orinoco_hw_program_rids(priv);
 
        /* FIXME: what about netif_tx_lock */
index 71b3d68b9403a8c4c142b776179c1edef9328ebd..32954c4b243a9dc70bbb0fd350c6c79ff67875d3 100644 (file)
@@ -151,20 +151,20 @@ orinoco_cs_config(struct pcmcia_device *link)
                goto failed;
        }
 
-       ret = pcmcia_request_irq(link, orinoco_interrupt);
-       if (ret)
-               goto failed;
-
-       /* We initialize the hermes structure before completing PCMCIA
-        * configuration just in case the interrupt handler gets
-        * called. */
        mem = ioport_map(link->resource[0]->start,
                        resource_size(link->resource[0]));
        if (!mem)
                goto failed;
 
+       /* We initialize the hermes structure before completing PCMCIA
+        * configuration just in case the interrupt handler gets
+        * called. */
        hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
 
+       ret = pcmcia_request_irq(link, orinoco_interrupt);
+       if (ret)
+               goto failed;
+
        ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
index 4300d9db7d8caab2d70442b7cbd37a9da69adef9..86cb54c842e745ffd7863457f23f45185440f556 100644 (file)
@@ -229,3 +229,11 @@ void orinoco_add_hostscan_results(struct orinoco_private *priv,
                priv->scan_request = NULL;
        }
 }
+
+void orinoco_scan_done(struct orinoco_private *priv, bool abort)
+{
+       if (priv->scan_request) {
+               cfg80211_scan_done(priv->scan_request, abort);
+               priv->scan_request = NULL;
+       }
+}
index 2dc4e046dbdb61c5c19f33e14f6ae4fae381a8c9..27281fb0a6dc02f529b4ea1edf2fb29e2a6903be 100644 (file)
@@ -16,5 +16,6 @@ void orinoco_add_extscan_result(struct orinoco_private *priv,
 void orinoco_add_hostscan_results(struct orinoco_private *dev,
                                  unsigned char *buf,
                                  size_t len);
+void orinoco_scan_done(struct orinoco_private *priv, bool abort);
 
 #endif /* _ORINOCO_SCAN_H_ */
index fb859a5ad2eb8a5c2e02f349cf4002caac32fc49..db34c282e59b39340a9bf7c6c51f529bf020a1c0 100644 (file)
@@ -214,21 +214,21 @@ spectrum_cs_config(struct pcmcia_device *link)
                goto failed;
        }
 
-       ret = pcmcia_request_irq(link, orinoco_interrupt);
-       if (ret)
-               goto failed;
-
-       /* We initialize the hermes structure before completing PCMCIA
-        * configuration just in case the interrupt handler gets
-        * called. */
        mem = ioport_map(link->resource[0]->start,
                        resource_size(link->resource[0]));
        if (!mem)
                goto failed;
 
+       /* We initialize the hermes structure before completing PCMCIA
+        * configuration just in case the interrupt handler gets
+        * called. */
        hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
        hw->eeprom_pda = true;
 
+       ret = pcmcia_request_irq(link, orinoco_interrupt);
+       if (ret)
+               goto failed;
+
        ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
index 93505f93bf97711019e86bbe27f39f4f727bce01..e5afabee60d1834b898193479cf710c3bb3eed22 100644 (file)
@@ -911,10 +911,10 @@ static int orinoco_ioctl_set_auth(struct net_device *dev,
                 */
                if (param->value) {
                        priv->tkip_cm_active = 1;
-                       ret = hermes_enable_port(hw, 0);
+                       ret = hermes_disable_port(hw, 0);
                } else {
                        priv->tkip_cm_active = 0;
-                       ret = hermes_disable_port(hw, 0);
+                       ret = hermes_enable_port(hw, 0);
                }
                break;
 
index 458bb57914a32d57948ff425508f6b40ac2de7e1..cdbeec9f83ea256507c57762dda8a7f73e69983e 100644 (file)
@@ -66,8 +66,8 @@ struct netfront_cb {
 
 #define GRANT_INVALID_REF      0
 
-#define NET_TX_RING_SIZE __RING_SIZE((struct xen_netif_tx_sring *)0, PAGE_SIZE)
-#define NET_RX_RING_SIZE __RING_SIZE((struct xen_netif_rx_sring *)0, PAGE_SIZE)
+#define NET_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE)
+#define NET_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE)
 #define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
 
 struct netfront_info {
index d9f51485beeee9940ab66e597c47f0d17869da46..9383063d2b16896bfcc740855221c5eccfbf0570 100644 (file)
@@ -349,7 +349,6 @@ static struct irq_chip dino_interrupt_type = {
        .name   = "GSC-PCI",
        .unmask = dino_unmask_irq,
        .mask   = dino_mask_irq,
-       .ack    = no_ack_irq,
 };
 
 
index 1211974f55aac78e8dee465c4300ee028fbfcf62..e860038b0b841952f29021a5fa752f6d9ee4ea3e 100644 (file)
@@ -186,7 +186,6 @@ static struct irq_chip eisa_interrupt_type = {
        .name   =       "EISA",
        .unmask =       eisa_unmask_irq,
        .mask   =       eisa_mask_irq,
-       .ack    =       no_ack_irq,
 };
 
 static irqreturn_t eisa_irq(int wax_irq, void *intr_dev)
@@ -340,7 +339,7 @@ static int __init eisa_probe(struct parisc_device *dev)
        setup_irq(2, &irq2_action);
        for (i = 0; i < 16; i++) {
                set_irq_chip_and_handler(i, &eisa_interrupt_type,
-                       handle_level_irq);
+                                        handle_simple_irq);
        }
        
        EISA_bus = 1;
index e605298e3aeed606bbb2bf57c286fbdea1fc6a9a..772b1939ac218a2b9fc936ce57bc567761f050fc 100644 (file)
@@ -143,7 +143,6 @@ static struct irq_chip gsc_asic_interrupt_type = {
        .name   =       "GSC-ASIC",
        .unmask =       gsc_asic_unmask_irq,
        .mask   =       gsc_asic_mask_irq,
-       .ack    =       no_ack_irq,
 };
 
 int gsc_assign_irq(struct irq_chip *type, void *data)
@@ -153,7 +152,7 @@ int gsc_assign_irq(struct irq_chip *type, void *data)
        if (irq > GSC_IRQ_MAX)
                return NO_IRQ;
 
-       set_irq_chip_and_handler(irq, type, handle_level_irq);
+       set_irq_chip_and_handler(irq, type, handle_simple_irq);
        set_irq_chip_data(irq, data);
 
        return irq++;
index a3120a09c43dd603d9b96b0c5926e77ceebb8095..0327894bf2355c23d3e2b3daae80c8a2cadf7aeb 100644 (file)
@@ -669,6 +669,13 @@ printk("\n");
        DBG(KERN_DEBUG "enable_irq(%d): eoi(%p, 0x%x)\n", irq,
                        vi->eoi_addr, vi->eoi_data);
        iosapic_eoi(vi->eoi_addr, vi->eoi_data);
+}
+
+static void iosapic_eoi_irq(unsigned int irq)
+{
+       struct vector_info *vi = get_irq_chip_data(irq);
+
+       iosapic_eoi(vi->eoi_addr, vi->eoi_data);
        cpu_eoi_irq(irq);
 }
 
@@ -705,6 +712,7 @@ static struct irq_chip iosapic_interrupt_type = {
        .unmask =       iosapic_unmask_irq,
        .mask   =       iosapic_mask_irq,
        .ack    =       cpu_ack_irq,
+       .eoi    =       iosapic_eoi_irq,
 #ifdef CONFIG_SMP
        .set_affinity = iosapic_set_affinity_irq,
 #endif
index 2350e8a86eefe807eaa2be1c814e614a688f2ad0..f2f501e5b6a0cb644b636937506734e436c76283 100644 (file)
@@ -64,6 +64,7 @@ static unsigned int led_diskio    __read_mostly = 1;
 static unsigned int led_lanrxtx   __read_mostly = 1;
 static char lcd_text[32]          __read_mostly;
 static char lcd_text_default[32]  __read_mostly;
+static int  lcd_no_led_support    __read_mostly = 0; /* KittyHawk doesn't support LED on its LCD */
 
 
 static struct workqueue_struct *led_wq;
@@ -115,7 +116,7 @@ lcd_info __attribute__((aligned(8))) __read_mostly =
        .lcd_width =            16,
        .lcd_cmd_reg_addr =     KITTYHAWK_LCD_CMD,
        .lcd_data_reg_addr =    KITTYHAWK_LCD_DATA,
-       .min_cmd_delay =        40,
+       .min_cmd_delay =        80,
        .reset_cmd1 =           0x80,
        .reset_cmd2 =           0xc0,
 };
@@ -135,6 +136,9 @@ static int start_task(void)
        /* Display the default text now */
        if (led_type == LED_HASLCD) lcd_print( lcd_text_default );
 
+       /* KittyHawk has no LED support on its LCD */
+       if (lcd_no_led_support) return 0;
+
        /* Create the work queue and queue the LED task */
        led_wq = create_singlethread_workqueue("led_wq");       
        queue_delayed_work(led_wq, &led_task, 0);
@@ -248,9 +252,13 @@ static int __init led_create_procfs(void)
 
        proc_pdc_root = proc_mkdir("pdc", 0);
        if (!proc_pdc_root) return -1;
-       ent = proc_create_data("led", S_IRUGO|S_IWUSR, proc_pdc_root,
-                               &led_proc_fops, (void *)LED_NOLCD); /* LED */
-       if (!ent) return -1;
+
+       if (!lcd_no_led_support)
+       {
+               ent = proc_create_data("led", S_IRUGO|S_IWUSR, proc_pdc_root,
+                                       &led_proc_fops, (void *)LED_NOLCD); /* LED */
+               if (!ent) return -1;
+       }
 
        if (led_type == LED_HASLCD)
        {
@@ -692,6 +700,7 @@ int __init led_init(void)
        case 0x58B:             /* KittyHawk DC2 100 (K200) */
                printk(KERN_INFO "%s: KittyHawk-Machine (hversion 0x%x) found, "
                                "LED detection skipped.\n", __FILE__, CPU_HVERSION);
+               lcd_no_led_support = 1;
                goto found;     /* use the preinitialized values of lcd_info */
        }
 
index 0846dafdfff10a2f1536fad7393459c4a08b6af0..28241532c0fd1b56c7f6bfa50d788c5fef1e9e3a 100644 (file)
@@ -323,7 +323,6 @@ static struct irq_chip superio_interrupt_type = {
        .name   =       SUPERIO,
        .unmask =       superio_unmask_irq,
        .mask   =       superio_mask_irq,
-       .ack =          no_ack_irq,
 };
 
 #ifdef DEBUG_SUPERIO_INIT
@@ -354,7 +353,7 @@ int superio_fixup_irq(struct pci_dev *pcidev)
 #endif
 
        for (i = 0; i < 16; i++) {
-               set_irq_chip_and_handler(i, &superio_interrupt_type, handle_level_irq);
+               set_irq_chip_and_handler(i, &superio_interrupt_type, handle_simple_irq);
        }
 
        /*
index f01e344cf4bd673c059044698f50896836d26fad..98e6fdf34d30d136290a794a6b2a62b0764fdf5b 100644 (file)
@@ -49,6 +49,7 @@ obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
 obj-$(CONFIG_X86_VISWS) += setup-irq.o
 obj-$(CONFIG_MN10300) += setup-bus.o
 obj-$(CONFIG_MICROBLAZE) += setup-bus.o
+obj-$(CONFIG_TILE) += setup-bus.o setup-irq.o
 
 #
 # ACPI Related PCI FW Functions
index 003170ea2e394193bdcb7af4033a98bca9d46127..69546e9213dd7727d7b0db8f9cd56d1772ea7431 100644 (file)
@@ -64,77 +64,6 @@ void pci_bus_remove_resources(struct pci_bus *bus)
        }
 }
 
-static bool pci_bus_resource_better(struct resource *res1, bool pos1,
-                                   struct resource *res2, bool pos2)
-{
-       /* If exactly one is positive decode, always prefer that one */
-       if (pos1 != pos2)
-               return pos1 ? true : false;
-
-       /* Prefer the one that contains the highest address */
-       if (res1->end != res2->end)
-               return (res1->end > res2->end) ? true : false;
-
-       /* Otherwise, prefer the one with highest "center of gravity" */
-       if (res1->start != res2->start)
-               return (res1->start > res2->start) ? true : false;
-
-       /* Otherwise, choose one arbitrarily (but consistently) */
-       return (res1 > res2) ? true : false;
-}
-
-static bool pci_bus_resource_positive(struct pci_bus *bus, struct resource *res)
-{
-       struct pci_bus_resource *bus_res;
-
-       /*
-        * This relies on the fact that pci_bus.resource[] refers to P2P or
-        * CardBus bridge base/limit registers, which are always positively
-        * decoded.  The pci_bus.resources list contains host bridge or
-        * subtractively decoded resources.
-        */
-       list_for_each_entry(bus_res, &bus->resources, list) {
-               if (bus_res->res == res)
-                       return (bus_res->flags & PCI_SUBTRACTIVE_DECODE) ?
-                               false : true;
-       }
-       return true;
-}
-
-/*
- * Find the next-best bus resource after the cursor "res".  If the cursor is
- * NULL, return the best resource.  "Best" means that we prefer positive
- * decode regions over subtractive decode, then those at higher addresses.
- */
-static struct resource *pci_bus_find_resource_prev(struct pci_bus *bus,
-                                                  unsigned int type,
-                                                  struct resource *res)
-{
-       bool res_pos, r_pos, prev_pos = false;
-       struct resource *r, *prev = NULL;
-       int i;
-
-       res_pos = pci_bus_resource_positive(bus, res);
-       pci_bus_for_each_resource(bus, r, i) {
-               if (!r)
-                       continue;
-
-               if ((r->flags & IORESOURCE_TYPE_BITS) != type)
-                       continue;
-
-               r_pos = pci_bus_resource_positive(bus, r);
-               if (!res || pci_bus_resource_better(res, res_pos, r, r_pos)) {
-                       if (!prev || pci_bus_resource_better(r, r_pos,
-                                                            prev, prev_pos)) {
-                               prev = r;
-                               prev_pos = r_pos;
-                       }
-               }
-       }
-
-       return prev;
-}
-
 /**
  * pci_bus_alloc_resource - allocate a resource from a parent bus
  * @bus: PCI bus
@@ -160,10 +89,9 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
                                          resource_size_t),
                void *alignf_data)
 {
-       int ret = -ENOMEM;
+       int i, ret = -ENOMEM;
        struct resource *r;
        resource_size_t max = -1;
-       unsigned int type = res->flags & IORESOURCE_TYPE_BITS;
 
        type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
 
@@ -171,9 +99,10 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
        if (!(res->flags & IORESOURCE_MEM_64))
                max = PCIBIOS_MAX_MEM_32;
 
-       /* Look for space at highest addresses first */
-       r = pci_bus_find_resource_prev(bus, type, NULL);
-       for ( ; r; r = pci_bus_find_resource_prev(bus, type, r)) {
+       pci_bus_for_each_resource(bus, r, i) {
+               if (!r)
+                       continue;
+
                /* type_mask must match */
                if ((res->flags ^ r->flags) & type_mask)
                        continue;
index 0157708d474da57ad0532a3bb8bbbd90f0204aeb..09933eb9126be48f154e809bdcfdc57292a4858a 100644 (file)
@@ -1417,6 +1417,11 @@ int __init enable_drhd_fault_handling(void)
                               (unsigned long long)drhd->reg_base_addr, ret);
                        return -1;
                }
+
+               /*
+                * Clear any previous faults.
+                */
+               dmar_fault(iommu->irq, iommu);
        }
 
        return 0;
index f5c63fe9db5c5b6666001ae03a1a4c561c644986..53a786fd0d40c88d978bd4a656971be7b09cdb4a 100644 (file)
@@ -2136,6 +2136,24 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82865_HB,
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82875_HB,
                        quirk_unhide_mch_dev6);
 
+#ifdef CONFIG_TILE
+/*
+ * The Tilera TILEmpower platform needs to set the link speed
+ * to 2.5GT(Giga-Transfers)/s (Gen 1). The default link speed
+ * setting is 5GT/s (Gen 2). 0x98 is the Link Control2 PCIe
+ * capability register of the PEX8624 PCIe switch. The switch
+ * supports link speed auto negotiation, but falsely sets
+ * the link speed to 5GT/s.
+ */
+static void __devinit quirk_tile_plx_gen1(struct pci_dev *dev)
+{
+       if (tile_plx_gen1) {
+               pci_write_config_dword(dev, 0x98, 0x1);
+               mdelay(50);
+       }
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8624, quirk_tile_plx_gen1);
+#endif /* CONFIG_TILE */
 
 #ifdef CONFIG_PCI_MSI
 /* Some chipsets do not support MSI. We cannot easily rely on setting
@@ -2311,6 +2329,9 @@ static void __devinit nvbridge_check_legacy_irq_routing(struct pci_dev *dev)
 {
        u32 cfg;
 
+       if (!pci_find_capability(dev, PCI_CAP_ID_HT))
+               return;
+
        pci_read_config_dword(dev, 0x74, &cfg);
 
        if (cfg & ((1 << 2) | (1 << 15))) {
@@ -2746,6 +2767,29 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_m
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832);
 #endif /*CONFIG_MMC_RICOH_MMC*/
 
+#if defined(CONFIG_DMAR) || defined(CONFIG_INTR_REMAP)
+#define VTUNCERRMSK_REG        0x1ac
+#define VTD_MSK_SPEC_ERRORS    (1 << 31)
+/*
+ * This is a quirk for masking vt-d spec defined errors to platform error
+ * handling logic. With out this, platforms using Intel 7500, 5500 chipsets
+ * (and the derivative chipsets like X58 etc) seem to generate NMI/SMI (based
+ * on the RAS config settings of the platform) when a vt-d fault happens.
+ * The resulting SMI caused the system to hang.
+ *
+ * VT-d spec related errors are already handled by the VT-d OS code, so no
+ * need to report the same error through other channels.
+ */
+static void vtd_mask_spec_errors(struct pci_dev *dev)
+{
+       u32 word;
+
+       pci_read_config_dword(dev, VTUNCERRMSK_REG, &word);
+       pci_write_config_dword(dev, VTUNCERRMSK_REG, word | VTD_MSK_SPEC_ERRORS);
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x342e, vtd_mask_spec_errors);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x3c28, vtd_mask_spec_errors);
+#endif
 
 static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
                          struct pci_fixup *end)
index 3753fd0722e72383137d57e839b377721ad86c7a..2fe8cb8e95cd3409d74d04e312388736234c5d0c 100644 (file)
@@ -70,6 +70,7 @@ void soc_pcmcia_debug(struct soc_pcmcia_socket *skt, const char *func,
                va_end(args);
        }
 }
+EXPORT_SYMBOL(soc_pcmcia_debug);
 
 #endif
 
index 60a5a5c6b50ac7d6dfb4767163d30446ef03f80f..d235f44fd7a3ca96f61abb7d90249afa6eed1493 100644 (file)
@@ -81,6 +81,8 @@ MODULE_PARM_DESC(wapf, "WAPF value");
 
 static int wlan_status = 1;
 static int bluetooth_status = 1;
+static int wimax_status = -1;
+static int wwan_status = -1;
 
 module_param(wlan_status, int, 0444);
 MODULE_PARM_DESC(wlan_status, "Set the wireless status on boot "
@@ -92,6 +94,16 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
                 "(0 = disabled, 1 = enabled, -1 = don't do anything). "
                 "default is 1");
 
+module_param(wimax_status, int, 0444);
+MODULE_PARM_DESC(wimax_status, "Set the wireless status on boot "
+                "(0 = disabled, 1 = enabled, -1 = don't do anything). "
+                "default is 1");
+
+module_param(wwan_status, int, 0444);
+MODULE_PARM_DESC(wwan_status, "Set the wireless status on boot "
+                "(0 = disabled, 1 = enabled, -1 = don't do anything). "
+                "default is 1");
+
 /*
  * Some events we use, same for all Asus
  */
@@ -114,6 +126,8 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
  */
 #define WL_RSTS                0x01    /* internal Wifi */
 #define BT_RSTS                0x02    /* internal Bluetooth */
+#define WM_RSTS                0x08    /* internal wimax */
+#define WW_RSTS                0x20    /* internal wwan */
 
 /* LED */
 #define METHOD_MLED            "MLED"
@@ -132,6 +146,11 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
  */
 #define METHOD_WLAN            "WLED"
 #define METHOD_BLUETOOTH       "BLED"
+
+/* WWAN and WIMAX */
+#define METHOD_WWAN            "GSMC"
+#define METHOD_WIMAX           "WMXC"
+
 #define METHOD_WL_STATUS       "RSTS"
 
 /* Brightness */
@@ -882,6 +901,64 @@ static ssize_t store_bluetooth(struct device *dev,
        return sysfs_acpi_set(asus, buf, count, METHOD_BLUETOOTH);
 }
 
+/*
+ * Wimax
+ */
+static int asus_wimax_set(struct asus_laptop *asus, int status)
+{
+       if (write_acpi_int(asus->handle, METHOD_WIMAX, !!status)) {
+               pr_warning("Error setting wimax status to %d", status);
+               return -EIO;
+       }
+       return 0;
+}
+
+static ssize_t show_wimax(struct device *dev,
+                             struct device_attribute *attr, char *buf)
+{
+       struct asus_laptop *asus = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%d\n", asus_wireless_status(asus, WM_RSTS));
+}
+
+static ssize_t store_wimax(struct device *dev,
+                              struct device_attribute *attr, const char *buf,
+                              size_t count)
+{
+       struct asus_laptop *asus = dev_get_drvdata(dev);
+
+       return sysfs_acpi_set(asus, buf, count, METHOD_WIMAX);
+}
+
+/*
+ * Wwan
+ */
+static int asus_wwan_set(struct asus_laptop *asus, int status)
+{
+       if (write_acpi_int(asus->handle, METHOD_WWAN, !!status)) {
+               pr_warning("Error setting wwan status to %d", status);
+               return -EIO;
+       }
+       return 0;
+}
+
+static ssize_t show_wwan(struct device *dev,
+                             struct device_attribute *attr, char *buf)
+{
+       struct asus_laptop *asus = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%d\n", asus_wireless_status(asus, WW_RSTS));
+}
+
+static ssize_t store_wwan(struct device *dev,
+                              struct device_attribute *attr, const char *buf,
+                              size_t count)
+{
+       struct asus_laptop *asus = dev_get_drvdata(dev);
+
+       return sysfs_acpi_set(asus, buf, count, METHOD_WWAN);
+}
+
 /*
  * Display
  */
@@ -1202,6 +1279,8 @@ static DEVICE_ATTR(infos, S_IRUGO, show_infos, NULL);
 static DEVICE_ATTR(wlan, S_IRUGO | S_IWUSR, show_wlan, store_wlan);
 static DEVICE_ATTR(bluetooth, S_IRUGO | S_IWUSR,
                   show_bluetooth, store_bluetooth);
+static DEVICE_ATTR(wimax, S_IRUGO | S_IWUSR, show_wimax, store_wimax);
+static DEVICE_ATTR(wwan, S_IRUGO | S_IWUSR, show_wwan, store_wwan);
 static DEVICE_ATTR(display, S_IRUGO | S_IWUSR, show_disp, store_disp);
 static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd);
 static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl);
@@ -1212,6 +1291,8 @@ static struct attribute *asus_attributes[] = {
        &dev_attr_infos.attr,
        &dev_attr_wlan.attr,
        &dev_attr_bluetooth.attr,
+       &dev_attr_wimax.attr,
+       &dev_attr_wwan.attr,
        &dev_attr_display.attr,
        &dev_attr_ledd.attr,
        &dev_attr_ls_level.attr,
@@ -1239,6 +1320,13 @@ static mode_t asus_sysfs_is_visible(struct kobject *kobj,
        } else if (attr == &dev_attr_display.attr) {
                supported = !acpi_check_handle(handle, METHOD_SWITCH_DISPLAY, NULL);
 
+       } else if (attr == &dev_attr_wimax.attr) {
+               supported =
+                       !acpi_check_handle(asus->handle, METHOD_WIMAX, NULL);
+
+       } else if (attr == &dev_attr_wwan.attr) {
+               supported = !acpi_check_handle(asus->handle, METHOD_WWAN, NULL);
+
        } else if (attr == &dev_attr_ledd.attr) {
                supported = !acpi_check_handle(handle, METHOD_LEDD, NULL);
 
@@ -1397,7 +1485,8 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
 
        /*
         * The HWRS method return informations about the hardware.
-        * 0x80 bit is for WLAN, 0x100 for Bluetooth.
+        * 0x80 bit is for WLAN, 0x100 for Bluetooth,
+        * 0x40 for WWAN, 0x10 for WIMAX.
         * The significance of others is yet to be found.
         */
        status =
@@ -1440,6 +1529,12 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
        if (wlan_status >= 0)
                asus_wlan_set(asus, !!wlan_status);
 
+       if (wimax_status >= 0)
+               asus_wimax_set(asus, !!wimax_status);
+
+       if (wwan_status >= 0)
+               asus_wwan_set(asus, !!wwan_status);
+
        /* Keyboard Backlight is on by default */
        if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL))
                asus_kled_set(asus, 1);
index 462ceab93f87b84d59796a58ac90703a2ffaddee..0d50fbbe24784e86e3eef1522134ac585d6b6a2c 100644 (file)
@@ -298,8 +298,8 @@ static void eeepc_wmi_notify(u32 value, void *context)
        kfree(obj);
 }
 
-static int store_cpufv(struct device *dev, struct device_attribute *attr,
-                      const char *buf, size_t count)
+static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
+                          const char *buf, size_t count)
 {
        int value;
        struct acpi_buffer input = { (acpi_size)sizeof(value), &value };
index 1dac659b5e0c84e7bc3ccefea144d6a3dc88993c..9e05af9c41cbcd129bc3912c4bff2b6b8ad61b96 100644 (file)
@@ -172,6 +172,8 @@ static int hp_wmi_perform_query(int query, int write, u32 *buffer,
        bios_return = *((struct bios_return *)obj->buffer.pointer);
 
        memcpy(buffer, &bios_return.value, sizeof(bios_return.value));
+
+       kfree(obj);
        return 0;
 }
 
index 3c2c6b91ecb37eeb2f322e4e85c88626cd541a08..94a114aa8e286fd5fc91f97d8c7b416204c19ea2 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/io.h>
 #include <linux/sysdev.h>
 #include <linux/dmi.h>
+#include <linux/efi.h>
 #include <linux/mutex.h>
 #include <asm/bios_ebda.h>
 
@@ -220,32 +221,13 @@ static void rtl_teardown_sysfs(void) {
        sysdev_class_unregister(&class_rtl);
 }
 
-static int dmi_check_cb(const struct dmi_system_id *id)
-{
-       RTL_DEBUG("found IBM server '%s'\n", id->ident);
-       return 0;
-}
-
-#define ibm_dmi_entry(NAME, TYPE)                  \
-{                                                  \
-       .ident = NAME,                             \
-       .matches = {                               \
-               DMI_MATCH(DMI_SYS_VENDOR, "IBM"),  \
-               DMI_MATCH(DMI_PRODUCT_NAME, TYPE), \
-       },                                         \
-       .callback = dmi_check_cb                   \
-}
 
 static struct dmi_system_id __initdata ibm_rtl_dmi_table[] = {
-       ibm_dmi_entry("BladeCenter LS21", "7971"),
-       ibm_dmi_entry("BladeCenter LS22", "7901"),
-       ibm_dmi_entry("BladeCenter HS21 XM", "7995"),
-       ibm_dmi_entry("BladeCenter HS22", "7870"),
-       ibm_dmi_entry("BladeCenter HS22V", "7871"),
-       ibm_dmi_entry("System x3550 M2", "7946"),
-       ibm_dmi_entry("System x3650 M2", "7947"),
-       ibm_dmi_entry("System x3550 M3", "7944"),
-       ibm_dmi_entry("System x3650 M3", "7945"),
+       {                                                  \
+               .matches = {                               \
+                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),  \
+               },                                         \
+       },
        { }
 };
 
@@ -257,7 +239,7 @@ static int __init ibm_rtl_init(void) {
        if (force)
                pr_warning("ibm-rtl: module loaded by force\n");
        /* first ensure that we are running on IBM HW */
-       else if (!dmi_check_system(ibm_rtl_dmi_table))
+       else if (efi_enabled || !dmi_check_system(ibm_rtl_dmi_table))
                return -ENODEV;
 
        /* Get the address for the Extended BIOS Data Area */
@@ -302,7 +284,7 @@ static int __init ibm_rtl_init(void) {
                        RTL_DEBUG("rtl_cmd_width = %u, rtl_cmd_type = %u\n",
                              rtl_cmd_width, rtl_cmd_type);
                        addr = ioread32(&rtl_table->cmd_port_address);
-                       RTL_DEBUG("addr = %#llx\n", addr);
+                       RTL_DEBUG("addr = %#llx\n", (unsigned long long)addr);
                        plen = rtl_cmd_width/sizeof(char);
                        rtl_cmd_addr = rtl_port_map(addr, plen);
                        RTL_DEBUG("rtl_cmd_addr = %#llx\n", (u64)rtl_cmd_addr);
index 42a5469a2459d9cf35f7a014f93e977fa0463df5..35278ad7e628412754e9d8bcc1281cfbfd38c178 100644 (file)
@@ -43,16 +43,18 @@ MODULE_ALIAS("wmi:B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2");
 
 #define dprintk(msg...) pr_debug(DRV_PFX msg)
 
-#define KEYCODE_BASE 0xD0
-#define MSI_WMI_BRIGHTNESSUP   KEYCODE_BASE
-#define MSI_WMI_BRIGHTNESSDOWN (KEYCODE_BASE + 1)
-#define MSI_WMI_VOLUMEUP       (KEYCODE_BASE + 2)
-#define MSI_WMI_VOLUMEDOWN     (KEYCODE_BASE + 3)
+#define SCANCODE_BASE 0xD0
+#define MSI_WMI_BRIGHTNESSUP   SCANCODE_BASE
+#define MSI_WMI_BRIGHTNESSDOWN (SCANCODE_BASE + 1)
+#define MSI_WMI_VOLUMEUP       (SCANCODE_BASE + 2)
+#define MSI_WMI_VOLUMEDOWN     (SCANCODE_BASE + 3)
+#define MSI_WMI_MUTE           (SCANCODE_BASE + 4)
 static struct key_entry msi_wmi_keymap[] = {
        { KE_KEY, MSI_WMI_BRIGHTNESSUP,   {KEY_BRIGHTNESSUP} },
        { KE_KEY, MSI_WMI_BRIGHTNESSDOWN, {KEY_BRIGHTNESSDOWN} },
        { KE_KEY, MSI_WMI_VOLUMEUP,       {KEY_VOLUMEUP} },
        { KE_KEY, MSI_WMI_VOLUMEDOWN,     {KEY_VOLUMEDOWN} },
+       { KE_KEY, MSI_WMI_MUTE,           {KEY_MUTE} },
        { KE_END, 0}
 };
 static ktime_t last_pressed[ARRAY_SIZE(msi_wmi_keymap) - 1];
@@ -169,7 +171,7 @@ static void msi_wmi_notify(u32 value, void *context)
                        ktime_t diff;
                        cur = ktime_get_real();
                        diff = ktime_sub(cur, last_pressed[key->code -
-                                       KEYCODE_BASE]);
+                                       SCANCODE_BASE]);
                        /* Ignore event if the same event happened in a 50 ms
                           timeframe -> Key press may result in 10-20 GPEs */
                        if (ktime_to_us(diff) < 1000 * 50) {
@@ -178,7 +180,7 @@ static void msi_wmi_notify(u32 value, void *context)
                                         key->code, ktime_to_us(diff));
                                return;
                        }
-                       last_pressed[key->code - KEYCODE_BASE] = cur;
+                       last_pressed[key->code - SCANCODE_BASE] = cur;
 
                        if (key->type == KE_KEY &&
                        /* Brightness is served via acpi video driver */
index 2d61186ad5a2e96708fcec4beb0a8402eb2bc09f..e8c21994b36da2c1bb9eb71af883a597566f532c 100644 (file)
@@ -8497,7 +8497,6 @@ static void ibm_exit(struct ibm_struct *ibm)
                                           ibm->acpi->type,
                                           dispatch_acpi_notify);
                ibm->flags.acpi_notify_installed = 0;
-               ibm->flags.acpi_notify_installed = 0;
        }
 
        if (ibm->flags.proc_created) {
index 06f304f46e0229427e039180abb6731bceb403bd..4276da7291b8e479d26ee7a55041c212a85ca74a 100644 (file)
@@ -135,6 +135,7 @@ static const struct key_entry toshiba_acpi_keymap[] __initconst = {
        { KE_KEY, 0x141, { KEY_BRIGHTNESSUP } },
        { KE_KEY, 0x142, { KEY_WLAN } },
        { KE_KEY, 0x143, { KEY_PROG1 } },
+       { KE_KEY, 0x17f, { KEY_FN } },
        { KE_KEY, 0xb05, { KEY_PROG2 } },
        { KE_KEY, 0xb06, { KEY_WWW } },
        { KE_KEY, 0xb07, { KEY_MAIL } },
index 104b77c87ef5ae36e0c4502c6487e1fb3aac428e..aecd9a9b549f004d692976ce2a911644e2c56eb7 100644 (file)
@@ -755,7 +755,7 @@ static bool guid_already_parsed(const char *guid_string)
        struct wmi_block *wblock;
 
        list_for_each_entry(wblock, &wmi_block_list, list)
-               if (strncmp(wblock->gblock.guid, guid_string, 16) == 0)
+               if (memcmp(wblock->gblock.guid, guid_string, 16) == 0)
                        return true;
 
        return false;
index 2d73dfcecdbb4e2098e3d881a6a091a9e8ca5e62..57313f4658bc55a00a5a7d36fbb86450f8144def 100644 (file)
@@ -180,7 +180,7 @@ struct pnp_protocol pnpacpi_protocol = {
 };
 EXPORT_SYMBOL(pnpacpi_protocol);
 
-static char *pnpacpi_get_id(struct acpi_device *device)
+static char *__init pnpacpi_get_id(struct acpi_device *device)
 {
        struct acpi_hardware_id *id;
 
index f1d10c974cd43f3387467524822b93d0bd68742f..ba521f0f0fac634753cc79afe84c27c451a6bda7 100644 (file)
@@ -911,7 +911,7 @@ out:
 }
 
 /**
- * set_consumer_device_supply: Bind a regulator to a symbolic supply
+ * set_consumer_device_supply - Bind a regulator to a symbolic supply
  * @rdev:         regulator source
  * @consumer_dev: device the supply applies to
  * @consumer_dev_name: dev_name() string for device supply applies to
@@ -1052,7 +1052,6 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
                        printk(KERN_WARNING
                               "%s: could not add device link %s err %d\n",
                               __func__, dev->kobj.name, err);
-                       device_remove_file(dev, &regulator->dev_attr);
                        goto link_name_err;
                }
        }
@@ -1268,13 +1267,17 @@ static int _regulator_enable(struct regulator_dev *rdev)
 {
        int ret, delay;
 
-       /* do we need to enable the supply regulator first */
-       if (rdev->supply) {
-               ret = _regulator_enable(rdev->supply);
-               if (ret < 0) {
-                       printk(KERN_ERR "%s: failed to enable %s: %d\n",
-                              __func__, rdev_get_name(rdev), ret);
-                       return ret;
+       if (rdev->use_count == 0) {
+               /* do we need to enable the supply regulator first */
+               if (rdev->supply) {
+                       mutex_lock(&rdev->supply->mutex);
+                       ret = _regulator_enable(rdev->supply);
+                       mutex_unlock(&rdev->supply->mutex);
+                       if (ret < 0) {
+                               printk(KERN_ERR "%s: failed to enable %s: %d\n",
+                                      __func__, rdev_get_name(rdev), ret);
+                               return ret;
+                       }
                }
        }
 
@@ -1313,10 +1316,12 @@ static int _regulator_enable(struct regulator_dev *rdev)
                        if (ret < 0)
                                return ret;
 
-                       if (delay >= 1000)
+                       if (delay >= 1000) {
                                mdelay(delay / 1000);
-                       else if (delay)
+                               udelay(delay % 1000);
+                       } else if (delay) {
                                udelay(delay);
+                       }
 
                } else if (ret < 0) {
                        printk(KERN_ERR "%s: is_enabled() failed for %s: %d\n",
@@ -1359,6 +1364,7 @@ static int _regulator_disable(struct regulator_dev *rdev,
                struct regulator_dev **supply_rdev_ptr)
 {
        int ret = 0;
+       *supply_rdev_ptr = NULL;
 
        if (WARN(rdev->use_count <= 0,
                        "unbalanced disables for %s\n",
@@ -2346,6 +2352,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
        if (init_data->supply_regulator && init_data->supply_regulator_dev) {
                dev_err(dev,
                        "Supply regulator specified by both name and dev\n");
+               ret = -EINVAL;
                goto scrub;
        }
 
@@ -2364,6 +2371,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
                if (!found) {
                        dev_err(dev, "Failed to find supply %s\n",
                                init_data->supply_regulator);
+                       ret = -ENODEV;
                        goto scrub;
                }
 
index 4597d508a229efe5bb12a985955ebb71931e3ee4..ecd99f59dba879f8d659845fef26875cf218ff70 100644 (file)
@@ -465,8 +465,8 @@ static struct regulator_ops mc13783_fixed_regulator_ops = {
        .get_voltage = mc13783_fixed_regulator_get_voltage,
 };
 
-int mc13783_powermisc_rmw(struct mc13783_regulator_priv *priv, u32 mask,
-                                                                       u32 val)
+static int mc13783_powermisc_rmw(struct mc13783_regulator_priv *priv, u32 mask,
+                                u32 val)
 {
        struct mc13783 *mc13783 = priv->mc13783;
        int ret;
index 51237fbb1bbb7e15f952296a9ffcb9f668418fc9..6d20b0454a1d7284c7728e3ec0c85d7d8e22f452 100644 (file)
@@ -231,8 +231,7 @@ static int tps6586x_dvm_voltages[] = {
 };
 
 #define TPS6586X_REGULATOR(_id, vdata, _ops, vreg, shift, nbits,       \
-                          ereg0, ebit0, ereg1, ebit1, goreg, gobit)    \
-{                                                                      \
+                          ereg0, ebit0, ereg1, ebit1)                  \
        .desc   = {                                                     \
                .name   = "REG-" #_id,                                  \
                .ops    = &tps6586x_regulator_##_ops,                   \
@@ -248,18 +247,26 @@ static int tps6586x_dvm_voltages[] = {
        .enable_bit[0]  = (ebit0),                                      \
        .enable_reg[1]  = TPS6586X_SUPPLY##ereg1,                       \
        .enable_bit[1]  = (ebit1),                                      \
-       .voltages       = tps6586x_##vdata##_voltages,                  \
-}
+       .voltages       = tps6586x_##vdata##_voltages,
+
+#define TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit)                     \
+       .go_reg = TPS6586X_##goreg,                                     \
+       .go_bit = (gobit),
 
 #define TPS6586X_LDO(_id, vdata, vreg, shift, nbits,                   \
                     ereg0, ebit0, ereg1, ebit1)                        \
+{                                                                      \
        TPS6586X_REGULATOR(_id, vdata, ldo_ops, vreg, shift, nbits,     \
-                          ereg0, ebit0, ereg1, ebit1, 0, 0)
+                          ereg0, ebit0, ereg1, ebit1)                  \
+}
 
 #define TPS6586X_DVM(_id, vdata, vreg, shift, nbits,                   \
                     ereg0, ebit0, ereg1, ebit1, goreg, gobit)          \
+{                                                                      \
        TPS6586X_REGULATOR(_id, vdata, dvm_ops, vreg, shift, nbits,     \
-                          ereg0, ebit0, ereg1, ebit1, goreg, gobit)
+                          ereg0, ebit0, ereg1, ebit1)                  \
+       TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit)                      \
+}
 
 static struct tps6586x_regulator tps6586x_regulator[] = {
        TPS6586X_LDO(LDO_0, ldo, SUPPLYV1, 5, 3, ENC, 0, END, 0),
@@ -267,11 +274,11 @@ static struct tps6586x_regulator tps6586x_regulator[] = {
        TPS6586X_LDO(LDO_5, ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6),
        TPS6586X_LDO(LDO_6, ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4),
        TPS6586X_LDO(LDO_7, ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5),
-       TPS6586X_LDO(LDO_8, ldo, SUPPLYV1, 5, 3, ENC, 6, END, 6),
+       TPS6586X_LDO(LDO_8, ldo, SUPPLYV2, 5, 3, ENC, 6, END, 6),
        TPS6586X_LDO(LDO_9, ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7),
-       TPS6586X_LDO(LDO_RTC, ldo, SUPPLYV4, 3, 3, ENE, 7, ENE, 7),
+       TPS6586X_LDO(LDO_RTC, ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7),
        TPS6586X_LDO(LDO_1, dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1),
-       TPS6586X_LDO(SM_2, sm2, SUPPLYV2, 0, 5, ENC, 1, END, 1),
+       TPS6586X_LDO(SM_2, sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7),
 
        TPS6586X_DVM(LDO_2, dvm, LDO2BV1, 0, 5, ENA, 3, ENB, 3, VCC2, 6),
        TPS6586X_DVM(LDO_4, ldo4, LDO4V1, 0, 5, ENC, 3, END, 3, VCC1, 6),
@@ -290,6 +297,10 @@ static inline int tps6586x_regulator_preinit(struct device *parent,
        uint8_t val1, val2;
        int ret;
 
+       if (ri->enable_reg[0] == ri->enable_reg[1] &&
+           ri->enable_bit[0] == ri->enable_bit[1])
+                       return 0;
+
        ret = tps6586x_read(parent, ri->enable_reg[0], &val1);
        if (ret)
                return ret;
@@ -298,14 +309,14 @@ static inline int tps6586x_regulator_preinit(struct device *parent,
        if (ret)
                return ret;
 
-       if (!(val2 & ri->enable_bit[1]))
+       if (!(val2 & (1 << ri->enable_bit[1])))
                return 0;
 
        /*
         * The regulator is on, but it's enabled with the bit we don't
         * want to use, so we switch the enable bits
         */
-       if (!(val1 & ri->enable_bit[0])) {
+       if (!(val1 & (1 << ri->enable_bit[0]))) {
                ret = tps6586x_set_bits(parent, ri->enable_reg[0],
                                        1 << ri->enable_bit[0]);
                if (ret)
index 7e5892efc4375d06b5bb2a15426f3abe95a29fba..a57262a4fa6c7a00e8aeb63f9a512ce0f83583b1 100644 (file)
@@ -219,12 +219,12 @@ static int twlreg_set_mode(struct regulator_dev *rdev, unsigned mode)
                return -EACCES;
 
        status = twl_i2c_write_u8(TWL_MODULE_PM_MASTER,
-                       message >> 8, 0x15 /* PB_WORD_MSB */ );
-       if (status >= 0)
+                       message >> 8, TWL4030_PM_MASTER_PB_WORD_MSB);
+       if (status < 0)
                return status;
 
        return twl_i2c_write_u8(TWL_MODULE_PM_MASTER,
-                       message, 0x16 /* PB_WORD_LSB */ );
+                       message & 0xff, TWL4030_PM_MASTER_PB_WORD_LSB);
 }
 
 /*----------------------------------------------------------------------*/
index a5050e2171504043d48e9aeaa78dc4dffc9536ac..825951b6b83f438a002102f372a90342b624be6f 100644 (file)
@@ -635,7 +635,7 @@ static void css_process_crw(struct crw *crw0, struct crw *crw1, int overflow)
        init_subchannel_id(&mchk_schid);
        mchk_schid.sch_no = crw0->rsid;
        if (crw1)
-               mchk_schid.ssid = (crw1->rsid >> 8) & 3;
+               mchk_schid.ssid = (crw1->rsid >> 4) & 3;
 
        /*
         * Since we are always presented with IPI in the CRW, we have to
index 752dbee06af582a4c2ac8481cb079658579bfcaa..5d9c66627b6eb7554b63bda327ce62ace37bc590 100644 (file)
@@ -292,8 +292,8 @@ void qdio_shutdown_thinint(struct qdio_irq *irq_ptr)
                return;
 
        /* reset adapter interrupt indicators */
-       put_indicator(irq_ptr->dsci);
        set_subchannel_ind(irq_ptr, 1);
+       put_indicator(irq_ptr->dsci);
 }
 
 void __exit tiqdio_unregister_thinints(void)
index d37c7331f244f1463c154a05ec9649306fe0c358..0bcd5806bd9a616df1f919f77c7e6a741e44533e 100644 (file)
@@ -156,6 +156,8 @@ static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter,
                if (!(a_status & ZFCP_STATUS_COMMON_RUNNING) ||
                      a_status & ZFCP_STATUS_COMMON_ERP_FAILED)
                        return 0;
+               if (p_status & ZFCP_STATUS_COMMON_NOESC)
+                       return need;
                if (!(a_status & ZFCP_STATUS_COMMON_UNBLOCKED))
                        need = ZFCP_ERP_ACTION_REOPEN_ADAPTER;
                /* fall through */
@@ -188,6 +190,9 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
                atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
                                &zfcp_sdev->status);
                erp_action = &zfcp_sdev->erp_action;
+               memset(erp_action, 0, sizeof(struct zfcp_erp_action));
+               erp_action->port = port;
+               erp_action->sdev = sdev;
                if (!(atomic_read(&zfcp_sdev->status) &
                      ZFCP_STATUS_COMMON_RUNNING))
                        act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
@@ -200,6 +205,8 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
                zfcp_erp_action_dismiss_port(port);
                atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status);
                erp_action = &port->erp_action;
+               memset(erp_action, 0, sizeof(struct zfcp_erp_action));
+               erp_action->port = port;
                if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING))
                        act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
                break;
@@ -209,6 +216,7 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
                zfcp_erp_action_dismiss_adapter(adapter);
                atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status);
                erp_action = &adapter->erp_action;
+               memset(erp_action, 0, sizeof(struct zfcp_erp_action));
                if (!(atomic_read(&adapter->status) &
                      ZFCP_STATUS_COMMON_RUNNING))
                        act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
@@ -218,10 +226,7 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
                return NULL;
        }
 
-       memset(erp_action, 0, sizeof(struct zfcp_erp_action));
        erp_action->adapter = adapter;
-       erp_action->port = port;
-       erp_action->sdev = sdev;
        erp_action->action = need;
        erp_action->status = act_status;
 
index be0317457147fc4a891f4b0be67c8116b98526b1..2eb7dd56ab800af62da15d6a4cde42f2caf6177f 100644 (file)
@@ -851,7 +851,7 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *scmnd)
 
        zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
-       req->data = zfcp_sdev;
+       req->data = sdev;
        req->handler = zfcp_fsf_abort_fcp_command_handler;
        req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
        req->qtcb->header.port_handle = zfcp_sdev->port->handle;
@@ -2069,8 +2069,6 @@ static void zfcp_fsf_fcp_cmnd_handler(struct zfcp_fsf_req *req)
        struct fcp_resp_with_ext *fcp_rsp;
        unsigned long flags;
 
-       zfcp_fsf_fcp_handler_common(req);
-
        read_lock_irqsave(&req->adapter->abort_lock, flags);
 
        scpnt = req->data;
@@ -2079,6 +2077,8 @@ static void zfcp_fsf_fcp_cmnd_handler(struct zfcp_fsf_req *req)
                return;
        }
 
+       zfcp_fsf_fcp_handler_common(req);
+
        if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
                set_host_byte(scpnt, DID_TRANSPORT_DISRUPTED);
                goto skip_fsfstatus;
@@ -2170,12 +2170,13 @@ int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
        struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
        struct zfcp_qdio *qdio = adapter->qdio;
        struct fsf_qtcb_bottom_io *io;
+       unsigned long flags;
 
        if (unlikely(!(atomic_read(&zfcp_sdev->status) &
                       ZFCP_STATUS_COMMON_UNBLOCKED)))
                return -EBUSY;
 
-       spin_lock(&qdio->req_q_lock);
+       spin_lock_irqsave(&qdio->req_q_lock, flags);
        if (atomic_read(&qdio->req_q_free) <= 0) {
                atomic_inc(&qdio->req_q_full);
                goto out;
@@ -2239,7 +2240,7 @@ failed_scsi_cmnd:
        zfcp_fsf_req_free(req);
        scsi_cmnd->host_scribble = NULL;
 out:
-       spin_unlock(&qdio->req_q_lock);
+       spin_unlock_irqrestore(&qdio->req_q_lock, flags);
        return retval;
 }
 
index 6bd2dbc4c31606d5019fb1e76d92ef88583a2140..63529ed801eb3e4a37c768f1b55851863b60e9cb 100644 (file)
@@ -76,8 +76,8 @@ static void zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result)
        scpnt->scsi_done(scpnt);
 }
 
-static int zfcp_scsi_queuecommand_lck(struct scsi_cmnd *scpnt,
-                                 void (*done) (struct scsi_cmnd *))
+static
+int zfcp_scsi_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scpnt)
 {
        struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
        struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
@@ -87,7 +87,6 @@ static int zfcp_scsi_queuecommand_lck(struct scsi_cmnd *scpnt,
        /* reset the status for this request */
        scpnt->result = 0;
        scpnt->host_scribble = NULL;
-       scpnt->scsi_done = done;
 
        scsi_result = fc_remote_port_chkready(rport);
        if (unlikely(scsi_result)) {
@@ -127,8 +126,6 @@ static int zfcp_scsi_queuecommand_lck(struct scsi_cmnd *scpnt,
        return ret;
 }
 
-static DEF_SCSI_QCMD(zfcp_scsi_queuecommand)
-
 static int zfcp_scsi_slave_alloc(struct scsi_device *sdev)
 {
        struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
index 377cfb72cc66ade722b441f6842c1f0ed3d7fc3b..f30f8d659dc4d47ef70d6e9be3b59f6a44dde00a 100644 (file)
@@ -345,7 +345,7 @@ extern int fas216_queue_command(struct Scsi_Host *h, struct scsi_cmnd *SCpnt);
  *        : SCpnt - Command to queue
  * Returns : 0 - success, else error
  */
-extern int fas216_noqueue_command(struct Scsi_Host *, struct scsi_cmnd *)
+extern int fas216_noqueue_command(struct Scsi_Host *, struct scsi_cmnd *);
 
 /* Function: irqreturn_t fas216_intr (FAS216_Info *info)
  * Purpose : handle interrupts from the interface to progress a command
index b2fb2b2a6e700e86d7de265503b70cb48830d994..a6dea08664fc638c611260cbdd067978fb8b8092 100644 (file)
@@ -90,11 +90,7 @@ static const struct pci_device_id hpsa_pci_device_id[] = {
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3252},
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3253},
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3254},
-#define PCI_DEVICE_ID_HP_CISSF 0x333f
-       {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSF,     0x103C, 0x333F},
-       {PCI_VENDOR_ID_HP,     PCI_ANY_ID,             PCI_ANY_ID, PCI_ANY_ID,
-               PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
-       {PCI_VENDOR_ID_COMPAQ,     PCI_ANY_ID,             PCI_ANY_ID, PCI_ANY_ID,
+       {PCI_VENDOR_ID_HP,     PCI_ANY_ID,      PCI_ANY_ID, PCI_ANY_ID,
                PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
        {0,}
 };
@@ -113,8 +109,6 @@ static struct board_type products[] = {
        {0x3249103C, "Smart Array P812", &SA5_access},
        {0x324a103C, "Smart Array P712m", &SA5_access},
        {0x324b103C, "Smart Array P711m", &SA5_access},
-       {0x3233103C, "StorageWorks P1210m", &SA5_access},
-       {0x333F103C, "StorageWorks P1210m", &SA5_access},
        {0x3250103C, "Smart Array", &SA5_access},
        {0x3250113C, "Smart Array", &SA5_access},
        {0x3250123C, "Smart Array", &SA5_access},
index 0433ea6f27c9c2db97c464ca238afce39ebd0fcb..b37c8a3c1bb0de6d1b64fdf9ea3cbb8357f13805 100644 (file)
@@ -951,8 +951,8 @@ static int _osd_req_finalize_cdb_cont(struct osd_request *or, const u8 *cap_key)
        /* create a bio for continuation segment */
        bio = bio_map_kern(req_q, or->cdb_cont.buff, or->cdb_cont.total_bytes,
                           GFP_KERNEL);
-       if (unlikely(!bio))
-               return -ENOMEM;
+       if (IS_ERR(bio))
+               return PTR_ERR(bio);
 
        bio->bi_rw |= REQ_WRITE;
 
index 5e76a624cb08a843d194e7102900dfac77c2aae4..300d59f389da76175ac4720fc2d9a69b0a16b163 100644 (file)
@@ -62,6 +62,7 @@
 static unsigned int pmcraid_debug_log;
 static unsigned int pmcraid_disable_aen;
 static unsigned int pmcraid_log_level = IOASC_LOG_LEVEL_MUST;
+static unsigned int pmcraid_enable_msix;
 
 /*
  * Data structures to support multiple adapters by the LLD.
@@ -4691,7 +4692,8 @@ pmcraid_register_interrupt_handler(struct pmcraid_instance *pinstance)
        int rc;
        struct pci_dev *pdev = pinstance->pdev;
 
-       if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) {
+       if ((pmcraid_enable_msix) &&
+               (pci_find_capability(pdev, PCI_CAP_ID_MSIX))) {
                int num_hrrq = PMCRAID_NUM_MSIX_VECTORS;
                struct msix_entry entries[PMCRAID_NUM_MSIX_VECTORS];
                int i;
index 1134279604e805780f84607c523bbdd647685f24..4db210d93947275efd67e493549d75162fdf21e1 100644 (file)
@@ -42,7 +42,7 @@
  */
 #define PMCRAID_DRIVER_NAME            "PMC MaxRAID"
 #define PMCRAID_DEVFILE                        "pmcsas"
-#define PMCRAID_DRIVER_VERSION         "2.0.3"
+#define PMCRAID_DRIVER_VERSION         "1.0.3"
 #define PMCRAID_DRIVER_DATE            __DATE__
 
 #define PMCRAID_FW_VERSION_1           0x002
@@ -333,11 +333,9 @@ struct pmcraid_config_table_entry {
        __u8  lun[PMCRAID_LUN_LEN];
 } __attribute__((packed, aligned(4)));
 
-/* extended configuration table sizes are of 64 bytes in size */
-#define PMCRAID_CFGTE_EXT_SIZE 32
+/* extended configuration table sizes are also of 32 bytes in size */
 struct pmcraid_config_table_entry_ext {
        struct pmcraid_config_table_entry cfgte;
-       __u8  cfgte_ext[PMCRAID_CFGTE_EXT_SIZE];
 };
 
 /* resource types (config_table_entry.resource_type values) */
index 3a22effced5fa1a94996582b9fd13ccf151d8861..9ce539d4557e2a18d495ec2a31366cf5ebccc4aa 100644 (file)
@@ -2409,7 +2409,6 @@ struct qla_hw_data {
                uint32_t        enable_target_reset     :1;
                uint32_t        enable_lip_full_login   :1;
                uint32_t        enable_led_scheme       :1;
-               uint32_t        inta_enabled            :1;
                uint32_t        msi_enabled             :1;
                uint32_t        msix_enabled            :1;
                uint32_t        disable_serdes          :1;
index 5f94430b42f03974fda76e9f1f969cedbf3e9047..4c1ba6263eb32c1a228f2044b314c4e902f1c677 100644 (file)
@@ -1061,6 +1061,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
                fcp_cmnd->additional_cdb_len |= 2;
 
        int_to_scsilun(sp->cmd->device->lun, &fcp_cmnd->lun);
+       host_to_fcp_swap((uint8_t *)&fcp_cmnd->lun, sizeof(fcp_cmnd->lun));
        memcpy(fcp_cmnd->cdb, cmd->cmnd, cmd->cmd_len);
        cmd_pkt->fcp_cmnd_dseg_len = cpu_to_le16(fcp_cmnd_len);
        cmd_pkt->fcp_cmnd_dseg_address[0] = cpu_to_le32(
index 1f06ddd9bdd10cdbe6526de1deaaab194a19118e..7f77898486a9014f1e4848e77648f78c5dce1c75 100644 (file)
@@ -2491,14 +2491,15 @@ skip_msix:
 skip_msi:
 
        ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler,
-           IRQF_SHARED, QLA2XXX_DRIVER_NAME, rsp);
+           ha->flags.msi_enabled ? 0 : IRQF_SHARED,
+           QLA2XXX_DRIVER_NAME, rsp);
        if (ret) {
                qla_printk(KERN_WARNING, ha,
                    "Failed to reserve interrupt %d already in use.\n",
                    ha->pdev->irq);
                goto fail;
        }
-       ha->flags.inta_enabled = 1;
+
 clear_risc_ints:
 
        /*
index 8d9edfb39803ff26809743ef8cf5e0b22abd305b..ae2acacc00036558c5ddb0e246e8b691097c80ca 100644 (file)
@@ -2749,6 +2749,7 @@ sufficient_dsds:
                        goto queuing_error_fcp_cmnd;
 
                int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun);
+               host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun));
 
                /* build FCP_CMND IU */
                memset(ctx->fcp_cmnd, 0, sizeof(struct fcp_cmnd));
index 1644eabaafeb58cb3130dccdb97b489bcd0c708e..2c0876c81a3f6e5793d504b825146b6de7c2ae81 100644 (file)
@@ -829,7 +829,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
 {
        scsi_qla_host_t *vha = shost_priv(cmd->device->host);
        srb_t *sp;
-       int ret;
+       int ret = SUCCESS;
        unsigned int id, lun;
        unsigned long flags;
        int wait = 0;
@@ -2064,6 +2064,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
                ha->init_cb_size = sizeof(struct mid_init_cb_81xx);
                ha->gid_list_info_size = 8;
                ha->optrom_size = OPTROM_SIZE_82XX;
+               ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX;
                ha->isp_ops = &qla82xx_isp_ops;
                ha->flash_conf_off = FARX_ACCESS_FLASH_CONF;
                ha->flash_data_off = FARX_ACCESS_FLASH_DATA;
index 8edbccb3232d3b68cb16d0054a444e657a452975..cf0075a2d0c2e66d93146bd92d95a5811f021327 100644 (file)
@@ -7,9 +7,9 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.03.04-k0"
+#define QLA2XXX_VERSION      "8.03.05-k0"
 
 #define QLA_DRIVER_MAJOR_VER   8
 #define QLA_DRIVER_MINOR_VER   3
-#define QLA_DRIVER_PATCH_VER   4
+#define QLA_DRIVER_PATCH_VER   5
 #define QLA_DRIVER_BETA_VER    0
index 824b8fc03ce52f087dd3ca4d0fdadab15dfcac17..30ac116186f5106f61415cbdd9ee0b67a3f3b88e 100644 (file)
@@ -615,7 +615,7 @@ static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
        return rtn;
 }
 
-static int __scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
+static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
 {
        if (!scmd->device->host->hostt->eh_abort_handler)
                return FAILED;
@@ -623,31 +623,9 @@ static int __scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
        return scmd->device->host->hostt->eh_abort_handler(scmd);
 }
 
-/**
- * scsi_try_to_abort_cmd - Ask host to abort a running command.
- * @scmd:      SCSI cmd to abort from Lower Level.
- *
- * Notes:
- *    This function will not return until the user's completion function
- *    has been called.  there is no timeout on this operation.  if the
- *    author of the low-level driver wishes this operation to be timed,
- *    they can provide this facility themselves.  helper functions in
- *    scsi_error.c can be supplied to make this easier to do.
- */
-static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
-{
-       /*
-        * scsi_done was called just after the command timed out and before
-        * we had a chance to process it. (db)
-        */
-       if (scmd->serial_number == 0)
-               return SUCCESS;
-       return __scsi_try_to_abort_cmd(scmd);
-}
-
 static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
 {
-       if (__scsi_try_to_abort_cmd(scmd) != SUCCESS)
+       if (scsi_try_to_abort_cmd(scmd) != SUCCESS)
                if (scsi_try_bus_device_reset(scmd) != SUCCESS)
                        if (scsi_try_target_reset(scmd) != SUCCESS)
                                if (scsi_try_bus_reset(scmd) != SUCCESS)
index eafeeda6e1942b7deda691f940c0f10efddee390..4a3842212c5062811c7973413e4d7aec62679951 100644 (file)
@@ -1403,11 +1403,6 @@ static void scsi_softirq_done(struct request *rq)
 
        INIT_LIST_HEAD(&cmd->eh_entry);
 
-       /*
-        * Set the serial numbers back to zero
-        */
-       cmd->serial_number = 0;
-
        atomic_inc(&cmd->device->iodone_cnt);
        if (cmd->result)
                atomic_inc(&cmd->device->ioerr_cnt);
@@ -1642,9 +1637,8 @@ struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost,
 
        blk_queue_max_segment_size(q, dma_get_max_seg_size(dev));
 
-       /* New queue, no concurrency on queue_flags */
        if (!shost->use_clustering)
-               queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q);
+               q->limits.cluster = 0;
 
        /*
         * set a reasonable default alignment on word boundaries: the
index 4d8e14b7aa931bcf3de11c6e5805005e0bf413ca..09a550860dcf7acc702523319332972ed02f7249 100644 (file)
@@ -2872,7 +2872,7 @@ static struct console serial8250_console = {
        .device         = uart_console_device,
        .setup          = serial8250_console_setup,
        .early_setup    = serial8250_console_early_setup,
-       .flags          = CON_PRINTBUFFER,
+       .flags          = CON_PRINTBUFFER | CON_ANYTIME,
        .index          = -1,
        .data           = &serial8250_reg,
 };
index 3374618300af87c16ac3ef6a674e9cb650e62f8c..25a8bc565f400b62c155dd31bb39ff08e8d85dd0 100644 (file)
@@ -90,7 +90,8 @@ static DECLARE_WORK(kgdboc_restore_input_work, kgdboc_restore_input_helper);
 
 static void kgdboc_restore_input(void)
 {
-       schedule_work(&kgdboc_restore_input_work);
+       if (likely(system_state == SYSTEM_RUNNING))
+               schedule_work(&kgdboc_restore_input_work);
 }
 
 static int kgdboc_register_kbd(char **cptr)
index 5fc699e929dc50dff6601c3b00a2762c1f673a1f..d40010a22ecd788e6d90c69337333c7bed0bfc7b 100644 (file)
@@ -900,8 +900,7 @@ serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios,
        unsigned char cval, fcr = 0;
        unsigned long flags;
        unsigned int baud, quot;
-       u32 mul = 0x3600;
-       u32 ps = 0x10;
+       u32 ps, mul;
 
        switch (termios->c_cflag & CSIZE) {
        case CS5:
@@ -943,31 +942,24 @@ serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios,
        baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
 
        quot = 1;
+       ps = 0x10;
+       mul = 0x3600;
        switch (baud) {
        case 3500000:
                mul = 0x3345;
                ps = 0xC;
                break;
-       case 3000000:
-               mul = 0x2EE0;
-               break;
-       case 2500000:
-               mul = 0x2710;
-               break;
-       case 2000000:
-               mul = 0x1F40;
-               break;
        case 1843200:
                mul = 0x2400;
                break;
+       case 3000000:
+       case 2500000:
+       case 2000000:
        case 1500000:
-               mul = 0x1770;
-               break;
        case 1000000:
-               mul = 0xFA0;
-               break;
        case 500000:
-               mul = 0x7D0;
+               /* mul/ps/quot = 0x9C4/0x10/0x1 will make a 500000 bps */
+               mul = baud / 500000 * 0x9C4;
                break;
        default:
                /* Use uart_get_divisor to get quot for other baud rates */
index cb12a8e1466b3d8cfe2ad13833d150eaaca90bc3..3f5e387ed56486ba5c454f4a809a9a57d84d80d5 100644 (file)
@@ -418,8 +418,11 @@ int clk_register(struct clk *clk)
                list_add(&clk->sibling, &root_clks);
 
        list_add(&clk->node, &clock_list);
+
+#ifdef CONFIG_SH_CLK_CPG_LEGACY
        if (clk->ops && clk->ops->init)
                clk->ops->init(clk);
+#endif
 
 out_unlock:
        mutex_unlock(&clock_list_sem);
@@ -454,12 +457,6 @@ unsigned long clk_get_rate(struct clk *clk)
 EXPORT_SYMBOL_GPL(clk_get_rate);
 
 int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-       return clk_set_rate_ex(clk, rate, 0);
-}
-EXPORT_SYMBOL_GPL(clk_set_rate);
-
-int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id)
 {
        int ret = -EOPNOTSUPP;
        unsigned long flags;
@@ -467,7 +464,7 @@ int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id)
        spin_lock_irqsave(&clock_lock, flags);
 
        if (likely(clk->ops && clk->ops->set_rate)) {
-               ret = clk->ops->set_rate(clk, rate, algo_id);
+               ret = clk->ops->set_rate(clk, rate);
                if (ret != 0)
                        goto out_unlock;
        } else {
@@ -485,7 +482,7 @@ out_unlock:
 
        return ret;
 }
-EXPORT_SYMBOL_GPL(clk_set_rate_ex);
+EXPORT_SYMBOL_GPL(clk_set_rate);
 
 int clk_set_parent(struct clk *clk, struct clk *parent)
 {
@@ -653,8 +650,7 @@ static int clks_sysdev_suspend(struct sys_device *dev, pm_message_t state)
                                        clkp->ops->set_parent(clkp,
                                                clkp->parent);
                                if (likely(clkp->ops->set_rate))
-                                       clkp->ops->set_rate(clkp,
-                                               rate, NO_CHANGE);
+                                       clkp->ops->set_rate(clkp, rate);
                                else if (likely(clkp->ops->recalc))
                                        clkp->rate = clkp->ops->recalc(clkp);
                        }
index 3aea5f0ceb09ebd3f5e3b59ae5b04128862afc9c..6172335ae3234b11d2bd37e4b57dad3c9061278c 100644 (file)
@@ -110,8 +110,7 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
        return 0;
 }
 
-static int sh_clk_div6_set_rate(struct clk *clk,
-                               unsigned long rate, int algo_id)
+static int sh_clk_div6_set_rate(struct clk *clk, unsigned long rate)
 {
        unsigned long value;
        int idx;
@@ -132,7 +131,7 @@ static int sh_clk_div6_enable(struct clk *clk)
        unsigned long value;
        int ret;
 
-       ret = sh_clk_div6_set_rate(clk, clk->rate, 0);
+       ret = sh_clk_div6_set_rate(clk, clk->rate);
        if (ret == 0) {
                value = __raw_readl(clk->enable_reg);
                value &= ~0x100; /* clear stop bit to enable clock */
@@ -253,7 +252,7 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
        return 0;
 }
 
-static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate, int algo_id)
+static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
 {
        struct clk_div4_table *d4t = clk->priv;
        unsigned long value;
index 154529aacc037e332b005c418659089d80d5c9c5..a067046c9da288b368fecc1aee31aa4cef32c2b7 100644 (file)
@@ -352,8 +352,12 @@ atmel_spi_dma_map_xfer(struct atmel_spi *as, struct spi_transfer *xfer)
 
        xfer->tx_dma = xfer->rx_dma = INVALID_DMA_ADDRESS;
        if (xfer->tx_buf) {
+               /* tx_buf is a const void* where we need a void * for the dma
+                * mapping */
+               void *nonconst_tx = (void *)xfer->tx_buf;
+
                xfer->tx_dma = dma_map_single(dev,
-                               (void *) xfer->tx_buf, xfer->len,
+                               nonconst_tx, xfer->len,
                                DMA_TO_DEVICE);
                if (dma_mapping_error(dev, xfer->tx_dma))
                        return -ENOMEM;
index 90439314cf673ce19c33747ab4f283f0f3f0bc01..0838c79861e49f9a0c97189af9ab25d3c0269b76 100644 (file)
@@ -413,6 +413,11 @@ static void poll_transfer(struct dw_spi *dws)
 {
        while (dws->write(dws))
                dws->read(dws);
+       /*
+        * There is a possibility that the last word of a transaction
+        * will be lost if data is not ready. Re-read to solve this issue.
+        */
+       dws->read(dws);
 
        transfer_complete(dws);
 }
index ef9c6a04ad8f01af0d402f9f0f03a08175c04524..744d3f6e470987c773f72a733dbbc146fa358706 100644 (file)
@@ -24,6 +24,7 @@ static const struct pci_device_id b43_pci_bridge_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4312) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4315) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4318) },
+       { PCI_DEVICE(PCI_VENDOR_ID_BCM_GVC,  0x4318) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) },
index 8c95d8c2a4f4992e51f8b147a2238ce7b2e02430..016c6f7f8630ac551631660f9c27dd529bb1cbd5 100644 (file)
@@ -620,13 +620,13 @@ static ssize_t class_set_picture(struct device *device,
 
 #define ASUS_OLED_DEVICE_ATTR(_file)           dev_attr_asus_oled_##_file
 
-static DEVICE_ATTR(asus_oled_enabled, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(asus_oled_enabled, S_IWUSR | S_IRUGO,
                   get_enabled, set_enabled);
-static DEVICE_ATTR(asus_oled_picture, S_IWUGO , NULL, set_picture);
+static DEVICE_ATTR(asus_oled_picture, S_IWUSR , NULL, set_picture);
 
-static DEVICE_ATTR(enabled, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(enabled, S_IWUSR | S_IRUGO,
                   class_get_enabled, class_set_enabled);
-static DEVICE_ATTR(picture, S_IWUGO, NULL, class_set_picture);
+static DEVICE_ATTR(picture, S_IWUSR, NULL, class_set_picture);
 
 static int asus_oled_probe(struct usb_interface *interface,
                           const struct usb_device_id *id)
index b68a7e5173be9279b44fbe5ce4f574b847c832b3..d85de82f941a4a8b302b5c4dd02eea8b0de79bcc 100644 (file)
@@ -463,9 +463,6 @@ static void hardif_remove_interface(struct batman_if *batman_if)
                return;
 
        batman_if->if_status = IF_TO_BE_REMOVED;
-
-       /* caller must take if_list_lock */
-       list_del_rcu(&batman_if->list);
        synchronize_rcu();
        sysfs_del_hardif(&batman_if->hardif_obj);
        hardif_put(batman_if);
@@ -474,13 +471,21 @@ static void hardif_remove_interface(struct batman_if *batman_if)
 void hardif_remove_interfaces(void)
 {
        struct batman_if *batman_if, *batman_if_tmp;
+       struct list_head if_queue;
+
+       INIT_LIST_HEAD(&if_queue);
 
-       rtnl_lock();
        spin_lock(&if_list_lock);
        list_for_each_entry_safe(batman_if, batman_if_tmp, &if_list, list) {
-               hardif_remove_interface(batman_if);
+               list_del_rcu(&batman_if->list);
+               list_add_tail(&batman_if->list, &if_queue);
        }
        spin_unlock(&if_list_lock);
+
+       rtnl_lock();
+       list_for_each_entry_safe(batman_if, batman_if_tmp, &if_queue, list) {
+               hardif_remove_interface(batman_if);
+       }
        rtnl_unlock();
 }
 
@@ -507,8 +512,10 @@ static int hard_if_event(struct notifier_block *this,
                break;
        case NETDEV_UNREGISTER:
                spin_lock(&if_list_lock);
-               hardif_remove_interface(batman_if);
+               list_del_rcu(&batman_if->list);
                spin_unlock(&if_list_lock);
+
+               hardif_remove_interface(batman_if);
                break;
        case NETDEV_CHANGEMTU:
                if (batman_if->soft_iface)
index 3904db9ce7b1f00909ecf2f07df7b561da28ec56..0e996181daf764b81965700b8b0dd90a0e39316d 100644 (file)
@@ -194,14 +194,15 @@ void interface_rx(struct net_device *soft_iface,
        struct bat_priv *priv = netdev_priv(soft_iface);
 
        /* check if enough space is available for pulling, and pull */
-       if (!pskb_may_pull(skb, hdr_size)) {
-               kfree_skb(skb);
-               return;
-       }
+       if (!pskb_may_pull(skb, hdr_size))
+               goto dropped;
+
        skb_pull_rcsum(skb, hdr_size);
 /*     skb_set_mac_header(skb, -sizeof(struct ethhdr));*/
 
        /* skb->dev & skb->pkt_type are set here */
+       if (unlikely(!pskb_may_pull(skb, ETH_HLEN)))
+               goto dropped;
        skb->protocol = eth_type_trans(skb, soft_iface);
 
        /* should not be neccesary anymore as we use skb_pull_rcsum()
@@ -216,6 +217,11 @@ void interface_rx(struct net_device *soft_iface,
        soft_iface->last_rx = jiffies;
 
        netif_rx(skb);
+       return;
+
+dropped:
+       kfree_skb(skb);
+       return;
 }
 
 #ifdef HAVE_NET_DEVICE_OPS
index c8f1cf1b440963280241229906452d227b3e9ad4..a27bb0b4f58126f24bb17a2d1448517948e5b917 100644 (file)
@@ -88,7 +88,9 @@ with the driver.
 
 Contact Info:
 =============
-Brett Rudley   brudley@broadcom.com
-Henry Ptasinski henryp@broadcom.com
-Dowan Kim      dowan@broadcom.com
+Brett Rudley           brudley@broadcom.com
+Henry Ptasinski                henryp@broadcom.com
+Dowan Kim                      dowan@broadcom.com
+Roland Vossen          rvossen@broadcom.com
+Arend van Spriel       arend@broadcom.com
 
index dbf904184899884c825dab5e1e290c962e5dad25..24ebadbe4241f1ffd5178178d7d07b4eb6451fa5 100644 (file)
@@ -46,4 +46,6 @@ Contact
 Brett Rudley <brudley@broadcom.com>
 Henry Ptasinski <henryp@broadcom.com>
 Dowan Kim <dowan@broadcom.com>
+Roland Vossen <rvossen@broadcom.com>
+Arend van Spriel <arend@broadcom.com>
 
index 1f177a67ff114f9098f3bcdb282068978c6567e3..de784ff08caaef9665e63a66d107a888400301cc 100644 (file)
@@ -2295,8 +2295,8 @@ static void tidy_up(struct usbduxsub *usbduxsub_tmp)
        usbduxsub_tmp->inBuffer = NULL;
        kfree(usbduxsub_tmp->insnBuffer);
        usbduxsub_tmp->insnBuffer = NULL;
-       kfree(usbduxsub_tmp->inBuffer);
-       usbduxsub_tmp->inBuffer = NULL;
+       kfree(usbduxsub_tmp->outBuffer);
+       usbduxsub_tmp->outBuffer = NULL;
        kfree(usbduxsub_tmp->dac_commands);
        usbduxsub_tmp->dac_commands = NULL;
        kfree(usbduxsub_tmp->dux_commands);
index e7f1d5778cec3f7b4044d5675caddfb0ecd10f54..52389308f3337ebb84daa31490f496b8057548ba 100644 (file)
@@ -92,7 +92,7 @@ int cx25821_get_format_size(void)
        return ARRAY_SIZE(formats);
 }
 
-struct cx25821_fmt *format_by_fourcc(unsigned int fourcc)
+struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc)
 {
        unsigned int i;
 
@@ -848,7 +848,7 @@ static int video_open(struct file *file)
        pix_format =
           (dev->channels[ch_id].pixel_formats ==
            PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV;
-       fh->fmt = format_by_fourcc(pix_format);
+       fh->fmt = cx25821_format_by_fourcc(pix_format);
 
        v4l2_prio_open(&dev->channels[ch_id].prio, &fh->prio);
 
@@ -1010,7 +1010,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
        if (0 != err)
               return err;
 
-       fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+       fh->fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
        fh->vidq.field = f->fmt.pix.field;
 
        /* check if width and height is valid based on set standard */
@@ -1119,7 +1119,7 @@ int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fo
        enum v4l2_field field;
        unsigned int maxw, maxh;
 
-       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+       fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
        if (NULL == fmt)
                return -EINVAL;
 
index cc6034b1a95d717ca632c1e95a70d49307449c45..a2415d33235b2b41a62a5230822a62250589e6b1 100644 (file)
@@ -87,7 +87,7 @@ extern unsigned int vid_limit;
 
 #define FORMAT_FLAGS_PACKED       0x01
 extern struct cx25821_fmt formats[];
-extern struct cx25821_fmt *format_by_fourcc(unsigned int fourcc);
+extern struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc);
 extern struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM];
 
 extern void cx25821_dump_video_queue(struct cx25821_dev *dev,
index acfd0176a184c05baa95fc1cf8e069bcde5695b3..c9400012578266c93b1bb65a0c5a84bdeab3bb40 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/delay.h>
 #include <linux/sched.h>
 #include <linux/kdev_t.h>
+#include <linux/smp_lock.h>
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
index 25961c23dc0f4dc3068e8d79eb9eaf7d749c5782..884263b2775d76a5d0840b59d25cf04453b5a9a2 100644 (file)
@@ -75,6 +75,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/module.h>
 #include <linux/kref.h>
 #include <linux/usb.h>
index a145a15cfdb39d865a62200a83298192f2670098..8894ab14f167755a242eda73b5465bb16aaa7b8c 100644 (file)
@@ -204,7 +204,7 @@ static void usb_tranzport_abort_transfers(struct usb_tranzport *dev)
                t->value = temp;        \
                return count;   \
        }       \
-       static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value);
+       static DEVICE_ATTR(value, S_IWUSR | S_IRUGO, show_##value, set_##value);
 
 show_int(enable);
 show_int(offline);
index b3f42f37a31381f3bc17d1e5f3bdf1c55ec94c95..48d4e483d8a40b3d2f99ab24b5e69cb3f119bde7 100644 (file)
@@ -199,7 +199,7 @@ static int init_i2c_module(struct i2c_adapter *adapter, const char *type,
        struct go7007 *go = i2c_get_adapdata(adapter);
        struct v4l2_device *v4l2_dev = &go->v4l2_dev;
 
-       if (v4l2_i2c_new_subdev(v4l2_dev, adapter, NULL, type, addr, NULL))
+       if (v4l2_i2c_new_subdev(v4l2_dev, adapter, type, addr, NULL))
                return 0;
 
        printk(KERN_INFO "go7007: probing for module i2c:%s failed\n", type);
index c86d1498737d0cbe7db91914f7865969662643a7..1c1e98aee2d9fdd78aeabeab1d604f344a092367 100644 (file)
@@ -507,7 +507,7 @@ static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL,
                adis16220_write_reset, 0);
 
 #define IIO_DEV_ATTR_CAPTURE(_store)                           \
-       IIO_DEVICE_ATTR(capture, S_IWUGO, NULL, _store, 0)
+       IIO_DEVICE_ATTR(capture, S_IWUSR, NULL, _store, 0)
 
 static IIO_DEV_ATTR_CAPTURE(adis16220_write_capture);
 
index fbae39fda5c0307151024edd92bc7c65523bb9f0..5c455608b02451ff83708ce847ee4df68d7617a8 100644 (file)
@@ -1269,7 +1269,7 @@ finish:
        dbufs->output_bytes_produced = total_output;
        str_info->status = str_info->prev;
        str_info->prev = STREAM_DECODE;
-       str_info->decode_ibuf = NULL;
        kfree(str_info->decode_ibuf);
+       str_info->decode_ibuf = NULL;
        return retval;
 }
index 040e25ca6d33ef3f4863cac1718ea08a69a09d31..67e23b6e2d3593b22566d54abc8fe9bcda1e41a7 100644 (file)
@@ -266,210 +266,210 @@ VARIAX_PARAM_R(float, mix2);
 VARIAX_PARAM_R(float, mix1);
 VARIAX_PARAM_R(int, pickup_wiring);
 
-static DEVICE_ATTR(tweak, S_IWUGO | S_IRUGO, pod_get_tweak, pod_set_tweak);
-static DEVICE_ATTR(wah_position, S_IWUGO | S_IRUGO, pod_get_wah_position,
+static DEVICE_ATTR(tweak, S_IWUSR | S_IRUGO, pod_get_tweak, pod_set_tweak);
+static DEVICE_ATTR(wah_position, S_IWUSR | S_IRUGO, pod_get_wah_position,
                   pod_set_wah_position);
-static DEVICE_ATTR(compression_gain, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(compression_gain, S_IWUSR | S_IRUGO,
                   pod_get_compression_gain, pod_set_compression_gain);
-static DEVICE_ATTR(vol_pedal_position, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(vol_pedal_position, S_IWUSR | S_IRUGO,
                   pod_get_vol_pedal_position, pod_set_vol_pedal_position);
-static DEVICE_ATTR(compression_threshold, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(compression_threshold, S_IWUSR | S_IRUGO,
                   pod_get_compression_threshold,
                   pod_set_compression_threshold);
-static DEVICE_ATTR(pan, S_IWUGO | S_IRUGO, pod_get_pan, pod_set_pan);
-static DEVICE_ATTR(amp_model_setup, S_IWUGO | S_IRUGO, pod_get_amp_model_setup,
+static DEVICE_ATTR(pan, S_IWUSR | S_IRUGO, pod_get_pan, pod_set_pan);
+static DEVICE_ATTR(amp_model_setup, S_IWUSR | S_IRUGO, pod_get_amp_model_setup,
                   pod_set_amp_model_setup);
-static DEVICE_ATTR(amp_model, S_IWUGO | S_IRUGO, pod_get_amp_model,
+static DEVICE_ATTR(amp_model, S_IWUSR | S_IRUGO, pod_get_amp_model,
                   pod_set_amp_model);
-static DEVICE_ATTR(drive, S_IWUGO | S_IRUGO, pod_get_drive, pod_set_drive);
-static DEVICE_ATTR(bass, S_IWUGO | S_IRUGO, pod_get_bass, pod_set_bass);
-static DEVICE_ATTR(mid, S_IWUGO | S_IRUGO, pod_get_mid, pod_set_mid);
-static DEVICE_ATTR(lowmid, S_IWUGO | S_IRUGO, pod_get_lowmid, pod_set_lowmid);
-static DEVICE_ATTR(treble, S_IWUGO | S_IRUGO, pod_get_treble, pod_set_treble);
-static DEVICE_ATTR(highmid, S_IWUGO | S_IRUGO, pod_get_highmid,
+static DEVICE_ATTR(drive, S_IWUSR | S_IRUGO, pod_get_drive, pod_set_drive);
+static DEVICE_ATTR(bass, S_IWUSR | S_IRUGO, pod_get_bass, pod_set_bass);
+static DEVICE_ATTR(mid, S_IWUSR | S_IRUGO, pod_get_mid, pod_set_mid);
+static DEVICE_ATTR(lowmid, S_IWUSR | S_IRUGO, pod_get_lowmid, pod_set_lowmid);
+static DEVICE_ATTR(treble, S_IWUSR | S_IRUGO, pod_get_treble, pod_set_treble);
+static DEVICE_ATTR(highmid, S_IWUSR | S_IRUGO, pod_get_highmid,
                   pod_set_highmid);
-static DEVICE_ATTR(chan_vol, S_IWUGO | S_IRUGO, pod_get_chan_vol,
+static DEVICE_ATTR(chan_vol, S_IWUSR | S_IRUGO, pod_get_chan_vol,
                   pod_set_chan_vol);
-static DEVICE_ATTR(reverb_mix, S_IWUGO | S_IRUGO, pod_get_reverb_mix,
+static DEVICE_ATTR(reverb_mix, S_IWUSR | S_IRUGO, pod_get_reverb_mix,
                   pod_set_reverb_mix);
-static DEVICE_ATTR(effect_setup, S_IWUGO | S_IRUGO, pod_get_effect_setup,
+static DEVICE_ATTR(effect_setup, S_IWUSR | S_IRUGO, pod_get_effect_setup,
                   pod_set_effect_setup);
-static DEVICE_ATTR(band_1_frequency, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(band_1_frequency, S_IWUSR | S_IRUGO,
                   pod_get_band_1_frequency, pod_set_band_1_frequency);
-static DEVICE_ATTR(presence, S_IWUGO | S_IRUGO, pod_get_presence,
+static DEVICE_ATTR(presence, S_IWUSR | S_IRUGO, pod_get_presence,
                   pod_set_presence);
-static DEVICE_ATTR2(treble__bass, treble, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR2(treble__bass, treble, S_IWUSR | S_IRUGO,
                    pod_get_treble__bass, pod_set_treble__bass);
-static DEVICE_ATTR(noise_gate_enable, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(noise_gate_enable, S_IWUSR | S_IRUGO,
                   pod_get_noise_gate_enable, pod_set_noise_gate_enable);
-static DEVICE_ATTR(gate_threshold, S_IWUGO | S_IRUGO, pod_get_gate_threshold,
+static DEVICE_ATTR(gate_threshold, S_IWUSR | S_IRUGO, pod_get_gate_threshold,
                   pod_set_gate_threshold);
-static DEVICE_ATTR(gate_decay_time, S_IWUGO | S_IRUGO, pod_get_gate_decay_time,
+static DEVICE_ATTR(gate_decay_time, S_IWUSR | S_IRUGO, pod_get_gate_decay_time,
                   pod_set_gate_decay_time);
-static DEVICE_ATTR(stomp_enable, S_IWUGO | S_IRUGO, pod_get_stomp_enable,
+static DEVICE_ATTR(stomp_enable, S_IWUSR | S_IRUGO, pod_get_stomp_enable,
                   pod_set_stomp_enable);
-static DEVICE_ATTR(comp_enable, S_IWUGO | S_IRUGO, pod_get_comp_enable,
+static DEVICE_ATTR(comp_enable, S_IWUSR | S_IRUGO, pod_get_comp_enable,
                   pod_set_comp_enable);
-static DEVICE_ATTR(stomp_time, S_IWUGO | S_IRUGO, pod_get_stomp_time,
+static DEVICE_ATTR(stomp_time, S_IWUSR | S_IRUGO, pod_get_stomp_time,
                   pod_set_stomp_time);
-static DEVICE_ATTR(delay_enable, S_IWUGO | S_IRUGO, pod_get_delay_enable,
+static DEVICE_ATTR(delay_enable, S_IWUSR | S_IRUGO, pod_get_delay_enable,
                   pod_set_delay_enable);
-static DEVICE_ATTR(mod_param_1, S_IWUGO | S_IRUGO, pod_get_mod_param_1,
+static DEVICE_ATTR(mod_param_1, S_IWUSR | S_IRUGO, pod_get_mod_param_1,
                   pod_set_mod_param_1);
-static DEVICE_ATTR(delay_param_1, S_IWUGO | S_IRUGO, pod_get_delay_param_1,
+static DEVICE_ATTR(delay_param_1, S_IWUSR | S_IRUGO, pod_get_delay_param_1,
                   pod_set_delay_param_1);
-static DEVICE_ATTR(delay_param_1_note_value, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(delay_param_1_note_value, S_IWUSR | S_IRUGO,
                   pod_get_delay_param_1_note_value,
                   pod_set_delay_param_1_note_value);
-static DEVICE_ATTR2(band_2_frequency__bass, band_2_frequency, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR2(band_2_frequency__bass, band_2_frequency, S_IWUSR | S_IRUGO,
                    pod_get_band_2_frequency__bass,
                    pod_set_band_2_frequency__bass);
-static DEVICE_ATTR(delay_param_2, S_IWUGO | S_IRUGO, pod_get_delay_param_2,
+static DEVICE_ATTR(delay_param_2, S_IWUSR | S_IRUGO, pod_get_delay_param_2,
                   pod_set_delay_param_2);
-static DEVICE_ATTR(delay_volume_mix, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(delay_volume_mix, S_IWUSR | S_IRUGO,
                   pod_get_delay_volume_mix, pod_set_delay_volume_mix);
-static DEVICE_ATTR(delay_param_3, S_IWUGO | S_IRUGO, pod_get_delay_param_3,
+static DEVICE_ATTR(delay_param_3, S_IWUSR | S_IRUGO, pod_get_delay_param_3,
                   pod_set_delay_param_3);
-static DEVICE_ATTR(reverb_enable, S_IWUGO | S_IRUGO, pod_get_reverb_enable,
+static DEVICE_ATTR(reverb_enable, S_IWUSR | S_IRUGO, pod_get_reverb_enable,
                   pod_set_reverb_enable);
-static DEVICE_ATTR(reverb_type, S_IWUGO | S_IRUGO, pod_get_reverb_type,
+static DEVICE_ATTR(reverb_type, S_IWUSR | S_IRUGO, pod_get_reverb_type,
                   pod_set_reverb_type);
-static DEVICE_ATTR(reverb_decay, S_IWUGO | S_IRUGO, pod_get_reverb_decay,
+static DEVICE_ATTR(reverb_decay, S_IWUSR | S_IRUGO, pod_get_reverb_decay,
                   pod_set_reverb_decay);
-static DEVICE_ATTR(reverb_tone, S_IWUGO | S_IRUGO, pod_get_reverb_tone,
+static DEVICE_ATTR(reverb_tone, S_IWUSR | S_IRUGO, pod_get_reverb_tone,
                   pod_set_reverb_tone);
-static DEVICE_ATTR(reverb_pre_delay, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(reverb_pre_delay, S_IWUSR | S_IRUGO,
                   pod_get_reverb_pre_delay, pod_set_reverb_pre_delay);
-static DEVICE_ATTR(reverb_pre_post, S_IWUGO | S_IRUGO, pod_get_reverb_pre_post,
+static DEVICE_ATTR(reverb_pre_post, S_IWUSR | S_IRUGO, pod_get_reverb_pre_post,
                   pod_set_reverb_pre_post);
-static DEVICE_ATTR(band_2_frequency, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(band_2_frequency, S_IWUSR | S_IRUGO,
                   pod_get_band_2_frequency, pod_set_band_2_frequency);
-static DEVICE_ATTR2(band_3_frequency__bass, band_3_frequency, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR2(band_3_frequency__bass, band_3_frequency, S_IWUSR | S_IRUGO,
                    pod_get_band_3_frequency__bass,
                    pod_set_band_3_frequency__bass);
-static DEVICE_ATTR(wah_enable, S_IWUGO | S_IRUGO, pod_get_wah_enable,
+static DEVICE_ATTR(wah_enable, S_IWUSR | S_IRUGO, pod_get_wah_enable,
                   pod_set_wah_enable);
-static DEVICE_ATTR(modulation_lo_cut, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(modulation_lo_cut, S_IWUSR | S_IRUGO,
                   pod_get_modulation_lo_cut, pod_set_modulation_lo_cut);
-static DEVICE_ATTR(delay_reverb_lo_cut, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(delay_reverb_lo_cut, S_IWUSR | S_IRUGO,
                   pod_get_delay_reverb_lo_cut, pod_set_delay_reverb_lo_cut);
-static DEVICE_ATTR(volume_pedal_minimum, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(volume_pedal_minimum, S_IWUSR | S_IRUGO,
                   pod_get_volume_pedal_minimum, pod_set_volume_pedal_minimum);
-static DEVICE_ATTR(eq_pre_post, S_IWUGO | S_IRUGO, pod_get_eq_pre_post,
+static DEVICE_ATTR(eq_pre_post, S_IWUSR | S_IRUGO, pod_get_eq_pre_post,
                   pod_set_eq_pre_post);
-static DEVICE_ATTR(volume_pre_post, S_IWUGO | S_IRUGO, pod_get_volume_pre_post,
+static DEVICE_ATTR(volume_pre_post, S_IWUSR | S_IRUGO, pod_get_volume_pre_post,
                   pod_set_volume_pre_post);
-static DEVICE_ATTR(di_model, S_IWUGO | S_IRUGO, pod_get_di_model,
+static DEVICE_ATTR(di_model, S_IWUSR | S_IRUGO, pod_get_di_model,
                   pod_set_di_model);
-static DEVICE_ATTR(di_delay, S_IWUGO | S_IRUGO, pod_get_di_delay,
+static DEVICE_ATTR(di_delay, S_IWUSR | S_IRUGO, pod_get_di_delay,
                   pod_set_di_delay);
-static DEVICE_ATTR(mod_enable, S_IWUGO | S_IRUGO, pod_get_mod_enable,
+static DEVICE_ATTR(mod_enable, S_IWUSR | S_IRUGO, pod_get_mod_enable,
                   pod_set_mod_enable);
-static DEVICE_ATTR(mod_param_1_note_value, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(mod_param_1_note_value, S_IWUSR | S_IRUGO,
                   pod_get_mod_param_1_note_value,
                   pod_set_mod_param_1_note_value);
-static DEVICE_ATTR(mod_param_2, S_IWUGO | S_IRUGO, pod_get_mod_param_2,
+static DEVICE_ATTR(mod_param_2, S_IWUSR | S_IRUGO, pod_get_mod_param_2,
                   pod_set_mod_param_2);
-static DEVICE_ATTR(mod_param_3, S_IWUGO | S_IRUGO, pod_get_mod_param_3,
+static DEVICE_ATTR(mod_param_3, S_IWUSR | S_IRUGO, pod_get_mod_param_3,
                   pod_set_mod_param_3);
-static DEVICE_ATTR(mod_param_4, S_IWUGO | S_IRUGO, pod_get_mod_param_4,
+static DEVICE_ATTR(mod_param_4, S_IWUSR | S_IRUGO, pod_get_mod_param_4,
                   pod_set_mod_param_4);
-static DEVICE_ATTR(mod_param_5, S_IWUGO | S_IRUGO, pod_get_mod_param_5,
+static DEVICE_ATTR(mod_param_5, S_IWUSR | S_IRUGO, pod_get_mod_param_5,
                   pod_set_mod_param_5);
-static DEVICE_ATTR(mod_volume_mix, S_IWUGO | S_IRUGO, pod_get_mod_volume_mix,
+static DEVICE_ATTR(mod_volume_mix, S_IWUSR | S_IRUGO, pod_get_mod_volume_mix,
                   pod_set_mod_volume_mix);
-static DEVICE_ATTR(mod_pre_post, S_IWUGO | S_IRUGO, pod_get_mod_pre_post,
+static DEVICE_ATTR(mod_pre_post, S_IWUSR | S_IRUGO, pod_get_mod_pre_post,
                   pod_set_mod_pre_post);
-static DEVICE_ATTR(modulation_model, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(modulation_model, S_IWUSR | S_IRUGO,
                   pod_get_modulation_model, pod_set_modulation_model);
-static DEVICE_ATTR(band_3_frequency, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(band_3_frequency, S_IWUSR | S_IRUGO,
                   pod_get_band_3_frequency, pod_set_band_3_frequency);
-static DEVICE_ATTR2(band_4_frequency__bass, band_4_frequency, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR2(band_4_frequency__bass, band_4_frequency, S_IWUSR | S_IRUGO,
                    pod_get_band_4_frequency__bass,
                    pod_set_band_4_frequency__bass);
-static DEVICE_ATTR(mod_param_1_double_precision, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(mod_param_1_double_precision, S_IWUSR | S_IRUGO,
                   pod_get_mod_param_1_double_precision,
                   pod_set_mod_param_1_double_precision);
-static DEVICE_ATTR(delay_param_1_double_precision, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(delay_param_1_double_precision, S_IWUSR | S_IRUGO,
                   pod_get_delay_param_1_double_precision,
                   pod_set_delay_param_1_double_precision);
-static DEVICE_ATTR(eq_enable, S_IWUGO | S_IRUGO, pod_get_eq_enable,
+static DEVICE_ATTR(eq_enable, S_IWUSR | S_IRUGO, pod_get_eq_enable,
                   pod_set_eq_enable);
-static DEVICE_ATTR(tap, S_IWUGO | S_IRUGO, pod_get_tap, pod_set_tap);
-static DEVICE_ATTR(volume_tweak_pedal_assign, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(tap, S_IWUSR | S_IRUGO, pod_get_tap, pod_set_tap);
+static DEVICE_ATTR(volume_tweak_pedal_assign, S_IWUSR | S_IRUGO,
                   pod_get_volume_tweak_pedal_assign,
                   pod_set_volume_tweak_pedal_assign);
-static DEVICE_ATTR(band_5_frequency, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(band_5_frequency, S_IWUSR | S_IRUGO,
                   pod_get_band_5_frequency, pod_set_band_5_frequency);
-static DEVICE_ATTR(tuner, S_IWUGO | S_IRUGO, pod_get_tuner, pod_set_tuner);
-static DEVICE_ATTR(mic_selection, S_IWUGO | S_IRUGO, pod_get_mic_selection,
+static DEVICE_ATTR(tuner, S_IWUSR | S_IRUGO, pod_get_tuner, pod_set_tuner);
+static DEVICE_ATTR(mic_selection, S_IWUSR | S_IRUGO, pod_get_mic_selection,
                   pod_set_mic_selection);
-static DEVICE_ATTR(cabinet_model, S_IWUGO | S_IRUGO, pod_get_cabinet_model,
+static DEVICE_ATTR(cabinet_model, S_IWUSR | S_IRUGO, pod_get_cabinet_model,
                   pod_set_cabinet_model);
-static DEVICE_ATTR(stomp_model, S_IWUGO | S_IRUGO, pod_get_stomp_model,
+static DEVICE_ATTR(stomp_model, S_IWUSR | S_IRUGO, pod_get_stomp_model,
                   pod_set_stomp_model);
-static DEVICE_ATTR(roomlevel, S_IWUGO | S_IRUGO, pod_get_roomlevel,
+static DEVICE_ATTR(roomlevel, S_IWUSR | S_IRUGO, pod_get_roomlevel,
                   pod_set_roomlevel);
-static DEVICE_ATTR(band_4_frequency, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(band_4_frequency, S_IWUSR | S_IRUGO,
                   pod_get_band_4_frequency, pod_set_band_4_frequency);
-static DEVICE_ATTR(band_6_frequency, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(band_6_frequency, S_IWUSR | S_IRUGO,
                   pod_get_band_6_frequency, pod_set_band_6_frequency);
-static DEVICE_ATTR(stomp_param_1_note_value, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(stomp_param_1_note_value, S_IWUSR | S_IRUGO,
                   pod_get_stomp_param_1_note_value,
                   pod_set_stomp_param_1_note_value);
-static DEVICE_ATTR(stomp_param_2, S_IWUGO | S_IRUGO, pod_get_stomp_param_2,
+static DEVICE_ATTR(stomp_param_2, S_IWUSR | S_IRUGO, pod_get_stomp_param_2,
                   pod_set_stomp_param_2);
-static DEVICE_ATTR(stomp_param_3, S_IWUGO | S_IRUGO, pod_get_stomp_param_3,
+static DEVICE_ATTR(stomp_param_3, S_IWUSR | S_IRUGO, pod_get_stomp_param_3,
                   pod_set_stomp_param_3);
-static DEVICE_ATTR(stomp_param_4, S_IWUGO | S_IRUGO, pod_get_stomp_param_4,
+static DEVICE_ATTR(stomp_param_4, S_IWUSR | S_IRUGO, pod_get_stomp_param_4,
                   pod_set_stomp_param_4);
-static DEVICE_ATTR(stomp_param_5, S_IWUGO | S_IRUGO, pod_get_stomp_param_5,
+static DEVICE_ATTR(stomp_param_5, S_IWUSR | S_IRUGO, pod_get_stomp_param_5,
                   pod_set_stomp_param_5);
-static DEVICE_ATTR(stomp_param_6, S_IWUGO | S_IRUGO, pod_get_stomp_param_6,
+static DEVICE_ATTR(stomp_param_6, S_IWUSR | S_IRUGO, pod_get_stomp_param_6,
                   pod_set_stomp_param_6);
-static DEVICE_ATTR(amp_switch_select, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(amp_switch_select, S_IWUSR | S_IRUGO,
                   pod_get_amp_switch_select, pod_set_amp_switch_select);
-static DEVICE_ATTR(delay_param_4, S_IWUGO | S_IRUGO, pod_get_delay_param_4,
+static DEVICE_ATTR(delay_param_4, S_IWUSR | S_IRUGO, pod_get_delay_param_4,
                   pod_set_delay_param_4);
-static DEVICE_ATTR(delay_param_5, S_IWUGO | S_IRUGO, pod_get_delay_param_5,
+static DEVICE_ATTR(delay_param_5, S_IWUSR | S_IRUGO, pod_get_delay_param_5,
                   pod_set_delay_param_5);
-static DEVICE_ATTR(delay_pre_post, S_IWUGO | S_IRUGO, pod_get_delay_pre_post,
+static DEVICE_ATTR(delay_pre_post, S_IWUSR | S_IRUGO, pod_get_delay_pre_post,
                   pod_set_delay_pre_post);
-static DEVICE_ATTR(delay_model, S_IWUGO | S_IRUGO, pod_get_delay_model,
+static DEVICE_ATTR(delay_model, S_IWUSR | S_IRUGO, pod_get_delay_model,
                   pod_set_delay_model);
-static DEVICE_ATTR(delay_verb_model, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(delay_verb_model, S_IWUSR | S_IRUGO,
                   pod_get_delay_verb_model, pod_set_delay_verb_model);
-static DEVICE_ATTR(tempo_msb, S_IWUGO | S_IRUGO, pod_get_tempo_msb,
+static DEVICE_ATTR(tempo_msb, S_IWUSR | S_IRUGO, pod_get_tempo_msb,
                   pod_set_tempo_msb);
-static DEVICE_ATTR(tempo_lsb, S_IWUGO | S_IRUGO, pod_get_tempo_lsb,
+static DEVICE_ATTR(tempo_lsb, S_IWUSR | S_IRUGO, pod_get_tempo_lsb,
                   pod_set_tempo_lsb);
-static DEVICE_ATTR(wah_model, S_IWUGO | S_IRUGO, pod_get_wah_model,
+static DEVICE_ATTR(wah_model, S_IWUSR | S_IRUGO, pod_get_wah_model,
                   pod_set_wah_model);
-static DEVICE_ATTR(bypass_volume, S_IWUGO | S_IRUGO, pod_get_bypass_volume,
+static DEVICE_ATTR(bypass_volume, S_IWUSR | S_IRUGO, pod_get_bypass_volume,
                   pod_set_bypass_volume);
-static DEVICE_ATTR(fx_loop_on_off, S_IWUGO | S_IRUGO, pod_get_fx_loop_on_off,
+static DEVICE_ATTR(fx_loop_on_off, S_IWUSR | S_IRUGO, pod_get_fx_loop_on_off,
                   pod_set_fx_loop_on_off);
-static DEVICE_ATTR(tweak_param_select, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(tweak_param_select, S_IWUSR | S_IRUGO,
                   pod_get_tweak_param_select, pod_set_tweak_param_select);
-static DEVICE_ATTR(amp1_engage, S_IWUGO | S_IRUGO, pod_get_amp1_engage,
+static DEVICE_ATTR(amp1_engage, S_IWUSR | S_IRUGO, pod_get_amp1_engage,
                   pod_set_amp1_engage);
-static DEVICE_ATTR(band_1_gain, S_IWUGO | S_IRUGO, pod_get_band_1_gain,
+static DEVICE_ATTR(band_1_gain, S_IWUSR | S_IRUGO, pod_get_band_1_gain,
                   pod_set_band_1_gain);
-static DEVICE_ATTR2(band_2_gain__bass, band_2_gain, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR2(band_2_gain__bass, band_2_gain, S_IWUSR | S_IRUGO,
                    pod_get_band_2_gain__bass, pod_set_band_2_gain__bass);
-static DEVICE_ATTR(band_2_gain, S_IWUGO | S_IRUGO, pod_get_band_2_gain,
+static DEVICE_ATTR(band_2_gain, S_IWUSR | S_IRUGO, pod_get_band_2_gain,
                   pod_set_band_2_gain);
-static DEVICE_ATTR2(band_3_gain__bass, band_3_gain, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR2(band_3_gain__bass, band_3_gain, S_IWUSR | S_IRUGO,
                    pod_get_band_3_gain__bass, pod_set_band_3_gain__bass);
-static DEVICE_ATTR(band_3_gain, S_IWUGO | S_IRUGO, pod_get_band_3_gain,
+static DEVICE_ATTR(band_3_gain, S_IWUSR | S_IRUGO, pod_get_band_3_gain,
                   pod_set_band_3_gain);
-static DEVICE_ATTR2(band_4_gain__bass, band_4_gain, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR2(band_4_gain__bass, band_4_gain, S_IWUSR | S_IRUGO,
                    pod_get_band_4_gain__bass, pod_set_band_4_gain__bass);
-static DEVICE_ATTR2(band_5_gain__bass, band_5_gain, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR2(band_5_gain__bass, band_5_gain, S_IWUSR | S_IRUGO,
                    pod_get_band_5_gain__bass, pod_set_band_5_gain__bass);
-static DEVICE_ATTR(band_4_gain, S_IWUGO | S_IRUGO, pod_get_band_4_gain,
+static DEVICE_ATTR(band_4_gain, S_IWUSR | S_IRUGO, pod_get_band_4_gain,
                   pod_set_band_4_gain);
-static DEVICE_ATTR2(band_6_gain__bass, band_6_gain, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR2(band_6_gain__bass, band_6_gain, S_IWUSR | S_IRUGO,
                    pod_get_band_6_gain__bass, pod_set_band_6_gain__bass);
 static DEVICE_ATTR(body, S_IRUGO, variax_get_body, line6_nop_write);
 static DEVICE_ATTR(pickup1_enable, S_IRUGO, variax_get_pickup1_enable,
index 4304dfe6c16608debc95f34b7d2cf1dd3a49d681..ab67e889d2c4b53f14f0488d96e3749de08565c7 100644 (file)
@@ -350,9 +350,9 @@ static ssize_t midi_set_midi_mask_receive(struct device *dev,
        return count;
 }
 
-static DEVICE_ATTR(midi_mask_transmit, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(midi_mask_transmit, S_IWUSR | S_IRUGO,
                   midi_get_midi_mask_transmit, midi_set_midi_mask_transmit);
-static DEVICE_ATTR(midi_mask_receive, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(midi_mask_receive, S_IWUSR | S_IRUGO,
                   midi_get_midi_mask_receive, midi_set_midi_mask_receive);
 
 /* MIDI device destructor */
index e54770e34d2e79440c62e08460c401e5c484ef23..b9c55f9eb501185bb63ad142ca2ea7f1f2bca950 100644 (file)
@@ -79,9 +79,9 @@ static ssize_t pcm_set_impulse_period(struct device *dev,
        return count;
 }
 
-static DEVICE_ATTR(impulse_volume, S_IWUGO | S_IRUGO, pcm_get_impulse_volume,
+static DEVICE_ATTR(impulse_volume, S_IWUSR | S_IRUGO, pcm_get_impulse_volume,
                   pcm_set_impulse_volume);
-static DEVICE_ATTR(impulse_period, S_IWUGO | S_IRUGO, pcm_get_impulse_period,
+static DEVICE_ATTR(impulse_period, S_IWUSR | S_IRUGO, pcm_get_impulse_period,
                   pcm_set_impulse_period);
 
 #endif
index 22e2cedcacf79f027c6b0505c99d66641ec03223..d9b30212585c6851c428a7c525976feb05e7b85d 100644 (file)
@@ -1051,48 +1051,48 @@ POD_GET_SYSTEM_PARAM(tuner_pitch, 1);
 #undef GET_SYSTEM_PARAM
 
 /* POD special files: */
-static DEVICE_ATTR(channel, S_IWUGO | S_IRUGO, pod_get_channel,
+static DEVICE_ATTR(channel, S_IWUSR | S_IRUGO, pod_get_channel,
                   pod_set_channel);
 static DEVICE_ATTR(clip, S_IRUGO, pod_wait_for_clip, line6_nop_write);
 static DEVICE_ATTR(device_id, S_IRUGO, pod_get_device_id, line6_nop_write);
 static DEVICE_ATTR(dirty, S_IRUGO, pod_get_dirty, line6_nop_write);
-static DEVICE_ATTR(dump, S_IWUGO | S_IRUGO, pod_get_dump, pod_set_dump);
-static DEVICE_ATTR(dump_buf, S_IWUGO | S_IRUGO, pod_get_dump_buf,
+static DEVICE_ATTR(dump, S_IWUSR | S_IRUGO, pod_get_dump, pod_set_dump);
+static DEVICE_ATTR(dump_buf, S_IWUSR | S_IRUGO, pod_get_dump_buf,
                   pod_set_dump_buf);
-static DEVICE_ATTR(finish, S_IWUGO, line6_nop_read, pod_set_finish);
+static DEVICE_ATTR(finish, S_IWUSR, line6_nop_read, pod_set_finish);
 static DEVICE_ATTR(firmware_version, S_IRUGO, pod_get_firmware_version,
                   line6_nop_write);
-static DEVICE_ATTR(midi_postprocess, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(midi_postprocess, S_IWUSR | S_IRUGO,
                   pod_get_midi_postprocess, pod_set_midi_postprocess);
-static DEVICE_ATTR(monitor_level, S_IWUGO | S_IRUGO, pod_get_monitor_level,
+static DEVICE_ATTR(monitor_level, S_IWUSR | S_IRUGO, pod_get_monitor_level,
                   pod_set_monitor_level);
 static DEVICE_ATTR(name, S_IRUGO, pod_get_name, line6_nop_write);
 static DEVICE_ATTR(name_buf, S_IRUGO, pod_get_name_buf, line6_nop_write);
-static DEVICE_ATTR(retrieve_amp_setup, S_IWUGO, line6_nop_read,
+static DEVICE_ATTR(retrieve_amp_setup, S_IWUSR, line6_nop_read,
                   pod_set_retrieve_amp_setup);
-static DEVICE_ATTR(retrieve_channel, S_IWUGO, line6_nop_read,
+static DEVICE_ATTR(retrieve_channel, S_IWUSR, line6_nop_read,
                   pod_set_retrieve_channel);
-static DEVICE_ATTR(retrieve_effects_setup, S_IWUGO, line6_nop_read,
+static DEVICE_ATTR(retrieve_effects_setup, S_IWUSR, line6_nop_read,
                   pod_set_retrieve_effects_setup);
-static DEVICE_ATTR(routing, S_IWUGO | S_IRUGO, pod_get_routing,
+static DEVICE_ATTR(routing, S_IWUSR | S_IRUGO, pod_get_routing,
                   pod_set_routing);
 static DEVICE_ATTR(serial_number, S_IRUGO, pod_get_serial_number,
                   line6_nop_write);
-static DEVICE_ATTR(store_amp_setup, S_IWUGO, line6_nop_read,
+static DEVICE_ATTR(store_amp_setup, S_IWUSR, line6_nop_read,
                   pod_set_store_amp_setup);
-static DEVICE_ATTR(store_channel, S_IWUGO, line6_nop_read,
+static DEVICE_ATTR(store_channel, S_IWUSR, line6_nop_read,
                   pod_set_store_channel);
-static DEVICE_ATTR(store_effects_setup, S_IWUGO, line6_nop_read,
+static DEVICE_ATTR(store_effects_setup, S_IWUSR, line6_nop_read,
                   pod_set_store_effects_setup);
-static DEVICE_ATTR(tuner_freq, S_IWUGO | S_IRUGO, pod_get_tuner_freq,
+static DEVICE_ATTR(tuner_freq, S_IWUSR | S_IRUGO, pod_get_tuner_freq,
                   pod_set_tuner_freq);
-static DEVICE_ATTR(tuner_mute, S_IWUGO | S_IRUGO, pod_get_tuner_mute,
+static DEVICE_ATTR(tuner_mute, S_IWUSR | S_IRUGO, pod_get_tuner_mute,
                   pod_set_tuner_mute);
 static DEVICE_ATTR(tuner_note, S_IRUGO, pod_get_tuner_note, line6_nop_write);
 static DEVICE_ATTR(tuner_pitch, S_IRUGO, pod_get_tuner_pitch, line6_nop_write);
 
 #ifdef CONFIG_LINE6_USB_RAW
-static DEVICE_ATTR(raw, S_IWUGO, line6_nop_read, line6_set_raw);
+static DEVICE_ATTR(raw, S_IWUSR, line6_nop_read, line6_set_raw);
 #endif
 
 /* control info callback */
index 6a10b0f9749a4cee25e54a717072b734a67e5baf..879e6992bbc6f8976c8fbea0c450db15428dda8e 100644 (file)
@@ -154,9 +154,9 @@ static ssize_t toneport_set_led_green(struct device *dev,
        return count;
 }
 
-static DEVICE_ATTR(led_red, S_IWUGO | S_IRUGO, line6_nop_read,
+static DEVICE_ATTR(led_red, S_IWUSR | S_IRUGO, line6_nop_read,
                   toneport_set_led_red);
-static DEVICE_ATTR(led_green, S_IWUGO | S_IRUGO, line6_nop_read,
+static DEVICE_ATTR(led_green, S_IWUSR | S_IRUGO, line6_nop_read,
                   toneport_set_led_green);
 
 static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2)
index 894eee7f2317b62c392dc426be44dee4479fb89c..81241cdf1be97ec60888550c128f3827f23713a2 100644 (file)
@@ -549,21 +549,21 @@ static ssize_t variax_set_raw2(struct device *dev,
 #endif
 
 /* Variax workbench special files: */
-static DEVICE_ATTR(model, S_IWUGO | S_IRUGO, variax_get_model,
+static DEVICE_ATTR(model, S_IWUSR | S_IRUGO, variax_get_model,
                   variax_set_model);
-static DEVICE_ATTR(volume, S_IWUGO | S_IRUGO, variax_get_volume,
+static DEVICE_ATTR(volume, S_IWUSR | S_IRUGO, variax_get_volume,
                   variax_set_volume);
-static DEVICE_ATTR(tone, S_IWUGO | S_IRUGO, variax_get_tone, variax_set_tone);
+static DEVICE_ATTR(tone, S_IWUSR | S_IRUGO, variax_get_tone, variax_set_tone);
 static DEVICE_ATTR(name, S_IRUGO, variax_get_name, line6_nop_write);
 static DEVICE_ATTR(bank, S_IRUGO, variax_get_bank, line6_nop_write);
 static DEVICE_ATTR(dump, S_IRUGO, variax_get_dump, line6_nop_write);
-static DEVICE_ATTR(active, S_IWUGO | S_IRUGO, variax_get_active,
+static DEVICE_ATTR(active, S_IWUSR | S_IRUGO, variax_get_active,
                   variax_set_active);
 static DEVICE_ATTR(guitar, S_IRUGO, variax_get_guitar, line6_nop_write);
 
 #ifdef CONFIG_LINE6_USB_RAW
-static DEVICE_ATTR(raw, S_IWUGO, line6_nop_read, line6_set_raw);
-static DEVICE_ATTR(raw2, S_IWUGO, line6_nop_read, variax_set_raw2);
+static DEVICE_ATTR(raw, S_IWUSR, line6_nop_read, line6_set_raw);
+static DEVICE_ATTR(raw2, S_IWUSR, line6_nop_read, variax_set_raw2);
 #endif
 
 /*
index d746715d3d894cbc10e02aa0e2c117442b30ddbf..d83bec876d2e3a1daf4e71dd4969df36e352ee78 100644 (file)
@@ -355,7 +355,6 @@ static int quickstart_acpi_remove(struct acpi_device *device, int type)
 static void quickstart_exit(void)
 {
        input_unregister_device(quickstart_input);
-       input_free_device(quickstart_input);
 
        device_remove_file(&pf_device->dev, &dev_attr_pressed_button);
        device_remove_file(&pf_device->dev, &dev_attr_buttons);
@@ -375,6 +374,7 @@ static int __init quickstart_init_input(void)
 {
        struct quickstart_btn **ptr = &quickstart_data.btn_lst;
        int count;
+       int ret;
 
        quickstart_input = input_allocate_device();
 
@@ -391,7 +391,13 @@ static int __init quickstart_init_input(void)
                ptr = &((*ptr)->next);
        }
 
-       return input_register_device(quickstart_input);
+       ret = input_register_device(quickstart_input);
+       if (ret) {
+               input_free_device(quickstart_input);
+               return ret;
+       }
+
+       return 0;
 }
 
 static int __init quickstart_init(void)
index ddacfc6c486179274394b330153c901dfc7c63b7..cd15daae5412f52339508db53d7353653175ffe0 100644 (file)
@@ -182,6 +182,7 @@ struct usb_device_id rtusb_usb_id[] = {
        {USB_DEVICE(0x2001, 0x3C09)},   /* D-Link */
        {USB_DEVICE(0x2001, 0x3C0A)},   /* D-Link 3072 */
        {USB_DEVICE(0x2019, 0xED14)},   /* Planex Communications, Inc. */
+       {USB_DEVICE(0x0411, 0x015D)},   /* Buffalo Airstation WLI-UC-GN */
        {}                      /* Terminating entry */
 };
 
index 46000d72f4c419b51f1dd090e3f1fbac17f6c22a..3bdf9b31cc4e2f4565d85a2e530effd56c0154ee 100644 (file)
@@ -264,8 +264,12 @@ HwHSSIThreeWire(
 
                        udelay(10);
                }
-               if (TryCnt == TC_3W_POLL_MAX_TRY_CNT)
-                       panic("HwThreeWire(): CmdReg: %#X RE|WE bits are not clear!!\n", u1bTmp);
+               if (TryCnt == TC_3W_POLL_MAX_TRY_CNT) {
+                       printk(KERN_ERR "rtl8187se: HwThreeWire(): CmdReg:"
+                              " %#X RE|WE bits are not clear!!\n", u1bTmp);
+                       dump_stack();
+                       return 0;
+               }
 
                /* RTL8187S HSSI Read/Write Function */
                u1bTmp = read_nic_byte(dev, RF_SW_CONFIG);
@@ -298,13 +302,23 @@ HwHSSIThreeWire(
                                int idx;
                                int ByteCnt = nDataBufBitCnt / 8;
                                                                /* printk("%d\n",nDataBufBitCnt); */
-                               if ((nDataBufBitCnt % 8) != 0)
-                               panic("HwThreeWire(): nDataBufBitCnt(%d) should be multiple of 8!!!\n",
-                               nDataBufBitCnt);
+                               if ((nDataBufBitCnt % 8) != 0) {
+                                       printk(KERN_ERR "rtl8187se: "
+                                              "HwThreeWire(): nDataBufBitCnt(%d)"
+                                              " should be multiple of 8!!!\n",
+                                              nDataBufBitCnt);
+                                       dump_stack();
+                                       nDataBufBitCnt += 8;
+                                       nDataBufBitCnt &= ~7;
+                               }
 
-                              if (nDataBufBitCnt > 64)
-                               panic("HwThreeWire(): nDataBufBitCnt(%d) should <= 64!!!\n",
-                               nDataBufBitCnt);
+                              if (nDataBufBitCnt > 64) {
+                                       printk(KERN_ERR "rtl8187se: HwThreeWire():"
+                                              " nDataBufBitCnt(%d) should <= 64!!!\n",
+                                              nDataBufBitCnt);
+                                       dump_stack();
+                                       nDataBufBitCnt = 64;
+                               }
 
                                for (idx = 0; idx < ByteCnt; idx++)
                                        write_nic_byte(dev, (SW_3W_DB0+idx), *(pDataBuf+idx));
index f6569dce30127c7c5b033f4a2e2b01e17c219938..0e9483bbabe17fb7cab00fc6e2c757a68190c814 100644 (file)
@@ -37,7 +37,7 @@ u8 r8712_usb_hal_bus_init(struct _adapter *padapter)
 {
        u8 val8 = 0;
        u8 ret = _SUCCESS;
-       u8 PollingCnt = 20;
+       int PollingCnt = 20;
        struct registry_priv *pregistrypriv = &padapter->registrypriv;
 
        if (pregistrypriv->chip_version == RTL8712_FPGA) {
index eb44b60e1eb542d735cb0cbabbff1e55109008c9..ac2bf11e1119904e76a6dace0ec2fb63ed33db56 100644 (file)
@@ -356,7 +356,7 @@ static ssize_t set_silent_state(struct device *dev,
        }
        return count;
 }
-static DEVICE_ATTR(silent, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(silent, S_IWUSR | S_IRUGO,
                   get_silent_state, set_silent_state);
 
 
index adb93f21c0d6c844b345d6c8fb9cec77d26c8efe..65b231178f0580d30a4233e17bf31eb73c7df6f7 100644 (file)
@@ -62,7 +62,6 @@ void speakup_remove_virtual_keyboard(void)
 {
        if (virt_keyboard != NULL) {
                input_unregister_device(virt_keyboard);
-               input_free_device(virt_keyboard);
                virt_keyboard = NULL;
        }
 }
index c7932da03c56df5d40182e24c039b28762fe8ba4..63a9d0adf32d1c12f04708c971162a480e3f8e33 100644 (file)
@@ -656,7 +656,7 @@ static int SBD_setup_device(struct spectra_nand_dev *dev, int which)
        /* Here we force report 512 byte hardware sector size to Kernel */
        blk_queue_logical_block_size(dev->queue, 512);
 
-       blk_queue_ordered(dev->queue, QUEUE_ORDERED_DRAIN_FLUSH);
+       blk_queue_flush(dev->queue, REQ_FLUSH);
 
        dev->thread = kthread_run(spectra_trans_thread, dev, "nand_thd");
        if (IS_ERR(dev->thread)) {
index 664e6038090dbf447aa78eca713d904c145fd54b..b143258f094a34d7cacdced5b5b0c3c0289313ad 100644 (file)
@@ -545,7 +545,7 @@ static void tm6000_config_tuner(struct tm6000_core *dev)
 
        /* Load tuner module */
        v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-               NULL, "tuner", dev->tuner_addr, NULL);
+               "tuner", dev->tuner_addr, NULL);
 
        memset(&tun_setup, 0, sizeof(tun_setup));
        tun_setup.type = dev->tuner_type;
@@ -683,7 +683,7 @@ static int tm6000_init_dev(struct tm6000_core *dev)
 
        if (dev->caps.has_tda9874)
                v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-                       NULL, "tvaudio", I2C_ADDR_TDA9874, NULL);
+                       "tvaudio", I2C_ADDR_TDA9874, NULL);
 
        /* register and initialize V4L2 */
        rc = tm6000_v4l2_register(dev);
index fed25105970a94d06ca185fa81603f79968d67f8..b7ac16005265ede845b8b5debfb03f601fe66992 100644 (file)
@@ -1441,7 +1441,7 @@ static struct device_attribute fb_device_attrs[] = {
        __ATTR_RO(metrics_bytes_identical),
        __ATTR_RO(metrics_bytes_sent),
        __ATTR_RO(metrics_cpu_kcycles_used),
-       __ATTR(metrics_reset, S_IWUGO, NULL, metrics_reset_store),
+       __ATTR(metrics_reset, S_IWUSR, NULL, metrics_reset_store),
 };
 
 /*
index 9195adf98e142dd34476dc229d4aa8f67ab236b6..d0d71f69bc8ccad684eae2712370679a1a1d752c 100644 (file)
@@ -2,6 +2,9 @@
 
 #ifndef SYS_DEF_H
 #define SYS_DEF_H
+
+#include <linux/delay.h>
+
 #define WB_LINUX
 #define WB_LINUX_WPA_PSK
 
index 6c574a994d11a23e2a0c0b4fc052769c8b0a9ccc..6b3cf00b0ff42aa83069bd1649b090c5e6e1b522 100644 (file)
@@ -189,10 +189,10 @@ static ssize_t mem_used_total_show(struct device *dev,
        return sprintf(buf, "%llu\n", val);
 }
 
-static DEVICE_ATTR(disksize, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(disksize, S_IRUGO | S_IWUSR,
                disksize_show, disksize_store);
 static DEVICE_ATTR(initstate, S_IRUGO, initstate_show, NULL);
-static DEVICE_ATTR(reset, S_IWUGO, NULL, reset_store);
+static DEVICE_ATTR(reset, S_IWUSR, NULL, reset_store);
 static DEVICE_ATTR(num_reads, S_IRUGO, num_reads_show, NULL);
 static DEVICE_ATTR(num_writes, S_IRUGO, num_writes_show, NULL);
 static DEVICE_ATTR(invalid_io, S_IRUGO, invalid_io_show, NULL);
index 81b46585edf797561828f2adfac2e598543690f3..c5f8e5bda2b29c4606f3245ba9388f943d3f2147 100644 (file)
@@ -716,8 +716,8 @@ static void __gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg)
                if (msg->len < 128)
                        *--dp = (msg->len << 1) | EA;
                else {
-                       *--dp = ((msg->len & 127) << 1) | EA;
-                       *--dp = (msg->len >> 6) & 0xfe;
+                       *--dp = (msg->len >> 7);        /* bits 7 - 15 */
+                       *--dp = (msg->len & 127) << 1;  /* bits 0 - 6 */
                }
        }
 
@@ -968,6 +968,8 @@ static void gsm_control_reply(struct gsm_mux *gsm, int cmd, u8 *data,
 {
        struct gsm_msg *msg;
        msg = gsm_data_alloc(gsm, 0, dlen + 2, gsm->ftype);
+       if (msg == NULL)
+               return;
        msg->data[0] = (cmd & 0xFE) << 1 | EA;  /* Clear C/R */
        msg->data[1] = (dlen << 1) | EA;
        memcpy(msg->data + 2, data, dlen);
index eaa5d3efa79da4cb061b4fbaf9d6acb6f21afd5e..c556ed9db13d82a4bd7dcff1bb599dce6abd8341 100644 (file)
@@ -554,7 +554,7 @@ EXPORT_SYMBOL(handle_sysrq);
 #ifdef CONFIG_INPUT
 
 /* Simple translation table for the SysRq keys */
-static const unsigned char sysrq_xlate[KEY_MAX + 1] =
+static const unsigned char sysrq_xlate[KEY_CNT] =
         "\000\0331234567890-=\177\t"                    /* 0x00 - 0x0f */
         "qwertyuiop[]\r\000as"                          /* 0x10 - 0x1f */
         "dfghjkl;'`\000\\zxcv"                          /* 0x20 - 0x2f */
@@ -563,53 +563,129 @@ static const unsigned char sysrq_xlate[KEY_MAX + 1] =
         "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
         "\r\000/";                                      /* 0x60 - 0x6f */
 
-static bool sysrq_down;
-static int sysrq_alt_use;
-static int sysrq_alt;
-static DEFINE_SPINLOCK(sysrq_event_lock);
+struct sysrq_state {
+       struct input_handle handle;
+       struct work_struct reinject_work;
+       unsigned long key_down[BITS_TO_LONGS(KEY_CNT)];
+       unsigned int alt;
+       unsigned int alt_use;
+       bool active;
+       bool need_reinject;
+};
+
+static void sysrq_reinject_alt_sysrq(struct work_struct *work)
+{
+       struct sysrq_state *sysrq =
+                       container_of(work, struct sysrq_state, reinject_work);
+       struct input_handle *handle = &sysrq->handle;
+       unsigned int alt_code = sysrq->alt_use;
+
+       if (sysrq->need_reinject) {
+               /* Simulate press and release of Alt + SysRq */
+               input_inject_event(handle, EV_KEY, alt_code, 1);
+               input_inject_event(handle, EV_KEY, KEY_SYSRQ, 1);
+               input_inject_event(handle, EV_SYN, SYN_REPORT, 1);
+
+               input_inject_event(handle, EV_KEY, KEY_SYSRQ, 0);
+               input_inject_event(handle, EV_KEY, alt_code, 0);
+               input_inject_event(handle, EV_SYN, SYN_REPORT, 1);
+       }
+}
 
-static bool sysrq_filter(struct input_handle *handle, unsigned int type,
-                        unsigned int code, int value)
+static bool sysrq_filter(struct input_handle *handle,
+                        unsigned int type, unsigned int code, int value)
 {
+       struct sysrq_state *sysrq = handle->private;
+       bool was_active = sysrq->active;
        bool suppress;
 
-       /* We are called with interrupts disabled, just take the lock */
-       spin_lock(&sysrq_event_lock);
+       switch (type) {
 
-       if (type != EV_KEY)
-               goto out;
+       case EV_SYN:
+               suppress = false;
+               break;
 
-       switch (code) {
+       case EV_KEY:
+               switch (code) {
 
-       case KEY_LEFTALT:
-       case KEY_RIGHTALT:
-               if (value)
-                       sysrq_alt = code;
-               else {
-                       if (sysrq_down && code == sysrq_alt_use)
-                               sysrq_down = false;
+               case KEY_LEFTALT:
+               case KEY_RIGHTALT:
+                       if (!value) {
+                               /* One of ALTs is being released */
+                               if (sysrq->active && code == sysrq->alt_use)
+                                       sysrq->active = false;
 
-                       sysrq_alt = 0;
+                               sysrq->alt = KEY_RESERVED;
+
+                       } else if (value != 2) {
+                               sysrq->alt = code;
+                               sysrq->need_reinject = false;
+                       }
+                       break;
+
+               case KEY_SYSRQ:
+                       if (value == 1 && sysrq->alt != KEY_RESERVED) {
+                               sysrq->active = true;
+                               sysrq->alt_use = sysrq->alt;
+                               /*
+                                * If nothing else will be pressed we'll need
+                                * to * re-inject Alt-SysRq keysroke.
+                                */
+                               sysrq->need_reinject = true;
+                       }
+
+                       /*
+                        * Pretend that sysrq was never pressed at all. This
+                        * is needed to properly handle KGDB which will try
+                        * to release all keys after exiting debugger. If we
+                        * do not clear key bit it KGDB will end up sending
+                        * release events for Alt and SysRq, potentially
+                        * triggering print screen function.
+                        */
+                       if (sysrq->active)
+                               clear_bit(KEY_SYSRQ, handle->dev->key);
+
+                       break;
+
+               default:
+                       if (sysrq->active && value && value != 2) {
+                               sysrq->need_reinject = false;
+                               __handle_sysrq(sysrq_xlate[code], true);
+                       }
+                       break;
                }
-               break;
 
-       case KEY_SYSRQ:
-               if (value == 1 && sysrq_alt) {
-                       sysrq_down = true;
-                       sysrq_alt_use = sysrq_alt;
+               suppress = sysrq->active;
+
+               if (!sysrq->active) {
+                       /*
+                        * If we are not suppressing key presses keep track of
+                        * keyboard state so we can release keys that have been
+                        * pressed before entering SysRq mode.
+                        */
+                       if (value)
+                               set_bit(code, sysrq->key_down);
+                       else
+                               clear_bit(code, sysrq->key_down);
+
+                       if (was_active)
+                               schedule_work(&sysrq->reinject_work);
+
+               } else if (value == 0 &&
+                          test_and_clear_bit(code, sysrq->key_down)) {
+                       /*
+                        * Pass on release events for keys that was pressed before
+                        * entering SysRq mode.
+                        */
+                       suppress = false;
                }
                break;
 
        default:
-               if (sysrq_down && value && value != 2)
-                       __handle_sysrq(sysrq_xlate[code], true);
+               suppress = sysrq->active;
                break;
        }
 
-out:
-       suppress = sysrq_down;
-       spin_unlock(&sysrq_event_lock);
-
        return suppress;
 }
 
@@ -617,28 +693,28 @@ static int sysrq_connect(struct input_handler *handler,
                         struct input_dev *dev,
                         const struct input_device_id *id)
 {
-       struct input_handle *handle;
+       struct sysrq_state *sysrq;
        int error;
 
-       sysrq_down = false;
-       sysrq_alt = 0;
-
-       handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
-       if (!handle)
+       sysrq = kzalloc(sizeof(struct sysrq_state), GFP_KERNEL);
+       if (!sysrq)
                return -ENOMEM;
 
-       handle->dev = dev;
-       handle->handler = handler;
-       handle->name = "sysrq";
+       INIT_WORK(&sysrq->reinject_work, sysrq_reinject_alt_sysrq);
+
+       sysrq->handle.dev = dev;
+       sysrq->handle.handler = handler;
+       sysrq->handle.name = "sysrq";
+       sysrq->handle.private = sysrq;
 
-       error = input_register_handle(handle);
+       error = input_register_handle(&sysrq->handle);
        if (error) {
                pr_err("Failed to register input sysrq handler, error %d\n",
                        error);
                goto err_free;
        }
 
-       error = input_open_device(handle);
+       error = input_open_device(&sysrq->handle);
        if (error) {
                pr_err("Failed to open input device, error %d\n", error);
                goto err_unregister;
@@ -647,17 +723,20 @@ static int sysrq_connect(struct input_handler *handler,
        return 0;
 
  err_unregister:
-       input_unregister_handle(handle);
+       input_unregister_handle(&sysrq->handle);
  err_free:
-       kfree(handle);
+       kfree(sysrq);
        return error;
 }
 
 static void sysrq_disconnect(struct input_handle *handle)
 {
+       struct sysrq_state *sysrq = handle->private;
+
        input_close_device(handle);
+       cancel_work_sync(&sysrq->reinject_work);
        input_unregister_handle(handle);
-       kfree(handle);
+       kfree(sysrq);
 }
 
 /*
index c05c5af5aa044029561e38de9683e12a26c0c0c4..35480dd57a307e72b2893d484a86783659c6a45d 100644 (file)
@@ -559,6 +559,9 @@ void __tty_hangup(struct tty_struct *tty)
 
        tty_lock();
 
+       /* some functions below drop BTM, so we need this bit */
+       set_bit(TTY_HUPPING, &tty->flags);
+
        /* inuse_filps is protected by the single tty lock,
           this really needs to change if we want to flush the
           workqueue with the lock held */
@@ -578,6 +581,10 @@ void __tty_hangup(struct tty_struct *tty)
        }
        spin_unlock(&tty_files_lock);
 
+       /*
+        * it drops BTM and thus races with reopen
+        * we protect the race by TTY_HUPPING
+        */
        tty_ldisc_hangup(tty);
 
        read_lock(&tasklist_lock);
@@ -615,7 +622,6 @@ void __tty_hangup(struct tty_struct *tty)
        tty->session = NULL;
        tty->pgrp = NULL;
        tty->ctrl_status = 0;
-       set_bit(TTY_HUPPED, &tty->flags);
        spin_unlock_irqrestore(&tty->ctrl_lock, flags);
 
        /* Account for the p->signal references we killed */
@@ -641,6 +647,7 @@ void __tty_hangup(struct tty_struct *tty)
         * can't yet guarantee all that.
         */
        set_bit(TTY_HUPPED, &tty->flags);
+       clear_bit(TTY_HUPPING, &tty->flags);
        tty_ldisc_enable(tty);
 
        tty_unlock();
@@ -1310,7 +1317,9 @@ static int tty_reopen(struct tty_struct *tty)
 {
        struct tty_driver *driver = tty->driver;
 
-       if (test_bit(TTY_CLOSING, &tty->flags))
+       if (test_bit(TTY_CLOSING, &tty->flags) ||
+                       test_bit(TTY_HUPPING, &tty->flags) ||
+                       test_bit(TTY_LDISC_CHANGING, &tty->flags))
                return -EIO;
 
        if (driver->type == TTY_DRIVER_TYPE_PTY &&
index d8e96b005023ad21ff22d143203ab0d59fb09611..4214d58276f709a8743c03f431cef5b6360c2b46 100644 (file)
@@ -454,6 +454,8 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld)
                 /* BTM here locks versus a hangup event */
                WARN_ON(!tty_locked());
                ret = ld->ops->open(tty);
+               if (ret)
+                       clear_bit(TTY_LDISC_OPEN, &tty->flags);
                return ret;
        }
        return 0;
index a858d2b87b942e13840b005e54079ab0d296354b..51fe1795d5a8197678a5a00763f62e8a9fe59183 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright(C) 2005, Benedikt Spranger <b.spranger@linutronix.de>
  * Copyright(C) 2005, Thomas Gleixner <tglx@linutronix.de>
- * Copyright(C) 2006, Hans J. Koch <hjk@linutronix.de>
+ * Copyright(C) 2006, Hans J. Koch <hjk@hansjkoch.de>
  * Copyright(C) 2006, Greg Kroah-Hartman <greg@kroah.com>
  *
  * Userspace IO
index a8ea2f19a0ccfb3a62b1649c28b54e810703d624..a84a451159edb2677ea0cad2ef2e7dd24211833f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * UIO Hilscher CIF card driver
  *
- * (C) 2007 Hans J. Koch <hjk@linutronix.de>
+ * (C) 2007 Hans J. Koch <hjk@hansjkoch.de>
  * Original code (C) 2005 Benedikt Spranger <b.spranger@linutronix.de>
  *
  * Licensed under GPL version 2 only.
index 5a18e9f7b8362787dbf60c0dc09fe48c23d627be..5ffdb483b0157a0c3998ae5cb8c1c0a316bb627a 100644 (file)
@@ -2,7 +2,7 @@
  * UIO driver for Hilscher NetX based fieldbus cards (cifX, comX).
  * See http://www.hilscher.com for details.
  *
- * (C) 2007 Hans J. Koch <hjk@linutronix.de>
+ * (C) 2007 Hans J. Koch <hjk@hansjkoch.de>
  * (C) 2008 Manuel Traut <manut@linutronix.de>
  *
  * Licensed under GPL version 2 only.
index ea071a5b6eee6aa929827851966dec80dfe070a0..44447f54942f6d6e1c7c7e2a777b4c882f6b546d 100644 (file)
@@ -2301,7 +2301,7 @@ out:
        return ret;
 }
 
-static DEVICE_ATTR(stat_status, S_IWUGO | S_IRUGO, read_status, reboot);
+static DEVICE_ATTR(stat_status, S_IWUSR | S_IRUGO, read_status, reboot);
 
 static ssize_t read_human_status(struct device *dev,
                        struct device_attribute *attr, char *buf)
@@ -2364,8 +2364,7 @@ out:
        return ret;
 }
 
-static DEVICE_ATTR(stat_human_status, S_IWUGO | S_IRUGO,
-                               read_human_status, NULL);
+static DEVICE_ATTR(stat_human_status, S_IRUGO, read_human_status, NULL);
 
 static ssize_t read_delin(struct device *dev, struct device_attribute *attr,
                char *buf)
@@ -2397,7 +2396,7 @@ out:
        return ret;
 }
 
-static DEVICE_ATTR(stat_delin, S_IWUGO | S_IRUGO, read_delin, NULL);
+static DEVICE_ATTR(stat_delin, S_IRUGO, read_delin, NULL);
 
 #define UEA_ATTR(name, reset)                                  \
                                                                \
index 05bf5a27b5b0491fd7fd6feaddb24f51983317d3..989e16e4ab5c4b4057f2069927d03474e8441a5c 100644 (file)
@@ -951,7 +951,9 @@ static int usbatm_atm_init(struct usbatm_data *instance)
         * condition: callbacks we register can be executed at once, before we have
         * initialized the struct atm_dev.  To protect against this, all callbacks
         * abort if atm_dev->dev_data is NULL. */
-       atm_dev = atm_dev_register(instance->driver_name, &usbatm_atm_devops, -1, NULL);
+       atm_dev = atm_dev_register(instance->driver_name,
+                                  &instance->usb_intf->dev, &usbatm_atm_devops,
+                                  -1, NULL);
        if (!atm_dev) {
                usb_err(instance, "%s: failed to register ATM device!\n", __func__);
                return -1;
@@ -966,14 +968,6 @@ static int usbatm_atm_init(struct usbatm_data *instance)
        /* temp init ATM device, set to 128kbit */
        atm_dev->link_rate = 128 * 1000 / 424;
 
-       ret = sysfs_create_link(&atm_dev->class_dev.kobj,
-                               &instance->usb_intf->dev.kobj, "device");
-       if (ret) {
-               atm_err(instance, "%s: sysfs_create_link failed: %d\n",
-                                       __func__, ret);
-               goto fail_sysfs;
-       }
-
        if (instance->driver->atm_start && ((ret = instance->driver->atm_start(instance, atm_dev)) < 0)) {
                atm_err(instance, "%s: atm_start failed: %d!\n", __func__, ret);
                goto fail;
@@ -992,8 +986,6 @@ static int usbatm_atm_init(struct usbatm_data *instance)
        return 0;
 
  fail:
-       sysfs_remove_link(&atm_dev->class_dev.kobj, "device");
- fail_sysfs:
        instance->atm_dev = NULL;
        atm_dev_deregister(atm_dev); /* usbatm_atm_dev_close will eventually be called */
        return ret;
@@ -1329,7 +1321,6 @@ void usbatm_usb_disconnect(struct usb_interface *intf)
 
        /* ATM finalize */
        if (instance->atm_dev) {
-               sysfs_remove_link(&instance->atm_dev->class_dev.kobj, "device");
                atm_dev_deregister(instance->atm_dev);
                instance->atm_dev = NULL;
        }
index 9eed5b52d9de22647f6ca7e94791cd97f6e60122..bcc24779ba0e3145f713dd7bf6c0f73368763de3 100644 (file)
@@ -107,11 +107,19 @@ config USB_SUSPEND
          If you are unsure about this, say N here.
 
 config USB_OTG
-       bool
+       bool "OTG support"
        depends on USB && EXPERIMENTAL
        depends on USB_SUSPEND
        default n
-
+       help
+         The most notable feature of USB OTG is support for a
+         "Dual-Role" device, which can act as either a device
+         or a host. The initial role is decided by the type of
+         plug inserted and can be changed later when two dual
+         role devices talk to each other.
+
+         Select this only if your board has Mini-AB/Micro-AB
+         connector.
 
 config USB_OTG_WHITELIST
        bool "Rely on OTG Targeted Peripherals List"
index 61800f77dac80f0064cd7184f858241a35e2fc8c..ced846ac4141e6f4540e0012f73afb9931b5de63 100644 (file)
@@ -1330,6 +1330,8 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
         */
 
        if (usb_endpoint_xfer_control(&urb->ep->desc)) {
+               if (hcd->self.uses_pio_for_control)
+                       return ret;
                if (hcd->self.uses_dma) {
                        urb->setup_dma = dma_map_single(
                                        hcd->self.controller,
index b5e20e873cbad09bbebb7134929cf97880532bea..717ff653fa2330a9e5b78774b1a084f80186faf0 100644 (file)
@@ -2017,7 +2017,7 @@ static int __init usba_udc_probe(struct platform_device *pdev)
                        }
                } else {
                        /* gpio_request fail so use -EINVAL for gpio_is_valid */
-                       ubc->vbus_pin = -EINVAL;
+                       udc->vbus_pin = -EINVAL;
                }
        }
 
index 7b5cc16e4a0bbc4b61e0627df7bee1479fbda2f4..8572dad5ecbbffd0e0eb71ece46559b30ca6f796 100644 (file)
@@ -1047,9 +1047,9 @@ composite_unbind(struct usb_gadget *gadget)
                kfree(cdev->req->buf);
                usb_ep_free_request(gadget->ep0, cdev->req);
        }
+       device_remove_file(&gadget->dev, &dev_attr_suspended);
        kfree(cdev);
        set_gadget_data(gadget, NULL);
-       device_remove_file(&gadget->dev, &dev_attr_suspended);
        composite = NULL;
 }
 
@@ -1107,14 +1107,6 @@ static int composite_bind(struct usb_gadget *gadget)
         */
        usb_ep_autoconfig_reset(cdev->gadget);
 
-       /* standardized runtime overrides for device ID data */
-       if (idVendor)
-               cdev->desc.idVendor = cpu_to_le16(idVendor);
-       if (idProduct)
-               cdev->desc.idProduct = cpu_to_le16(idProduct);
-       if (bcdDevice)
-               cdev->desc.bcdDevice = cpu_to_le16(bcdDevice);
-
        /* composite gadget needs to assign strings for whole device (like
         * serial number), register function drivers, potentially update
         * power state and consumption, etc
@@ -1126,6 +1118,14 @@ static int composite_bind(struct usb_gadget *gadget)
        cdev->desc = *composite->dev;
        cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
 
+       /* standardized runtime overrides for device ID data */
+       if (idVendor)
+               cdev->desc.idVendor = cpu_to_le16(idVendor);
+       if (idProduct)
+               cdev->desc.idProduct = cpu_to_le16(idProduct);
+       if (bcdDevice)
+               cdev->desc.bcdDevice = cpu_to_le16(bcdDevice);
+
        /* stirng overrides */
        if (iManufacturer || !cdev->desc.iManufacturer) {
                if (!iManufacturer && !composite->iManufacturer &&
index 86afdc73322f21787bf0d1e003acbe563f8f316e..6e2599661b5bdcad9323185bd992dbdb7df45b21 100644 (file)
@@ -1067,7 +1067,7 @@ static inline void create_debug_files (struct ehci_hcd *ehci)
                                                    &debug_registers_fops))
                goto file_error;
 
-       if (!debugfs_create_file("lpm", S_IRUGO|S_IWUGO, ehci->debug_dir, bus,
+       if (!debugfs_create_file("lpm", S_IRUGO|S_IWUSR, ehci->debug_dir, bus,
                                                    &debug_lpm_fops))
                goto file_error;
 
index 502a7e6fef42a5a5c9ddbfa0ca26b4b971b043e1..e9062806d4a24898286240f139a2f28dadd8522c 100644 (file)
@@ -1063,10 +1063,11 @@ rescan:
                                tmp && tmp != qh;
                                tmp = tmp->qh_next.qh)
                        continue;
-               /* periodic qh self-unlinks on empty */
-               if (!tmp)
-                       goto nogood;
-               unlink_async (ehci, qh);
+               /* periodic qh self-unlinks on empty, and a COMPLETING qh
+                * may already be unlinked.
+                */
+               if (tmp)
+                       unlink_async(ehci, qh);
                /* FALL THROUGH */
        case QH_STATE_UNLINK:           /* wait for hw to finish? */
        case QH_STATE_UNLINK_WAIT:
@@ -1083,7 +1084,6 @@ idle_timeout:
                }
                /* else FALL THROUGH */
        default:
-nogood:
                /* caller was supposed to have unlinked any requests;
                 * that's not our job.  just leak this memory.
                 */
index d36e4e75e08d4e476249a71259d8d760d5158a7b..12f70c302b0b73089451e8e93dbeb66f3c068723 100644 (file)
@@ -141,6 +141,10 @@ static void ehci_mem_cleanup (struct ehci_hcd *ehci)
                qh_put (ehci->async);
        ehci->async = NULL;
 
+       if (ehci->dummy)
+               qh_put(ehci->dummy);
+       ehci->dummy = NULL;
+
        /* DMA consistent memory and pools */
        if (ehci->qtd_pool)
                dma_pool_destroy (ehci->qtd_pool);
@@ -227,8 +231,26 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
        if (ehci->periodic == NULL) {
                goto fail;
        }
-       for (i = 0; i < ehci->periodic_size; i++)
-               ehci->periodic [i] = EHCI_LIST_END(ehci);
+
+       if (ehci->use_dummy_qh) {
+               struct ehci_qh_hw       *hw;
+               ehci->dummy = ehci_qh_alloc(ehci, flags);
+               if (!ehci->dummy)
+                       goto fail;
+
+               hw = ehci->dummy->hw;
+               hw->hw_next = EHCI_LIST_END(ehci);
+               hw->hw_qtd_next = EHCI_LIST_END(ehci);
+               hw->hw_alt_next = EHCI_LIST_END(ehci);
+               hw->hw_token &= ~QTD_STS_ACTIVE;
+               ehci->dummy->hw = hw;
+
+               for (i = 0; i < ehci->periodic_size; i++)
+                       ehci->periodic[i] = ehci->dummy->qh_dma;
+       } else {
+               for (i = 0; i < ehci->periodic_size; i++)
+                       ehci->periodic[i] = EHCI_LIST_END(ehci);
+       }
 
        /* software shadow of hardware table */
        ehci->pshadow = kcalloc(ehci->periodic_size, sizeof(void *), flags);
index a1e8d273103f77b2d237a5f68438b289b51bb92a..655f3c9f88bfbb6740e0ac5cc377b45c1af8adae 100644 (file)
@@ -103,6 +103,19 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
        if (retval)
                return retval;
 
+       if ((pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == 0x7808) ||
+           (pdev->vendor == PCI_VENDOR_ID_ATI && pdev->device == 0x4396)) {
+               /* EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may
+                * read/write memory space which does not belong to it when
+                * there is NULL pointer with T-bit set to 1 in the frame list
+                * table. To avoid the issue, the frame list link pointer
+                * should always contain a valid pointer to a inactive qh.
+                */
+               ehci->use_dummy_qh = 1;
+               ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI "
+                               "dummy qh workaround\n");
+       }
+
        /* data structure init */
        retval = ehci_init(hcd);
        if (retval)
@@ -148,6 +161,18 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                        if (pdev->revision < 0xa4)
                                ehci->no_selective_suspend = 1;
                        break;
+
+               /* MCP89 chips on the MacBookAir3,1 give EPROTO when
+                * fetching device descriptors unless LPM is disabled.
+                * There are also intermittent problems enumerating
+                * devices with PPCD enabled.
+                */
+               case 0x0d9d:
+                       ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89");
+                       ehci->has_lpm = 0;
+                       ehci->has_ppcd = 0;
+                       ehci->command &= ~CMD_PPCEE;
+                       break;
                }
                break;
        case PCI_VENDOR_ID_VIA:
index a92526d6e5aeb4a306442df77d27b702e00c0d0c..d9f78eb265721bb065f23482e482b50d2bc8430a 100644 (file)
@@ -98,7 +98,14 @@ static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
         */
        *prev_p = *periodic_next_shadow(ehci, &here,
                        Q_NEXT_TYPE(ehci, *hw_p));
-       *hw_p = *shadow_next_periodic(ehci, &here, Q_NEXT_TYPE(ehci, *hw_p));
+
+       if (!ehci->use_dummy_qh ||
+           *shadow_next_periodic(ehci, &here, Q_NEXT_TYPE(ehci, *hw_p))
+                       != EHCI_LIST_END(ehci))
+               *hw_p = *shadow_next_periodic(ehci, &here,
+                               Q_NEXT_TYPE(ehci, *hw_p));
+       else
+               *hw_p = ehci->dummy->qh_dma;
 }
 
 /* how many of the uframe's 125 usecs are allocated? */
@@ -2335,7 +2342,11 @@ restart:
                                 * pointer for much longer, if at all.
                                 */
                                *q_p = q.itd->itd_next;
-                               *hw_p = q.itd->hw_next;
+                               if (!ehci->use_dummy_qh ||
+                                   q.itd->hw_next != EHCI_LIST_END(ehci))
+                                       *hw_p = q.itd->hw_next;
+                               else
+                                       *hw_p = ehci->dummy->qh_dma;
                                type = Q_NEXT_TYPE(ehci, q.itd->hw_next);
                                wmb();
                                modified = itd_complete (ehci, q.itd);
@@ -2368,7 +2379,11 @@ restart:
                                 * URB completion.
                                 */
                                *q_p = q.sitd->sitd_next;
-                               *hw_p = q.sitd->hw_next;
+                               if (!ehci->use_dummy_qh ||
+                                   q.sitd->hw_next != EHCI_LIST_END(ehci))
+                                       *hw_p = q.sitd->hw_next;
+                               else
+                                       *hw_p = ehci->dummy->qh_dma;
                                type = Q_NEXT_TYPE(ehci, q.sitd->hw_next);
                                wmb();
                                modified = sitd_complete (ehci, q.sitd);
index bde823f704e9a6d496cf735f08658fa7f2f6397b..ba8eab366b823fd7153879a801ce7a60c915af08 100644 (file)
@@ -73,6 +73,7 @@ struct ehci_hcd {                     /* one per controller */
 
        /* async schedule support */
        struct ehci_qh          *async;
+       struct ehci_qh          *dummy;         /* For AMD quirk use */
        struct ehci_qh          *reclaim;
        unsigned                scanning : 1;
 
@@ -131,6 +132,7 @@ struct ehci_hcd {                   /* one per controller */
        unsigned                need_io_watchdog:1;
        unsigned                broken_periodic:1;
        unsigned                fs_i_thresh:1;  /* Intel iso scheduling */
+       unsigned                use_dummy_qh:1; /* AMD Frame List table quirk*/
 
        /* required for usb32 quirk */
        #define OHCI_CTRL_HCFS          (3 << 6)
index 6c4fb4efb4bb9251c531df4cabd51e8b7a65607b..43a39eb56cc6ea77af2cc7ae930392f1cd70325a 100644 (file)
@@ -2683,7 +2683,7 @@ static int __devexit isp1362_remove(struct platform_device *pdev)
        return 0;
 }
 
-static int __init isp1362_probe(struct platform_device *pdev)
+static int __devinit isp1362_probe(struct platform_device *pdev)
 {
        struct usb_hcd *hcd;
        struct isp1362_hcd *isp1362_hcd;
index fef5a1f9d483ac99a49f9c904ea2c7f692442ace..5d963e350494ee44983e6ac72428899e32db9a04 100644 (file)
@@ -229,6 +229,13 @@ void xhci_ring_device(struct xhci_hcd *xhci, int slot_id)
 static void xhci_disable_port(struct xhci_hcd *xhci, u16 wIndex,
                u32 __iomem *addr, u32 port_status)
 {
+       /* Don't allow the USB core to disable SuperSpeed ports. */
+       if (xhci->port_array[wIndex] == 0x03) {
+               xhci_dbg(xhci, "Ignoring request to disable "
+                               "SuperSpeed port.\n");
+               return;
+       }
+
        /* Write 1 to disable the port */
        xhci_writel(xhci, port_status | PORT_PE, addr);
        port_status = xhci_readl(xhci, addr);
index 202770676da30c409652dc1aca0b4d33a857d366..1d0f45f0e7a62fd191d4c856d0de87715456bfbf 100644 (file)
@@ -1045,7 +1045,7 @@ static inline u32 xhci_get_max_esit_payload(struct xhci_hcd *xhci,
        if (udev->speed == USB_SPEED_SUPER)
                return ep->ss_ep_comp.wBytesPerInterval;
 
-       max_packet = ep->desc.wMaxPacketSize & 0x3ff;
+       max_packet = GET_MAX_PACKET(ep->desc.wMaxPacketSize);
        max_burst = (ep->desc.wMaxPacketSize & 0x1800) >> 11;
        /* A 0 in max burst means 1 transfer per ESIT */
        return max_packet * (max_burst + 1);
@@ -1135,7 +1135,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
                /* Fall through */
        case USB_SPEED_FULL:
        case USB_SPEED_LOW:
-               max_packet = ep->desc.wMaxPacketSize & 0x3ff;
+               max_packet = GET_MAX_PACKET(ep->desc.wMaxPacketSize);
                ep_ctx->ep_info2 |= MAX_PACKET(max_packet);
                break;
        default:
@@ -1443,6 +1443,13 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
        xhci->dcbaa = NULL;
 
        scratchpad_free(xhci);
+
+       xhci->num_usb2_ports = 0;
+       xhci->num_usb3_ports = 0;
+       kfree(xhci->usb2_ports);
+       kfree(xhci->usb3_ports);
+       kfree(xhci->port_array);
+
        xhci->page_size = 0;
        xhci->page_shift = 0;
        xhci->bus_suspended = 0;
@@ -1627,6 +1634,166 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
                        &xhci->ir_set->erst_dequeue);
 }
 
+static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
+               u32 __iomem *addr, u8 major_revision)
+{
+       u32 temp, port_offset, port_count;
+       int i;
+
+       if (major_revision > 0x03) {
+               xhci_warn(xhci, "Ignoring unknown port speed, "
+                               "Ext Cap %p, revision = 0x%x\n",
+                               addr, major_revision);
+               /* Ignoring port protocol we can't understand. FIXME */
+               return;
+       }
+
+       /* Port offset and count in the third dword, see section 7.2 */
+       temp = xhci_readl(xhci, addr + 2);
+       port_offset = XHCI_EXT_PORT_OFF(temp);
+       port_count = XHCI_EXT_PORT_COUNT(temp);
+       xhci_dbg(xhci, "Ext Cap %p, port offset = %u, "
+                       "count = %u, revision = 0x%x\n",
+                       addr, port_offset, port_count, major_revision);
+       /* Port count includes the current port offset */
+       if (port_offset == 0 || (port_offset + port_count - 1) > num_ports)
+               /* WTF? "Valid values are â€˜1’ to MaxPorts" */
+               return;
+       port_offset--;
+       for (i = port_offset; i < (port_offset + port_count); i++) {
+               /* Duplicate entry.  Ignore the port if the revisions differ. */
+               if (xhci->port_array[i] != 0) {
+                       xhci_warn(xhci, "Duplicate port entry, Ext Cap %p,"
+                                       " port %u\n", addr, i);
+                       xhci_warn(xhci, "Port was marked as USB %u, "
+                                       "duplicated as USB %u\n",
+                                       xhci->port_array[i], major_revision);
+                       /* Only adjust the roothub port counts if we haven't
+                        * found a similar duplicate.
+                        */
+                       if (xhci->port_array[i] != major_revision &&
+                               xhci->port_array[i] != (u8) -1) {
+                               if (xhci->port_array[i] == 0x03)
+                                       xhci->num_usb3_ports--;
+                               else
+                                       xhci->num_usb2_ports--;
+                               xhci->port_array[i] = (u8) -1;
+                       }
+                       /* FIXME: Should we disable the port? */
+                       continue;
+               }
+               xhci->port_array[i] = major_revision;
+               if (major_revision == 0x03)
+                       xhci->num_usb3_ports++;
+               else
+                       xhci->num_usb2_ports++;
+       }
+       /* FIXME: Should we disable ports not in the Extended Capabilities? */
+}
+
+/*
+ * Scan the Extended Capabilities for the "Supported Protocol Capabilities" that
+ * specify what speeds each port is supposed to be.  We can't count on the port
+ * speed bits in the PORTSC register being correct until a device is connected,
+ * but we need to set up the two fake roothubs with the correct number of USB
+ * 3.0 and USB 2.0 ports at host controller initialization time.
+ */
+static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
+{
+       u32 __iomem *addr;
+       u32 offset;
+       unsigned int num_ports;
+       int i, port_index;
+
+       addr = &xhci->cap_regs->hcc_params;
+       offset = XHCI_HCC_EXT_CAPS(xhci_readl(xhci, addr));
+       if (offset == 0) {
+               xhci_err(xhci, "No Extended Capability registers, "
+                               "unable to set up roothub.\n");
+               return -ENODEV;
+       }
+
+       num_ports = HCS_MAX_PORTS(xhci->hcs_params1);
+       xhci->port_array = kzalloc(sizeof(*xhci->port_array)*num_ports, flags);
+       if (!xhci->port_array)
+               return -ENOMEM;
+
+       /*
+        * For whatever reason, the first capability offset is from the
+        * capability register base, not from the HCCPARAMS register.
+        * See section 5.3.6 for offset calculation.
+        */
+       addr = &xhci->cap_regs->hc_capbase + offset;
+       while (1) {
+               u32 cap_id;
+
+               cap_id = xhci_readl(xhci, addr);
+               if (XHCI_EXT_CAPS_ID(cap_id) == XHCI_EXT_CAPS_PROTOCOL)
+                       xhci_add_in_port(xhci, num_ports, addr,
+                                       (u8) XHCI_EXT_PORT_MAJOR(cap_id));
+               offset = XHCI_EXT_CAPS_NEXT(cap_id);
+               if (!offset || (xhci->num_usb2_ports + xhci->num_usb3_ports)
+                               == num_ports)
+                       break;
+               /*
+                * Once you're into the Extended Capabilities, the offset is
+                * always relative to the register holding the offset.
+                */
+               addr += offset;
+       }
+
+       if (xhci->num_usb2_ports == 0 && xhci->num_usb3_ports == 0) {
+               xhci_warn(xhci, "No ports on the roothubs?\n");
+               return -ENODEV;
+       }
+       xhci_dbg(xhci, "Found %u USB 2.0 ports and %u USB 3.0 ports.\n",
+                       xhci->num_usb2_ports, xhci->num_usb3_ports);
+       /*
+        * Note we could have all USB 3.0 ports, or all USB 2.0 ports.
+        * Not sure how the USB core will handle a hub with no ports...
+        */
+       if (xhci->num_usb2_ports) {
+               xhci->usb2_ports = kmalloc(sizeof(*xhci->usb2_ports)*
+                               xhci->num_usb2_ports, flags);
+               if (!xhci->usb2_ports)
+                       return -ENOMEM;
+
+               port_index = 0;
+               for (i = 0; i < num_ports; i++) {
+                       if (xhci->port_array[i] == 0x03 ||
+                                       xhci->port_array[i] == 0 ||
+                                       xhci->port_array[i] == -1)
+                               continue;
+
+                       xhci->usb2_ports[port_index] =
+                               &xhci->op_regs->port_status_base +
+                               NUM_PORT_REGS*i;
+                       xhci_dbg(xhci, "USB 2.0 port at index %u, "
+                                       "addr = %p\n", i,
+                                       xhci->usb2_ports[port_index]);
+                       port_index++;
+               }
+       }
+       if (xhci->num_usb3_ports) {
+               xhci->usb3_ports = kmalloc(sizeof(*xhci->usb3_ports)*
+                               xhci->num_usb3_ports, flags);
+               if (!xhci->usb3_ports)
+                       return -ENOMEM;
+
+               port_index = 0;
+               for (i = 0; i < num_ports; i++)
+                       if (xhci->port_array[i] == 0x03) {
+                               xhci->usb3_ports[port_index] =
+                                       &xhci->op_regs->port_status_base +
+                                       NUM_PORT_REGS*i;
+                               xhci_dbg(xhci, "USB 3.0 port at index %u, "
+                                               "addr = %p\n", i,
+                                               xhci->usb3_ports[port_index]);
+                               port_index++;
+                       }
+       }
+       return 0;
+}
 
 int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
 {
@@ -1809,6 +1976,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
 
        if (scratchpad_alloc(xhci, flags))
                goto fail;
+       if (xhci_setup_port_arrays(xhci, flags))
+               goto fail;
 
        return 0;
 
index 9f3115e729b173605cb36c278509b7befb68f825..df558f6f84e30eff6d6df0fc61c3bd67fb183387 100644 (file)
@@ -2104,7 +2104,6 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
 
        if (!(status & STS_EINT)) {
                spin_unlock(&xhci->lock);
-               xhci_warn(xhci, "Spurious interrupt.\n");
                return IRQ_NONE;
        }
        xhci_dbg(xhci, "op reg status = %08x\n", status);
index 5d7d4e951ea4bc951c4783729472467a383ec1c2..45e4a3108cc31285fcb41c7a83972a621a72a68b 100644 (file)
@@ -577,6 +577,65 @@ static void xhci_restore_registers(struct xhci_hcd *xhci)
        xhci_write_64(xhci, xhci->s3.erst_base, &xhci->ir_set->erst_base);
 }
 
+static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci)
+{
+       u64     val_64;
+
+       /* step 2: initialize command ring buffer */
+       val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
+       val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
+               (xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
+                                     xhci->cmd_ring->dequeue) &
+                (u64) ~CMD_RING_RSVD_BITS) |
+               xhci->cmd_ring->cycle_state;
+       xhci_dbg(xhci, "// Setting command ring address to 0x%llx\n",
+                       (long unsigned long) val_64);
+       xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
+}
+
+/*
+ * The whole command ring must be cleared to zero when we suspend the host.
+ *
+ * The host doesn't save the command ring pointer in the suspend well, so we
+ * need to re-program it on resume.  Unfortunately, the pointer must be 64-byte
+ * aligned, because of the reserved bits in the command ring dequeue pointer
+ * register.  Therefore, we can't just set the dequeue pointer back in the
+ * middle of the ring (TRBs are 16-byte aligned).
+ */
+static void xhci_clear_command_ring(struct xhci_hcd *xhci)
+{
+       struct xhci_ring *ring;
+       struct xhci_segment *seg;
+
+       ring = xhci->cmd_ring;
+       seg = ring->deq_seg;
+       do {
+               memset(seg->trbs, 0, SEGMENT_SIZE);
+               seg = seg->next;
+       } while (seg != ring->deq_seg);
+
+       /* Reset the software enqueue and dequeue pointers */
+       ring->deq_seg = ring->first_seg;
+       ring->dequeue = ring->first_seg->trbs;
+       ring->enq_seg = ring->deq_seg;
+       ring->enqueue = ring->dequeue;
+
+       /*
+        * Ring is now zeroed, so the HW should look for change of ownership
+        * when the cycle bit is set to 1.
+        */
+       ring->cycle_state = 1;
+
+       /*
+        * Reset the hardware dequeue pointer.
+        * Yes, this will need to be re-written after resume, but we're paranoid
+        * and want to make sure the hardware doesn't access bogus memory
+        * because, say, the BIOS or an SMI started the host without changing
+        * the command ring pointers.
+        */
+       xhci_set_cmd_ring_deq(xhci);
+}
+
 /*
  * Stop HC (not bus-specific)
  *
@@ -604,6 +663,7 @@ int xhci_suspend(struct xhci_hcd *xhci)
                spin_unlock_irq(&xhci->lock);
                return -ETIMEDOUT;
        }
+       xhci_clear_command_ring(xhci);
 
        /* step 3: save registers */
        xhci_save_registers(xhci);
@@ -635,7 +695,6 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
        u32                     command, temp = 0;
        struct usb_hcd          *hcd = xhci_to_hcd(xhci);
        struct pci_dev          *pdev = to_pci_dev(hcd->self.controller);
-       u64     val_64;
        int     old_state, retval;
 
        old_state = hcd->state;
@@ -648,15 +707,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
                /* step 1: restore register */
                xhci_restore_registers(xhci);
                /* step 2: initialize command ring buffer */
-               val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
-               val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
-                        (xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
-                                              xhci->cmd_ring->dequeue) &
-                        (u64) ~CMD_RING_RSVD_BITS) |
-                        xhci->cmd_ring->cycle_state;
-               xhci_dbg(xhci, "// Setting command ring address to 0x%llx\n",
-                               (long unsigned long) val_64);
-               xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
+               xhci_set_cmd_ring_deq(xhci);
                /* step 3: restore state and start state*/
                /* step 3: set CRS flag */
                command = xhci_readl(xhci, &xhci->op_regs->command);
@@ -714,6 +765,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
                return retval;
        }
 
+       spin_unlock_irq(&xhci->lock);
        /* Re-setup MSI-X */
        if (hcd->irq)
                free_irq(hcd->irq, hcd);
@@ -736,6 +788,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
                hcd->irq = pdev->irq;
        }
 
+       spin_lock_irq(&xhci->lock);
        /* step 4: set Run/Stop bit */
        command = xhci_readl(xhci, &xhci->op_regs->command);
        command |= CMD_RUN;
@@ -1496,6 +1549,15 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
                cmd_completion = command->completion;
                cmd_status = &command->status;
                command->command_trb = xhci->cmd_ring->enqueue;
+
+               /* Enqueue pointer can be left pointing to the link TRB,
+                * we must handle that
+                */
+               if ((command->command_trb->link.control & TRB_TYPE_BITMASK)
+                               == TRB_TYPE(TRB_LINK))
+                       command->command_trb =
+                               xhci->cmd_ring->enq_seg->next->trbs;
+
                list_add_tail(&command->cmd_list, &virt_dev->cmd_list);
        } else {
                in_ctx = virt_dev->in_ctx;
@@ -2219,6 +2281,15 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
        /* Attempt to submit the Reset Device command to the command ring */
        spin_lock_irqsave(&xhci->lock, flags);
        reset_device_cmd->command_trb = xhci->cmd_ring->enqueue;
+
+       /* Enqueue pointer can be left pointing to the link TRB,
+        * we must handle that
+        */
+       if ((reset_device_cmd->command_trb->link.control & TRB_TYPE_BITMASK)
+                       == TRB_TYPE(TRB_LINK))
+               reset_device_cmd->command_trb =
+                       xhci->cmd_ring->enq_seg->next->trbs;
+
        list_add_tail(&reset_device_cmd->cmd_list, &virt_dev->cmd_list);
        ret = xhci_queue_reset_device(xhci, slot_id);
        if (ret) {
index 93d3bf4d213c76dbacc8d964f72bda2a4c2c32c5..170c367112d2e8046f39ec596703c126f2050f84 100644 (file)
@@ -453,6 +453,24 @@ struct xhci_doorbell_array {
 #define STREAM_ID_TO_DB(p)     (((p) & 0xffff) << 16)
 
 
+/**
+ * struct xhci_protocol_caps
+ * @revision:          major revision, minor revision, capability ID,
+ *                     and next capability pointer.
+ * @name_string:       Four ASCII characters to say which spec this xHC
+ *                     follows, typically "USB ".
+ * @port_info:         Port offset, count, and protocol-defined information.
+ */
+struct xhci_protocol_caps {
+       u32     revision;
+       u32     name_string;
+       u32     port_info;
+};
+
+#define        XHCI_EXT_PORT_MAJOR(x)  (((x) >> 24) & 0xff)
+#define        XHCI_EXT_PORT_OFF(x)    ((x) & 0xff)
+#define        XHCI_EXT_PORT_COUNT(x)  (((x) >> 8) & 0xff)
+
 /**
  * struct xhci_container_ctx
  * @type: Type of context.  Used to calculated offsets to contained contexts.
@@ -621,6 +639,11 @@ struct xhci_ep_ctx {
 #define MAX_PACKET_MASK                (0xffff << 16)
 #define MAX_PACKET_DECODED(p)  (((p) >> 16) & 0xffff)
 
+/* Get max packet size from ep desc. Bit 10..0 specify the max packet size.
+ * USB2.0 spec 9.6.6.
+ */
+#define GET_MAX_PACKET(p)      ((p) & 0x7ff)
+
 /* tx_info bitmasks */
 #define AVG_TRB_LENGTH_FOR_EP(p)       ((p) & 0xffff)
 #define MAX_ESIT_PAYLOAD_FOR_EP(p)     (((p) & 0xffff) << 16)
@@ -1235,6 +1258,14 @@ struct xhci_hcd {
        u32                     suspended_ports[8];     /* which ports are
                                                           suspended */
        unsigned long           resume_done[MAX_HC_PORTS];
+       /* Is each xHCI roothub port a USB 3.0, USB 2.0, or USB 1.1 port? */
+       u8                      *port_array;
+       /* Array of pointers to USB 3.0 PORTSC registers */
+       u32 __iomem             **usb3_ports;
+       unsigned int            num_usb3_ports;
+       /* Array of pointers to USB 2.0 PORTSC registers */
+       u32 __iomem             **usb2_ports;
+       unsigned int            num_usb2_ports;
 };
 
 /* For testing purposes */
index 2f43c57743c9c905b26e8e06dc517df6b5bb7c26..9251773ecef4ffae6102a29f356bad68cf7dd574 100644 (file)
@@ -196,11 +196,9 @@ static ssize_t get_port1_handler(struct device *dev,
        return read_port(dev, attr, buf, 1, CYPRESS_READ_PORT_ID1);
 }
 
-static DEVICE_ATTR(port0, S_IWUGO | S_IRUGO,
-                  get_port0_handler, set_port0_handler);
+static DEVICE_ATTR(port0, S_IRUGO | S_IWUSR, get_port0_handler, set_port0_handler);
 
-static DEVICE_ATTR(port1, S_IWUGO | S_IRUGO,
-                  get_port1_handler, set_port1_handler);
+static DEVICE_ATTR(port1, S_IRUGO | S_IWUSR, get_port1_handler, set_port1_handler);
 
 
 static int cypress_probe(struct usb_interface *interface,
index d77aba46ae85675e58afb532078458b74b7b29a7..f63776a48e2a8717f37d5ebf68cb6b408a5d895a 100644 (file)
@@ -86,7 +86,7 @@ static ssize_t set_speed(struct device *dev, struct device_attribute *attr,
        return count;
 }
 
-static DEVICE_ATTR(speed, S_IWUGO | S_IRUGO, show_speed, set_speed);
+static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR, show_speed, set_speed);
 
 static int tv_probe(struct usb_interface *interface,
                    const struct usb_device_id *id)
index 63da2c3c838fd0b6495d0429a870e3b1e035e9dd..c96f51de1696581faba425fb29db3a18f9ef1458 100644 (file)
@@ -94,7 +94,7 @@ static ssize_t set_##value(struct device *dev, struct device_attribute *attr, co
        change_color(led);                                              \
        return count;                                                   \
 }                                                                      \
-static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value);
+static DEVICE_ATTR(value, S_IRUGO | S_IWUSR, show_##value, set_##value);
 show_set(blue);
 show_set(red);
 show_set(green);
index de8ef945b536d07a277c56bff506798bd90620e3..417b8f207e8b126ac5b2ee33bab0dc5fdaa232b0 100644 (file)
@@ -192,7 +192,7 @@ static ssize_t set_attr_##name(struct device *dev,          \
                                                                \
        return count;                                           \
 }                                                              \
-static DEVICE_ATTR(name, S_IWUGO | S_IRUGO, show_attr_##name, set_attr_##name);
+static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_attr_##name, set_attr_##name);
 
 static ssize_t show_attr_text(struct device *dev,
        struct device_attribute *attr, char *buf)
@@ -223,7 +223,7 @@ static ssize_t set_attr_text(struct device *dev,
        return count;
 }
 
-static DEVICE_ATTR(text, S_IWUGO | S_IRUGO, show_attr_text, set_attr_text);
+static DEVICE_ATTR(text, S_IRUGO | S_IWUSR, show_attr_text, set_attr_text);
 
 static ssize_t show_attr_decimals(struct device *dev,
        struct device_attribute *attr, char *buf)
@@ -272,8 +272,7 @@ static ssize_t set_attr_decimals(struct device *dev,
        return count;
 }
 
-static DEVICE_ATTR(decimals, S_IWUGO | S_IRUGO,
-       show_attr_decimals, set_attr_decimals);
+static DEVICE_ATTR(decimals, S_IRUGO | S_IWUSR, show_attr_decimals, set_attr_decimals);
 
 static ssize_t show_attr_textmode(struct device *dev,
        struct device_attribute *attr, char *buf)
@@ -319,8 +318,7 @@ static ssize_t set_attr_textmode(struct device *dev,
        return -EINVAL;
 }
 
-static DEVICE_ATTR(textmode, S_IWUGO | S_IRUGO,
-       show_attr_textmode, set_attr_textmode);
+static DEVICE_ATTR(textmode, S_IRUGO | S_IWUSR, show_attr_textmode, set_attr_textmode);
 
 
 MYDEV_ATTR_SIMPLE_UNSIGNED(powered, update_display_powered);
index 796e2f68f7494fad857349e9ffc82ac4f9303984..4ff21587ab03214373364681a664df5d56a66a16 100644 (file)
@@ -3,7 +3,7 @@
 /*
  *     uss720.c  --  USS720 USB Parport Cable.
  *
- *     Copyright (C) 1999, 2005
+ *     Copyright (C) 1999, 2005, 2010
  *         Thomas Sailer (t.sailer@alumni.ethz.ch)
  *
  *     This program is free software; you can redistribute it and/or modify
@@ -776,6 +776,8 @@ static const struct usb_device_id uss720_table[] = {
        { USB_DEVICE(0x0557, 0x2001) },
        { USB_DEVICE(0x0729, 0x1284) },
        { USB_DEVICE(0x1293, 0x0002) },
+       { USB_DEVICE(0x1293, 0x0002) },
+       { USB_DEVICE(0x050d, 0x0002) },
        { }                                             /* Terminating entry */
 };
 
index 719c6180b31ff1b94815737c5d129dd3aac8a408..ac5bfd619e62ab4dad5d05772ece6fcc13744159 100644 (file)
@@ -536,6 +536,7 @@ static const struct file_operations yurex_fops = {
        .open =         yurex_open,
        .release =      yurex_release,
        .fasync =       yurex_fasync,
+       .llseek =       default_llseek,
 };
 
 
index e6669fc3b8048c3dfdbbbf5ee1e1a2048561cfaf..99beebce85506128cf40d9556465900aebbd1ad4 100644 (file)
@@ -2116,12 +2116,15 @@ bad_config:
         * Otherwise, wait till the gadget driver hooks up.
         */
        if (!is_otg_enabled(musb) && is_host_enabled(musb)) {
+               struct usb_hcd  *hcd = musb_to_hcd(musb);
+
                MUSB_HST_MODE(musb);
                musb->xceiv->default_a = 1;
                musb->xceiv->state = OTG_STATE_A_IDLE;
 
                status = usb_add_hcd(musb_to_hcd(musb), -1, 0);
 
+               hcd->self.uses_pio_for_control = 1;
                DBG(1, "%s mode, status %d, devctl %02x %c\n",
                        "HOST", status,
                        musb_readb(musb->mregs, MUSB_DEVCTL),
index 36cfd060dbe55bffb7707293f3c1182ed7cbff6e..9d6ade82b9f2906b632cacaadbebdf34294dab83 100644 (file)
 
 /* ----------------------------------------------------------------------- */
 
+/* Maps the buffer to dma  */
+
+static inline void map_dma_buffer(struct musb_request *request,
+                               struct musb *musb)
+{
+       if (request->request.dma == DMA_ADDR_INVALID) {
+               request->request.dma = dma_map_single(
+                               musb->controller,
+                               request->request.buf,
+                               request->request.length,
+                               request->tx
+                                       ? DMA_TO_DEVICE
+                                       : DMA_FROM_DEVICE);
+               request->mapped = 1;
+       } else {
+               dma_sync_single_for_device(musb->controller,
+                       request->request.dma,
+                       request->request.length,
+                       request->tx
+                               ? DMA_TO_DEVICE
+                               : DMA_FROM_DEVICE);
+               request->mapped = 0;
+       }
+}
+
+/* Unmap the buffer from dma and maps it back to cpu */
+static inline void unmap_dma_buffer(struct musb_request *request,
+                               struct musb *musb)
+{
+       if (request->request.dma == DMA_ADDR_INVALID) {
+               DBG(20, "not unmapping a never mapped buffer\n");
+               return;
+       }
+       if (request->mapped) {
+               dma_unmap_single(musb->controller,
+                       request->request.dma,
+                       request->request.length,
+                       request->tx
+                               ? DMA_TO_DEVICE
+                               : DMA_FROM_DEVICE);
+               request->request.dma = DMA_ADDR_INVALID;
+               request->mapped = 0;
+       } else {
+               dma_sync_single_for_cpu(musb->controller,
+                       request->request.dma,
+                       request->request.length,
+                       request->tx
+                               ? DMA_TO_DEVICE
+                               : DMA_FROM_DEVICE);
+
+       }
+}
+
 /*
  * Immediately complete a request.
  *
@@ -119,24 +172,8 @@ __acquires(ep->musb->lock)
 
        ep->busy = 1;
        spin_unlock(&musb->lock);
-       if (is_dma_capable()) {
-               if (req->mapped) {
-                       dma_unmap_single(musb->controller,
-                                       req->request.dma,
-                                       req->request.length,
-                                       req->tx
-                                               ? DMA_TO_DEVICE
-                                               : DMA_FROM_DEVICE);
-                       req->request.dma = DMA_ADDR_INVALID;
-                       req->mapped = 0;
-               } else if (req->request.dma != DMA_ADDR_INVALID)
-                       dma_sync_single_for_cpu(musb->controller,
-                                       req->request.dma,
-                                       req->request.length,
-                                       req->tx
-                                               ? DMA_TO_DEVICE
-                                               : DMA_FROM_DEVICE);
-       }
+       if (is_dma_capable() && ep->dma)
+               unmap_dma_buffer(req, musb);
        if (request->status == 0)
                DBG(5, "%s done request %p,  %d/%d\n",
                                ep->end_point.name, request,
@@ -395,6 +432,13 @@ static void txstate(struct musb *musb, struct musb_request *req)
 #endif
 
        if (!use_dma) {
+               /*
+                * Unmap the dma buffer back to cpu if dma channel
+                * programming fails
+                */
+               if (is_dma_capable() && musb_ep->dma)
+                       unmap_dma_buffer(req, musb);
+
                musb_write_fifo(musb_ep->hw_ep, fifo_count,
                                (u8 *) (request->buf + request->actual));
                request->actual += fifo_count;
@@ -713,6 +757,21 @@ static void rxstate(struct musb *musb, struct musb_request *req)
                                        return;
                        }
 #endif
+                       /*
+                        * Unmap the dma buffer back to cpu if dma channel
+                        * programming fails. This buffer is mapped if the
+                        * channel allocation is successful
+                        */
+                        if (is_dma_capable() && musb_ep->dma) {
+                               unmap_dma_buffer(req, musb);
+
+                               /*
+                                * Clear DMAENAB and AUTOCLEAR for the
+                                * PIO mode transfer
+                                */
+                               csr &= ~(MUSB_RXCSR_DMAENAB | MUSB_RXCSR_AUTOCLEAR);
+                               musb_writew(epio, MUSB_RXCSR, csr);
+                       }
 
                        musb_read_fifo(musb_ep->hw_ep, fifo_count, (u8 *)
                                        (request->buf + request->actual));
@@ -837,7 +896,9 @@ void musb_g_rx(struct musb *musb, u8 epnum)
                if (!request)
                        return;
        }
+#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_TUSB_OMAP_DMA)
 exit:
+#endif
        /* Analyze request */
        rxstate(musb, to_musb_request(request));
 }
@@ -1150,26 +1211,9 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
        request->epnum = musb_ep->current_epnum;
        request->tx = musb_ep->is_in;
 
-       if (is_dma_capable() && musb_ep->dma) {
-               if (request->request.dma == DMA_ADDR_INVALID) {
-                       request->request.dma = dma_map_single(
-                                       musb->controller,
-                                       request->request.buf,
-                                       request->request.length,
-                                       request->tx
-                                               ? DMA_TO_DEVICE
-                                               : DMA_FROM_DEVICE);
-                       request->mapped = 1;
-               } else {
-                       dma_sync_single_for_device(musb->controller,
-                                       request->request.dma,
-                                       request->request.length,
-                                       request->tx
-                                               ? DMA_TO_DEVICE
-                                               : DMA_FROM_DEVICE);
-                       request->mapped = 0;
-               }
-       } else
+       if (is_dma_capable() && musb_ep->dma)
+               map_dma_buffer(request, musb);
+       else
                request->mapped = 0;
 
        spin_lock_irqsave(&musb->lock, lockflags);
@@ -1789,6 +1833,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
                spin_unlock_irqrestore(&musb->lock, flags);
 
                if (is_otg_enabled(musb)) {
+                       struct usb_hcd  *hcd = musb_to_hcd(musb);
+
                        DBG(3, "OTG startup...\n");
 
                        /* REVISIT:  funcall to other code, which also
@@ -1803,6 +1849,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
                                musb->gadget_driver = NULL;
                                musb->g.dev.driver = NULL;
                                spin_unlock_irqrestore(&musb->lock, flags);
+                       } else {
+                               hcd->self.uses_pio_for_control = 1;
                        }
                }
        }
index bdc3ea66be692dd1155828d97971cb11970a77f5..9fea48264fa2049fe7eefd18cada2013a180a5e0 100644 (file)
@@ -1896,7 +1896,7 @@ set_a_bus_req(struct device *dev, struct device_attribute *attr,
        }
        return count;
 }
-static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUGO, get_a_bus_req, set_a_bus_req);
+static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUSR, get_a_bus_req, set_a_bus_req);
 
 static ssize_t
 get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf)
@@ -1942,8 +1942,7 @@ set_a_bus_drop(struct device *dev, struct device_attribute *attr,
        }
        return count;
 }
-static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUGO,
-       get_a_bus_drop, set_a_bus_drop);
+static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUSR, get_a_bus_drop, set_a_bus_drop);
 
 static ssize_t
 get_b_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
@@ -1988,7 +1987,7 @@ set_b_bus_req(struct device *dev, struct device_attribute *attr,
        }
        return count;
 }
-static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUGO, get_b_bus_req, set_b_bus_req);
+static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUSR, get_b_bus_req, set_b_bus_req);
 
 static ssize_t
 set_a_clr_err(struct device *dev, struct device_attribute *attr,
@@ -2012,7 +2011,7 @@ set_a_clr_err(struct device *dev, struct device_attribute *attr,
        }
        return count;
 }
-static DEVICE_ATTR(a_clr_err, S_IWUGO, NULL, set_a_clr_err);
+static DEVICE_ATTR(a_clr_err, S_IWUSR, NULL, set_a_clr_err);
 
 static struct attribute *inputs_attrs[] = {
        &dev_attr_a_bus_req.attr,
index 76f8b3556672307452c991d6144d6395c7395c65..2dec500135282af0c668d58974c7d190519cf1b7 100644 (file)
@@ -201,6 +201,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_R2000KU_TRUE_RNG) },
+       { USB_DEVICE(FTDI_VID, FTDI_VARDAAN_PID) },
        { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) },
        { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) },
        { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) },
@@ -696,6 +697,7 @@ static struct usb_device_id id_table_combined [] = {
                .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
        { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
        { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_SERIAL_VX7_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_CT29B_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) },
        { USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) },
@@ -794,6 +796,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) },
        { USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { },                                    /* Optional parameter entry */
index 263f625511972137585c8cdcee3f1fe7a0a74ab9..bf0867285481bef7f839c5e2c2e7e5fa124f52bd 100644 (file)
 /* Lenz LI-USB Computer Interface. */
 #define FTDI_LENZ_LIUSB_PID    0xD780
 
+/* Vardaan Enterprises Serial Interface VEUSB422R3 */
+#define FTDI_VARDAAN_PID       0xF070
+
 /*
  * Xsens Technologies BV products (http://www.xsens.com).
  */
  */
 #define RTSYSTEMS_VID                  0x2100  /* Vendor ID */
 #define RTSYSTEMS_SERIAL_VX7_PID       0x9e52  /* Serial converter for VX-7 Radios using FT232RL */
+#define RTSYSTEMS_CT29B_PID            0x9e54  /* CT29B Radio Cable */
 
 /*
  * Bayer Ascensia Contour blood glucose meter USB-converter cable.
 #define MJSG_XM_RADIO_PID      0x937A
 #define MJSG_HD_RADIO_PID      0x937C
 
+/*
+ * D.O.Tec products (http://www.directout.eu)
+ */
+#define FTDI_DOTEC_PID 0x9868
+
 /*
  * Xverve Signalyzer tools (http://www.signalyzer.com/)
  */
index 861223f2af6eddc0a3fb3c4a449b71af9221eed4..6954de50c0ffe5e22cc85ad909af0ceef1dde4fd 100644 (file)
@@ -51,6 +51,7 @@ static struct usb_driver usb_serial_driver = {
        .suspend =      usb_serial_suspend,
        .resume =       usb_serial_resume,
        .no_dynamic_id =        1,
+       .supports_autosuspend = 1,
 };
 
 /* There is no MODULE_DEVICE_TABLE for usbserial.c.  Instead
@@ -1343,6 +1344,8 @@ int usb_serial_register(struct usb_serial_driver *driver)
                return -ENODEV;
 
        fixup_generic(driver);
+       if (driver->usb_driver)
+               driver->usb_driver->supports_autosuspend = 1;
 
        if (!driver->description)
                driver->description = driver->driver.name;
index 57fc2f532cabe985b9b10fdd57c7042b6d0fd4be..ceba512f84d0eeeb2f3170a14df915528304dbe2 100644 (file)
@@ -121,7 +121,7 @@ static ssize_t show_truinst(struct device *dev, struct device_attribute *attr,
        }
        return result;
 }
-static DEVICE_ATTR(truinst, S_IWUGO | S_IRUGO, show_truinst, NULL);
+static DEVICE_ATTR(truinst, S_IRUGO, show_truinst, NULL);
 
 int sierra_ms_init(struct us_data *us)
 {
index 6ccdd3dd5259b6887fb4b93b5a165feb83b54f51..fcc1e32ce2566332a3bc6ad41b35fdaf5a23e8ff 100644 (file)
@@ -481,6 +481,13 @@ UNUSUAL_DEV(  0x04e8, 0x507c, 0x0220, 0x0220,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_MAX_SECTORS_64),
 
+/* Reported by Vitaly Kuznetsov <vitty@altlinux.ru> */
+UNUSUAL_DEV(  0x04e8, 0x5122, 0x0000, 0x9999,
+               "Samsung",
+               "YP-CP3",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_MAX_SECTORS_64 | US_FL_BULK_IGNORE_TAG),
+
 /* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>.
  * Device uses standards-violating 32-byte Bulk Command Block Wrappers and
  * reports itself as "Proprietary SCSI Bulk." Cf. device entry 0x084d:0x0011.
index 4b4da5b86ff99337fc0d81afeb48363918df65c3..f442668a1e52e137b347419f9938d386f638b16b 100644 (file)
@@ -129,8 +129,9 @@ static void handle_tx(struct vhost_net *net)
        size_t hdr_size;
        struct socket *sock;
 
-       sock = rcu_dereference_check(vq->private_data,
-                                    lockdep_is_held(&vq->mutex));
+       /* TODO: check that we are running from vhost_worker?
+        * Not sure it's worth it, it's straight-forward enough. */
+       sock = rcu_dereference_check(vq->private_data, 1);
        if (!sock)
                return;
 
index 94701ff3a23ad957a9c675bd3ccd74418c2f989e..159c77a5746fecfd6c6eeb687cf11e747e194fba 100644 (file)
@@ -884,6 +884,7 @@ static int log_write(void __user *log_base,
        int r;
        if (!write_length)
                return 0;
+       write_length += write_address % VHOST_PAGE_SIZE;
        write_address /= VHOST_PAGE_SIZE;
        for (;;) {
                u64 base = (u64)(unsigned long)log_base;
@@ -897,7 +898,7 @@ static int log_write(void __user *log_base,
                if (write_length <= VHOST_PAGE_SIZE)
                        break;
                write_length -= VHOST_PAGE_SIZE;
-               write_address += VHOST_PAGE_SIZE;
+               write_address += 1;
        }
        return r;
 }
index 27c1fb4b1e0d71f91dcdd7d528dafa3b3457cb32..e231041a5e3395977762c1555331cc7f72cde92c 100644 (file)
@@ -186,6 +186,14 @@ config FB_SYS_FOPS
        depends on FB
        default n
 
+config FB_WMT_GE_ROPS
+       tristate
+       depends on FB
+       default n
+       ---help---
+         Include functions for accelerated rectangle filling and area
+         copying using WonderMedia Graphics Engine operations.
+
 config FB_DEFERRED_IO
        bool
        depends on FB
@@ -635,6 +643,72 @@ config FB_BFIN_LQ035Q1
          To compile this driver as a module, choose M here: the
          module will be called bfin-lq035q1-fb.
 
+config FB_BF537_LQ035
+       tristate "SHARP LQ035 TFT LCD (BF537 STAMP)"
+       depends on FB && (BF534 || BF536 || BF537) && I2C_BLACKFIN_TWI
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       select BFIN_GPTIMERS
+       help
+         This is the framebuffer device for a SHARP LQ035Q7DB03 TFT LCD
+         attached to a BF537.
+
+         To compile this driver as a module, choose M here: the
+         module will be called bf537-lq035.
+
+config FB_BFIN_7393
+       tristate "Blackfin ADV7393 Video encoder"
+       depends on FB && BLACKFIN
+       select I2C
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       help
+         This is the framebuffer device for a ADV7393 video encoder
+         attached to a Blackfin on the PPI port.
+         If your Blackfin board has a ADV7393 select Y.
+
+         To compile this driver as a module, choose M here: the
+         module will be called bfin_adv7393fb.
+
+choice
+       prompt  "Video mode support"
+       depends on FB_BFIN_7393
+       default NTSC
+
+config NTSC
+       bool 'NTSC 720x480'
+
+config PAL
+       bool 'PAL 720x576'
+
+config NTSC_640x480
+       bool 'NTSC 640x480 (Experimental)'
+
+config PAL_640x480
+       bool 'PAL 640x480 (Experimental)'
+
+config NTSC_YCBCR
+       bool 'NTSC 720x480 YCbCR input'
+
+config PAL_YCBCR
+       bool 'PAL 720x576 YCbCR input'
+
+endchoice
+
+choice
+       prompt  "Size of ADV7393 frame buffer memory Single/Double Size"
+       depends on (FB_BFIN_7393)
+       default ADV7393_1XMEM
+
+config ADV7393_1XMEM
+       bool 'Single'
+
+config ADV7393_2XMEM
+       bool 'Double'
+endchoice
+
 config FB_STI
        tristate "HP STI frame buffer device support"
        depends on FB && PARISC
@@ -1722,6 +1796,24 @@ config FB_AU1200
          various panels and CRTs by passing in kernel cmd line option
          au1200fb:panel=<name>.
 
+config FB_VT8500
+       bool "VT8500 LCD Driver"
+       depends on (FB = y) && ARM && ARCH_VT8500 && VTWM_VERSION_VT8500
+       select FB_WMT_GE_ROPS
+       select FB_SYS_IMAGEBLIT
+       help
+         This is the framebuffer driver for VIA VT8500 integrated LCD
+         controller.
+
+config FB_WM8505
+       bool "WM8505 frame buffer support"
+       depends on (FB = y) && ARM && ARCH_VT8500 && VTWM_VERSION_WM8505
+       select FB_WMT_GE_ROPS
+       select FB_SYS_IMAGEBLIT
+       help
+         This is the framebuffer driver for WonderMedia WM8505
+         integrated LCD controller.
+
 source "drivers/video/geode/Kconfig"
 
 config FB_HIT
index 485e8ed1318c4bd0a055553f784b6c642ca6cf81..bdf626419433a4eace336fe8c414df14c94d7acf 100644 (file)
@@ -26,6 +26,7 @@ obj-$(CONFIG_FB_SVGALIB)       += svgalib.o
 obj-$(CONFIG_FB_MACMODES)      += macmodes.o
 obj-$(CONFIG_FB_DDC)           += fb_ddc.o
 obj-$(CONFIG_FB_DEFERRED_IO)   += fb_defio.o
+obj-$(CONFIG_FB_WMT_GE_ROPS)   += wmt_ge_rops.o
 
 # Hardware specific drivers go first
 obj-$(CONFIG_FB_AMIGA)            += amifb.o c2p_planar.o
@@ -104,6 +105,8 @@ obj-$(CONFIG_FB_W100)                 += w100fb.o
 obj-$(CONFIG_FB_TMIO)            += tmiofb.o
 obj-$(CONFIG_FB_AU1100)                  += au1100fb.o
 obj-$(CONFIG_FB_AU1200)                  += au1200fb.o
+obj-$(CONFIG_FB_VT8500)                  += vt8500lcdfb.o
+obj-$(CONFIG_FB_WM8505)                  += wm8505fb.o
 obj-$(CONFIG_FB_PMAG_AA)         += pmag-aa-fb.o
 obj-$(CONFIG_FB_PMAG_BA)         += pmag-ba-fb.o
 obj-$(CONFIG_FB_PMAGB_B)         += pmagb-b-fb.o
@@ -141,9 +144,11 @@ obj-$(CONFIG_FB_VESA)             += vesafb.o
 obj-$(CONFIG_FB_EFI)              += efifb.o
 obj-$(CONFIG_FB_VGA16)            += vga16fb.o
 obj-$(CONFIG_FB_OF)               += offb.o
+obj-$(CONFIG_FB_BF537_LQ035)      += bf537-lq035.o
 obj-$(CONFIG_FB_BF54X_LQ043)     += bf54x-lq043fb.o
 obj-$(CONFIG_FB_BFIN_LQ035Q1)     += bfin-lq035q1-fb.o
 obj-$(CONFIG_FB_BFIN_T350MCQB)   += bfin-t350mcqb-fb.o
+obj-$(CONFIG_FB_BFIN_7393)        += bfin_adv7393fb.o
 obj-$(CONFIG_FB_MX3)             += mx3fb.o
 obj-$(CONFIG_FB_DA8XX)           += da8xx-fb.o
 
index e207810bba3cfe9e0042f02bc447ad5b01564ff0..08703299ef61184bf3e0cd212601f2817e9e8e63 100644 (file)
@@ -197,12 +197,12 @@ static int backlight_suspend(struct device *dev, pm_message_t state)
 {
        struct backlight_device *bd = to_backlight_device(dev);
 
-       if (bd->ops->options & BL_CORE_SUSPENDRESUME) {
-               mutex_lock(&bd->ops_lock);
+       mutex_lock(&bd->ops_lock);
+       if (bd->ops && bd->ops->options & BL_CORE_SUSPENDRESUME) {
                bd->props.state |= BL_CORE_SUSPENDED;
                backlight_update_status(bd);
-               mutex_unlock(&bd->ops_lock);
        }
+       mutex_unlock(&bd->ops_lock);
 
        return 0;
 }
@@ -211,12 +211,12 @@ static int backlight_resume(struct device *dev)
 {
        struct backlight_device *bd = to_backlight_device(dev);
 
-       if (bd->ops->options & BL_CORE_SUSPENDRESUME) {
-               mutex_lock(&bd->ops_lock);
+       mutex_lock(&bd->ops_lock);
+       if (bd->ops && bd->ops->options & BL_CORE_SUSPENDRESUME) {
                bd->props.state &= ~BL_CORE_SUSPENDED;
                backlight_update_status(bd);
-               mutex_unlock(&bd->ops_lock);
        }
+       mutex_unlock(&bd->ops_lock);
 
        return 0;
 }
diff --git a/drivers/video/bf537-lq035.c b/drivers/video/bf537-lq035.c
new file mode 100644 (file)
index 0000000..18c5078
--- /dev/null
@@ -0,0 +1,914 @@
+/*
+ * Analog Devices Blackfin(BF537 STAMP) + SHARP TFT LCD.
+ * http://docs.blackfin.uclinux.org/doku.php?id=hw:cards:tft-lcd
+ *
+ * Copyright 2006-2010 Analog Devices Inc.
+ * Licensed under the GPL-2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/device.h>
+#include <linux/backlight.h>
+#include <linux/lcd.h>
+#include <linux/i2c.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include <asm/blackfin.h>
+#include <asm/irq.h>
+#include <asm/dpmc.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+
+#define NO_BL 1
+
+#define MAX_BRIGHENESS 95
+#define MIN_BRIGHENESS 5
+#define NBR_PALETTE    256
+
+static const unsigned short ppi_pins[] = {
+       P_PPI0_CLK, P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
+       P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
+       P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
+       P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15, 0
+};
+
+static unsigned char *fb_buffer;          /* RGB Buffer */
+static unsigned long *dma_desc_table;
+static int t_conf_done, lq035_open_cnt;
+static DEFINE_SPINLOCK(bfin_lq035_lock);
+
+static int landscape;
+module_param(landscape, int, 0);
+MODULE_PARM_DESC(landscape,
+       "LANDSCAPE use 320x240 instead of Native 240x320 Resolution");
+
+static int bgr;
+module_param(bgr, int, 0);
+MODULE_PARM_DESC(bgr,
+       "BGR use 16-bit BGR-565 instead of RGB-565");
+
+static int nocursor = 1;
+module_param(nocursor, int, 0644);
+MODULE_PARM_DESC(nocursor, "cursor enable/disable");
+
+static unsigned long current_brightness;  /* backlight */
+
+/* AD5280 vcomm */
+static unsigned char vcomm_value = 150;
+static struct i2c_client *ad5280_client;
+
+static void set_vcomm(void)
+{
+       int nr;
+
+       if (!ad5280_client)
+               return;
+
+       nr = i2c_smbus_write_byte_data(ad5280_client, 0x00, vcomm_value);
+       if (nr)
+               pr_err("i2c_smbus_write_byte_data fail: %d\n", nr);
+}
+
+static int __devinit ad5280_probe(struct i2c_client *client,
+                                 const struct i2c_device_id *id)
+{
+       int ret;
+       if (!i2c_check_functionality(client->adapter,
+                                    I2C_FUNC_SMBUS_BYTE_DATA)) {
+               dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
+               return -EIO;
+       }
+
+       ret = i2c_smbus_write_byte_data(client, 0x00, vcomm_value);
+       if (ret) {
+               dev_err(&client->dev, "write fail: %d\n", ret);
+               return ret;
+       }
+
+       ad5280_client = client;
+
+       return 0;
+}
+
+static int __devexit ad5280_remove(struct i2c_client *client)
+{
+       ad5280_client = NULL;
+       return 0;
+}
+
+static const struct i2c_device_id ad5280_id[] = {
+       {"bf537-lq035-ad5280", 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, ad5280_id);
+
+static struct i2c_driver ad5280_driver = {
+       .driver = {
+               .name = "bf537-lq035-ad5280",
+       },
+       .probe = ad5280_probe,
+       .remove = __devexit_p(ad5280_remove),
+       .id_table = ad5280_id,
+};
+
+#ifdef CONFIG_PNAV10
+#define MOD GPIO_PH13
+
+#define bfin_write_TIMER_LP_CONFIG     bfin_write_TIMER0_CONFIG
+#define bfin_write_TIMER_LP_WIDTH      bfin_write_TIMER0_WIDTH
+#define bfin_write_TIMER_LP_PERIOD     bfin_write_TIMER0_PERIOD
+#define bfin_read_TIMER_LP_COUNTER     bfin_read_TIMER0_COUNTER
+#define TIMDIS_LP                      TIMDIS0
+#define TIMEN_LP                       TIMEN0
+
+#define bfin_write_TIMER_SPS_CONFIG    bfin_write_TIMER1_CONFIG
+#define bfin_write_TIMER_SPS_WIDTH     bfin_write_TIMER1_WIDTH
+#define bfin_write_TIMER_SPS_PERIOD    bfin_write_TIMER1_PERIOD
+#define TIMDIS_SPS                     TIMDIS1
+#define TIMEN_SPS                      TIMEN1
+
+#define bfin_write_TIMER_SP_CONFIG     bfin_write_TIMER5_CONFIG
+#define bfin_write_TIMER_SP_WIDTH      bfin_write_TIMER5_WIDTH
+#define bfin_write_TIMER_SP_PERIOD     bfin_write_TIMER5_PERIOD
+#define TIMDIS_SP                      TIMDIS5
+#define TIMEN_SP                       TIMEN5
+
+#define bfin_write_TIMER_PS_CLS_CONFIG bfin_write_TIMER2_CONFIG
+#define bfin_write_TIMER_PS_CLS_WIDTH  bfin_write_TIMER2_WIDTH
+#define bfin_write_TIMER_PS_CLS_PERIOD bfin_write_TIMER2_PERIOD
+#define TIMDIS_PS_CLS                  TIMDIS2
+#define TIMEN_PS_CLS                   TIMEN2
+
+#define bfin_write_TIMER_REV_CONFIG    bfin_write_TIMER3_CONFIG
+#define bfin_write_TIMER_REV_WIDTH     bfin_write_TIMER3_WIDTH
+#define bfin_write_TIMER_REV_PERIOD    bfin_write_TIMER3_PERIOD
+#define TIMDIS_REV                     TIMDIS3
+#define TIMEN_REV                      TIMEN3
+#define bfin_read_TIMER_REV_COUNTER    bfin_read_TIMER3_COUNTER
+
+#define        FREQ_PPI_CLK         (5*1024*1024)  /* PPI_CLK 5MHz */
+
+#define TIMERS {P_TMR0, P_TMR1, P_TMR2, P_TMR3, P_TMR5, 0}
+
+#else
+
+#define UD      GPIO_PF13      /* Up / Down */
+#define MOD     GPIO_PF10
+#define LBR     GPIO_PF14      /* Left Right */
+
+#define bfin_write_TIMER_LP_CONFIG     bfin_write_TIMER6_CONFIG
+#define bfin_write_TIMER_LP_WIDTH      bfin_write_TIMER6_WIDTH
+#define bfin_write_TIMER_LP_PERIOD     bfin_write_TIMER6_PERIOD
+#define bfin_read_TIMER_LP_COUNTER     bfin_read_TIMER6_COUNTER
+#define TIMDIS_LP                      TIMDIS6
+#define TIMEN_LP                       TIMEN6
+
+#define bfin_write_TIMER_SPS_CONFIG    bfin_write_TIMER1_CONFIG
+#define bfin_write_TIMER_SPS_WIDTH     bfin_write_TIMER1_WIDTH
+#define bfin_write_TIMER_SPS_PERIOD    bfin_write_TIMER1_PERIOD
+#define TIMDIS_SPS                     TIMDIS1
+#define TIMEN_SPS                      TIMEN1
+
+#define bfin_write_TIMER_SP_CONFIG     bfin_write_TIMER0_CONFIG
+#define bfin_write_TIMER_SP_WIDTH      bfin_write_TIMER0_WIDTH
+#define bfin_write_TIMER_SP_PERIOD     bfin_write_TIMER0_PERIOD
+#define TIMDIS_SP                      TIMDIS0
+#define TIMEN_SP                       TIMEN0
+
+#define bfin_write_TIMER_PS_CLS_CONFIG bfin_write_TIMER7_CONFIG
+#define bfin_write_TIMER_PS_CLS_WIDTH  bfin_write_TIMER7_WIDTH
+#define bfin_write_TIMER_PS_CLS_PERIOD bfin_write_TIMER7_PERIOD
+#define TIMDIS_PS_CLS                  TIMDIS7
+#define TIMEN_PS_CLS                   TIMEN7
+
+#define bfin_write_TIMER_REV_CONFIG    bfin_write_TIMER5_CONFIG
+#define bfin_write_TIMER_REV_WIDTH     bfin_write_TIMER5_WIDTH
+#define bfin_write_TIMER_REV_PERIOD    bfin_write_TIMER5_PERIOD
+#define TIMDIS_REV                     TIMDIS5
+#define TIMEN_REV                      TIMEN5
+#define bfin_read_TIMER_REV_COUNTER    bfin_read_TIMER5_COUNTER
+
+#define        FREQ_PPI_CLK         (6*1000*1000)  /* PPI_CLK 6MHz */
+#define TIMERS {P_TMR0, P_TMR1, P_TMR5, P_TMR6, P_TMR7, 0}
+
+#endif
+
+#define LCD_X_RES                      240 /* Horizontal Resolution */
+#define LCD_Y_RES                      320 /* Vertical Resolution */
+
+#define LCD_BBP                                16  /* Bit Per Pixel */
+
+/* the LCD and the DMA start counting differently;
+ * since one starts at 0 and the other starts at 1,
+ * we have a difference of 1 between START_LINES
+ * and U_LINES.
+ */
+#define START_LINES       8   /* lines for field flyback or field blanking signal */
+#define U_LINES           9   /* number of undisplayed blanking lines */
+
+#define FRAMES_PER_SEC    (60)
+
+#define DCLKS_PER_FRAME   (FREQ_PPI_CLK/FRAMES_PER_SEC)
+#define DCLKS_PER_LINE    (DCLKS_PER_FRAME/(LCD_Y_RES+U_LINES))
+
+#define PPI_CONFIG_VALUE  (PORT_DIR|XFR_TYPE|DLEN_16|POLS)
+#define PPI_DELAY_VALUE   (0)
+#define TIMER_CONFIG      (PWM_OUT|PERIOD_CNT|TIN_SEL|CLK_SEL)
+
+#define ACTIVE_VIDEO_MEM_OFFSET        (LCD_X_RES*START_LINES*(LCD_BBP/8))
+#define ACTIVE_VIDEO_MEM_SIZE  (LCD_Y_RES*LCD_X_RES*(LCD_BBP/8))
+#define TOTAL_VIDEO_MEM_SIZE   ((LCD_Y_RES+U_LINES)*LCD_X_RES*(LCD_BBP/8))
+#define TOTAL_DMA_DESC_SIZE    (2 * sizeof(u32) * (LCD_Y_RES + U_LINES))
+
+static void start_timers(void) /* CHECK with HW */
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       bfin_write_TIMER_ENABLE(TIMEN_REV);
+       SSYNC();
+
+       while (bfin_read_TIMER_REV_COUNTER() <= 11)
+               continue;
+       bfin_write_TIMER_ENABLE(TIMEN_LP);
+       SSYNC();
+
+       while (bfin_read_TIMER_LP_COUNTER() < 3)
+               continue;
+       bfin_write_TIMER_ENABLE(TIMEN_SP|TIMEN_SPS|TIMEN_PS_CLS);
+       SSYNC();
+       t_conf_done = 1;
+       local_irq_restore(flags);
+}
+
+static void config_timers(void)
+{
+       /* Stop timers */
+       bfin_write_TIMER_DISABLE(TIMDIS_SP|TIMDIS_SPS|TIMDIS_REV|
+                                TIMDIS_LP|TIMDIS_PS_CLS);
+       SSYNC();
+
+       /* LP, timer 6 */
+       bfin_write_TIMER_LP_CONFIG(TIMER_CONFIG|PULSE_HI);
+       bfin_write_TIMER_LP_WIDTH(1);
+
+       bfin_write_TIMER_LP_PERIOD(DCLKS_PER_LINE);
+       SSYNC();
+
+       /* SPS, timer 1 */
+       bfin_write_TIMER_SPS_CONFIG(TIMER_CONFIG|PULSE_HI);
+       bfin_write_TIMER_SPS_WIDTH(DCLKS_PER_LINE*2);
+       bfin_write_TIMER_SPS_PERIOD((DCLKS_PER_LINE * (LCD_Y_RES+U_LINES)));
+       SSYNC();
+
+       /* SP, timer 0 */
+       bfin_write_TIMER_SP_CONFIG(TIMER_CONFIG|PULSE_HI);
+       bfin_write_TIMER_SP_WIDTH(1);
+       bfin_write_TIMER_SP_PERIOD(DCLKS_PER_LINE);
+       SSYNC();
+
+       /* PS & CLS, timer 7 */
+       bfin_write_TIMER_PS_CLS_CONFIG(TIMER_CONFIG);
+       bfin_write_TIMER_PS_CLS_WIDTH(LCD_X_RES + START_LINES);
+       bfin_write_TIMER_PS_CLS_PERIOD(DCLKS_PER_LINE);
+
+       SSYNC();
+
+#ifdef NO_BL
+       /* REV, timer 5 */
+       bfin_write_TIMER_REV_CONFIG(TIMER_CONFIG|PULSE_HI);
+
+       bfin_write_TIMER_REV_WIDTH(DCLKS_PER_LINE);
+       bfin_write_TIMER_REV_PERIOD(DCLKS_PER_LINE*2);
+
+       SSYNC();
+#endif
+}
+
+static void config_ppi(void)
+{
+       bfin_write_PPI_DELAY(PPI_DELAY_VALUE);
+       bfin_write_PPI_COUNT(LCD_X_RES-1);
+       /* 0x10 -> PORT_CFG -> 2 or 3 frame syncs */
+       bfin_write_PPI_CONTROL((PPI_CONFIG_VALUE|0x10) & (~POLS));
+}
+
+static int config_dma(void)
+{
+       u32 i;
+
+       if (landscape) {
+
+               for (i = 0; i < U_LINES; ++i) {
+                       /* blanking lines point to first line of fb_buffer */
+                       dma_desc_table[2*i] = (unsigned long)&dma_desc_table[2*i+2];
+                       dma_desc_table[2*i+1] = (unsigned long)fb_buffer;
+               }
+
+               for (i = U_LINES; i < U_LINES + LCD_Y_RES; ++i) {
+                       /* visible lines */
+                       dma_desc_table[2*i] = (unsigned long)&dma_desc_table[2*i+2];
+                       dma_desc_table[2*i+1] = (unsigned long)fb_buffer +
+                                               (LCD_Y_RES+U_LINES-1-i)*2;
+               }
+
+               /* last descriptor points to first */
+               dma_desc_table[2*(LCD_Y_RES+U_LINES-1)] = (unsigned long)&dma_desc_table[0];
+
+               set_dma_x_count(CH_PPI, LCD_X_RES);
+               set_dma_x_modify(CH_PPI, LCD_Y_RES * (LCD_BBP / 8));
+               set_dma_y_count(CH_PPI, 0);
+               set_dma_y_modify(CH_PPI, 0);
+               set_dma_next_desc_addr(CH_PPI, (void *)dma_desc_table[0]);
+               set_dma_config(CH_PPI, DMAFLOW_LARGE | NDSIZE_4 | WDSIZE_16);
+
+       } else {
+
+               set_dma_config(CH_PPI, set_bfin_dma_config(DIR_READ,
+                               DMA_FLOW_AUTO,
+                               INTR_DISABLE,
+                               DIMENSION_2D,
+                               DATA_SIZE_16,
+                               DMA_NOSYNC_KEEP_DMA_BUF));
+               set_dma_x_count(CH_PPI, LCD_X_RES);
+               set_dma_x_modify(CH_PPI, LCD_BBP / 8);
+               set_dma_y_count(CH_PPI, LCD_Y_RES+U_LINES);
+               set_dma_y_modify(CH_PPI, LCD_BBP / 8);
+               set_dma_start_addr(CH_PPI, (unsigned long) fb_buffer);
+       }
+
+       return 0;
+}
+
+static int __devinit request_ports(void)
+{
+       u16 tmr_req[] = TIMERS;
+
+       /*
+               UD:      PF13
+               MOD:     PF10
+               LBR:     PF14
+               PPI_CLK: PF15
+       */
+
+       if (peripheral_request_list(ppi_pins, KBUILD_MODNAME)) {
+               pr_err("requesting PPI peripheral failed\n");
+               return -EBUSY;
+       }
+
+       if (peripheral_request_list(tmr_req, KBUILD_MODNAME)) {
+               peripheral_free_list(ppi_pins);
+               pr_err("requesting timer peripheral failed\n");
+               return -EBUSY;
+       }
+
+#if (defined(UD) && defined(LBR))
+       if (gpio_request(UD, KBUILD_MODNAME)) {
+               pr_err("requesting GPIO %d failed\n", UD);
+               return -EBUSY;
+       }
+
+       if (gpio_request(LBR, KBUILD_MODNAME)) {
+               pr_err("requesting GPIO %d failed\n", LBR);
+               gpio_free(UD);
+               return -EBUSY;
+       }
+
+       gpio_direction_output(UD, 0);
+       gpio_direction_output(LBR, 1);
+
+#endif
+
+       if (gpio_request(MOD, KBUILD_MODNAME)) {
+               pr_err("requesting GPIO %d failed\n", MOD);
+#if (defined(UD) && defined(LBR))
+               gpio_free(LBR);
+               gpio_free(UD);
+#endif
+               return -EBUSY;
+       }
+
+       gpio_direction_output(MOD, 1);
+
+       SSYNC();
+       return 0;
+}
+
+static void free_ports(void)
+{
+       u16 tmr_req[] = TIMERS;
+
+       peripheral_free_list(ppi_pins);
+       peripheral_free_list(tmr_req);
+
+#if defined(UD) && defined(LBR)
+       gpio_free(LBR);
+       gpio_free(UD);
+#endif
+       gpio_free(MOD);
+}
+
+static struct fb_info bfin_lq035_fb;
+
+static struct fb_var_screeninfo bfin_lq035_fb_defined = {
+       .bits_per_pixel         = LCD_BBP,
+       .activate               = FB_ACTIVATE_TEST,
+       .xres                   = LCD_X_RES,    /*default portrait mode RGB*/
+       .yres                   = LCD_Y_RES,
+       .xres_virtual           = LCD_X_RES,
+       .yres_virtual           = LCD_Y_RES,
+       .height                 = -1,
+       .width                  = -1,
+       .left_margin            = 0,
+       .right_margin           = 0,
+       .upper_margin           = 0,
+       .lower_margin           = 0,
+       .red                    = {11, 5, 0},
+       .green                  = {5, 6, 0},
+       .blue                   = {0, 5, 0},
+       .transp         = {0, 0, 0},
+};
+
+static struct fb_fix_screeninfo bfin_lq035_fb_fix __devinitdata = {
+       .id             = KBUILD_MODNAME,
+       .smem_len       = ACTIVE_VIDEO_MEM_SIZE,
+       .type           = FB_TYPE_PACKED_PIXELS,
+       .visual         = FB_VISUAL_TRUECOLOR,
+       .xpanstep       = 0,
+       .ypanstep       = 0,
+       .line_length    = LCD_X_RES*(LCD_BBP/8),
+       .accel          = FB_ACCEL_NONE,
+};
+
+
+static int bfin_lq035_fb_open(struct fb_info *info, int user)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&bfin_lq035_lock, flags);
+       lq035_open_cnt++;
+       spin_unlock_irqrestore(&bfin_lq035_lock, flags);
+
+       if (lq035_open_cnt <= 1) {
+               bfin_write_PPI_CONTROL(0);
+               SSYNC();
+
+               set_vcomm();
+               config_dma();
+               config_ppi();
+
+               /* start dma */
+               enable_dma(CH_PPI);
+               SSYNC();
+               bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
+               SSYNC();
+
+               if (!t_conf_done) {
+                       config_timers();
+                       start_timers();
+               }
+               /* gpio_set_value(MOD,1); */
+       }
+
+       return 0;
+}
+
+static int bfin_lq035_fb_release(struct fb_info *info, int user)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&bfin_lq035_lock, flags);
+       lq035_open_cnt--;
+       spin_unlock_irqrestore(&bfin_lq035_lock, flags);
+
+
+       if (lq035_open_cnt <= 0) {
+
+               bfin_write_PPI_CONTROL(0);
+               SSYNC();
+
+               disable_dma(CH_PPI);
+       }
+
+       return 0;
+}
+
+
+static int bfin_lq035_fb_check_var(struct fb_var_screeninfo *var,
+                                  struct fb_info *info)
+{
+       switch (var->bits_per_pixel) {
+       case 16:/* DIRECTCOLOUR, 64k */
+               var->red.offset = info->var.red.offset;
+               var->green.offset = info->var.green.offset;
+               var->blue.offset = info->var.blue.offset;
+               var->red.length = info->var.red.length;
+               var->green.length = info->var.green.length;
+               var->blue.length = info->var.blue.length;
+               var->transp.offset = 0;
+               var->transp.length = 0;
+               var->transp.msb_right = 0;
+               var->red.msb_right = 0;
+               var->green.msb_right = 0;
+               var->blue.msb_right = 0;
+               break;
+       default:
+               pr_debug("%s: depth not supported: %u BPP\n", __func__,
+                        var->bits_per_pixel);
+               return -EINVAL;
+       }
+
+       if (info->var.xres != var->xres ||
+           info->var.yres != var->yres ||
+           info->var.xres_virtual != var->xres_virtual ||
+           info->var.yres_virtual != var->yres_virtual) {
+               pr_debug("%s: Resolution not supported: X%u x Y%u\n",
+                        __func__, var->xres, var->yres);
+               return -EINVAL;
+       }
+
+       /*
+        *  Memory limit
+        */
+
+       if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
+               pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
+                        __func__, var->yres_virtual);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+/* fb_rotate
+ * Rotate the display of this angle. This doesn't seems to be used by the core,
+ * but as our hardware supports it, so why not implementing it...
+ */
+static void bfin_lq035_fb_rotate(struct fb_info *fbi, int angle)
+{
+       pr_debug("%s: %p %d", __func__, fbi, angle);
+#if (defined(UD) && defined(LBR))
+       switch (angle) {
+
+       case 180:
+               gpio_set_value(LBR, 0);
+               gpio_set_value(UD, 1);
+               break;
+       default:
+               gpio_set_value(LBR, 1);
+               gpio_set_value(UD, 0);
+               break;
+       }
+#endif
+}
+
+static int bfin_lq035_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+       if (nocursor)
+               return 0;
+       else
+               return -EINVAL; /* just to force soft_cursor() call */
+}
+
+static int bfin_lq035_fb_setcolreg(u_int regno, u_int red, u_int green,
+                                  u_int blue, u_int transp,
+                                  struct fb_info *info)
+{
+       if (regno >= NBR_PALETTE)
+               return -EINVAL;
+
+       if (info->var.grayscale)
+               /* grayscale = 0.30*R + 0.59*G + 0.11*B */
+               red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+
+       if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+
+               u32 value;
+               /* Place color in the pseudopalette */
+               if (regno > 16)
+                       return -EINVAL;
+
+               red   >>= (16 - info->var.red.length);
+               green >>= (16 - info->var.green.length);
+               blue  >>= (16 - info->var.blue.length);
+
+               value = (red   << info->var.red.offset) |
+                       (green << info->var.green.offset)|
+                       (blue  << info->var.blue.offset);
+               value &= 0xFFFF;
+
+               ((u32 *) (info->pseudo_palette))[regno] = value;
+
+       }
+
+       return 0;
+}
+
+static struct fb_ops bfin_lq035_fb_ops = {
+       .owner                  = THIS_MODULE,
+       .fb_open                = bfin_lq035_fb_open,
+       .fb_release             = bfin_lq035_fb_release,
+       .fb_check_var           = bfin_lq035_fb_check_var,
+       .fb_rotate              = bfin_lq035_fb_rotate,
+       .fb_fillrect            = cfb_fillrect,
+       .fb_copyarea            = cfb_copyarea,
+       .fb_imageblit           = cfb_imageblit,
+       .fb_cursor              = bfin_lq035_fb_cursor,
+       .fb_setcolreg           = bfin_lq035_fb_setcolreg,
+};
+
+static int bl_get_brightness(struct backlight_device *bd)
+{
+       return current_brightness;
+}
+
+static const struct backlight_ops bfin_lq035fb_bl_ops = {
+       .get_brightness = bl_get_brightness,
+};
+
+static struct backlight_device *bl_dev;
+
+static int bfin_lcd_get_power(struct lcd_device *dev)
+{
+       return 0;
+}
+
+static int bfin_lcd_set_power(struct lcd_device *dev, int power)
+{
+       return 0;
+}
+
+static int bfin_lcd_get_contrast(struct lcd_device *dev)
+{
+       return (int)vcomm_value;
+}
+
+static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast)
+{
+       if (contrast > 255)
+               contrast = 255;
+       if (contrast < 0)
+               contrast = 0;
+
+       vcomm_value = (unsigned char)contrast;
+       set_vcomm();
+       return 0;
+}
+
+static int bfin_lcd_check_fb(struct lcd_device *lcd, struct fb_info *fi)
+{
+       if (!fi || (fi == &bfin_lq035_fb))
+               return 1;
+       return 0;
+}
+
+static struct lcd_ops bfin_lcd_ops = {
+       .get_power      = bfin_lcd_get_power,
+       .set_power      = bfin_lcd_set_power,
+       .get_contrast   = bfin_lcd_get_contrast,
+       .set_contrast   = bfin_lcd_set_contrast,
+       .check_fb       = bfin_lcd_check_fb,
+};
+
+static struct lcd_device *lcd_dev;
+
+static int __devinit bfin_lq035_probe(struct platform_device *pdev)
+{
+       struct backlight_properties props;
+       dma_addr_t dma_handle;
+
+       if (request_dma(CH_PPI, KBUILD_MODNAME)) {
+               pr_err("couldn't request PPI DMA\n");
+               return -EFAULT;
+       }
+
+       if (request_ports()) {
+               pr_err("couldn't request gpio port\n");
+               free_dma(CH_PPI);
+               return -EFAULT;
+       }
+
+       fb_buffer = dma_alloc_coherent(NULL, TOTAL_VIDEO_MEM_SIZE,
+                                      &dma_handle, GFP_KERNEL);
+       if (fb_buffer == NULL) {
+               pr_err("couldn't allocate dma buffer\n");
+               free_dma(CH_PPI);
+               free_ports();
+               return -ENOMEM;
+       }
+
+       if (L1_DATA_A_LENGTH)
+               dma_desc_table = l1_data_sram_zalloc(TOTAL_DMA_DESC_SIZE);
+       else
+               dma_desc_table = dma_alloc_coherent(NULL, TOTAL_DMA_DESC_SIZE,
+                                                   &dma_handle, 0);
+
+       if (dma_desc_table == NULL) {
+               pr_err("couldn't allocate dma descriptor\n");
+               free_dma(CH_PPI);
+               free_ports();
+               dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
+               return -ENOMEM;
+       }
+
+       bfin_lq035_fb.screen_base = (void *)fb_buffer;
+       bfin_lq035_fb_fix.smem_start = (int)fb_buffer;
+       if (landscape) {
+               bfin_lq035_fb_defined.xres = LCD_Y_RES;
+               bfin_lq035_fb_defined.yres = LCD_X_RES;
+               bfin_lq035_fb_defined.xres_virtual = LCD_Y_RES;
+               bfin_lq035_fb_defined.yres_virtual = LCD_X_RES;
+
+               bfin_lq035_fb_fix.line_length = LCD_Y_RES*(LCD_BBP/8);
+       } else {
+               bfin_lq035_fb.screen_base += ACTIVE_VIDEO_MEM_OFFSET;
+               bfin_lq035_fb_fix.smem_start += ACTIVE_VIDEO_MEM_OFFSET;
+       }
+
+       bfin_lq035_fb_defined.green.msb_right = 0;
+       bfin_lq035_fb_defined.red.msb_right   = 0;
+       bfin_lq035_fb_defined.blue.msb_right  = 0;
+       bfin_lq035_fb_defined.green.offset    = 5;
+       bfin_lq035_fb_defined.green.length    = 6;
+       bfin_lq035_fb_defined.red.length      = 5;
+       bfin_lq035_fb_defined.blue.length     = 5;
+
+       if (bgr) {
+               bfin_lq035_fb_defined.red.offset  = 0;
+               bfin_lq035_fb_defined.blue.offset = 11;
+       } else {
+               bfin_lq035_fb_defined.red.offset  = 11;
+               bfin_lq035_fb_defined.blue.offset = 0;
+       }
+
+       bfin_lq035_fb.fbops = &bfin_lq035_fb_ops;
+       bfin_lq035_fb.var = bfin_lq035_fb_defined;
+
+       bfin_lq035_fb.fix = bfin_lq035_fb_fix;
+       bfin_lq035_fb.flags = FBINFO_DEFAULT;
+
+
+       bfin_lq035_fb.pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL);
+       if (bfin_lq035_fb.pseudo_palette == NULL) {
+               pr_err("failed to allocate pseudo_palette\n");
+               free_dma(CH_PPI);
+               free_ports();
+               dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
+               return -ENOMEM;
+       }
+
+       if (fb_alloc_cmap(&bfin_lq035_fb.cmap, NBR_PALETTE, 0) < 0) {
+               pr_err("failed to allocate colormap (%d entries)\n",
+                       NBR_PALETTE);
+               free_dma(CH_PPI);
+               free_ports();
+               dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
+               kfree(bfin_lq035_fb.pseudo_palette);
+               return -EFAULT;
+       }
+
+       if (register_framebuffer(&bfin_lq035_fb) < 0) {
+               pr_err("unable to register framebuffer\n");
+               free_dma(CH_PPI);
+               free_ports();
+               dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
+               fb_buffer = NULL;
+               kfree(bfin_lq035_fb.pseudo_palette);
+               fb_dealloc_cmap(&bfin_lq035_fb.cmap);
+               return -EINVAL;
+       }
+
+       i2c_add_driver(&ad5280_driver);
+
+       memset(&props, 0, sizeof(props));
+       props.max_brightness = MAX_BRIGHENESS;
+       bl_dev = backlight_device_register("bf537-bl", NULL, NULL,
+                                          &bfin_lq035fb_bl_ops, &props);
+
+       lcd_dev = lcd_device_register(KBUILD_MODNAME, &pdev->dev, NULL,
+                                     &bfin_lcd_ops);
+       lcd_dev->props.max_contrast = 255,
+
+       pr_info("initialized");
+
+       return 0;
+}
+
+static int __devexit bfin_lq035_remove(struct platform_device *pdev)
+{
+       if (fb_buffer != NULL)
+               dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
+
+       if (L1_DATA_A_LENGTH)
+               l1_data_sram_free(dma_desc_table);
+       else
+               dma_free_coherent(NULL, TOTAL_DMA_DESC_SIZE, NULL, 0);
+
+       bfin_write_TIMER_DISABLE(TIMEN_SP|TIMEN_SPS|TIMEN_PS_CLS|
+                                TIMEN_LP|TIMEN_REV);
+       t_conf_done = 0;
+
+       free_dma(CH_PPI);
+
+
+       kfree(bfin_lq035_fb.pseudo_palette);
+       fb_dealloc_cmap(&bfin_lq035_fb.cmap);
+
+
+       lcd_device_unregister(lcd_dev);
+       backlight_device_unregister(bl_dev);
+
+       unregister_framebuffer(&bfin_lq035_fb);
+       i2c_del_driver(&ad5280_driver);
+
+       free_ports();
+
+       pr_info("unregistered LCD driver\n");
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int bfin_lq035_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       if (lq035_open_cnt > 0) {
+               bfin_write_PPI_CONTROL(0);
+               SSYNC();
+               disable_dma(CH_PPI);
+       }
+
+       return 0;
+}
+
+static int bfin_lq035_resume(struct platform_device *pdev)
+{
+       if (lq035_open_cnt > 0) {
+               bfin_write_PPI_CONTROL(0);
+               SSYNC();
+
+               config_dma();
+               config_ppi();
+
+               enable_dma(CH_PPI);
+               bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
+               SSYNC();
+
+               config_timers();
+               start_timers();
+       } else {
+               t_conf_done = 0;
+       }
+
+       return 0;
+}
+#else
+# define bfin_lq035_suspend    NULL
+# define bfin_lq035_resume     NULL
+#endif
+
+static struct platform_driver bfin_lq035_driver = {
+       .probe = bfin_lq035_probe,
+       .remove = __devexit_p(bfin_lq035_remove),
+       .suspend = bfin_lq035_suspend,
+       .resume = bfin_lq035_resume,
+       .driver = {
+               .name = KBUILD_MODNAME,
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init bfin_lq035_driver_init(void)
+{
+       request_module("i2c-bfin-twi");
+       return platform_driver_register(&bfin_lq035_driver);
+}
+module_init(bfin_lq035_driver_init);
+
+static void __exit bfin_lq035_driver_cleanup(void)
+{
+       platform_driver_unregister(&bfin_lq035_driver);
+}
+module_exit(bfin_lq035_driver_cleanup);
+
+MODULE_DESCRIPTION("SHARP LQ035Q7DB03 TFT LCD Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/bfin_adv7393fb.c b/drivers/video/bfin_adv7393fb.c
new file mode 100644 (file)
index 0000000..8486f54
--- /dev/null
@@ -0,0 +1,832 @@
+/*
+ * Frame buffer driver for ADV7393/2 video encoder
+ *
+ * Copyright 2006-2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or late.
+ */
+
+/*
+ * TODO: Remove Globals
+ * TODO: Code Cleanup
+ */
+
+#define pr_fmt(fmt) DRIVER_NAME ": " fmt
+
+#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/ioport.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <asm/blackfin.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <linux/uaccess.h>
+#include <linux/gpio.h>
+#include <asm/portmux.h>
+
+#include <linux/dma-mapping.h>
+#include <linux/proc_fs.h>
+#include <linux/platform_device.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+
+#include "bfin_adv7393fb.h"
+
+static int mode = VMODE;
+static int mem = VMEM;
+static int nocursor = 1;
+
+static const unsigned short ppi_pins[] = {
+       P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+       P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
+       P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
+       P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
+       P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15,
+       0
+};
+
+/*
+ * card parameters
+ */
+
+static struct bfin_adv7393_fb_par {
+       /* structure holding blackfin / adv7393 paramters when
+          screen is blanked */
+       struct {
+               u8 Mode;        /* ntsc/pal/? */
+       } vga_state;
+       atomic_t ref_count;
+} bfin_par;
+
+/* --------------------------------------------------------------------- */
+
+static struct fb_var_screeninfo bfin_adv7393_fb_defined = {
+       .xres = 720,
+       .yres = 480,
+       .xres_virtual = 720,
+       .yres_virtual = 480,
+       .bits_per_pixel = 16,
+       .activate = FB_ACTIVATE_TEST,
+       .height = -1,
+       .width = -1,
+       .left_margin = 0,
+       .right_margin = 0,
+       .upper_margin = 0,
+       .lower_margin = 0,
+       .vmode = FB_VMODE_INTERLACED,
+       .red = {11, 5, 0},
+       .green = {5, 6, 0},
+       .blue = {0, 5, 0},
+       .transp = {0, 0, 0},
+};
+
+static struct fb_fix_screeninfo bfin_adv7393_fb_fix __devinitdata = {
+       .id = "BFIN ADV7393",
+       .smem_len = 720 * 480 * 2,
+       .type = FB_TYPE_PACKED_PIXELS,
+       .visual = FB_VISUAL_TRUECOLOR,
+       .xpanstep = 0,
+       .ypanstep = 0,
+       .line_length = 720 * 2,
+       .accel = FB_ACCEL_NONE
+};
+
+static struct fb_ops bfin_adv7393_fb_ops = {
+       .owner = THIS_MODULE,
+       .fb_open = bfin_adv7393_fb_open,
+       .fb_release = bfin_adv7393_fb_release,
+       .fb_check_var = bfin_adv7393_fb_check_var,
+       .fb_pan_display = bfin_adv7393_fb_pan_display,
+       .fb_blank = bfin_adv7393_fb_blank,
+       .fb_fillrect = cfb_fillrect,
+       .fb_copyarea = cfb_copyarea,
+       .fb_imageblit = cfb_imageblit,
+       .fb_cursor = bfin_adv7393_fb_cursor,
+       .fb_setcolreg = bfin_adv7393_fb_setcolreg,
+};
+
+static int dma_desc_list(struct adv7393fb_device *fbdev, u16 arg)
+{
+       if (arg == BUILD) {     /* Build */
+               fbdev->vb1 = l1_data_sram_zalloc(sizeof(struct dmasg));
+               if (fbdev->vb1 == NULL)
+                       goto error;
+
+               fbdev->av1 = l1_data_sram_zalloc(sizeof(struct dmasg));
+               if (fbdev->av1 == NULL)
+                       goto error;
+
+               fbdev->vb2 = l1_data_sram_zalloc(sizeof(struct dmasg));
+               if (fbdev->vb2 == NULL)
+                       goto error;
+
+               fbdev->av2 = l1_data_sram_zalloc(sizeof(struct dmasg));
+               if (fbdev->av2 == NULL)
+                       goto error;
+
+               /* Build linked DMA descriptor list */
+               fbdev->vb1->next_desc_addr = fbdev->av1;
+               fbdev->av1->next_desc_addr = fbdev->vb2;
+               fbdev->vb2->next_desc_addr = fbdev->av2;
+               fbdev->av2->next_desc_addr = fbdev->vb1;
+
+               /* Save list head */
+               fbdev->descriptor_list_head = fbdev->av2;
+
+               /* Vertical Blanking Field 1 */
+               fbdev->vb1->start_addr = VB_DUMMY_MEMORY_SOURCE;
+               fbdev->vb1->cfg = DMA_CFG_VAL;
+
+               fbdev->vb1->x_count =
+                   fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank;
+
+               fbdev->vb1->x_modify = 0;
+               fbdev->vb1->y_count = fbdev->modes[mode].vb1_lines;
+               fbdev->vb1->y_modify = 0;
+
+               /* Active Video Field 1 */
+
+               fbdev->av1->start_addr = (unsigned long)fbdev->fb_mem;
+               fbdev->av1->cfg = DMA_CFG_VAL;
+               fbdev->av1->x_count =
+                   fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank;
+               fbdev->av1->x_modify = fbdev->modes[mode].bpp / 8;
+               fbdev->av1->y_count = fbdev->modes[mode].a_lines;
+               fbdev->av1->y_modify =
+                   (fbdev->modes[mode].xres - fbdev->modes[mode].boeft_blank +
+                    1) * (fbdev->modes[mode].bpp / 8);
+
+               /* Vertical Blanking Field 2 */
+
+               fbdev->vb2->start_addr = VB_DUMMY_MEMORY_SOURCE;
+               fbdev->vb2->cfg = DMA_CFG_VAL;
+               fbdev->vb2->x_count =
+                   fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank;
+
+               fbdev->vb2->x_modify = 0;
+               fbdev->vb2->y_count = fbdev->modes[mode].vb2_lines;
+               fbdev->vb2->y_modify = 0;
+
+               /* Active Video Field 2 */
+
+               fbdev->av2->start_addr =
+                   (unsigned long)fbdev->fb_mem + fbdev->line_len;
+
+               fbdev->av2->cfg = DMA_CFG_VAL;
+
+               fbdev->av2->x_count =
+                   fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank;
+
+               fbdev->av2->x_modify = (fbdev->modes[mode].bpp / 8);
+               fbdev->av2->y_count = fbdev->modes[mode].a_lines;
+
+               fbdev->av2->y_modify =
+                   (fbdev->modes[mode].xres - fbdev->modes[mode].boeft_blank +
+                    1) * (fbdev->modes[mode].bpp / 8);
+
+               return 1;
+       }
+
+error:
+       l1_data_sram_free(fbdev->vb1);
+       l1_data_sram_free(fbdev->av1);
+       l1_data_sram_free(fbdev->vb2);
+       l1_data_sram_free(fbdev->av2);
+
+       return 0;
+}
+
+static int bfin_config_dma(struct adv7393fb_device *fbdev)
+{
+       BUG_ON(!(fbdev->fb_mem));
+
+       set_dma_x_count(CH_PPI, fbdev->descriptor_list_head->x_count);
+       set_dma_x_modify(CH_PPI, fbdev->descriptor_list_head->x_modify);
+       set_dma_y_count(CH_PPI, fbdev->descriptor_list_head->y_count);
+       set_dma_y_modify(CH_PPI, fbdev->descriptor_list_head->y_modify);
+       set_dma_start_addr(CH_PPI, fbdev->descriptor_list_head->start_addr);
+       set_dma_next_desc_addr(CH_PPI,
+                              fbdev->descriptor_list_head->next_desc_addr);
+       set_dma_config(CH_PPI, fbdev->descriptor_list_head->cfg);
+
+       return 1;
+}
+
+static void bfin_disable_dma(void)
+{
+       bfin_write_DMA0_CONFIG(bfin_read_DMA0_CONFIG() & ~DMAEN);
+}
+
+static void bfin_config_ppi(struct adv7393fb_device *fbdev)
+{
+       if (ANOMALY_05000183) {
+               bfin_write_TIMER2_CONFIG(WDTH_CAP);
+               bfin_write_TIMER_ENABLE(TIMEN2);
+       }
+
+       bfin_write_PPI_CONTROL(0x381E);
+       bfin_write_PPI_FRAME(fbdev->modes[mode].tot_lines);
+       bfin_write_PPI_COUNT(fbdev->modes[mode].xres +
+                            fbdev->modes[mode].boeft_blank - 1);
+       bfin_write_PPI_DELAY(fbdev->modes[mode].aoeft_blank - 1);
+}
+
+static void bfin_enable_ppi(void)
+{
+       bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
+}
+
+static void bfin_disable_ppi(void)
+{
+       bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() & ~PORT_EN);
+}
+
+static inline int adv7393_write(struct i2c_client *client, u8 reg, u8 value)
+{
+       return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+static inline int adv7393_read(struct i2c_client *client, u8 reg)
+{
+       return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int
+adv7393_write_block(struct i2c_client *client,
+                   const u8 *data, unsigned int len)
+{
+       int ret = -1;
+       u8 reg;
+
+       while (len >= 2) {
+               reg = *data++;
+               ret = adv7393_write(client, reg, *data++);
+               if (ret < 0)
+                       break;
+               len -= 2;
+       }
+
+       return ret;
+}
+
+static int adv7393_mode(struct i2c_client *client, u16 mode)
+{
+       switch (mode) {
+       case POWER_ON:          /* ADV7393 Sleep mode OFF */
+               adv7393_write(client, 0x00, 0x1E);
+               break;
+       case POWER_DOWN:        /* ADV7393 Sleep mode ON */
+               adv7393_write(client, 0x00, 0x1F);
+               break;
+       case BLANK_OFF:         /* Pixel Data Valid */
+               adv7393_write(client, 0x82, 0xCB);
+               break;
+       case BLANK_ON:          /* Pixel Data Invalid */
+               adv7393_write(client, 0x82, 0x8B);
+               break;
+       default:
+               return -EINVAL;
+               break;
+       }
+       return 0;
+}
+
+static irqreturn_t ppi_irq_error(int irq, void *dev_id)
+{
+
+       struct adv7393fb_device *fbdev = (struct adv7393fb_device *)dev_id;
+
+       u16 status = bfin_read_PPI_STATUS();
+
+       pr_debug("%s: PPI Status = 0x%X\n", __func__, status);
+
+       if (status) {
+               bfin_disable_dma();     /* TODO: Check Sequence */
+               bfin_disable_ppi();
+               bfin_clear_PPI_STATUS();
+               bfin_config_dma(fbdev);
+               bfin_enable_ppi();
+       }
+
+       return IRQ_HANDLED;
+
+}
+
+static int proc_output(char *buf)
+{
+       char *p = buf;
+
+       p += sprintf(p,
+               "Usage:\n"
+               "echo 0x[REG][Value] > adv7393\n"
+               "example: echo 0x1234 >adv7393\n"
+               "writes 0x34 into Register 0x12\n");
+
+       return p - buf;
+}
+
+static int
+adv7393_read_proc(char *page, char **start, off_t off,
+                 int count, int *eof, void *data)
+{
+       int len;
+
+       len = proc_output(page);
+       if (len <= off + count)
+               *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len > count)
+               len = count;
+       if (len < 0)
+               len = 0;
+       return len;
+}
+
+static int
+adv7393_write_proc(struct file *file, const char __user * buffer,
+                  unsigned long count, void *data)
+{
+       struct adv7393fb_device *fbdev = data;
+       char line[8];
+       unsigned int val;
+       int ret;
+
+       ret = copy_from_user(line, buffer, count);
+       if (ret)
+               return -EFAULT;
+
+       val = simple_strtoul(line, NULL, 0);
+       adv7393_write(fbdev->client, val >> 8, val & 0xff);
+
+       return count;
+}
+
+static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client,
+                                          const struct i2c_device_id *id)
+{
+       int ret = 0;
+       struct proc_dir_entry *entry;
+       int num_modes = ARRAY_SIZE(known_modes);
+
+       struct adv7393fb_device *fbdev = NULL;
+
+       if (mem > 2) {
+               dev_err(&client->dev, "mem out of allowed range [1;2]\n");
+               return -EINVAL;
+       }
+
+       if (mode > num_modes) {
+               dev_err(&client->dev, "mode %d: not supported", mode);
+               return -EFAULT;
+       }
+
+       fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
+       if (!fbdev) {
+               dev_err(&client->dev, "failed to allocate device private record");
+               return -ENOMEM;
+       }
+
+       i2c_set_clientdata(client, fbdev);
+
+       fbdev->modes = known_modes;
+       fbdev->client = client;
+
+       fbdev->fb_len =
+           mem * fbdev->modes[mode].xres * fbdev->modes[mode].xres *
+           (fbdev->modes[mode].bpp / 8);
+
+       fbdev->line_len =
+           fbdev->modes[mode].xres * (fbdev->modes[mode].bpp / 8);
+
+       /* Workaround "PPI Does Not Start Properly In Specific Mode" */
+       if (ANOMALY_05000400) {
+               if (gpio_request(P_IDENT(P_PPI0_FS3), "PPI0_FS3")) {
+                       dev_err(&client->dev, "PPI0_FS3 GPIO request failed\n");
+                       ret = -EBUSY;
+                       goto out_8;
+               }
+               gpio_direction_output(P_IDENT(P_PPI0_FS3), 0);
+       }
+
+       if (peripheral_request_list(ppi_pins, DRIVER_NAME)) {
+               dev_err(&client->dev, "requesting PPI peripheral failed\n");
+               ret = -EFAULT;
+               goto out_8;
+       }
+
+       fbdev->fb_mem =
+           dma_alloc_coherent(NULL, fbdev->fb_len, &fbdev->dma_handle,
+                              GFP_KERNEL);
+
+       if (NULL == fbdev->fb_mem) {
+               dev_err(&client->dev, "couldn't allocate dma buffer (%d bytes)\n",
+                      (u32) fbdev->fb_len);
+               ret = -ENOMEM;
+               goto out_7;
+       }
+
+       fbdev->info.screen_base = (void *)fbdev->fb_mem;
+       bfin_adv7393_fb_fix.smem_start = (int)fbdev->fb_mem;
+
+       bfin_adv7393_fb_fix.smem_len = fbdev->fb_len;
+       bfin_adv7393_fb_fix.line_length = fbdev->line_len;
+
+       if (mem > 1)
+               bfin_adv7393_fb_fix.ypanstep = 1;
+
+       bfin_adv7393_fb_defined.red.length = 5;
+       bfin_adv7393_fb_defined.green.length = 6;
+       bfin_adv7393_fb_defined.blue.length = 5;
+
+       bfin_adv7393_fb_defined.xres = fbdev->modes[mode].xres;
+       bfin_adv7393_fb_defined.yres = fbdev->modes[mode].yres;
+       bfin_adv7393_fb_defined.xres_virtual = fbdev->modes[mode].xres;
+       bfin_adv7393_fb_defined.yres_virtual = mem * fbdev->modes[mode].yres;
+       bfin_adv7393_fb_defined.bits_per_pixel = fbdev->modes[mode].bpp;
+
+       fbdev->info.fbops = &bfin_adv7393_fb_ops;
+       fbdev->info.var = bfin_adv7393_fb_defined;
+       fbdev->info.fix = bfin_adv7393_fb_fix;
+       fbdev->info.par = &bfin_par;
+       fbdev->info.flags = FBINFO_DEFAULT;
+
+       fbdev->info.pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL);
+       if (!fbdev->info.pseudo_palette) {
+               dev_err(&client->dev, "failed to allocate pseudo_palette\n");
+               ret = -ENOMEM;
+               goto out_6;
+       }
+
+       if (fb_alloc_cmap(&fbdev->info.cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {
+               dev_err(&client->dev, "failed to allocate colormap (%d entries)\n",
+                          BFIN_LCD_NBR_PALETTE_ENTRIES);
+               ret = -EFAULT;
+               goto out_5;
+       }
+
+       if (request_dma(CH_PPI, "BF5xx_PPI_DMA") < 0) {
+               dev_err(&client->dev, "unable to request PPI DMA\n");
+               ret = -EFAULT;
+               goto out_4;
+       }
+
+       if (request_irq(IRQ_PPI_ERROR, ppi_irq_error, IRQF_DISABLED,
+                       "PPI ERROR", fbdev) < 0) {
+               dev_err(&client->dev, "unable to request PPI ERROR IRQ\n");
+               ret = -EFAULT;
+               goto out_3;
+       }
+
+       fbdev->open = 0;
+
+       ret = adv7393_write_block(client, fbdev->modes[mode].adv7393_i2c_initd,
+                               fbdev->modes[mode].adv7393_i2c_initd_len);
+
+       if (ret) {
+               dev_err(&client->dev, "i2c attach: init error\n");
+               goto out_1;
+       }
+
+
+       if (register_framebuffer(&fbdev->info) < 0) {
+               dev_err(&client->dev, "unable to register framebuffer\n");
+               ret = -EFAULT;
+               goto out_1;
+       }
+
+       dev_info(&client->dev, "fb%d: %s frame buffer device\n",
+              fbdev->info.node, fbdev->info.fix.id);
+       dev_info(&client->dev, "fb memory address : 0x%p\n", fbdev->fb_mem);
+
+       entry = create_proc_entry("driver/adv7393", 0, NULL);
+       if (!entry) {
+               dev_err(&client->dev, "unable to create /proc entry\n");
+               ret = -EFAULT;
+               goto out_0;
+       }
+
+       entry->read_proc = adv7393_read_proc;
+       entry->write_proc = adv7393_write_proc;
+       entry->data = fbdev;
+
+       return 0;
+
+ out_0:
+       unregister_framebuffer(&fbdev->info);
+ out_1:
+       free_irq(IRQ_PPI_ERROR, fbdev);
+ out_3:
+       free_dma(CH_PPI);
+ out_4:
+       dma_free_coherent(NULL, fbdev->fb_len, fbdev->fb_mem,
+                         fbdev->dma_handle);
+ out_5:
+       fb_dealloc_cmap(&fbdev->info.cmap);
+ out_6:
+       kfree(fbdev->info.pseudo_palette);
+ out_7:
+       peripheral_free_list(ppi_pins);
+ out_8:
+       kfree(fbdev);
+
+       return ret;
+}
+
+static int bfin_adv7393_fb_open(struct fb_info *info, int user)
+{
+       struct adv7393fb_device *fbdev = to_adv7393fb_device(info);
+
+       fbdev->info.screen_base = (void *)fbdev->fb_mem;
+       if (!fbdev->info.screen_base) {
+               dev_err(&fbdev->client->dev, "unable to map device\n");
+               return -ENOMEM;
+       }
+
+       fbdev->open = 1;
+       dma_desc_list(fbdev, BUILD);
+       adv7393_mode(fbdev->client, BLANK_OFF);
+       bfin_config_ppi(fbdev);
+       bfin_config_dma(fbdev);
+       bfin_enable_ppi();
+
+       return 0;
+}
+
+static int bfin_adv7393_fb_release(struct fb_info *info, int user)
+{
+       struct adv7393fb_device *fbdev = to_adv7393fb_device(info);
+
+       adv7393_mode(fbdev->client, BLANK_ON);
+       bfin_disable_dma();
+       bfin_disable_ppi();
+       dma_desc_list(fbdev, DESTRUCT);
+       fbdev->open = 0;
+       return 0;
+}
+
+static int
+bfin_adv7393_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+
+       switch (var->bits_per_pixel) {
+       case 16:/* DIRECTCOLOUR, 64k */
+               var->red.offset = info->var.red.offset;
+               var->green.offset = info->var.green.offset;
+               var->blue.offset = info->var.blue.offset;
+               var->red.length = info->var.red.length;
+               var->green.length = info->var.green.length;
+               var->blue.length = info->var.blue.length;
+               var->transp.offset = 0;
+               var->transp.length = 0;
+               var->transp.msb_right = 0;
+               var->red.msb_right = 0;
+               var->green.msb_right = 0;
+               var->blue.msb_right = 0;
+               break;
+       default:
+               pr_debug("%s: depth not supported: %u BPP\n", __func__,
+                        var->bits_per_pixel);
+               return -EINVAL;
+       }
+
+       if (info->var.xres != var->xres ||
+           info->var.yres != var->yres ||
+           info->var.xres_virtual != var->xres_virtual ||
+           info->var.yres_virtual != var->yres_virtual) {
+               pr_debug("%s: Resolution not supported: X%u x Y%u\n",
+                        __func__, var->xres, var->yres);
+               return -EINVAL;
+       }
+
+       /*
+        *  Memory limit
+        */
+
+       if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
+               pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
+                        __func__, var->yres_virtual);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static int
+bfin_adv7393_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       int dy;
+       u32 dmaaddr;
+       struct adv7393fb_device *fbdev = to_adv7393fb_device(info);
+
+       if (!var || !info)
+               return -EINVAL;
+
+       if (var->xoffset - info->var.xoffset) {
+               /* No support for X panning for now! */
+               return -EINVAL;
+       }
+       dy = var->yoffset - info->var.yoffset;
+
+       if (dy) {
+               pr_debug("%s: Panning screen of %d lines\n", __func__, dy);
+
+               dmaaddr = fbdev->av1->start_addr;
+               dmaaddr += (info->fix.line_length * dy);
+               /* TODO: Wait for current frame to finished */
+
+               fbdev->av1->start_addr = (unsigned long)dmaaddr;
+               fbdev->av2->start_addr = (unsigned long)dmaaddr + fbdev->line_len;
+       }
+
+       return 0;
+
+}
+
+/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
+static int bfin_adv7393_fb_blank(int blank, struct fb_info *info)
+{
+       struct adv7393fb_device *fbdev = to_adv7393fb_device(info);
+
+       switch (blank) {
+
+       case VESA_NO_BLANKING:
+               /* Turn on panel */
+               adv7393_mode(fbdev->client, BLANK_OFF);
+               break;
+
+       case VESA_VSYNC_SUSPEND:
+       case VESA_HSYNC_SUSPEND:
+       case VESA_POWERDOWN:
+               /* Turn off panel */
+               adv7393_mode(fbdev->client, BLANK_ON);
+               break;
+
+       default:
+               return -EINVAL;
+               break;
+       }
+       return 0;
+}
+
+int bfin_adv7393_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+       if (nocursor)
+               return 0;
+       else
+               return -EINVAL; /* just to force soft_cursor() call */
+}
+
+static int bfin_adv7393_fb_setcolreg(u_int regno, u_int red, u_int green,
+                                    u_int blue, u_int transp,
+                                    struct fb_info *info)
+{
+       if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES)
+               return -EINVAL;
+
+       if (info->var.grayscale)
+               /* grayscale = 0.30*R + 0.59*G + 0.11*B */
+               red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+
+       if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+               u32 value;
+               /* Place color in the pseudopalette */
+               if (regno > 16)
+                       return -EINVAL;
+
+               red   >>= (16 - info->var.red.length);
+               green >>= (16 - info->var.green.length);
+               blue  >>= (16 - info->var.blue.length);
+
+               value = (red   << info->var.red.offset) |
+                       (green << info->var.green.offset)|
+                       (blue  << info->var.blue.offset);
+               value &= 0xFFFF;
+
+               ((u32 *) (info->pseudo_palette))[regno] = value;
+       }
+
+       return 0;
+}
+
+static int __devexit bfin_adv7393_fb_remove(struct i2c_client *client)
+{
+       struct adv7393fb_device *fbdev = i2c_get_clientdata(client);
+
+       adv7393_mode(client, POWER_DOWN);
+
+       if (fbdev->fb_mem)
+               dma_free_coherent(NULL, fbdev->fb_len, fbdev->fb_mem, fbdev->dma_handle);
+       free_dma(CH_PPI);
+       free_irq(IRQ_PPI_ERROR, fbdev);
+       unregister_framebuffer(&fbdev->info);
+       remove_proc_entry("driver/adv7393", NULL);
+       fb_dealloc_cmap(&fbdev->info.cmap);
+       kfree(fbdev->info.pseudo_palette);
+
+       if (ANOMALY_05000400)
+               gpio_free(P_IDENT(P_PPI0_FS3)); /* FS3 */
+       peripheral_free_list(ppi_pins);
+       kfree(fbdev);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int bfin_adv7393_fb_suspend(struct device *dev)
+{
+       struct adv7393fb_device *fbdev = dev_get_drvdata(dev);
+
+       if (fbdev->open) {
+               bfin_disable_dma();
+               bfin_disable_ppi();
+               dma_desc_list(fbdev, DESTRUCT);
+       }
+       adv7393_mode(fbdev->client, POWER_DOWN);
+
+       return 0;
+}
+
+static int bfin_adv7393_fb_resume(struct device *dev)
+{
+       struct adv7393fb_device *fbdev = dev_get_drvdata(dev);
+
+       adv7393_mode(fbdev->client, POWER_ON);
+
+       if (fbdev->open) {
+               dma_desc_list(fbdev, BUILD);
+               bfin_config_ppi(fbdev);
+               bfin_config_dma(fbdev);
+               bfin_enable_ppi();
+       }
+
+       return 0;
+}
+
+static const struct dev_pm_ops bfin_adv7393_dev_pm_ops = {
+       .suspend = bfin_adv7393_fb_suspend,
+       .resume  = bfin_adv7393_fb_resume,
+};
+#endif
+
+static const struct i2c_device_id bfin_adv7393_id[] = {
+       {DRIVER_NAME, 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, bfin_adv7393_id);
+
+static struct i2c_driver bfin_adv7393_fb_driver = {
+       .driver = {
+               .name = DRIVER_NAME,
+#ifdef CONFIG_PM
+               .pm   = &bfin_adv7393_dev_pm_ops,
+#endif
+       },
+       .probe = bfin_adv7393_fb_probe,
+       .remove = __devexit_p(bfin_adv7393_fb_remove),
+       .id_table = bfin_adv7393_id,
+};
+
+static int __init bfin_adv7393_fb_driver_init(void)
+{
+#if  defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+       request_module("i2c-bfin-twi");
+#else
+       request_module("i2c-gpio");
+#endif
+
+       return i2c_add_driver(&bfin_adv7393_fb_driver);
+}
+module_init(bfin_adv7393_fb_driver_init);
+
+static void __exit bfin_adv7393_fb_driver_cleanup(void)
+{
+       i2c_del_driver(&bfin_adv7393_fb_driver);
+}
+module_exit(bfin_adv7393_fb_driver_cleanup);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Frame buffer driver for ADV7393/2 Video Encoder");
+
+module_param(mode, int, 0);
+MODULE_PARM_DESC(mode,
+       "Video Mode (0=NTSC,1=PAL,2=NTSC 640x480,3=PAL 640x480,4=NTSC YCbCr input,5=PAL YCbCr input)");
+
+module_param(mem, int, 0);
+MODULE_PARM_DESC(mem,
+       "Size of frame buffer memory 1=Single 2=Double Size (allows y-panning / frame stacking)");
+
+module_param(nocursor, int, 0644);
+MODULE_PARM_DESC(nocursor, "cursor enable/disable");
diff --git a/drivers/video/bfin_adv7393fb.h b/drivers/video/bfin_adv7393fb.h
new file mode 100644 (file)
index 0000000..8c7f9e4
--- /dev/null
@@ -0,0 +1,321 @@
+/*
+ * Frame buffer driver for ADV7393/2 video encoder
+ *
+ * Copyright 2006-2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or late.
+ */
+
+#ifndef __BFIN_ADV7393FB_H__
+#define __BFIN_ADV7393FB_H__
+
+#define BFIN_LCD_NBR_PALETTE_ENTRIES   256
+
+#ifdef CONFIG_NTSC
+# define VMODE 0
+#endif
+#ifdef CONFIG_PAL
+# define VMODE 1
+#endif
+#ifdef CONFIG_NTSC_640x480
+# define VMODE 2
+#endif
+#ifdef CONFIG_PAL_640x480
+# define VMODE 3
+#endif
+#ifdef CONFIG_NTSC_YCBCR
+# define VMODE 4
+#endif
+#ifdef CONFIG_PAL_YCBCR
+# define VMODE 5
+#endif
+
+#ifndef VMODE
+# define VMODE 1
+#endif
+
+#ifdef CONFIG_ADV7393_2XMEM
+# define VMEM 2
+#else
+# define VMEM 1
+#endif
+
+#if defined(CONFIG_BF537) || defined(CONFIG_BF536) || defined(CONFIG_BF534)
+# define DMA_CFG_VAL   0x7935  /* Set Sync Bit */
+# define VB_DUMMY_MEMORY_SOURCE        L1_DATA_B_START
+#else
+# define DMA_CFG_VAL   0x7915
+# define VB_DUMMY_MEMORY_SOURCE        BOOT_ROM_START
+#endif
+
+enum {
+       DESTRUCT,
+       BUILD,
+};
+
+enum {
+       POWER_ON,
+       POWER_DOWN,
+       BLANK_ON,
+       BLANK_OFF,
+};
+
+#define DRIVER_NAME "bfin-adv7393"
+
+struct adv7393fb_modes {
+       const s8 name[25];      /* Full name */
+       u16 xres;               /* Active Horizonzal Pixels  */
+       u16 yres;               /* Active Vertical Pixels  */
+       u16 bpp;
+       u16 vmode;
+       u16 a_lines;            /* Active Lines per Field */
+       u16 vb1_lines;          /* Vertical Blanking Field 1 Lines */
+       u16 vb2_lines;          /* Vertical Blanking Field 2 Lines */
+       u16 tot_lines;          /* Total Lines per Frame */
+       u16 boeft_blank;        /* Before Odd/Even Field Transition No. of Blank Pixels */
+       u16 aoeft_blank;        /* After Odd/Even Field Transition No. of Blank Pixels */
+       const s8 *adv7393_i2c_initd;
+       u16 adv7393_i2c_initd_len;
+};
+
+static const u8 init_NTSC_TESTPATTERN[] = {
+       0x00, 0x1E,     /* Power up all DACs and PLL */
+       0x01, 0x00,     /* SD-Only Mode */
+       0x80, 0x10,     /* SSAF Luma Filter Enabled, NTSC Mode */
+       0x82, 0xCB,     /* Step control on, pixel data valid, pedestal on, PrPb SSAF on, CVBS/YC output */
+       0x84, 0x40,     /* SD Color Bar Test Pattern Enabled, DAC 2 = Luma, DAC 3 = Chroma */
+};
+
+static const u8 init_NTSC[] = {
+       0x00, 0x1E,     /* Power up all DACs and PLL */
+       0xC3, 0x26,     /* Program RGB->YCrCb Color Space convertion matrix */
+       0xC5, 0x12,     /* Program RGB->YCrCb Color Space convertion matrix */
+       0xC2, 0x4A,     /* Program RGB->YCrCb Color Space convertion matrix */
+       0xC6, 0x5E,     /* Program RGB->YCrCb Color Space convertion matrix */
+       0xBD, 0x19,     /* Program RGB->YCrCb Color Space convertion matrix */
+       0xBF, 0x42,     /* Program RGB->YCrCb Color Space convertion matrix */
+       0x8C, 0x1F,     /* NTSC Subcarrier Frequency */
+       0x8D, 0x7C,     /* NTSC Subcarrier Frequency */
+       0x8E, 0xF0,     /* NTSC Subcarrier Frequency */
+       0x8F, 0x21,     /* NTSC Subcarrier Frequency */
+       0x01, 0x00,     /* SD-Only Mode */
+       0x80, 0x30,     /* SSAF Luma Filter Enabled, NTSC Mode */
+       0x82, 0x8B,     /* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
+       0x87, 0x80,     /* SD Color Bar Test Pattern Enabled, DAC 2 = Luma, DAC 3 = Chroma */
+       0x86, 0x82,
+       0x8B, 0x11,
+       0x88, 0x20,
+       0x8A, 0x0d,
+};
+
+static const u8 init_PAL[] = {
+       0x00, 0x1E,     /* Power up all DACs and PLL */
+       0xC3, 0x26,     /* Program RGB->YCrCb Color Space convertion matrix */
+       0xC5, 0x12,     /* Program RGB->YCrCb Color Space convertion matrix */
+       0xC2, 0x4A,     /* Program RGB->YCrCb Color Space convertion matrix */
+       0xC6, 0x5E,     /* Program RGB->YCrCb Color Space convertion matrix */
+       0xBD, 0x19,     /* Program RGB->YCrCb Color Space convertion matrix */
+       0xBF, 0x42,     /* Program RGB->YCrCb Color Space convertion matrix */
+       0x8C, 0xCB,     /* PAL Subcarrier Frequency */
+       0x8D, 0x8A,     /* PAL Subcarrier Frequency */
+       0x8E, 0x09,     /* PAL Subcarrier Frequency */
+       0x8F, 0x2A,     /* PAL Subcarrier Frequency */
+       0x01, 0x00,     /* SD-Only Mode */
+       0x80, 0x11,     /* SSAF Luma Filter Enabled, PAL Mode */
+       0x82, 0x8B,     /* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
+       0x87, 0x80,     /* SD Color Bar Test Pattern Enabled, DAC 2 = Luma, DAC 3 = Chroma */
+       0x86, 0x82,
+       0x8B, 0x11,
+       0x88, 0x20,
+       0x8A, 0x0d,
+};
+
+static const u8 init_NTSC_YCbCr[] = {
+       0x00, 0x1E,     /* Power up all DACs and PLL */
+       0x8C, 0x1F,     /* NTSC Subcarrier Frequency */
+       0x8D, 0x7C,     /* NTSC Subcarrier Frequency */
+       0x8E, 0xF0,     /* NTSC Subcarrier Frequency */
+       0x8F, 0x21,     /* NTSC Subcarrier Frequency */
+       0x01, 0x00,     /* SD-Only Mode */
+       0x80, 0x30,     /* SSAF Luma Filter Enabled, NTSC Mode */
+       0x82, 0x8B,     /* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
+       0x87, 0x00,     /* DAC 2 = Luma, DAC 3 = Chroma */
+       0x86, 0x82,
+       0x8B, 0x11,
+       0x88, 0x08,
+       0x8A, 0x0d,
+};
+
+static const u8 init_PAL_YCbCr[] = {
+       0x00, 0x1E,     /* Power up all DACs and PLL */
+       0x8C, 0xCB,     /* PAL Subcarrier Frequency */
+       0x8D, 0x8A,     /* PAL Subcarrier Frequency */
+       0x8E, 0x09,     /* PAL Subcarrier Frequency */
+       0x8F, 0x2A,     /* PAL Subcarrier Frequency */
+       0x01, 0x00,     /* SD-Only Mode */
+       0x80, 0x11,     /* SSAF Luma Filter Enabled, PAL Mode */
+       0x82, 0x8B,     /* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
+       0x87, 0x00,     /* DAC 2 = Luma, DAC 3 = Chroma */
+       0x86, 0x82,
+       0x8B, 0x11,
+       0x88, 0x08,
+       0x8A, 0x0d,
+};
+
+static struct adv7393fb_modes known_modes[] = {
+       /* NTSC 720x480 CRT */
+       {
+               .name = "NTSC 720x480",
+               .xres = 720,
+               .yres = 480,
+               .bpp = 16,
+               .vmode = FB_VMODE_INTERLACED,
+               .a_lines = 240,
+               .vb1_lines = 22,
+               .vb2_lines = 23,
+               .tot_lines = 525,
+               .boeft_blank = 16,
+               .aoeft_blank = 122,
+               .adv7393_i2c_initd = init_NTSC,
+               .adv7393_i2c_initd_len = sizeof(init_NTSC)
+       },
+       /* PAL 720x480 CRT */
+       {
+               .name = "PAL 720x576",
+               .xres = 720,
+               .yres = 576,
+               .bpp = 16,
+               .vmode = FB_VMODE_INTERLACED,
+               .a_lines = 288,
+               .vb1_lines = 24,
+               .vb2_lines = 25,
+               .tot_lines = 625,
+               .boeft_blank = 12,
+               .aoeft_blank = 132,
+               .adv7393_i2c_initd = init_PAL,
+               .adv7393_i2c_initd_len = sizeof(init_PAL)
+       },
+       /* NTSC 640x480 CRT Experimental */
+       {
+               .name = "NTSC 640x480",
+               .xres = 640,
+               .yres = 480,
+               .bpp = 16,
+               .vmode = FB_VMODE_INTERLACED,
+               .a_lines = 240,
+               .vb1_lines = 22,
+               .vb2_lines = 23,
+               .tot_lines = 525,
+               .boeft_blank = 16 + 40,
+               .aoeft_blank = 122 + 40,
+               .adv7393_i2c_initd = init_NTSC,
+               .adv7393_i2c_initd_len = sizeof(init_NTSC)
+       },
+       /* PAL 640x480 CRT Experimental */
+       {
+               .name = "PAL 640x480",
+               .xres = 640,
+               .yres = 480,
+               .bpp = 16,
+               .vmode = FB_VMODE_INTERLACED,
+               .a_lines = 288 - 20,
+               .vb1_lines = 24 + 20,
+               .vb2_lines = 25 + 20,
+               .tot_lines = 625,
+               .boeft_blank = 12 + 40,
+               .aoeft_blank = 132 + 40,
+               .adv7393_i2c_initd = init_PAL,
+               .adv7393_i2c_initd_len = sizeof(init_PAL)
+       },
+       /* NTSC 720x480 YCbCR */
+       {
+               .name = "NTSC 720x480 YCbCR",
+               .xres = 720,
+               .yres = 480,
+               .bpp = 16,
+               .vmode = FB_VMODE_INTERLACED,
+               .a_lines = 240,
+               .vb1_lines = 22,
+               .vb2_lines = 23,
+               .tot_lines = 525,
+               .boeft_blank = 16,
+               .aoeft_blank = 122,
+               .adv7393_i2c_initd = init_NTSC_YCbCr,
+               .adv7393_i2c_initd_len = sizeof(init_NTSC_YCbCr)
+       },
+       /* PAL 720x480 CRT */
+       {
+               .name = "PAL 720x576 YCbCR",
+               .xres = 720,
+               .yres = 576,
+               .bpp = 16,
+               .vmode = FB_VMODE_INTERLACED,
+               .a_lines = 288,
+               .vb1_lines = 24,
+               .vb2_lines = 25,
+               .tot_lines = 625,
+               .boeft_blank = 12,
+               .aoeft_blank = 132,
+               .adv7393_i2c_initd = init_PAL_YCbCr,
+               .adv7393_i2c_initd_len = sizeof(init_PAL_YCbCr)
+       }
+};
+
+struct adv7393fb_regs {
+
+};
+
+struct adv7393fb_device {
+       struct fb_info info;    /* FB driver info record */
+
+       struct i2c_client *client;
+
+       struct dmasg *descriptor_list_head;
+       struct dmasg *vb1;
+       struct dmasg *av1;
+       struct dmasg *vb2;
+       struct dmasg *av2;
+
+       dma_addr_t dma_handle;
+
+       struct fb_info bfin_adv7393_fb;
+
+       struct adv7393fb_modes *modes;
+
+       struct adv7393fb_regs *regs;    /* Registers memory map */
+       size_t regs_len;
+       size_t fb_len;
+       size_t line_len;
+       u16 open;
+       u16 *fb_mem;            /* RGB Buffer */
+
+};
+
+#define to_adv7393fb_device(_info) \
+         (_info ? container_of(_info, struct adv7393fb_device, info) : NULL);
+
+static int bfin_adv7393_fb_open(struct fb_info *info, int user);
+static int bfin_adv7393_fb_release(struct fb_info *info, int user);
+static int bfin_adv7393_fb_check_var(struct fb_var_screeninfo *var,
+                                    struct fb_info *info);
+
+static int bfin_adv7393_fb_pan_display(struct fb_var_screeninfo *var,
+                                      struct fb_info *info);
+
+static int bfin_adv7393_fb_blank(int blank, struct fb_info *info);
+
+static void bfin_config_ppi(struct adv7393fb_device *fbdev);
+static int bfin_config_dma(struct adv7393fb_device *fbdev);
+static void bfin_disable_dma(void);
+static void bfin_enable_ppi(void);
+static void bfin_disable_ppi(void);
+
+static inline int adv7393_write(struct i2c_client *client, u8 reg, u8 value);
+static inline int adv7393_read(struct i2c_client *client, u8 reg);
+static int adv7393_write_block(struct i2c_client *client, const u8 *data,
+                              unsigned int len);
+
+int bfin_adv7393_fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
+static int bfin_adv7393_fb_setcolreg(u_int, u_int, u_int, u_int,
+                                    u_int, struct fb_info *info);
+
+#endif
index cad7d45c8bac2b94a1e3f06b57a241d26ed4570c..c265aed09e04a2061ca224dd4354ffd178d9ccdc 100644 (file)
@@ -1029,10 +1029,6 @@ static int __init fb_probe(struct platform_device *device)
                goto err_release_pl_mem;
        }
 
-       ret = request_irq(par->irq, lcdc_irq_handler, 0, DRIVER_NAME, par);
-       if (ret)
-               goto err_release_pl_mem;
-
        /* Initialize par */
        da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp;
 
@@ -1060,7 +1056,7 @@ static int __init fb_probe(struct platform_device *device)
 
        ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0);
        if (ret)
-               goto err_free_irq;
+               goto err_release_pl_mem;
        da8xx_fb_info->cmap.len = par->palette_sz;
 
        /* initialize var_screeninfo */
@@ -1088,8 +1084,13 @@ static int __init fb_probe(struct platform_device *device)
                goto err_cpu_freq;
        }
 #endif
+
+       ret = request_irq(par->irq, lcdc_irq_handler, 0, DRIVER_NAME, par);
+       if (ret)
+               goto irq_freq;
        return 0;
 
+irq_freq:
 #ifdef CONFIG_CPU_FREQ
 err_cpu_freq:
        unregister_framebuffer(da8xx_fb_info);
@@ -1098,9 +1099,6 @@ err_cpu_freq:
 err_dealloc_cmap:
        fb_dealloc_cmap(&da8xx_fb_info->cmap);
 
-err_free_irq:
-       free_irq(par->irq, par);
-
 err_release_pl_mem:
        dma_free_coherent(NULL, PALETTE_SIZE, par->v_palette_base,
                          par->p_palette_base);
index f53b9f1d6aba23830d3b5c1a551054cf9f8b4538..5c3960da755aa52eefe1069442e9a43341e43e8c 100644 (file)
@@ -80,6 +80,7 @@ static const struct fb_cmap default_16_colors = {
  *     @cmap: frame buffer colormap structure
  *     @len: length of @cmap
  *     @transp: boolean, 1 if there is transparency, 0 otherwise
+ *     @flags: flags for kmalloc memory allocation
  *
  *     Allocates memory for a colormap @cmap.  @len is the
  *     number of entries in the palette.
@@ -88,34 +89,48 @@ static const struct fb_cmap default_16_colors = {
  *
  */
 
-int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp)
+int fb_alloc_cmap_gfp(struct fb_cmap *cmap, int len, int transp, gfp_t flags)
 {
-    int size = len*sizeof(u16);
-
-    if (cmap->len != len) {
-       fb_dealloc_cmap(cmap);
-       if (!len)
-           return 0;
-       if (!(cmap->red = kmalloc(size, GFP_ATOMIC)))
-           goto fail;
-       if (!(cmap->green = kmalloc(size, GFP_ATOMIC)))
-           goto fail;
-       if (!(cmap->blue = kmalloc(size, GFP_ATOMIC)))
-           goto fail;
-       if (transp) {
-           if (!(cmap->transp = kmalloc(size, GFP_ATOMIC)))
+       int size = len * sizeof(u16);
+       int ret = -ENOMEM;
+
+       if (cmap->len != len) {
+               fb_dealloc_cmap(cmap);
+               if (!len)
+                       return 0;
+
+               cmap->red = kmalloc(size, flags);
+               if (!cmap->red)
+                       goto fail;
+               cmap->green = kmalloc(size, flags);
+               if (!cmap->green)
+                       goto fail;
+               cmap->blue = kmalloc(size, flags);
+               if (!cmap->blue)
+                       goto fail;
+               if (transp) {
+                       cmap->transp = kmalloc(size, flags);
+                       if (!cmap->transp)
+                               goto fail;
+               } else {
+                       cmap->transp = NULL;
+               }
+       }
+       cmap->start = 0;
+       cmap->len = len;
+       ret = fb_copy_cmap(fb_default_cmap(len), cmap);
+       if (ret)
                goto fail;
-       } else
-           cmap->transp = NULL;
-    }
-    cmap->start = 0;
-    cmap->len = len;
-    fb_copy_cmap(fb_default_cmap(len), cmap);
-    return 0;
+       return 0;
 
 fail:
-    fb_dealloc_cmap(cmap);
-    return -ENOMEM;
+       fb_dealloc_cmap(cmap);
+       return ret;
+}
+
+int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp)
+{
+       return fb_alloc_cmap_gfp(cmap, len, transp, GFP_ATOMIC);
 }
 
 /**
@@ -250,8 +265,12 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info)
        int rc, size = cmap->len * sizeof(u16);
        struct fb_cmap umap;
 
+       if (size < 0 || size < cmap->len)
+               return -E2BIG;
+
        memset(&umap, 0, sizeof(struct fb_cmap));
-       rc = fb_alloc_cmap(&umap, cmap->len, cmap->transp != NULL);
+       rc = fb_alloc_cmap_gfp(&umap, cmap->len, cmap->transp != NULL,
+                               GFP_KERNEL);
        if (rc)
                return rc;
        if (copy_from_user(umap.red, cmap->red, size) ||
index 563a98b88e9bf17ce32edeaf4268fbfcee48681c..4f57485f8c54580a30519add3a26d72779d9ebcd 100644 (file)
@@ -973,6 +973,90 @@ void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
        DPRINTK("========================================\n");
 }
 
+/**
+ * fb_edid_add_monspecs() - add monitor video modes from E-EDID data
+ * @edid:      128 byte array with an E-EDID block
+ * @spacs:     monitor specs to be extended
+ */
+void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs)
+{
+       unsigned char *block;
+       struct fb_videomode *m;
+       int num = 0, i;
+       u8 svd[64], edt[(128 - 4) / DETAILED_TIMING_DESCRIPTION_SIZE];
+       u8 pos = 4, svd_n = 0;
+
+       if (!edid)
+               return;
+
+       if (!edid_checksum(edid))
+               return;
+
+       if (edid[0] != 0x2 ||
+           edid[2] < 4 || edid[2] > 128 - DETAILED_TIMING_DESCRIPTION_SIZE)
+               return;
+
+       DPRINTK("  Short Video Descriptors\n");
+
+       while (pos < edid[2]) {
+               u8 len = edid[pos] & 0x1f, type = (edid[pos] >> 5) & 7;
+               pr_debug("Data block %u of %u bytes\n", type, len);
+               if (type == 2)
+                       for (i = pos; i < pos + len; i++) {
+                               u8 idx = edid[pos + i] & 0x7f;
+                               svd[svd_n++] = idx;
+                               pr_debug("N%sative mode #%d\n",
+                                        edid[pos + i] & 0x80 ? "" : "on-n", idx);
+                       }
+               pos += len + 1;
+       }
+
+       block = edid + edid[2];
+
+       DPRINTK("  Extended Detailed Timings\n");
+
+       for (i = 0; i < (128 - edid[2]) / DETAILED_TIMING_DESCRIPTION_SIZE;
+            i++, block += DETAILED_TIMING_DESCRIPTION_SIZE)
+               if (PIXEL_CLOCK)
+                       edt[num++] = block - edid;
+
+       /* Yikes, EDID data is totally useless */
+       if (!(num + svd_n))
+               return;
+
+       m = kzalloc((specs->modedb_len + num + svd_n) *
+                      sizeof(struct fb_videomode), GFP_KERNEL);
+
+       if (!m)
+               return;
+
+       memcpy(m, specs->modedb, specs->modedb_len * sizeof(struct fb_videomode));
+
+       for (i = specs->modedb_len; i < specs->modedb_len + num; i++) {
+               get_detailed_timing(edid + edt[i - specs->modedb_len], &m[i]);
+               if (i == specs->modedb_len)
+                       m[i].flag |= FB_MODE_IS_FIRST;
+               pr_debug("Adding %ux%u@%u\n", m[i].xres, m[i].yres, m[i].refresh);
+       }
+
+       for (i = specs->modedb_len + num; i < specs->modedb_len + num + svd_n; i++) {
+               int idx = svd[i - specs->modedb_len - num];
+               if (!idx || idx > 63) {
+                       pr_warning("Reserved SVD code %d\n", idx);
+               } else if (idx > ARRAY_SIZE(cea_modes) || !cea_modes[idx].xres) {
+                       pr_warning("Unimplemented SVD code %d\n", idx);
+               } else {
+                       memcpy(&m[i], cea_modes + idx, sizeof(m[i]));
+                       pr_debug("Adding SVD #%d: %ux%u@%u\n", idx,
+                                m[i].xres, m[i].yres, m[i].refresh);
+               }
+       }
+
+       kfree(specs->modedb);
+       specs->modedb = m;
+       specs->modedb_len = specs->modedb_len + num + svd_n;
+}
+
 /*
  * VESA Generalized Timing Formula (GTF)
  */
@@ -1289,6 +1373,9 @@ void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
 {
        specs = NULL;
 }
+void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs)
+{
+}
 void fb_destroy_modedb(struct fb_videomode *modedb)
 {
 }
@@ -1396,6 +1483,7 @@ EXPORT_SYMBOL(fb_firmware_edid);
 
 EXPORT_SYMBOL(fb_parse_edid);
 EXPORT_SYMBOL(fb_edid_to_monspecs);
+EXPORT_SYMBOL(fb_edid_add_monspecs);
 EXPORT_SYMBOL(fb_get_mode);
 EXPORT_SYMBOL(fb_validate_mode);
 EXPORT_SYMBOL(fb_destroy_modedb);
index e4c4d89b786034c33aaf687b9616feddd3c76bbd..be8ccb47ebe039e11a84c32892ddfa046a000df8 100644 (file)
@@ -22,6 +22,7 @@
 #define DC_HFILT_COUNT 0x100
 #define DC_VFILT_COUNT 0x100
 #define VP_COEFF_SIZE  0x1000
+#define VP_PAL_COUNT   0x100
 
 #define OUTPUT_CRT   0x01
 #define OUTPUT_PANEL 0x02
@@ -48,7 +49,8 @@ struct lxfb_par {
        uint64_t vp[VP_REG_COUNT];
        uint64_t fp[FP_REG_COUNT];
 
-       uint32_t pal[DC_PAL_COUNT];
+       uint32_t dc_pal[DC_PAL_COUNT];
+       uint32_t vp_pal[VP_PAL_COUNT];
        uint32_t hcoeff[DC_HFILT_COUNT * 2];
        uint32_t vcoeff[DC_VFILT_COUNT];
        uint32_t vp_coeff[VP_COEFF_SIZE / 4];
index bc35a95e59d417ef85df900e26824f5de67eaa35..79e9abc72b836ea0c8cbd3c28e5db87284a9e118 100644 (file)
@@ -276,10 +276,10 @@ static void lx_graphics_enable(struct fb_info *info)
                write_fp(par, FP_PT1, 0);
                temp = FP_PT2_SCRC;
 
-               if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+               if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
                        temp |= FP_PT2_HSP;
 
-               if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+               if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
                        temp |= FP_PT2_VSP;
 
                write_fp(par, FP_PT2, temp);
@@ -610,10 +610,15 @@ static void lx_save_regs(struct lxfb_par *par)
        memcpy(par->vp, par->vp_regs, sizeof(par->vp));
        memcpy(par->fp, par->vp_regs + VP_FP_START, sizeof(par->fp));
 
-       /* save the palette */
+       /* save the display controller palette */
        write_dc(par, DC_PAL_ADDRESS, 0);
-       for (i = 0; i < ARRAY_SIZE(par->pal); i++)
-               par->pal[i] = read_dc(par, DC_PAL_DATA);
+       for (i = 0; i < ARRAY_SIZE(par->dc_pal); i++)
+               par->dc_pal[i] = read_dc(par, DC_PAL_DATA);
+
+       /* save the video processor palette */
+       write_vp(par, VP_PAR, 0);
+       for (i = 0; i < ARRAY_SIZE(par->vp_pal); i++)
+               par->vp_pal[i] = read_vp(par, VP_PDR);
 
        /* save the horizontal filter coefficients */
        filt = par->dc[DC_IRQ_FILT_CTL] | DC_IRQ_FILT_CTL_H_FILT_SEL;
@@ -706,8 +711,8 @@ static void lx_restore_display_ctlr(struct lxfb_par *par)
 
        /* restore the palette */
        write_dc(par, DC_PAL_ADDRESS, 0);
-       for (i = 0; i < ARRAY_SIZE(par->pal); i++)
-               write_dc(par, DC_PAL_DATA, par->pal[i]);
+       for (i = 0; i < ARRAY_SIZE(par->dc_pal); i++)
+               write_dc(par, DC_PAL_DATA, par->dc_pal[i]);
 
        /* restore the horizontal filter coefficients */
        filt = par->dc[DC_IRQ_FILT_CTL] | DC_IRQ_FILT_CTL_H_FILT_SEL;
@@ -751,6 +756,11 @@ static void lx_restore_video_proc(struct lxfb_par *par)
                }
        }
 
+       /* restore video processor palette */
+       write_vp(par, VP_PAR, 0);
+       for (i = 0; i < ARRAY_SIZE(par->vp_pal); i++)
+               write_vp(par, VP_PDR, par->vp_pal[i]);
+
        /* restore video coeff ram */
        memcpy(par->vp_regs + VP_VCR, par->vp_coeff, sizeof(par->vp_coeff));
 }
index 0a4dbdc1693a4462bddb82cdf5e0b9ab5ec4bed2..7a61ba6a485059d28a62048bc509ce122abfd880 100644 (file)
@@ -278,6 +278,53 @@ static const struct fb_videomode modedb[] = {
 };
 
 #ifdef CONFIG_FB_MODE_HELPERS
+const struct fb_videomode cea_modes[64] = {
+       /* #1: 640x480p@59.94/60Hz */
+       [1] = {
+               NULL, 60, 640, 480, 39722, 48, 16, 33, 10, 96, 2, 0, FB_VMODE_NONINTERLACED, 0,
+       },
+       /* #3: 720x480p@59.94/60Hz */
+       [3] = {
+               NULL, 60, 720, 480, 37037, 60, 16, 30, 9, 62, 6, 0, FB_VMODE_NONINTERLACED, 0,
+       },
+       /* #5: 1920x1080i@59.94/60Hz */
+       [5] = {
+               NULL, 60, 1920, 1080, 13763, 148, 88, 15, 2, 44, 5,
+               FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED, 0,
+       },
+       /* #7: 720(1440)x480iH@59.94/60Hz */
+       [7] = {
+               NULL, 60, 1440, 480, 18554/*37108*/, 114, 38, 15, 4, 124, 3, 0, FB_VMODE_INTERLACED, 0,
+       },
+       /* #9: 720(1440)x240pH@59.94/60Hz */
+       [9] = {
+               NULL, 60, 1440, 240, 18554, 114, 38, 16, 4, 124, 3, 0, FB_VMODE_NONINTERLACED, 0,
+       },
+       /* #18: 720x576pH@50Hz */
+       [18] = {
+               NULL, 50, 720, 576, 37037, 68, 12, 39, 5, 64, 5, 0, FB_VMODE_NONINTERLACED, 0,
+       },
+       /* #19: 1280x720p@50Hz */
+       [19] = {
+               NULL, 50, 1280, 720, 13468, 220, 440, 20, 5, 40, 5,
+               FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0,
+       },
+       /* #20: 1920x1080i@50Hz */
+       [20] = {
+               NULL, 50, 1920, 1080, 13480, 148, 528, 15, 5, 528, 5,
+               FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED, 0,
+       },
+       /* #32: 1920x1080p@23.98/24Hz */
+       [32] = {
+               NULL, 24, 1920, 1080, 13468, 148, 638, 36, 4, 44, 5,
+               FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0,
+       },
+       /* #35: (2880)x480p4x@59.94/60Hz */
+       [35] = {
+               NULL, 60, 2880, 480, 9250, 240, 64, 30, 9, 248, 6, 0, FB_VMODE_NONINTERLACED, 0,
+       },
+};
+
 const struct fb_videomode vesa_modes[] = {
        /* 0 640x350-85 VESA */
        { NULL, 85, 640, 350, 31746,  96, 32, 60, 32, 64, 3,
@@ -855,6 +902,7 @@ const struct fb_videomode *fb_find_nearest_mode(const struct fb_videomode *mode,
                        abs(cmode->yres - mode->yres);
                if (diff > d) {
                        diff = d;
+                       diff_refresh = abs(cmode->refresh - mode->refresh);
                        best = cmode;
                } else if (diff == d) {
                        d = abs(cmode->refresh - mode->refresh);
index 7cfc170bce196d28492fd4f4bbc5d9aace16ce31..cb013919e9ce5fbfd29bb3f27521f62c99e394e1 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/clk.h>
 #include <linux/mutex.h>
 
+#include <mach/dma.h>
 #include <mach/hardware.h>
 #include <mach/ipu.h>
 #include <mach/mx3fb.h>
@@ -1420,6 +1421,9 @@ static bool chan_filter(struct dma_chan *chan, void *arg)
        struct device *dev;
        struct mx3fb_platform_data *mx3fb_pdata;
 
+       if (!imx_dma_is_ipu(chan))
+               return false;
+
        if (!rq)
                return false;
 
@@ -1470,8 +1474,7 @@ static int mx3fb_probe(struct platform_device *pdev)
                goto eremap;
        }
 
-       pr_debug("Remapped %x to %x at %p\n", sdc_reg->start, sdc_reg->end,
-                mx3fb->reg_base);
+       pr_debug("Remapped %pR at %p\n", sdc_reg, mx3fb->reg_base);
 
        /* IDMAC interface */
        dmaengine_get();
index 455c6055325dcae647858eb6cede512388f033dc..083c8fe53e24147962a1f821657cf1bfcff8608c 100644 (file)
@@ -1,7 +1,7 @@
 config FB_OMAP
        tristate "OMAP frame buffer support (EXPERIMENTAL)"
-       depends on FB && ARCH_OMAP && (OMAP2_DSS = "n")
-
+       depends on FB && (OMAP2_DSS = "n")
+       depends on ARCH_OMAP1 || ARCH_OMAP2 || ARCH_OMAP3
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
index 2fd7e5271be91ea1c9cd5b202ef40f985266dd46..9441e2eb3dee1a1d66259a406d0653da323570e6 100644 (file)
@@ -551,7 +551,7 @@ void __init omap_vram_reserve_sdram_memblock(void)
        if (!size)
                return;
 
-       size = PAGE_ALIGN(size);
+       size = ALIGN(size, SZ_2M);
 
        if (paddr) {
                if (paddr & ~PAGE_MASK) {
@@ -576,7 +576,7 @@ void __init omap_vram_reserve_sdram_memblock(void)
                        return;
                }
        } else {
-               paddr = memblock_alloc(size, PAGE_SIZE);
+               paddr = memblock_alloc(size, SZ_2M);
        }
 
        memblock_free(paddr, size);
index a6247fc081ab9fb80671b6fd34b611d0484586d5..28b1c6c3d8ac98054ca2aad04021d4107cd01662 100644 (file)
@@ -409,28 +409,6 @@ s1d13xxxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
  functions to handle bitblt acceleration
  ************************************************************/
 
-/**
- *     bltbit_wait_bitset - waits for change in register value
- *     @info : framebuffer structure
- *     @bit  : value expected in register
- *     @timeout : ...
- *
- *     waits until value changes INTO bit
- */
-static u8
-bltbit_wait_bitset(struct fb_info *info, u8 bit, int timeout)
-{
-       while (!(s1d13xxxfb_readreg(info->par, S1DREG_BBLT_CTL0) & bit)) {
-               udelay(10);
-               if (!--timeout) {
-                       dbg_blit("wait_bitset timeout\n");
-                       break;
-               }
-       }
-
-       return timeout;
-}
-
 /**
  *     bltbit_wait_bitclear - waits for change in register value
  *     @info : frambuffer structure
@@ -454,34 +432,6 @@ bltbit_wait_bitclear(struct fb_info *info, u8 bit, int timeout)
        return timeout;
 }
 
-/**
- *     bltbit_fifo_status - checks the current status of the fifo
- *     @info : framebuffer structure
- *
- *     returns number of free words in buffer
- */
-static u8
-bltbit_fifo_status(struct fb_info *info)
-{
-       u8 status;
-
-       status = s1d13xxxfb_readreg(info->par, S1DREG_BBLT_CTL0);
-
-       /* its empty so room for 16 words */
-       if (status & BBLT_FIFO_EMPTY)
-               return 16;
-
-       /* its full so we dont want to add */
-       if (status & BBLT_FIFO_FULL)
-               return 0;
-
-       /* its atleast half full but we can add one atleast */
-       if (status & BBLT_FIFO_NOT_FULL)
-               return 1;
-
-       return 0;
-}
-
 /*
  *     s1d13xxxfb_bitblt_copyarea - accelerated copyarea function
  *     @info : framebuffer structure
index f9aca9d13d1b566e1da5e035a98f7e1ee34c0b1d..83ce9a04d872427013348665a58b89789bfdfc8f 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 #include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
 
 #include <mach/map.h>
 #include <plat/regs-fb-v4.h>
@@ -1013,8 +1014,30 @@ static int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd,
        return ret;
 }
 
+static int s3c_fb_open(struct fb_info *info, int user)
+{
+       struct s3c_fb_win *win = info->par;
+       struct s3c_fb *sfb = win->parent;
+
+       pm_runtime_get_sync(sfb->dev);
+
+       return 0;
+}
+
+static int s3c_fb_release(struct fb_info *info, int user)
+{
+       struct s3c_fb_win *win = info->par;
+       struct s3c_fb *sfb = win->parent;
+
+       pm_runtime_put_sync(sfb->dev);
+
+       return 0;
+}
+
 static struct fb_ops s3c_fb_ops = {
        .owner          = THIS_MODULE,
+       .fb_open        = s3c_fb_open,
+       .fb_release     = s3c_fb_release,
        .fb_check_var   = s3c_fb_check_var,
        .fb_set_par     = s3c_fb_set_par,
        .fb_blank       = s3c_fb_blank,
@@ -1322,6 +1345,8 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
 
        clk_enable(sfb->bus_clk);
 
+       pm_runtime_enable(sfb->dev);
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
                dev_err(dev, "failed to find registers\n");
@@ -1360,6 +1385,9 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
 
        dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs);
 
+       platform_set_drvdata(pdev, sfb);
+       pm_runtime_get_sync(sfb->dev);
+
        /* setup gpio and output polarity controls */
 
        pd->setup_gpio();
@@ -1400,6 +1428,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
        }
 
        platform_set_drvdata(pdev, sfb);
+       pm_runtime_put_sync(sfb->dev);
 
        return 0;
 
@@ -1434,6 +1463,8 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
        struct s3c_fb *sfb = platform_get_drvdata(pdev);
        int win;
 
+       pm_runtime_get_sync(sfb->dev);
+
        for (win = 0; win < S3C_FB_MAX_WIN; win++)
                if (sfb->windows[win])
                        s3c_fb_release_win(sfb, sfb->windows[win]);
@@ -1450,12 +1481,74 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
 
        kfree(sfb);
 
+       pm_runtime_put_sync(sfb->dev);
+       pm_runtime_disable(sfb->dev);
+
        return 0;
 }
 
 #ifdef CONFIG_PM
-static int s3c_fb_suspend(struct platform_device *pdev, pm_message_t state)
+static int s3c_fb_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct s3c_fb *sfb = platform_get_drvdata(pdev);
+       struct s3c_fb_win *win;
+       int win_no;
+
+       for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) {
+               win = sfb->windows[win_no];
+               if (!win)
+                       continue;
+
+               /* use the blank function to push into power-down */
+               s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
+       }
+
+       clk_disable(sfb->bus_clk);
+       return 0;
+}
+
+static int s3c_fb_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct s3c_fb *sfb = platform_get_drvdata(pdev);
+       struct s3c_fb_platdata *pd = sfb->pdata;
+       struct s3c_fb_win *win;
+       int win_no;
+
+       clk_enable(sfb->bus_clk);
+
+       /* setup registers */
+       writel(pd->vidcon1, sfb->regs + VIDCON1);
+
+       /* zero all windows before we do anything */
+       for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++)
+               s3c_fb_clear_win(sfb, win_no);
+
+       for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) {
+               void __iomem *regs = sfb->regs + sfb->variant.keycon;
+
+               regs += (win_no * 8);
+               writel(0xffffff, regs + WKEYCON0);
+               writel(0xffffff, regs + WKEYCON1);
+       }
+
+       /* restore framebuffers */
+       for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) {
+               win = sfb->windows[win_no];
+               if (!win)
+                       continue;
+
+               dev_dbg(&pdev->dev, "resuming window %d\n", win_no);
+               s3c_fb_set_par(win->fbinfo);
+       }
+
+       return 0;
+}
+
+int s3c_fb_runtime_suspend(struct device *dev)
 {
+       struct platform_device *pdev = to_platform_device(dev);
        struct s3c_fb *sfb = platform_get_drvdata(pdev);
        struct s3c_fb_win *win;
        int win_no;
@@ -1473,8 +1566,9 @@ static int s3c_fb_suspend(struct platform_device *pdev, pm_message_t state)
        return 0;
 }
 
-static int s3c_fb_resume(struct platform_device *pdev)
+int s3c_fb_runtime_resume(struct device *dev)
 {
+       struct platform_device *pdev = to_platform_device(dev);
        struct s3c_fb *sfb = platform_get_drvdata(pdev);
        struct s3c_fb_platdata *pd = sfb->pdata;
        struct s3c_fb_win *win;
@@ -1509,9 +1603,12 @@ static int s3c_fb_resume(struct platform_device *pdev)
 
        return 0;
 }
+
 #else
 #define s3c_fb_suspend NULL
 #define s3c_fb_resume  NULL
+#define s3c_fb_runtime_suspend NULL
+#define s3c_fb_runtime_resume NULL
 #endif
 
 
@@ -1710,15 +1807,21 @@ static struct platform_device_id s3c_fb_driver_ids[] = {
 };
 MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids);
 
+static const struct dev_pm_ops s3cfb_pm_ops = {
+       .suspend        = s3c_fb_suspend,
+       .resume         = s3c_fb_resume,
+       .runtime_suspend        = s3c_fb_runtime_suspend,
+       .runtime_resume         = s3c_fb_runtime_resume,
+};
+
 static struct platform_driver s3c_fb_driver = {
        .probe          = s3c_fb_probe,
        .remove         = __devexit_p(s3c_fb_remove),
-       .suspend        = s3c_fb_suspend,
-       .resume         = s3c_fb_resume,
        .id_table       = s3c_fb_driver_ids,
        .driver         = {
                .name   = "s3c-fb",
                .owner  = THIS_MODULE,
+               .pm     = &s3cfb_pm_ops,
        },
 };
 
index d7df10315d8d6f51aba676328985a52128e81876..76f9fac9020ff7967b424e998ef0c16cdb71a658 100644 (file)
@@ -209,7 +209,11 @@ enum hotplug_state {
 struct sh_hdmi {
        void __iomem *base;
        enum hotplug_state hp_state;    /* hot-plug status */
-       bool preprogrammed_mode;        /* use a pre-programmed VIC or the external mode */
+       u8 preprogrammed_vic;           /* use a pre-programmed VIC or
+                                          the external mode */
+       u8 edid_block_addr;
+       u8 edid_segment_nr;
+       u8 edid_blocks;
        struct clk *hdmi_clk;
        struct device *dev;
        struct fb_info *info;
@@ -342,7 +346,7 @@ static void sh_hdmi_external_video_param(struct sh_hdmi *hdmi)
        hdmi_write(hdmi, var->vsync_len, HDMI_EXTERNAL_V_DURATION);
 
        /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for external mode */
-       if (!hdmi->preprogrammed_mode)
+       if (!hdmi->preprogrammed_vic)
                hdmi_write(hdmi, sync | 1 | (voffset << 4),
                           HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS);
 }
@@ -466,7 +470,18 @@ static void sh_hdmi_audio_config(struct sh_hdmi *hdmi)
  */
 static void sh_hdmi_phy_config(struct sh_hdmi *hdmi)
 {
-       if (hdmi->var.yres > 480) {
+       if (hdmi->var.pixclock < 10000) {
+               /* for 1080p8bit 148MHz */
+               hdmi_write(hdmi, 0x1d, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
+               hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
+               hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3);
+               hdmi_write(hdmi, 0x4c, HDMI_SLIPHDMIT_PARAM_SETTINGS_5);
+               hdmi_write(hdmi, 0x1e, HDMI_SLIPHDMIT_PARAM_SETTINGS_6);
+               hdmi_write(hdmi, 0x48, HDMI_SLIPHDMIT_PARAM_SETTINGS_7);
+               hdmi_write(hdmi, 0x0e, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
+               hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
+               hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
+       } else if (hdmi->var.pixclock < 30000) {
                /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */
                /*
                 * [1:0]        Speed_A
@@ -565,13 +580,11 @@ static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi)
        hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB3);
 
        /*
-        * VIC = 1280 x 720p: ignored if external config is used
-        * Send 2 for 720 x 480p, 16 for 1080p, ignored in external mode
+        * VIC should be ignored if external config is used, so, we could just use 0,
+        * but play safe and use a valid value in any case just in case
         */
-       if (hdmi->var.yres == 1080 && hdmi->var.xres == 1920)
-               vic = 16;
-       else if (hdmi->var.yres == 480 && hdmi->var.xres == 720)
-               vic = 2;
+       if (hdmi->preprogrammed_vic)
+               vic = hdmi->preprogrammed_vic;
        else
                vic = 4;
        hdmi_write(hdmi, vic, HDMI_CTRL_PKT_BUF_ACCESS_PB4);
@@ -685,11 +698,21 @@ static void sh_hdmi_configure(struct sh_hdmi *hdmi)
 }
 
 static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi,
-                                       const struct fb_videomode *mode)
+               const struct fb_videomode *mode,
+               unsigned long *hdmi_rate, unsigned long *parent_rate)
 {
-       long target = PICOS2KHZ(mode->pixclock) * 1000,
-               rate = clk_round_rate(hdmi->hdmi_clk, target);
-       unsigned long rate_error = rate > 0 ? abs(rate - target) : ULONG_MAX;
+       unsigned long target = PICOS2KHZ(mode->pixclock) * 1000, rate_error;
+       struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
+
+       *hdmi_rate = clk_round_rate(hdmi->hdmi_clk, target);
+       if ((long)*hdmi_rate < 0)
+               *hdmi_rate = clk_get_rate(hdmi->hdmi_clk);
+
+       rate_error = (long)*hdmi_rate > 0 ? abs(*hdmi_rate - target) : ULONG_MAX;
+       if (rate_error && pdata->clk_optimize_parent)
+               rate_error = pdata->clk_optimize_parent(target, hdmi_rate, parent_rate);
+       else if (clk_get_parent(hdmi->hdmi_clk))
+               *parent_rate = clk_get_rate(clk_get_parent(hdmi->hdmi_clk));
 
        dev_dbg(hdmi->dev, "%u-%u-%u-%u x %u-%u-%u-%u\n",
                mode->left_margin, mode->xres,
@@ -697,14 +720,15 @@ static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi,
                mode->upper_margin, mode->yres,
                mode->lower_margin, mode->vsync_len);
 
-       dev_dbg(hdmi->dev, "\t@%lu(+/-%lu)Hz, e=%lu / 1000, r=%uHz\n", target,
-                rate_error, rate_error ? 10000 / (10 * target / rate_error) : 0,
-                mode->refresh);
+       dev_dbg(hdmi->dev, "\t@%lu(+/-%lu)Hz, e=%lu / 1000, r=%uHz, p=%luHz\n", target,
+               rate_error, rate_error ? 10000 / (10 * target / rate_error) : 0,
+               mode->refresh, *parent_rate);
 
        return rate_error;
 }
 
-static int sh_hdmi_read_edid(struct sh_hdmi *hdmi)
+static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
+                            unsigned long *parent_rate)
 {
        struct fb_var_screeninfo tmpvar;
        struct fb_var_screeninfo *var = &tmpvar;
@@ -735,7 +759,38 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi)
        printk(KERN_CONT "\n");
 #endif
 
-       fb_edid_to_monspecs(edid, &hdmi->monspec);
+       if (!hdmi->edid_blocks) {
+               fb_edid_to_monspecs(edid, &hdmi->monspec);
+               hdmi->edid_blocks = edid[126] + 1;
+
+               dev_dbg(hdmi->dev, "%d main modes, %d extension blocks\n",
+                       hdmi->monspec.modedb_len, hdmi->edid_blocks - 1);
+       } else {
+               dev_dbg(hdmi->dev, "Extension %u detected, DTD start %u\n",
+                       edid[0], edid[2]);
+               fb_edid_add_monspecs(edid, &hdmi->monspec);
+       }
+
+       if (hdmi->edid_blocks > hdmi->edid_segment_nr * 2 +
+           (hdmi->edid_block_addr >> 7) + 1) {
+               /* More blocks to read */
+               if (hdmi->edid_block_addr) {
+                       hdmi->edid_block_addr = 0;
+                       hdmi->edid_segment_nr++;
+               } else {
+                       hdmi->edid_block_addr = 0x80;
+               }
+               /* Set EDID word address  */
+               hdmi_write(hdmi, hdmi->edid_block_addr, HDMI_EDID_WORD_ADDRESS);
+               /* Enable EDID interrupt */
+               hdmi_write(hdmi, 0xC6, HDMI_INTERRUPT_MASK_1);
+               /* Set EDID segment pointer - starts reading EDID */
+               hdmi_write(hdmi, hdmi->edid_segment_nr, HDMI_EDID_SEGMENT_POINTER);
+               return -EAGAIN;
+       }
+
+       /* All E-EDID blocks ready */
+       dev_dbg(hdmi->dev, "%d main and extended modes\n", hdmi->monspec.modedb_len);
 
        fb_get_options("sh_mobile_lcdc", &forced);
        if (forced && *forced) {
@@ -754,11 +809,14 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi)
        for (i = 0, mode = hdmi->monspec.modedb;
             f_width && f_height && i < hdmi->monspec.modedb_len && !exact_match;
             i++, mode++) {
-               unsigned long rate_error = sh_hdmi_rate_error(hdmi, mode);
+               unsigned long rate_error;
 
                /* No interest in unmatching modes */
                if (f_width != mode->xres || f_height != mode->yres)
                        continue;
+
+               rate_error = sh_hdmi_rate_error(hdmi, mode, hdmi_rate, parent_rate);
+
                if (f_refresh == mode->refresh || (!f_refresh && !rate_error))
                        /*
                         * Exact match if either the refresh rate matches or it
@@ -802,7 +860,7 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi)
 
                if (modelist) {
                        found = &modelist->mode;
-                       found_rate_error = sh_hdmi_rate_error(hdmi, found);
+                       found_rate_error = sh_hdmi_rate_error(hdmi, found, hdmi_rate, parent_rate);
                }
        }
 
@@ -810,16 +868,27 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi)
        if (!found)
                return -ENXIO;
 
-       dev_info(hdmi->dev, "Using %s mode %ux%u@%uHz (%luHz), clock error %luHz\n",
-                modelist ? "default" : "EDID", found->xres, found->yres,
-                found->refresh, PICOS2KHZ(found->pixclock) * 1000, found_rate_error);
-
-       if ((found->xres == 720 && found->yres == 480) ||
-           (found->xres == 1280 && found->yres == 720) ||
-           (found->xres == 1920 && found->yres == 1080))
-               hdmi->preprogrammed_mode = true;
+       if (found->xres == 640 && found->yres == 480 && found->refresh == 60)
+               hdmi->preprogrammed_vic = 1;
+       else if (found->xres == 720 && found->yres == 480 && found->refresh == 60)
+               hdmi->preprogrammed_vic = 2;
+       else if (found->xres == 720 && found->yres == 576 && found->refresh == 50)
+               hdmi->preprogrammed_vic = 17;
+       else if (found->xres == 1280 && found->yres == 720 && found->refresh == 60)
+               hdmi->preprogrammed_vic = 4;
+       else if (found->xres == 1920 && found->yres == 1080 && found->refresh == 24)
+               hdmi->preprogrammed_vic = 32;
+       else if (found->xres == 1920 && found->yres == 1080 && found->refresh == 50)
+               hdmi->preprogrammed_vic = 31;
+       else if (found->xres == 1920 && found->yres == 1080 && found->refresh == 60)
+               hdmi->preprogrammed_vic = 16;
        else
-               hdmi->preprogrammed_mode = false;
+               hdmi->preprogrammed_vic = 0;
+
+       dev_dbg(hdmi->dev, "Using %s %s mode %ux%u@%uHz (%luHz), clock error %luHz\n",
+               modelist ? "default" : "EDID", hdmi->preprogrammed_vic ? "VIC" : "external",
+               found->xres, found->yres, found->refresh,
+               PICOS2KHZ(found->pixclock) * 1000, found_rate_error);
 
        fb_videomode_to_var(&hdmi->var, found);
        sh_hdmi_external_video_param(hdmi);
@@ -868,32 +937,34 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
                /* Check, if hot plug & MSENS pin status are both high */
                if ((msens & 0xC0) == 0xC0) {
                        /* Display plug in */
+                       hdmi->edid_segment_nr = 0;
+                       hdmi->edid_block_addr = 0;
+                       hdmi->edid_blocks = 0;
                        hdmi->hp_state = HDMI_HOTPLUG_CONNECTED;
 
                        /* Set EDID word address  */
                        hdmi_write(hdmi, 0x00, HDMI_EDID_WORD_ADDRESS);
-                       /* Set EDID segment pointer */
-                       hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER);
                        /* Enable EDID interrupt */
                        hdmi_write(hdmi, 0xC6, HDMI_INTERRUPT_MASK_1);
+                       /* Set EDID segment pointer - starts reading EDID */
+                       hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER);
                } else if (!(status1 & 0x80)) {
                        /* Display unplug, beware multiple interrupts */
-                       if (hdmi->hp_state != HDMI_HOTPLUG_DISCONNECTED)
+                       if (hdmi->hp_state != HDMI_HOTPLUG_DISCONNECTED) {
+                               hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
                                schedule_delayed_work(&hdmi->edid_work, 0);
-
-                       hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
+                       }
                        /* display_off will switch back to mode_a */
                }
        } else if (status1 & 2) {
                /* EDID error interrupt: retry */
                /* Set EDID word address  */
-               hdmi_write(hdmi, 0x00, HDMI_EDID_WORD_ADDRESS);
+               hdmi_write(hdmi, hdmi->edid_block_addr, HDMI_EDID_WORD_ADDRESS);
                /* Set EDID segment pointer */
-               hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER);
+               hdmi_write(hdmi, hdmi->edid_segment_nr, HDMI_EDID_SEGMENT_POINTER);
        } else if (status1 & 4) {
                /* Disable EDID interrupt */
                hdmi_write(hdmi, 0xC0, HDMI_INTERRUPT_MASK_1);
-               hdmi->hp_state = HDMI_HOTPLUG_EDID_DONE;
                schedule_delayed_work(&hdmi->edid_work, msecs_to_jiffies(10));
        }
 
@@ -972,39 +1043,37 @@ static bool sh_hdmi_must_reconfigure(struct sh_hdmi *hdmi)
 
 /**
  * sh_hdmi_clk_configure() - set HDMI clock frequency and enable the clock
- * @hdmi:      driver context
- * @pixclock:  pixel clock period in picoseconds
- * return:     configured positive rate if successful
- *             0 if couldn't set the rate, but managed to enable the clock
- *             negative error, if couldn't enable the clock
+ * @hdmi:              driver context
+ * @hdmi_rate:         HDMI clock frequency in Hz
+ * @parent_rate:       if != 0 - set parent clock rate for optimal precision
+ * return:             configured positive rate if successful
+ *                     0 if couldn't set the rate, but managed to enable the
+ *                     clock, negative error, if couldn't enable the clock
  */
-static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long pixclock)
+static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long hdmi_rate,
+                                 unsigned long parent_rate)
 {
-       long rate;
        int ret;
 
-       rate = PICOS2KHZ(pixclock) * 1000;
-       rate = clk_round_rate(hdmi->hdmi_clk, rate);
-       if (rate > 0) {
-               ret = clk_set_rate(hdmi->hdmi_clk, rate);
+       if (parent_rate && clk_get_parent(hdmi->hdmi_clk)) {
+               ret = clk_set_rate(clk_get_parent(hdmi->hdmi_clk), parent_rate);
                if (ret < 0) {
-                       dev_warn(hdmi->dev, "Cannot set rate %ld: %d\n", rate, ret);
-                       rate = 0;
+                       dev_warn(hdmi->dev, "Cannot set parent rate %ld: %d\n", parent_rate, ret);
+                       hdmi_rate = clk_round_rate(hdmi->hdmi_clk, hdmi_rate);
                } else {
-                       dev_dbg(hdmi->dev, "HDMI set frequency %lu\n", rate);
+                       dev_dbg(hdmi->dev, "HDMI set parent frequency %lu\n", parent_rate);
                }
-       } else {
-               rate = 0;
-               dev_warn(hdmi->dev, "Cannot get suitable rate: %ld\n", rate);
        }
 
-       ret = clk_enable(hdmi->hdmi_clk);
+       ret = clk_set_rate(hdmi->hdmi_clk, hdmi_rate);
        if (ret < 0) {
-               dev_err(hdmi->dev, "Cannot enable clock: %d\n", ret);
-               return ret;
+               dev_warn(hdmi->dev, "Cannot set rate %ld: %d\n", hdmi_rate, ret);
+               hdmi_rate = 0;
+       } else {
+               dev_dbg(hdmi->dev, "HDMI set frequency %lu\n", hdmi_rate);
        }
 
-       return rate;
+       return hdmi_rate;
 }
 
 /* Hotplug interrupt occurred, read EDID */
@@ -1023,17 +1092,20 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
 
        mutex_lock(&hdmi->mutex);
 
-       if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) {
+       if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) {
+               unsigned long parent_rate = 0, hdmi_rate;
+
                /* A device has been plugged in */
                pm_runtime_get_sync(hdmi->dev);
 
-               ret = sh_hdmi_read_edid(hdmi);
+               ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate);
                if (ret < 0)
                        goto out;
 
+               hdmi->hp_state = HDMI_HOTPLUG_EDID_DONE;
+
                /* Reconfigure the clock */
-               clk_disable(hdmi->hdmi_clk);
-               ret = sh_hdmi_clk_configure(hdmi, hdmi->var.pixclock);
+               ret = sh_hdmi_clk_configure(hdmi, hdmi_rate, parent_rate);
                if (ret < 0)
                        goto out;
 
@@ -1085,7 +1157,7 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
        }
 
 out:
-       if (ret < 0)
+       if (ret < 0 && ret != -EAGAIN)
                hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
        mutex_unlock(&hdmi->mutex);
 
@@ -1166,13 +1238,22 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
                goto egetclk;
        }
 
-       /* Some arbitrary relaxed pixclock just to get things started */
-       rate = sh_hdmi_clk_configure(hdmi, 37037);
+       /* An arbitrary relaxed pixclock just to get things started: from standard 480p */
+       rate = clk_round_rate(hdmi->hdmi_clk, PICOS2KHZ(37037));
+       if (rate > 0)
+               rate = sh_hdmi_clk_configure(hdmi, rate, 0);
+
        if (rate < 0) {
                ret = rate;
                goto erate;
        }
 
+       ret = clk_enable(hdmi->hdmi_clk);
+       if (ret < 0) {
+               dev_err(hdmi->dev, "Cannot enable clock: %d\n", ret);
+               goto erate;
+       }
+
        dev_dbg(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate);
 
        if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) {
@@ -1190,10 +1271,6 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, hdmi);
 
-       /* Product and revision IDs are 0 in sh-mobile version */
-       dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
-                hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID));
-
        /* Set up LCDC callbacks */
        board_cfg = &pdata->lcd_chan->board_cfg;
        board_cfg->owner = THIS_MODULE;
@@ -1206,6 +1283,10 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
        pm_runtime_enable(&pdev->dev);
        pm_runtime_resume(&pdev->dev);
 
+       /* Product and revision IDs are 0 in sh-mobile version */
+       dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
+                hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID));
+
        ret = request_irq(irq, sh_hdmi_hotplug, 0,
                          dev_name(&pdev->dev), hdmi);
        if (ret < 0) {
index 9b1364723c65e2fcff4dcec661d59ab50b960ee1..778bffbbdbb7abf194757860bb93d600bb56212d 100644 (file)
@@ -54,8 +54,8 @@ static int lcdc_shared_regs[] = {
 };
 #define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs)
 
-#define DEFAULT_XRES 1280
-#define DEFAULT_YRES 1024
+#define MAX_XRES 1920
+#define MAX_YRES 1080
 
 static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
        [LDDCKPAT1R] = 0x400,
@@ -860,7 +860,7 @@ static void sh_mobile_fb_reconfig(struct fb_info *info)
                /* Couldn't reconfigure, hopefully, can continue as before */
                return;
 
-       info->fix.line_length = mode2.xres * (ch->cfg.bpp / 8);
+       info->fix.line_length = mode1.xres * (ch->cfg.bpp / 8);
 
        /*
         * fb_set_var() calls the notifier change internally, only if
@@ -868,7 +868,7 @@ static void sh_mobile_fb_reconfig(struct fb_info *info)
         * user event, we have to call the chain ourselves.
         */
        event.info = info;
-       event.data = &mode2;
+       event.data = &mode1;
        fb_notifier_call_chain(evnt, &event);
 }
 
@@ -914,22 +914,12 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
 {
        struct sh_mobile_lcdc_chan *ch = info->par;
 
-       if (var->xres < 160 || var->xres > 1920 ||
-           var->yres < 120 || var->yres > 1080 ||
-           var->left_margin < 32 || var->left_margin > 320 ||
-           var->right_margin < 12 || var->right_margin > 240 ||
-           var->upper_margin < 12 || var->upper_margin > 120 ||
-           var->lower_margin < 1 || var->lower_margin > 64 ||
-           var->hsync_len < 32 || var->hsync_len > 240 ||
-           var->vsync_len < 2 || var->vsync_len > 64 ||
-           var->pixclock < 6000 || var->pixclock > 40000 ||
+       if (var->xres > MAX_XRES || var->yres > MAX_YRES ||
            var->xres * var->yres * (ch->cfg.bpp / 8) * 2 > info->fix.smem_len) {
-               dev_warn(info->dev, "Invalid info: %u %u %u %u %u %u %u %u %u!\n",
-                        var->xres, var->yres,
-                        var->left_margin, var->right_margin,
-                        var->upper_margin, var->lower_margin,
-                        var->hsync_len, var->vsync_len,
-                        var->pixclock);
+               dev_warn(info->dev, "Invalid info: %u-%u-%u-%u x %u-%u-%u-%u @ %lukHz!\n",
+                        var->left_margin, var->xres, var->right_margin, var->hsync_len,
+                        var->upper_margin, var->yres, var->lower_margin, var->vsync_len,
+                        PICOS2KHZ(var->pixclock));
                return -EINVAL;
        }
        return 0;
@@ -1226,7 +1216,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
                }
 
                if (!mode)
-                       max_size = DEFAULT_XRES * DEFAULT_YRES;
+                       max_size = MAX_XRES * MAX_YRES;
                else if (max_cfg)
                        dev_dbg(&pdev->dev, "Found largest videomode %ux%u\n",
                                max_cfg->xres, max_cfg->yres);
index c311ad3c3687c739a558fc9baea8d9393aef756a..66de832361cccd4ad085d2bd1e2f27662c9486c1 100644 (file)
  * Used by permission.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include "init.h"
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
 #include "300vtbl.h"
 #endif
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 #include "310vtbl.h"
 #endif
 
@@ -78,7 +74,7 @@
 /*         POINTER INITIALIZATION            */
 /*********************************************/
 
-#if defined(SIS300) || defined(SIS315H)
+#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
 static void
 InitCommonPointer(struct SiS_Private *SiS_Pr)
 {
@@ -160,7 +156,7 @@ InitCommonPointer(struct SiS_Private *SiS_Pr)
 }
 #endif
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
 static void
 InitTo300Pointer(struct SiS_Private *SiS_Pr)
 {
@@ -237,7 +233,7 @@ InitTo300Pointer(struct SiS_Private *SiS_Pr)
 }
 #endif
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 static void
 InitTo310Pointer(struct SiS_Private *SiS_Pr)
 {
@@ -321,13 +317,13 @@ bool
 SiSInitPtr(struct SiS_Private *SiS_Pr)
 {
    if(SiS_Pr->ChipType < SIS_315H) {
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
       InitTo300Pointer(SiS_Pr);
 #else
       return false;
 #endif
    } else {
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
       InitTo310Pointer(SiS_Pr);
 #else
       return false;
@@ -340,9 +336,7 @@ SiSInitPtr(struct SiS_Private *SiS_Pr)
 /*            HELPER: Get ModeID             */
 /*********************************************/
 
-#ifndef SIS_XORG_XF86
 static
-#endif
 unsigned short
 SiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
                int Depth, bool FSTN, int LCDwidth, int LCDheight)
@@ -882,59 +876,59 @@ SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDispl
 /*********************************************/
 
 void
-SiS_SetReg(SISIOADDRESS port, unsigned short index, unsigned short data)
+SiS_SetReg(SISIOADDRESS port, u8 index, u8 data)
 {
-   OutPortByte(port, index);
-   OutPortByte(port + 1, data);
+       outb(index, port);
+       outb(data, port + 1);
 }
 
 void
-SiS_SetRegByte(SISIOADDRESS port, unsigned short data)
+SiS_SetRegByte(SISIOADDRESS port, u8 data)
 {
-   OutPortByte(port, data);
+       outb(data, port);
 }
 
 void
-SiS_SetRegShort(SISIOADDRESS port, unsigned short data)
+SiS_SetRegShort(SISIOADDRESS port, u16 data)
 {
-   OutPortWord(port, data);
+       outw(data, port);
 }
 
 void
-SiS_SetRegLong(SISIOADDRESS port, unsigned int data)
+SiS_SetRegLong(SISIOADDRESS port, u32 data)
 {
-   OutPortLong(port, data);
+       outl(data, port);
 }
 
-unsigned char
-SiS_GetReg(SISIOADDRESS port, unsigned short index)
+u8
+SiS_GetReg(SISIOADDRESS port, u8 index)
 {
-   OutPortByte(port, index);
-   return(InPortByte(port + 1));
+       outb(index, port);
+       return inb(port + 1);
 }
 
-unsigned char
+u8
 SiS_GetRegByte(SISIOADDRESS port)
 {
-   return(InPortByte(port));
+       return inb(port);
 }
 
-unsigned short
+u16
 SiS_GetRegShort(SISIOADDRESS port)
 {
-   return(InPortWord(port));
+       return inw(port);
 }
 
-unsigned int
+u32
 SiS_GetRegLong(SISIOADDRESS port)
 {
-   return(InPortLong(port));
+       return inl(port);
 }
 
 void
-SiS_SetRegANDOR(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND, unsigned short DataOR)
+SiS_SetRegANDOR(SISIOADDRESS Port, u8 Index, u8 DataAND, u8 DataOR)
 {
-   unsigned short temp;
+   u8 temp;
 
    temp = SiS_GetReg(Port, Index);
    temp = (temp & (DataAND)) | DataOR;
@@ -942,9 +936,9 @@ SiS_SetRegANDOR(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND,
 }
 
 void
-SiS_SetRegAND(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND)
+SiS_SetRegAND(SISIOADDRESS Port, u8 Index, u8 DataAND)
 {
-   unsigned short temp;
+   u8 temp;
 
    temp = SiS_GetReg(Port, Index);
    temp &= DataAND;
@@ -952,9 +946,9 @@ SiS_SetRegAND(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND)
 }
 
 void
-SiS_SetRegOR(SISIOADDRESS Port, unsigned short Index, unsigned short DataOR)
+SiS_SetRegOR(SISIOADDRESS Port, u8 Index, u8 DataOR)
 {
-   unsigned short temp;
+   u8 temp;
 
    temp = SiS_GetReg(Port, Index);
    temp |= DataOR;
@@ -1089,7 +1083,7 @@ static void
 SiSInitPCIetc(struct SiS_Private *SiS_Pr)
 {
    switch(SiS_Pr->ChipType) {
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
    case SIS_300:
    case SIS_540:
    case SIS_630:
@@ -1108,7 +1102,7 @@ SiSInitPCIetc(struct SiS_Private *SiS_Pr)
       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x5A);
       break;
 #endif
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
    case SIS_315H:
    case SIS_315:
    case SIS_315PRO:
@@ -1152,9 +1146,7 @@ SiSInitPCIetc(struct SiS_Private *SiS_Pr)
 /*             HELPER: SetLVDSetc            */
 /*********************************************/
 
-#ifdef SIS_LINUX_KERNEL
 static
-#endif
 void
 SiSSetLVDSetc(struct SiS_Private *SiS_Pr)
 {
@@ -1174,7 +1166,7 @@ SiSSetLVDSetc(struct SiS_Private *SiS_Pr)
    if((temp == 1) || (temp == 2)) return;
 
    switch(SiS_Pr->ChipType) {
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
    case SIS_540:
    case SIS_630:
    case SIS_730:
@@ -1188,7 +1180,7 @@ SiSSetLVDSetc(struct SiS_Private *SiS_Pr)
        }
        break;
 #endif
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
    case SIS_550:
    case SIS_650:
    case SIS_740:
@@ -1420,9 +1412,7 @@ SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr)
 /*             HELPER: GetVBType             */
 /*********************************************/
 
-#ifdef SIS_LINUX_KERNEL
 static
-#endif
 void
 SiS_GetVBType(struct SiS_Private *SiS_Pr)
 {
@@ -1487,7 +1477,6 @@ SiS_GetVBType(struct SiS_Private *SiS_Pr)
 /*           HELPER: Check RAM size          */
 /*********************************************/
 
-#ifdef SIS_LINUX_KERNEL
 static bool
 SiS_CheckMemorySize(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
                unsigned short ModeIdIndex)
@@ -1501,13 +1490,12 @@ SiS_CheckMemorySize(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
    if(AdapterMemSize < memorysize) return false;
    return true;
 }
-#endif
 
 /*********************************************/
 /*           HELPER: Get DRAM type           */
 /*********************************************/
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 static unsigned char
 SiS_Get310DRAMType(struct SiS_Private *SiS_Pr)
 {
@@ -1574,7 +1562,6 @@ SiS_GetMCLK(struct SiS_Private *SiS_Pr)
 /*           HELPER: ClearBuffer             */
 /*********************************************/
 
-#ifdef SIS_LINUX_KERNEL
 static void
 SiS_ClearBuffer(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 {
@@ -1587,7 +1574,7 @@ SiS_ClearBuffer(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 
    if(SiS_Pr->SiS_ModeType >= ModeEGA) {
       if(ModeNo > 0x13) {
-        SiS_SetMemory(memaddr, memsize, 0);
+        memset_io(memaddr, 0, memsize);
       } else {
         pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;
         for(i = 0; i < 0x4000; i++) writew(0x0000, &pBuffer[i]);
@@ -1596,10 +1583,9 @@ SiS_ClearBuffer(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
       pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;
       for(i = 0; i < 0x4000; i++) writew(0x0720, &pBuffer[i]);
    } else {
-      SiS_SetMemory(memaddr, 0x8000, 0);
+      memset_io(memaddr, 0, 0x8000);
    }
 }
-#endif
 
 /*********************************************/
 /*           HELPER: SearchModeID            */
@@ -2132,7 +2118,7 @@ SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
       SiS_SetReg(SiS_Pr->SiS_P3d4,0x14,0x4F);
    }
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
    if(SiS_Pr->ChipType == XGI_20) {
       SiS_SetReg(SiS_Pr->SiS_P3d4,0x04,crt1data[4] - 1);
       if(!(temp = crt1data[5] & 0x1f)) {
@@ -2215,7 +2201,7 @@ SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
    SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,clkb);
 
    if(SiS_Pr->ChipType >= SIS_315H) {
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
       SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x01);
       if(SiS_Pr->ChipType == XGI_20) {
          unsigned short mf = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
@@ -2236,7 +2222,7 @@ SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
 /*                  FIFO                     */
 /*********************************************/
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
 void
 SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *idx1,
                unsigned short *idx2)
@@ -2506,11 +2492,7 @@ SiS_SetCRT1FIFO_630(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
    SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x09,0x80,data);
 
   /* Write foreground and background queue */
-#ifdef SIS_LINUX_KERNEL
    templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
-#else
-   templ = pciReadLong(0x00000000, 0x50);
-#endif
 
    if(SiS_Pr->ChipType == SIS_730) {
 
@@ -2530,13 +2512,8 @@ SiS_SetCRT1FIFO_630(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
 
    }
 
-#ifdef SIS_LINUX_KERNEL
    sisfb_write_nbridge_pci_dword(SiS_Pr, 0x50, templ);
    templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xA0);
-#else
-   pciWriteLong(0x00000000, 0x50, templ);
-   templ = pciReadLong(0x00000000, 0xA0);
-#endif
 
    /* GUI grant timer (PCI config 0xA3) */
    if(SiS_Pr->ChipType == SIS_730) {
@@ -2552,15 +2529,11 @@ SiS_SetCRT1FIFO_630(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
 
    }
 
-#ifdef SIS_LINUX_KERNEL
    sisfb_write_nbridge_pci_dword(SiS_Pr, 0xA0, templ);
-#else
-   pciWriteLong(0x00000000, 0xA0, templ);
-#endif
 }
-#endif /* SIS300 */
+#endif /* CONFIG_FB_SIS_300 */
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 static void
 SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
 {
@@ -2612,7 +2585,7 @@ SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
    }
 
    if(SiS_Pr->ChipType < SIS_315H) {
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
       if(VCLK > 150) data |= 0x80;
       SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data);
 
@@ -2621,7 +2594,7 @@ SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
       SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data);
 #endif
    } else if(SiS_Pr->ChipType < XGI_20) {
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
       if(VCLK >= 166) data |= 0x0c;
       SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
 
@@ -2630,7 +2603,7 @@ SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
       }
 #endif
    } else {
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
       if(VCLK >= 200) data |= 0x0c;
       if(SiS_Pr->ChipType == XGI_20) data &= ~0x04;
       SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
@@ -2675,7 +2648,7 @@ SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
                unsigned short ModeIdIndex, unsigned short RRTI)
 {
    unsigned short data, infoflag = 0, modeflag, resindex;
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
    unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
    unsigned short data2, data3;
 #endif
@@ -2736,7 +2709,7 @@ SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
       SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,data);
    }
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
    if(SiS_Pr->ChipType >= SIS_315H) {
       SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xfb);
    }
@@ -2826,7 +2799,7 @@ SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
 
    SiS_SetVCLKState(SiS_Pr, ModeNo, RRTI, ModeIdIndex);
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
    if(((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) ||
        (SiS_Pr->ChipType == XGI_40)) {
       if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
@@ -2845,7 +2818,7 @@ SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
 #endif
 }
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 static void
 SiS_SetupDualChip(struct SiS_Private *SiS_Pr)
 {
@@ -2999,11 +2972,6 @@ SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned sho
    SiS_Pr->SiS_SelectCRT2Rate = 0;
    SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
 
-#ifdef SIS_XORG_XF86
-   xf86DrvMsgVerb(0, X_PROBED, 4, "(init: VBType=0x%04x, VBInfo=0x%04x)\n",
-                    SiS_Pr->SiS_VBType, SiS_Pr->SiS_VBInfo);
-#endif
-
    if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
          SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
@@ -3028,7 +2996,7 @@ SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned sho
    }
 
    switch(SiS_Pr->ChipType) {
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
    case SIS_300:
       SiS_SetCRT1FIFO_300(SiS_Pr, ModeNo, RefreshRateTableIndex);
       break;
@@ -3039,7 +3007,7 @@ SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned sho
       break;
 #endif
    default:
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
       if(SiS_Pr->ChipType == XGI_20) {
          unsigned char sr2b = 0, sr2c = 0;
          switch(ModeNo) {
@@ -3062,7 +3030,7 @@ SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned sho
 
    SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
    if(SiS_Pr->ChipType == XGI_40) {
       SiS_SetupDualChip(SiS_Pr);
    }
@@ -3070,11 +3038,9 @@ SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned sho
 
    SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
 
-#ifdef SIS_LINUX_KERNEL
    if(SiS_Pr->SiS_flag_clearbuffer) {
       SiS_ClearBuffer(SiS_Pr, ModeNo);
    }
-#endif
 
    if(!(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA))) {
       SiS_WaitRetrace1(SiS_Pr);
@@ -3104,7 +3070,7 @@ SiS_InitVB(struct SiS_Private *SiS_Pr)
 static void
 SiS_ResetVB(struct SiS_Private *SiS_Pr)
 {
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
    unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
    unsigned short temp;
 
@@ -3139,7 +3105,7 @@ SiS_StrangeStuff(struct SiS_Private *SiS_Pr)
     * which locks CRT2 in some way to CRT1 timing. Disable
     * this here.
     */
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
    if((IS_SIS651) || (IS_SISM650) ||
       SiS_Pr->ChipType == SIS_340 ||
       SiS_Pr->ChipType == XGI_40) {
@@ -3160,7 +3126,7 @@ SiS_StrangeStuff(struct SiS_Private *SiS_Pr)
 static void
 SiS_Handle760(struct SiS_Private *SiS_Pr)
 {
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
    unsigned int somebase;
    unsigned char temp1, temp2, temp3;
 
@@ -3170,11 +3136,7 @@ SiS_Handle760(struct SiS_Private *SiS_Pr)
        (!(SiS_Pr->SiS_SysFlags & SF_760UMA)) )
       return;
 
-#ifdef SIS_LINUX_KERNEL
    somebase = sisfb_read_mio_pci_word(SiS_Pr, 0x74);
-#else
-   somebase = pciReadWord(0x00001000, 0x74);
-#endif
    somebase &= 0xffff;
 
    if(somebase == 0) return;
@@ -3190,105 +3152,34 @@ SiS_Handle760(struct SiS_Private *SiS_Pr)
       temp2 = 0x0b;
    }
 
-#ifdef SIS_LINUX_KERNEL
    sisfb_write_nbridge_pci_byte(SiS_Pr, 0x7e, temp1);
    sisfb_write_nbridge_pci_byte(SiS_Pr, 0x8d, temp2);
-#else
-   pciWriteByte(0x00000000, 0x7e, temp1);
-   pciWriteByte(0x00000000, 0x8d, temp2);
-#endif
 
    SiS_SetRegByte((somebase + 0x85), temp3);
 #endif
 }
 
-/*********************************************/
-/*      X.org/XFree86: SET SCREEN PITCH      */
-/*********************************************/
-
-#ifdef SIS_XORG_XF86
-static void
-SiS_SetPitchCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
-{
-   SISPtr pSiS = SISPTR(pScrn);
-   unsigned short HDisplay = pSiS->scrnPitch >> 3;
-
-   SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,(HDisplay & 0xFF));
-   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,(HDisplay >> 8));
-}
-
-static void
-SiS_SetPitchCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
-{
-   SISPtr pSiS = SISPTR(pScrn);
-   unsigned short HDisplay = pSiS->scrnPitch2 >> 3;
-
-    /* Unlock CRT2 */
-   if(pSiS->VGAEngine == SIS_315_VGA)
-      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2F, 0x01);
-   else
-      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24, 0x01);
-
-   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(HDisplay & 0xFF));
-   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0xF0,(HDisplay >> 8));
-}
-
-static void
-SiS_SetPitch(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
-{
-   SISPtr pSiS = SISPTR(pScrn);
-   bool isslavemode = false;
-
-   if( (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) &&
-       ( ((pSiS->VGAEngine == SIS_300_VGA) &&
-         (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0xa0) == 0x20) ||
-        ((pSiS->VGAEngine == SIS_315_VGA) &&
-         (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x50) == 0x10) ) ) {
-      isslavemode = true;
-   }
-
-   /* We need to set pitch for CRT1 if bridge is in slave mode, too */
-   if((pSiS->VBFlags & DISPTYPE_DISP1) || (isslavemode)) {
-      SiS_SetPitchCRT1(SiS_Pr, pScrn);
-   }
-   /* We must not set the pitch for CRT2 if bridge is in slave mode */
-   if((pSiS->VBFlags & DISPTYPE_DISP2) && (!isslavemode)) {
-      SiS_SetPitchCRT2(SiS_Pr, pScrn);
-   }
-}
-#endif
-
 /*********************************************/
 /*                 SiSSetMode()              */
 /*********************************************/
 
-#ifdef SIS_XORG_XF86
-/* We need pScrn for setting the pitch correctly */
-bool
-SiSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, unsigned short ModeNo, bool dosetpitch)
-#else
 bool
 SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
-#endif
 {
    SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
    unsigned short RealModeNo, ModeIdIndex;
    unsigned char  backupreg = 0;
-#ifdef SIS_LINUX_KERNEL
    unsigned short KeepLockReg;
 
    SiS_Pr->UseCustomMode = false;
    SiS_Pr->CRT1UsesCustomMode = false;
-#endif
 
    SiS_Pr->SiS_flag_clearbuffer = 0;
 
    if(SiS_Pr->UseCustomMode) {
       ModeNo = 0xfe;
    } else {
-#ifdef SIS_LINUX_KERNEL
       if(!(ModeNo & 0x80)) SiS_Pr->SiS_flag_clearbuffer = 1;
-#endif
       ModeNo &= 0x7f;
    }
 
@@ -3301,13 +3192,8 @@ SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
    SiS_GetSysFlags(SiS_Pr);
 
    SiS_Pr->SiS_VGAINFO = 0x11;
-#if defined(SIS_XORG_XF86) && (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__) || defined(__amd64__) || defined(__x86_64__))
-   if(pScrn) SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
-#endif
 
-#ifdef SIS_LINUX_KERNEL
    KeepLockReg = SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);
-#endif
    SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
 
    SiSInitPCIetc(SiS_Pr);
@@ -3344,12 +3230,10 @@ SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
    SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
    SiS_SetLowModeTest(SiS_Pr, ModeNo);
 
-#ifdef SIS_LINUX_KERNEL
    /* Check memory size (kernel framebuffer driver only) */
    if(!SiS_CheckMemorySize(SiS_Pr, ModeNo, ModeIdIndex)) {
       return false;
    }
-#endif
 
    SiS_OpenCRTC(SiS_Pr);
 
@@ -3384,7 +3268,7 @@ SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
    SiS_DisplayOn(SiS_Pr);
    SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
    if(SiS_Pr->ChipType >= SIS_315H) {
       if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
         if(!(SiS_IsDualEdge(SiS_Pr))) {
@@ -3396,7 +3280,7 @@ SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 
    if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
       if(SiS_Pr->ChipType >= SIS_315H) {
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
         if(!SiS_Pr->SiS_ROMNew) {
            if(SiS_IsVAMode(SiS_Pr)) {
               SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
@@ -3424,424 +3308,16 @@ SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
       }
    }
 
-#ifdef SIS_XORG_XF86
-   if(pScrn) {
-      /* SetPitch: Adapt to virtual size & position */
-      if((ModeNo > 0x13) && (dosetpitch)) {
-        SiS_SetPitch(SiS_Pr, pScrn);
-      }
-
-      /* Backup/Set ModeNo in BIOS scratch area */
-      SiS_GetSetModeID(pScrn, ModeNo);
-   }
-#endif
-
    SiS_CloseCRTC(SiS_Pr);
 
    SiS_Handle760(SiS_Pr);
 
-#ifdef SIS_LINUX_KERNEL
    /* We never lock registers in XF86 */
    if(KeepLockReg != 0xA1) SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x00);
-#endif
 
    return true;
 }
 
-/*********************************************/
-/*       X.org/XFree86: SiSBIOSSetMode()     */
-/*           for non-Dual-Head mode          */
-/*********************************************/
-
-#ifdef SIS_XORG_XF86
-bool
-SiSBIOSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
-               DisplayModePtr mode, bool IsCustom)
-{
-   SISPtr pSiS = SISPTR(pScrn);
-   unsigned short ModeNo = 0;
-
-   SiS_Pr->UseCustomMode = false;
-
-   if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
-
-      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting custom mode %dx%d\n",
-               SiS_Pr->CHDisplay,
-               (mode->Flags & V_INTERLACE ? SiS_Pr->CVDisplay * 2 :
-                  (mode->Flags & V_DBLSCAN ? SiS_Pr->CVDisplay / 2 :
-                     SiS_Pr->CVDisplay)));
-
-   } else {
-
-      /* Don't need vbflags here; checks done earlier */
-      ModeNo = SiS_GetModeNumber(pScrn, mode, pSiS->VBFlags);
-      if(!ModeNo) return false;
-
-      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting standard mode 0x%x\n", ModeNo);
-
-   }
-
-   return(SiSSetMode(SiS_Pr, pScrn, ModeNo, true));
-}
-
-/*********************************************/
-/*    X.org/XFree86: SiSBIOSSetModeCRT2()    */
-/*           for Dual-Head modes             */
-/*********************************************/
-
-bool
-SiSBIOSSetModeCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
-               DisplayModePtr mode, bool IsCustom)
-{
-   SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
-   SISPtr  pSiS = SISPTR(pScrn);
-#ifdef SISDUALHEAD
-   SISEntPtr pSiSEnt = pSiS->entityPrivate;
-#endif
-   unsigned short ModeIdIndex;
-   unsigned short ModeNo = 0;
-   unsigned char  backupreg = 0;
-
-   SiS_Pr->UseCustomMode = false;
-
-   /* Remember: Custom modes for CRT2 are ONLY supported
-    *     -) on the 30x/B/C, and
-    *     -) if CRT2 is LCD or VGA, or CRT1 is LCDA
-    */
-
-   if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
-
-        ModeNo = 0xfe;
-
-   } else {
-
-        ModeNo = SiS_GetModeNumber(pScrn, mode, pSiS->VBFlags);
-        if(!ModeNo) return false;
-
-   }
-
-   SiSRegInit(SiS_Pr, BaseAddr);
-   SiSInitPtr(SiS_Pr);
-   SiS_GetSysFlags(SiS_Pr);
-#if defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__) || defined(__amd64__) || defined(__x86_64__)
-   SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
-#else
-   SiS_Pr->SiS_VGAINFO = 0x11;
-#endif
-
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
-
-   SiSInitPCIetc(SiS_Pr);
-   SiSSetLVDSetc(SiS_Pr);
-   SiSDetermineROMUsage(SiS_Pr);
-
-   /* Save mode info so we can set it from within SetMode for CRT1 */
-#ifdef SISDUALHEAD
-   if(pSiS->DualHeadMode) {
-      pSiSEnt->CRT2ModeNo = ModeNo;
-      pSiSEnt->CRT2DMode = mode;
-      pSiSEnt->CRT2IsCustom = IsCustom;
-      pSiSEnt->CRT2CR30 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-      pSiSEnt->CRT2CR31 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
-      pSiSEnt->CRT2CR35 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
-      pSiSEnt->CRT2CR38 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-#if 0
-      /* We can't set CRT2 mode before CRT1 mode is set - says who...? */
-      if(pSiSEnt->CRT1ModeNo == -1) {
-        xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
-               "Setting CRT2 mode delayed until after setting CRT1 mode\n");
-        return true;
-      }
-#endif
-      pSiSEnt->CRT2ModeSet = true;
-   }
-#endif
-
-   if(SiS_Pr->UseCustomMode) {
-
-      unsigned short temptemp = SiS_Pr->CVDisplay;
-
-      if(SiS_Pr->CModeFlag & DoubleScanMode)     temptemp >>= 1;
-      else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1;
-
-      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
-         "Setting custom mode %dx%d on CRT2\n",
-         SiS_Pr->CHDisplay, temptemp);
-
-   } else {
-
-      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
-         "Setting standard mode 0x%x on CRT2\n", ModeNo);
-
-   }
-
-   SiS_UnLockCRT2(SiS_Pr);
-
-   if(!SiS_Pr->UseCustomMode) {
-      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;
-   } else {
-      ModeIdIndex = 0;
-   }
-
-   SiS_GetVBType(SiS_Pr);
-
-   SiS_InitVB(SiS_Pr);
-   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-      if(SiS_Pr->ChipType >= SIS_315H) {
-        SiS_ResetVB(SiS_Pr);
-        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10);
-        SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c);
-        backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-      } else {
-        backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
-      }
-   }
-
-   /* Get VB information (connectors, connected devices) */
-   if(!SiS_Pr->UseCustomMode) {
-      SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, 1);
-   } else {
-      /* If this is a custom mode, we don't check the modeflag for CRT2Mode */
-      SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, 0);
-   }
-   SiS_SetYPbPr(SiS_Pr);
-   SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);
-   SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
-   SiS_SetLowModeTest(SiS_Pr, ModeNo);
-
-   SiS_ResetSegmentRegisters(SiS_Pr);
-
-   /* Set mode on CRT2 */
-   if( (SiS_Pr->SiS_VBType & VB_SISVB)    ||
-       (SiS_Pr->SiS_IF_DEF_LVDS     == 1) ||
-       (SiS_Pr->SiS_IF_DEF_CH70xx   != 0) ||
-       (SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) {
-      SiS_SetCRT2Group(SiS_Pr, ModeNo);
-   }
-
-   SiS_StrangeStuff(SiS_Pr);
-
-   SiS_DisplayOn(SiS_Pr);
-   SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
-
-   if(SiS_Pr->ChipType >= SIS_315H) {
-      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-        if(!(SiS_IsDualEdge(SiS_Pr))) {
-           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
-        }
-      }
-   }
-
-   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-      if(SiS_Pr->ChipType >= SIS_315H) {
-        if(!SiS_Pr->SiS_ROMNew) {
-           if(SiS_IsVAMode(SiS_Pr)) {
-              SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
-           } else {
-              SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0xFE);
-           }
-        }
-
-        SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg);
-
-        if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) {
-           SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
-        }
-      } else if((SiS_Pr->ChipType == SIS_630) ||
-               (SiS_Pr->ChipType == SIS_730)) {
-         SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
-      }
-   }
-
-   /* SetPitch: Adapt to virtual size & position */
-   SiS_SetPitchCRT2(SiS_Pr, pScrn);
-
-   SiS_Handle760(SiS_Pr);
-
-   return true;
-}
-
-/*********************************************/
-/*    X.org/XFree86: SiSBIOSSetModeCRT1()    */
-/*           for Dual-Head modes             */
-/*********************************************/
-
-bool
-SiSBIOSSetModeCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
-                   DisplayModePtr mode, bool IsCustom)
-{
-   SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
-   SISPtr  pSiS = SISPTR(pScrn);
-   unsigned short ModeIdIndex, ModeNo = 0;
-   unsigned char  backupreg = 0;
-#ifdef SISDUALHEAD
-   SISEntPtr pSiSEnt = pSiS->entityPrivate;
-   unsigned char  backupcr30, backupcr31, backupcr38, backupcr35, backupp40d=0;
-   bool backupcustom;
-#endif
-
-   SiS_Pr->UseCustomMode = false;
-
-   if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
-
-        unsigned short temptemp = SiS_Pr->CVDisplay;
-
-        if(SiS_Pr->CModeFlag & DoubleScanMode)     temptemp >>= 1;
-        else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1;
-
-        xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
-               "Setting custom mode %dx%d on CRT1\n",
-               SiS_Pr->CHDisplay, temptemp);
-        ModeNo = 0xfe;
-
-   } else {
-
-        ModeNo = SiS_GetModeNumber(pScrn, mode, 0); /* don't give VBFlags */
-        if(!ModeNo) return false;
-
-        xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
-               "Setting standard mode 0x%x on CRT1\n", ModeNo);
-   }
-
-   SiSInitPtr(SiS_Pr);
-   SiSRegInit(SiS_Pr, BaseAddr);
-   SiS_GetSysFlags(SiS_Pr);
-#if defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__) || defined(__amd64__) || defined(__x86_64__)
-   SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
-#else
-   SiS_Pr->SiS_VGAINFO = 0x11;
-#endif
-
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
-
-   SiSInitPCIetc(SiS_Pr);
-   SiSSetLVDSetc(SiS_Pr);
-   SiSDetermineROMUsage(SiS_Pr);
-
-   SiS_UnLockCRT2(SiS_Pr);
-
-   if(!SiS_Pr->UseCustomMode) {
-      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;
-   } else {
-      ModeIdIndex = 0;
-   }
-
-   /* Determine VBType */
-   SiS_GetVBType(SiS_Pr);
-
-   SiS_InitVB(SiS_Pr);
-   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-      if(SiS_Pr->ChipType >= SIS_315H) {
-         backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-      } else {
-         backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
-      }
-   }
-
-   /* Get VB information (connectors, connected devices) */
-   /* (We don't care if the current mode is a CRT2 mode) */
-   SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, 0);
-   SiS_SetYPbPr(SiS_Pr);
-   SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);
-   SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
-   SiS_SetLowModeTest(SiS_Pr, ModeNo);
-
-   SiS_OpenCRTC(SiS_Pr);
-
-   /* Set mode on CRT1 */
-   SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
-   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-      SiS_SetCRT2Group(SiS_Pr, ModeNo);
-   }
-
-   /* SetPitch: Adapt to virtual size & position */
-   SiS_SetPitchCRT1(SiS_Pr, pScrn);
-
-   SiS_HandleCRT1(SiS_Pr);
-
-   SiS_StrangeStuff(SiS_Pr);
-
-   SiS_CloseCRTC(SiS_Pr);
-
-#ifdef SISDUALHEAD
-   if(pSiS->DualHeadMode) {
-      pSiSEnt->CRT1ModeNo = ModeNo;
-      pSiSEnt->CRT1DMode = mode;
-   }
-#endif
-
-   if(SiS_Pr->UseCustomMode) {
-      SiS_Pr->CRT1UsesCustomMode = true;
-      SiS_Pr->CSRClock_CRT1 = SiS_Pr->CSRClock;
-      SiS_Pr->CModeFlag_CRT1 = SiS_Pr->CModeFlag;
-   } else {
-      SiS_Pr->CRT1UsesCustomMode = false;
-   }
-
-   /* Reset CRT2 if changing mode on CRT1 */
-#ifdef SISDUALHEAD
-   if(pSiS->DualHeadMode) {
-      if(pSiSEnt->CRT2ModeNo != -1) {
-        xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
-                               "(Re-)Setting mode for CRT2\n");
-        backupcustom = SiS_Pr->UseCustomMode;
-        backupcr30 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-        backupcr31 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
-        backupcr35 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
-        backupcr38 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-        if(SiS_Pr->SiS_VBType & VB_SISVB) {
-           /* Backup LUT-enable */
-           if(pSiSEnt->CRT2ModeSet) {
-              backupp40d = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x0d) & 0x08;
-           }
-        }
-        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-           SiS_SetReg(SiS_Pr->SiS_P3d4,0x30,pSiSEnt->CRT2CR30);
-           SiS_SetReg(SiS_Pr->SiS_P3d4,0x31,pSiSEnt->CRT2CR31);
-           SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,pSiSEnt->CRT2CR35);
-           SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,pSiSEnt->CRT2CR38);
-        }
-
-        SiSBIOSSetModeCRT2(SiS_Pr, pSiSEnt->pScrn_1,
-                           pSiSEnt->CRT2DMode, pSiSEnt->CRT2IsCustom);
-
-        SiS_SetReg(SiS_Pr->SiS_P3d4,0x30,backupcr30);
-        SiS_SetReg(SiS_Pr->SiS_P3d4,0x31,backupcr31);
-        SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupcr35);
-        SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupcr38);
-        if(SiS_Pr->SiS_VBType & VB_SISVB) {
-           SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d, ~0x08, backupp40d);
-        }
-        SiS_Pr->UseCustomMode = backupcustom;
-      }
-   }
-#endif
-
-   /* Warning: From here, the custom mode entries in SiS_Pr are
-    * possibly overwritten
-    */
-
-   SiS_DisplayOn(SiS_Pr);
-   SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
-
-   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-      if(SiS_Pr->ChipType >= SIS_315H) {
-        SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg);
-      } else if((SiS_Pr->ChipType == SIS_630) ||
-                (SiS_Pr->ChipType == SIS_730)) {
-         SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
-      }
-   }
-
-   SiS_Handle760(SiS_Pr);
-
-   /* Backup/Set ModeNo in BIOS scratch area */
-   SiS_GetSetModeID(pScrn,ModeNo);
-
-   return true;
-}
-#endif /* Linux_XF86 */
-
 #ifndef GETBITSTR
 #define BITMASK(h,l)           (((unsigned)(1U << ((h)-(l)+1))-1)<<(l))
 #define GENMASK(mask)          BITMASK(1?mask,0?mask)
@@ -3927,7 +3403,7 @@ SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
    SiS_Pr->CVBlankStart = SiS_Pr->SiS_VGAVDE;
 
    if(SiS_Pr->ChipType < SIS_315H) {
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
       tempbx = SiS_Pr->SiS_VGAHT;
       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
          tempbx = SiS_Pr->PanelHT;
@@ -3936,7 +3412,7 @@ SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
       remaining = tempbx % 8;
 #endif
    } else {
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
       /* OK for LCDA, LVDS */
       tempbx = SiS_Pr->PanelHT - SiS_Pr->PanelXRes;
       tempax = SiS_Pr->SiS_VGAHDE;  /* not /2 ! */
@@ -3950,7 +3426,7 @@ SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
    SiS_Pr->CHTotal = SiS_Pr->CHBlankEnd = tempbx;
 
    if(SiS_Pr->ChipType < SIS_315H) {
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
       if(SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) {
         SiS_Pr->CHSyncStart = SiS_Pr->SiS_VGAHDE + ((SiS_Pr->PanelHRS + 1) & ~1);
         SiS_Pr->CHSyncEnd = SiS_Pr->CHSyncStart + SiS_Pr->PanelHRE;
@@ -3982,7 +3458,7 @@ SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
       }
 #endif
    } else {
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
       tempax = VGAHDE;
       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
         tempbx = SiS_Pr->PanelXRes;
@@ -4001,7 +3477,7 @@ SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
    if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
       tempax = SiS_Pr->PanelYRes;
    } else if(SiS_Pr->ChipType < SIS_315H) {
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
       /* Stupid hack for 640x400/320x200 */
       if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
         if((tempax + tempbx) == 438) tempbx += 16;
@@ -4054,36 +3530,12 @@ SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
    if(modeflag & DoubleScanMode) tempax |= 0x80;
    SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,tempax);
 
-#ifdef SIS_XORG_XF86
-#ifdef TWDEBUG
-   xf86DrvMsg(0, X_INFO, "%d %d %d %d  %d %d %d %d  (%d %d %d %d)\n",
-       SiS_Pr->CHDisplay, SiS_Pr->CHSyncStart, SiS_Pr->CHSyncEnd, SiS_Pr->CHTotal,
-       SiS_Pr->CVDisplay, SiS_Pr->CVSyncStart, SiS_Pr->CVSyncEnd, SiS_Pr->CVTotal,
-       SiS_Pr->CHBlankStart, SiS_Pr->CHBlankEnd, SiS_Pr->CVBlankStart, SiS_Pr->CVBlankEnd);
-   xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
-       SiS_Pr->CCRT1CRTC[0], SiS_Pr->CCRT1CRTC[1],
-       SiS_Pr->CCRT1CRTC[2], SiS_Pr->CCRT1CRTC[3],
-       SiS_Pr->CCRT1CRTC[4], SiS_Pr->CCRT1CRTC[5],
-       SiS_Pr->CCRT1CRTC[6], SiS_Pr->CCRT1CRTC[7]);
-   xf86DrvMsg(0, X_INFO, "   0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
-       SiS_Pr->CCRT1CRTC[8], SiS_Pr->CCRT1CRTC[9],
-       SiS_Pr->CCRT1CRTC[10], SiS_Pr->CCRT1CRTC[11],
-       SiS_Pr->CCRT1CRTC[12], SiS_Pr->CCRT1CRTC[13],
-       SiS_Pr->CCRT1CRTC[14], SiS_Pr->CCRT1CRTC[15]);
-   xf86DrvMsg(0, X_INFO, "   0x%02x}},\n", SiS_Pr->CCRT1CRTC[16]);
-#endif
-#endif
 }
 
 void
 SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
                        int xres, int yres,
-#ifdef SIS_XORG_XF86
-                       DisplayModePtr current
-#endif
-#ifdef SIS_LINUX_KERNEL
                        struct fb_var_screeninfo *var, bool writeres
-#endif
 )
 {
    unsigned short HRE, HBE, HRS, HBS, HDE, HT;
@@ -4127,25 +3579,10 @@ SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
 
    D = B - F - C;
 
-#ifdef SIS_XORG_XF86
-   current->HDisplay   = (E * 8);
-   current->HSyncStart = (E * 8) + (F * 8);
-   current->HSyncEnd   = (E * 8) + (F * 8) + (C * 8);
-   current->HTotal     = (E * 8) + (F * 8) + (C * 8) + (D * 8);
-#ifdef TWDEBUG
-   xf86DrvMsg(0, X_INFO,
-               "H: A %d B %d C %d D %d E %d F %d  HT %d HDE %d HRS %d HBS %d HBE %d HRE %d\n",
-               A, B, C, D, E, F, HT, HDE, HRS, HBS, HBE, HRE);
-#else
-   (void)VBS;  (void)HBS;  (void)A;
-#endif
-#endif
-#ifdef SIS_LINUX_KERNEL
    if(writeres) var->xres = xres = E * 8;
    var->left_margin = D * 8;
    var->right_margin = F * 8;
    var->hsync_len = C * 8;
-#endif
 
    /* Vertical */
    sr_data = crdata[13];
@@ -4192,30 +3629,10 @@ SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
 
    D = B - F - C;
 
-#ifdef SIS_XORG_XF86
-   current->VDisplay   = VDE + 1;
-   current->VSyncStart = VRS + 1;
-   current->VSyncEnd   = ((VRS & ~0x1f) | VRE) + 1;
-   if(VRE <= (VRS & 0x1f)) current->VSyncEnd += 32;
-   current->VTotal     = E + D + C + F;
-#if 0
-   current->VDisplay   = E;
-   current->VSyncStart = E + D;
-   current->VSyncEnd   = E + D + C;
-   current->VTotal     = E + D + C + F;
-#endif
-#ifdef TWDEBUG
-   xf86DrvMsg(0, X_INFO,
-       "V: A %d B %d C %d D %d E %d F %d  VT %d VDE %d VRS %d VBS %d VBE %d VRE %d\n",
-       A, B, C, D, E, F, VT, VDE, VRS, VBS, VBE, VRE);
-#endif
-#endif
-#ifdef SIS_LINUX_KERNEL
    if(writeres) var->yres = yres = E;
    var->upper_margin = D;
    var->lower_margin = F;
    var->vsync_len = C;
-#endif
 
    if((xres == 320) && ((yres == 200) || (yres == 240))) {
        /* Terrible hack, but correct CRTC data for
@@ -4224,17 +3641,9 @@ SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
         * a negative D. The CRT controller does not
         * seem to like correcting HRE to 50)
         */
-#ifdef SIS_XORG_XF86
-      current->HDisplay   = 320;
-      current->HSyncStart = 328;
-      current->HSyncEnd   = 376;
-      current->HTotal     = 400;
-#endif
-#ifdef SIS_LINUX_KERNEL
       var->left_margin = (400 - 376);
       var->right_margin = (328 - 320);
       var->hsync_len = (376 - 328);
-#endif
 
    }
 
index b96005c39c67fdbe4d63e034123a328e53282cd0..aff73842d877b3b98c287b50dc1cbdf138ed6cc7 100644 (file)
 #ifndef _INIT_H_
 #define _INIT_H_
 
-#include "osdef.h"
 #include "initdef.h"
 
-#ifdef SIS_XORG_XF86
-#include "sis.h"
-#define SIS_NEED_inSISREG
-#define SIS_NEED_inSISREGW
-#define SIS_NEED_inSISREGL
-#define SIS_NEED_outSISREG
-#define SIS_NEED_outSISREGW
-#define SIS_NEED_outSISREGL
-#include "sis_regs.h"
-#endif
-
-#ifdef SIS_LINUX_KERNEL
 #include "vgatypes.h"
 #include "vstruct.h"
 #ifdef SIS_CP
@@ -78,7 +65,6 @@
 #include <linux/fb.h>
 #include "sis.h"
 #include <video/sisfb.h>
-#endif
 
 /* Mode numbers */
 static const unsigned short ModeIndex_320x200[]      = {0x59, 0x41, 0x00, 0x4f};
@@ -286,7 +272,7 @@ static const struct SiS_ModeResInfo_S SiS_ModeResInfo[] =
        { 1280, 854, 8,16}    /* 0x22 */
 };
 
-#if defined(SIS300) || defined(SIS315H)
+#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
 static const struct SiS_StandTable_S SiS_StandTable[]=
 {
 /* 0x00: MD_0_200 */
@@ -1521,10 +1507,6 @@ static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1640x480_1_H[] =
 };
 
 bool           SiSInitPtr(struct SiS_Private *SiS_Pr);
-#ifdef SIS_XORG_XF86
-unsigned short SiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
-                               int Depth, bool FSTN, int LCDwith, int LCDheight);
-#endif
 unsigned short SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay,
                                int VDisplay, int Depth, bool FSTN,
                                unsigned short CustomT, int LCDwith, int LCDheight,
@@ -1534,33 +1516,14 @@ unsigned short  SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDispla
 unsigned short SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay,
                                int VDisplay, int Depth, unsigned int VBFlags2);
 
-void           SiS_SetReg(SISIOADDRESS port, unsigned short index, unsigned short data);
-void           SiS_SetRegByte(SISIOADDRESS port, unsigned short data);
-void           SiS_SetRegShort(SISIOADDRESS port, unsigned short data);
-void           SiS_SetRegLong(SISIOADDRESS port, unsigned int data);
-unsigned char  SiS_GetReg(SISIOADDRESS port, unsigned short index);
-unsigned char  SiS_GetRegByte(SISIOADDRESS port);
-unsigned short SiS_GetRegShort(SISIOADDRESS port);
-unsigned int   SiS_GetRegLong(SISIOADDRESS port);
-void           SiS_SetRegANDOR(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND,
-                               unsigned short DataOR);
-void           SiS_SetRegAND(SISIOADDRESS Port,unsigned short Index, unsigned short DataAND);
-void           SiS_SetRegOR(SISIOADDRESS Port,unsigned short Index, unsigned short DataOR);
-
 void           SiS_DisplayOn(struct SiS_Private *SiS_Pr);
 void           SiS_DisplayOff(struct SiS_Private *SiS_Pr);
 void           SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
-#ifndef SIS_LINUX_KERNEL
-void           SiSSetLVDSetc(struct SiS_Private *SiS_Pr);
-#endif
 void           SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable);
 void           SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable);
 unsigned short SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
                                unsigned short ModeIdIndex);
 bool           SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
-#ifndef SIS_LINUX_KERNEL
-void           SiS_GetVBType(struct SiS_Private *SiS_Pr);
-#endif
 
 bool           SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
                                unsigned short *ModeIdIndex);
@@ -1572,37 +1535,19 @@ unsigned short  SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short Mode
                                unsigned short ModeIdIndex);
 unsigned short SiS_GetOffset(struct SiS_Private *SiS_Pr,unsigned short ModeNo,
                                unsigned short ModeIdIndex, unsigned short RRTI);
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
 void           SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *idx1,
                                unsigned short *idx2);
 unsigned short SiS_GetFIFOThresholdB300(unsigned short idx1, unsigned short idx2);
 unsigned short SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index);
 #endif
 void           SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
-#ifdef SIS_XORG_XF86
-bool           SiSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, unsigned short ModeNo,
-                               bool dosetpitch);
-bool           SiSBIOSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
-                               DisplayModePtr mode, bool IsCustom);
-bool           SiSBIOSSetModeCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
-                               DisplayModePtr mode, bool IsCustom);
-bool           SiSBIOSSetModeCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
-                               DisplayModePtr mode, bool IsCustom);
-#endif
-#ifdef SIS_LINUX_KERNEL
 bool           SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
-#endif
 void           SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth);
 void           SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
                                unsigned short ModeIdIndex);
-#ifdef SIS_XORG_XF86
-void           SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, int xres,
-                               int yres, DisplayModePtr current);
-#endif
-#ifdef SIS_LINUX_KERNEL
 void           SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, int xres,
                                int yres, struct fb_var_screeninfo *var, bool writeres);
-#endif
 
 /* From init301.c: */
 extern void            SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
@@ -1626,29 +1571,16 @@ extern unsigned short   SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short
 extern bool            SiS_IsVAMode(struct SiS_Private *);
 extern bool            SiS_IsDualEdge(struct SiS_Private *);
 
-#ifdef SIS_XORG_XF86
-/* From other modules: */
-extern unsigned short  SiS_CheckBuildCustomMode(ScrnInfoPtr pScrn, DisplayModePtr mode,
-                               unsigned int VBFlags);
-extern unsigned char   SiS_GetSetBIOSScratch(ScrnInfoPtr pScrn, unsigned short offset,
-                               unsigned char value);
-extern unsigned char   SiS_GetSetModeID(ScrnInfoPtr pScrn, unsigned char id);
-extern unsigned short  SiS_GetModeNumber(ScrnInfoPtr pScrn, DisplayModePtr mode,
-                               unsigned int VBFlags);
-#endif
-
-#ifdef SIS_LINUX_KERNEL
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
 extern unsigned int    sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
 extern void            sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg,
                                unsigned int val);
 #endif
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 extern void            sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg,
                                unsigned char val);
 extern unsigned int    sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg);
 #endif
-#endif
 
 #endif
 
index da33d801c22e0c114147335701535c2c69e45d88..a89e3cafd5adbfd6c2d8a1622b97c47a339aef81 100644 (file)
  *
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #if 1
 #define SET_EMI                /* 302LV/ELV: Set EMI values */
 #endif
 
 #include "init301.h"
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
 #include "oem300.h"
 #endif
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 #include "oem310.h"
 #endif
 
@@ -87,9 +83,7 @@
 #define SiS_I2CDELAYSHORT  150
 
 static unsigned short  SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr);
-#ifdef SIS_LINUX_KERNEL
 static void            SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
-#endif
 
 /*********************************************/
 /*         HELPER: Lock/Unlock CRT2          */
@@ -106,9 +100,7 @@ SiS_UnLockCRT2(struct SiS_Private *SiS_Pr)
       SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);
 }
 
-#ifdef SIS_LINUX_KERNEL
 static
-#endif
 void
 SiS_LockCRT2(struct SiS_Private *SiS_Pr)
 {
@@ -138,7 +130,7 @@ SiS_SetRegSR11ANDOR(struct SiS_Private *SiS_Pr, unsigned short DataAND, unsigned
 /*    HELPER: Get Pointer to LCD structure   */
 /*********************************************/
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 static unsigned char *
 GetLCDStructPtr661(struct SiS_Private *SiS_Pr)
 {
@@ -404,7 +396,7 @@ SiS_SaveCRT2Info(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 /*    HELPER: GET SOME DATA FROM BIOS ROM    */
 /*********************************************/
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
 static bool
 SiS_CR36BIOSWord23b(struct SiS_Private *SiS_Pr)
 {
@@ -449,7 +441,7 @@ SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime)
       SiS_GetReg(SiS_Pr->SiS_P3c4, 0x05);
 }
 
-#if defined(SIS300) || defined(SIS315H)
+#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
 static void
 SiS_GenericDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
 {
@@ -457,7 +449,7 @@ SiS_GenericDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
 }
 #endif
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 static void
 SiS_LongDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
 {
@@ -467,7 +459,7 @@ SiS_LongDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
 }
 #endif
 
-#if defined(SIS300) || defined(SIS315H)
+#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
 static void
 SiS_ShortDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
 {
@@ -480,14 +472,14 @@ SiS_ShortDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
 static void
 SiS_PanelDelay(struct SiS_Private *SiS_Pr, unsigned short DelayTime)
 {
-#if defined(SIS300) || defined(SIS315H)
+#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
    unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
    unsigned short PanelID, DelayIndex, Delay=0;
 #endif
 
    if(SiS_Pr->ChipType < SIS_315H) {
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
 
       PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
       if(SiS_Pr->SiS_VBType & VB_SISVB) {
@@ -513,11 +505,11 @@ SiS_PanelDelay(struct SiS_Private *SiS_Pr, unsigned short DelayTime)
       }
       SiS_ShortDelay(SiS_Pr, Delay);
 
-#endif  /* SIS300 */
+#endif  /* CONFIG_FB_SIS_300 */
 
    } else {
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 
       if((SiS_Pr->ChipType >= SIS_661)    ||
         (SiS_Pr->ChipType <= SIS_315PRO) ||
@@ -579,12 +571,12 @@ SiS_PanelDelay(struct SiS_Private *SiS_Pr, unsigned short DelayTime)
 
       }
 
-#endif /* SIS315H */
+#endif /* CONFIG_FB_SIS_315 */
 
    }
 }
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 static void
 SiS_PanelDelayLoop(struct SiS_Private *SiS_Pr, unsigned short DelayTime, unsigned short DelayLoop)
 {
@@ -613,7 +605,7 @@ SiS_WaitRetrace1(struct SiS_Private *SiS_Pr)
    while((!(SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog);
 }
 
-#if defined(SIS300) || defined(SIS315H)
+#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
 static void
 SiS_WaitRetrace2(struct SiS_Private *SiS_Pr, unsigned short reg)
 {
@@ -630,7 +622,7 @@ static void
 SiS_WaitVBRetrace(struct SiS_Private *SiS_Pr)
 {
    if(SiS_Pr->ChipType < SIS_315H) {
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
       if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
         if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x20)) return;
       }
@@ -641,7 +633,7 @@ SiS_WaitVBRetrace(struct SiS_Private *SiS_Pr)
       }
 #endif
    } else {
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
       if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x40)) {
         SiS_WaitRetrace1(SiS_Pr);
       } else {
@@ -686,7 +678,7 @@ SiS_VBLongWait(struct SiS_Private *SiS_Pr)
 /*               HELPER: MISC                */
 /*********************************************/
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
 static bool
 SiS_Is301B(struct SiS_Private *SiS_Pr)
 {
@@ -708,7 +700,7 @@ SiS_CRT2IsLCD(struct SiS_Private *SiS_Pr)
 bool
 SiS_IsDualEdge(struct SiS_Private *SiS_Pr)
 {
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
    if(SiS_Pr->ChipType >= SIS_315H) {
       if((SiS_Pr->ChipType != SIS_650) || (SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) {
         if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableDualEdge) return true;
@@ -721,7 +713,7 @@ SiS_IsDualEdge(struct SiS_Private *SiS_Pr)
 bool
 SiS_IsVAMode(struct SiS_Private *SiS_Pr)
 {
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
    unsigned short flag;
 
    if(SiS_Pr->ChipType >= SIS_315H) {
@@ -732,7 +724,7 @@ SiS_IsVAMode(struct SiS_Private *SiS_Pr)
    return false;
 }
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 static bool
 SiS_IsVAorLCD(struct SiS_Private *SiS_Pr)
 {
@@ -745,7 +737,7 @@ SiS_IsVAorLCD(struct SiS_Private *SiS_Pr)
 static bool
 SiS_IsDualLink(struct SiS_Private *SiS_Pr)
 {
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
    if(SiS_Pr->ChipType >= SIS_315H) {
       if((SiS_CRT2IsLCD(SiS_Pr)) ||
          (SiS_IsVAMode(SiS_Pr))) {
@@ -756,7 +748,7 @@ SiS_IsDualLink(struct SiS_Private *SiS_Pr)
    return false;
 }
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 static bool
 SiS_TVEnabled(struct SiS_Private *SiS_Pr)
 {
@@ -768,7 +760,7 @@ SiS_TVEnabled(struct SiS_Private *SiS_Pr)
 }
 #endif
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 static bool
 SiS_LCDAEnabled(struct SiS_Private *SiS_Pr)
 {
@@ -777,7 +769,7 @@ SiS_LCDAEnabled(struct SiS_Private *SiS_Pr)
 }
 #endif
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 static bool
 SiS_WeHaveBacklightCtrl(struct SiS_Private *SiS_Pr)
 {
@@ -788,7 +780,7 @@ SiS_WeHaveBacklightCtrl(struct SiS_Private *SiS_Pr)
 }
 #endif
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 static bool
 SiS_IsNotM650orLater(struct SiS_Private *SiS_Pr)
 {
@@ -804,7 +796,7 @@ SiS_IsNotM650orLater(struct SiS_Private *SiS_Pr)
 }
 #endif
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 static bool
 SiS_IsYPbPr(struct SiS_Private *SiS_Pr)
 {
@@ -816,7 +808,7 @@ SiS_IsYPbPr(struct SiS_Private *SiS_Pr)
 }
 #endif
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 static bool
 SiS_IsChScart(struct SiS_Private *SiS_Pr)
 {
@@ -828,7 +820,7 @@ SiS_IsChScart(struct SiS_Private *SiS_Pr)
 }
 #endif
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 static bool
 SiS_IsTVOrYPbPrOrScart(struct SiS_Private *SiS_Pr)
 {
@@ -848,7 +840,7 @@ SiS_IsTVOrYPbPrOrScart(struct SiS_Private *SiS_Pr)
 }
 #endif
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 static bool
 SiS_IsLCDOrLCDA(struct SiS_Private *SiS_Pr)
 {
@@ -914,7 +906,7 @@ SiS_BridgeInSlavemode(struct SiS_Private *SiS_Pr)
 /*********************************************/
 
 /* Setup general purpose IO for Chrontel communication */
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
 void
 SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo)
 {
@@ -923,11 +915,7 @@ SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo)
 
    if(!(SiS_Pr->SiS_ChSW)) return;
 
-#ifdef SIS_LINUX_KERNEL
    acpibase = sisfb_read_lpc_pci_dword(SiS_Pr, 0x74);
-#else
-   acpibase = pciReadLong(0x00000800, 0x74);
-#endif
    acpibase &= 0xFFFF;
    if(!acpibase) return;
    temp = SiS_GetRegShort((acpibase + 0x3c));  /* ACPI register 0x3c: GP Event 1 I/O mode select */
@@ -969,7 +957,7 @@ SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
        tempax &= (DriverMode | LoadDACFlag | SetNotSimuMode | SetPALTV);
        tempbx |= tempax;
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
        if(SiS_Pr->ChipType >= SIS_315H) {
           if(SiS_Pr->SiS_VBType & VB_SISLCDA) {
              if(ModeNo == 0x03) {
@@ -1019,7 +1007,7 @@ SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
           }
        }
 
-#endif  /* SIS315H */
+#endif  /* CONFIG_FB_SIS_315 */
 
         if(!(SiS_Pr->SiS_VBType & VB_SISVGA2)) {
           tempbx &= ~(SetCRT2ToRAMDAC);
@@ -1154,24 +1142,16 @@ SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
 
    SiS_Pr->SiS_VBInfo = tempbx;
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
    if(SiS_Pr->ChipType == SIS_630) {
       SiS_SetChrontelGPIO(SiS_Pr, SiS_Pr->SiS_VBInfo);
    }
 #endif
 
-#ifdef SIS_LINUX_KERNEL
 #if 0
    printk(KERN_DEBUG "sisfb: (init301: VBInfo= 0x%04x, SetFlag=0x%04x)\n",
       SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
 #endif
-#endif
-#ifdef SIS_XORG_XF86
-#ifdef TWDEBUG
-   xf86DrvMsg(0, X_PROBED, "(init301: VBInfo=0x%04x, SetFlag=0x%04x)\n",
-      SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
-#endif
-#endif
 }
 
 /*********************************************/
@@ -1415,12 +1395,6 @@ SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
    }
 
    SiS_Pr->SiS_VBInfo &= ~SetPALTV;
-
-#ifdef SIS_XORG_XF86
-#ifdef TWDEBUG
-   xf86DrvMsg(0, X_INFO, "(init301: TVMode %x, VBInfo %x)\n", SiS_Pr->SiS_TVMode, SiS_Pr->SiS_VBInfo);
-#endif
-#endif
 }
 
 /*********************************************/
@@ -1443,22 +1417,10 @@ SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr)
 static void
 SiS_GetLCDInfoBIOS(struct SiS_Private *SiS_Pr)
 {
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
    unsigned char  *ROMAddr;
    unsigned short temp;
 
-#ifdef SIS_XORG_XF86
-#ifdef TWDEBUG
-   xf86DrvMsg(0, X_INFO, "Paneldata driver: [%d %d] [H %d %d] [V %d %d] [C %d 0x%02x 0x%02x]\n",
-       SiS_Pr->PanelHT, SiS_Pr->PanelVT,
-       SiS_Pr->PanelHRS, SiS_Pr->PanelHRE,
-       SiS_Pr->PanelVRS, SiS_Pr->PanelVRE,
-       SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK,
-       SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A,
-       SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B);
-#endif
-#endif
-
    if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
       if((temp = SISGETROMW(6)) != SiS_Pr->PanelHT) {
         SiS_Pr->SiS_NeedRomModeData = true;
@@ -1480,18 +1442,6 @@ SiS_GetLCDInfoBIOS(struct SiS_Private *SiS_Pr)
       SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2C =
         SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_B = ROMAddr[20];
 
-#ifdef SIS_XORG_XF86
-#ifdef TWDEBUG
-      xf86DrvMsg(0, X_INFO, "Paneldata BIOS:  [%d %d] [H %d %d] [V %d %d] [C %d 0x%02x 0x%02x]\n",
-       SiS_Pr->PanelHT, SiS_Pr->PanelVT,
-       SiS_Pr->PanelHRS, SiS_Pr->PanelHRE,
-       SiS_Pr->PanelVRS, SiS_Pr->PanelVRE,
-       SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK,
-       SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A,
-       SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B);
-#endif
-#endif
-
    }
 #endif
 }
@@ -1517,13 +1467,13 @@ SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned sh
 {
   unsigned short temp,modeflag,resinfo=0,modexres=0,modeyres=0;
   bool panelcanscale = false;
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
   unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
   static const unsigned char SiS300SeriesLCDRes[] =
           { 0,  1,  2,  3,  7,  4,  5,  8,
            0,  0, 10,  0,  0,  0,  0, 15 };
 #endif
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
   unsigned char   *myptr = NULL;
 #endif
 
@@ -1562,7 +1512,7 @@ SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned sh
      SiS_Pr->SiS_LCDTypeInfo = (temp & 0x0F) - 1;
   }
   temp &= 0x0f;
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
   if(SiS_Pr->ChipType < SIS_315H) {
      /* Very old BIOSes only know 7 sizes (NetVista 2179, 1.01g) */
      if(SiS_Pr->SiS_VBType & VB_SIS301) {
@@ -1574,7 +1524,7 @@ SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned sh
 #endif
 
   /* Translate to our internal types */
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
   if(SiS_Pr->ChipType == SIS_550) {
      if     (temp == Panel310_1152x768)  temp = Panel_320x240_2; /* Verified working */
      else if(temp == Panel310_320x240_2) temp = Panel_320x240_2;
@@ -1597,7 +1547,7 @@ SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned sh
 
   SiS_Pr->SiS_LCDResInfo = temp;
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
      if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
        SiS_Pr->SiS_LCDResInfo = Panel_Barco1366;
@@ -1639,7 +1589,7 @@ SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned sh
   else if(SiS_Pr->UsePanelScaler == 1) SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
 
   /* Dual link, Pass 1:1 BIOS default, etc. */
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
   if(SiS_Pr->ChipType >= SIS_661) {
      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
        if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11;
@@ -2076,7 +2026,7 @@ SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned sh
      }
   }
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
      if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
        SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20;   /* neg h/v sync, RGB24(D0 = 0) */
@@ -2186,17 +2136,10 @@ SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned sh
      SiS_Pr->SiS_SetFlag |= LCDVESATiming;
   }
 
-#ifdef SIS_LINUX_KERNEL
 #if 0
   printk(KERN_DEBUG "sisfb: (LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x)\n",
        SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo);
 #endif
-#endif
-#ifdef SIS_XORG_XF86
-  xf86DrvMsgVerb(0, X_PROBED, 4,
-       "(init301: LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x SetFlag=0x%04x)\n",
-       SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo, SiS_Pr->SiS_SetFlag);
-#endif
 }
 
 /*********************************************/
@@ -2359,7 +2302,7 @@ SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned shor
              VCLKIndex = SiS_Pr->PanelVCLKIdx315;
           }
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
           /* Special Timing: Barco iQ Pro R series */
           if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) VCLKIndex = 0x44;
 
@@ -2410,12 +2353,6 @@ SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned shor
 
   }
 
-#ifdef SIS_XORG_XF86
-#ifdef TWDEBUG
-  xf86DrvMsg(0, X_INFO, "VCLKIndex %d (0x%x)\n", VCLKIndex, VCLKIndex);
-#endif
-#endif
-
   return VCLKIndex;
 }
 
@@ -2428,10 +2365,10 @@ SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
 {
   unsigned short i, j, modeflag, tempah=0;
   short tempcl;
-#if defined(SIS300) || defined(SIS315H)
+#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
   unsigned short tempbl;
 #endif
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
   unsigned short tempah2, tempbl2;
 #endif
@@ -2454,7 +2391,7 @@ SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
 
      if(SiS_Pr->ChipType < SIS_315H) {
 
-#ifdef SIS300    /* ---- 300 series ---- */
+#ifdef CONFIG_FB_SIS_300    /* ---- 300 series ---- */
 
        /* For 301BDH: (with LCD via LVDS) */
        if(SiS_Pr->SiS_VBType & VB_NoLCD) {
@@ -2477,11 +2414,11 @@ SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
 
        if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)  tempah ^= 0xA0;
 
-#endif  /* SIS300 */
+#endif  /* CONFIG_FB_SIS_300 */
 
      } else {
 
-#ifdef SIS315H    /* ------- 315/330 series ------ */
+#ifdef CONFIG_FB_SIS_315    /* ------- 315/330 series ------ */
 
        if(ModeNo > 0x13) {
           tempcl -= ModeVGA;
@@ -2494,7 +2431,7 @@ SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
 
        if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0x50;
 
-#endif  /* SIS315H */
+#endif  /* CONFIG_FB_SIS_315 */
 
      }
 
@@ -2503,7 +2440,7 @@ SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
      if(SiS_Pr->ChipType < SIS_315H) {
        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
      } else {
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
        if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
        } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
@@ -2584,7 +2521,7 @@ SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
 
        if(SiS_Pr->ChipType >= SIS_315H) {
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
           /* LVDS can only be slave in 8bpp modes */
           tempah = 0x80;
           if((modeflag & CRT2Mode) && (SiS_Pr->SiS_ModeType > ModeVGA)) {
@@ -2604,7 +2541,7 @@ SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
 
        } else {
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
           tempah = 0;
           if( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) && (SiS_Pr->SiS_ModeType > ModeVGA) ) {
              tempah |= 0x02;
@@ -2626,7 +2563,7 @@ SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
 
      if(SiS_Pr->ChipType >= SIS_315H) {
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
        /* unsigned char bridgerev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01); */
 
        /* The following is nearly unpreditable and varies from machine
@@ -2718,11 +2655,11 @@ SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
           SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
        }
 
-#endif /* SIS315H */
+#endif /* CONFIG_FB_SIS_315 */
 
      } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
        SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
 
        if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
@@ -2745,7 +2682,7 @@ SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
 
   } else {  /* LVDS */
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
      if(SiS_Pr->ChipType >= SIS_315H) {
 
        if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
@@ -2931,7 +2868,7 @@ SiS_GetCRT2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
           }
        }
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
        if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
           if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
              if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
@@ -3036,7 +2973,7 @@ SiS_GetCRT2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
        case Panel_1280x1024: tempbx = 24; break;
        case Panel_1400x1050: tempbx = 26; break;
        case Panel_1600x1200: tempbx = 28; break;
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
        case Panel_Barco1366: tempbx = 80; break;
 #endif
        }
@@ -3053,7 +2990,7 @@ SiS_GetCRT2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
 
        if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempbx = 30;
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
        if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
           tempbx = 82;
           if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
@@ -3189,7 +3126,7 @@ SiS_GetCRT2DataLVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
 
    if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
       SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
       SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
 #endif
@@ -3214,7 +3151,7 @@ SiS_GetCRT2DataLVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
         case 16: LVDSData = SiS_Pr->SiS_LVDS800x600Data_1;    break;
         case 18: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1;   break;
         case 20: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1;   break;
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
         case 80: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1;  break;
         case 81: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2;  break;
         case 82: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1;  break;
@@ -3248,7 +3185,7 @@ SiS_GetCRT2DataLVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
             (SiS_Pr->SiS_SetFlag & SetDOSMode) ) {
            SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
             SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
            if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
               if(ResIndex < 0x08) {
                  SiS_Pr->SiS_HDE = 1280;
@@ -3270,7 +3207,7 @@ SiS_GetCRT2Data301(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
   unsigned short resinfo, CRT2Index, ResIndex;
   const struct SiS_LCDData *LCDPtr = NULL;
   const struct SiS_TVData  *TVPtr  = NULL;
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
   short resinfo661;
 #endif
 
@@ -3283,7 +3220,7 @@ SiS_GetCRT2Data301(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
   } else {
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
      resinfo661 = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].ROMMODEIDX661;
      if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)   &&
         (SiS_Pr->SiS_SetFlag & LCDVESATiming) &&
@@ -3460,7 +3397,7 @@ SiS_GetCRT2Data301(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
 
        } else if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) && (romptr) && (ROMAddr) ) {
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
           SiS_Pr->SiS_RVBHCMAX  = ROMAddr[romptr];
           SiS_Pr->SiS_RVBHCFACT = ROMAddr[romptr+1];
           SiS_Pr->SiS_VGAHT     = ROMAddr[romptr+2] | ((ROMAddr[romptr+3] & 0x0f) << 8);
@@ -3520,19 +3457,13 @@ SiS_GetCRT2Data301(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
              case Panel_1680x1050     :
              case Panel_1680x1050 + 32: LCDPtr = SiS_Pr->SiS_LCD1680x1050Data;     break;
              case 100                 : LCDPtr = SiS_Pr->SiS_NoScaleData;          break;
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
              case 200                 : LCDPtr = SiS310_ExtCompaq1280x1024Data;    break;
              case 201                 : LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;  break;
 #endif
              default                  : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;   break;
           }
 
-#ifdef SIS_XORG_XF86
-#ifdef TWDEBUG
-          xf86DrvMsg(0, X_INFO, "GetCRT2Data: Index %d ResIndex %d\n", CRT2Index, ResIndex);
-#endif
-#endif
-
           SiS_Pr->SiS_RVBHCMAX  = (LCDPtr+ResIndex)->RVBHCMAX;
           SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
           SiS_Pr->SiS_VGAHT     = (LCDPtr+ResIndex)->VGAHT;
@@ -3624,7 +3555,7 @@ SiS_GetLVDSDesPtr(struct SiS_Private *SiS_Pr)
 {
    const struct SiS_LVDSDes *PanelDesPtr = NULL;
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
    if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
 
       if(SiS_Pr->ChipType < SIS_315H) {
@@ -3696,7 +3627,7 @@ SiS_GetLVDSDesData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
 
   if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
        /* non-pass 1:1 only, see above */
        if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
@@ -3771,7 +3702,7 @@ SiS_GetLVDSDesData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
      } else {
 
         if(SiS_Pr->ChipType < SIS_315H) {
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
           switch(SiS_Pr->SiS_LCDResInfo) {
           case Panel_800x600:
              if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
@@ -3816,7 +3747,7 @@ SiS_GetLVDSDesData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
           }
 #endif
         } else {
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
           switch(SiS_Pr->SiS_LCDResInfo) {
           case Panel_1024x768:
           case Panel_1280x1024:
@@ -3844,7 +3775,7 @@ SiS_GetLVDSDesData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
                 if(SiS_Pr->ChipType < SIS_315H) {
                    if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 320;
                 } else {
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
                    if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)  SiS_Pr->SiS_LCDHDES = 480;
                    if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 804;
                    if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 704;
@@ -3866,7 +3797,7 @@ SiS_GetLVDSDesData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
 /*           DISABLE VIDEO BRIDGE            */
 /*********************************************/
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 static int
 SiS_HandlePWD(struct SiS_Private *SiS_Pr)
 {
@@ -3891,11 +3822,6 @@ SiS_HandlePWD(struct SiS_Private *SiS_Pr)
         ret = 1;
       }
       SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x27,0x7f,temp);
-#ifdef SIS_XORG_XF86
-#ifdef TWDEBUG
-      xf86DrvMsg(0, 0, "Setting PWD %x\n", temp);
-#endif
-#endif
    }
 #endif
    return ret;
@@ -3909,7 +3835,7 @@ SiS_HandlePWD(struct SiS_Private *SiS_Pr)
 void
 SiS_DisableBridge(struct SiS_Private *SiS_Pr)
 {
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
   unsigned short tempah, pushax=0, modenum;
 #endif
   unsigned short temp=0;
@@ -3920,7 +3846,7 @@ SiS_DisableBridge(struct SiS_Private *SiS_Pr)
 
        if(SiS_Pr->ChipType < SIS_315H) {
 
-#ifdef SIS300     /* 300 series */
+#ifdef CONFIG_FB_SIS_300          /* 300 series */
 
           if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
              if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
@@ -3953,11 +3879,11 @@ SiS_DisableBridge(struct SiS_Private *SiS_Pr)
              }
           }
 
-#endif  /* SIS300 */
+#endif  /* CONFIG_FB_SIS_300 */
 
         } else {
 
-#ifdef SIS315H    /* 315 series */
+#ifdef CONFIG_FB_SIS_315          /* 315 series */
 
           int didpwd = 0;
           bool custom1 = (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
@@ -4081,14 +4007,14 @@ SiS_DisableBridge(struct SiS_Private *SiS_Pr)
 
           }
 
-#endif /* SIS315H */
+#endif /* CONFIG_FB_SIS_315 */
 
        }
 
      } else {     /* ============ For 301 ================ */
 
         if(SiS_Pr->ChipType < SIS_315H) {
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
           if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
              SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
              SiS_PanelDelay(SiS_Pr, 3);
@@ -4111,7 +4037,7 @@ SiS_DisableBridge(struct SiS_Private *SiS_Pr)
            SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
            SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
        } else {
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
            SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);            /* disable CRT2 */
            if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
                (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
@@ -4127,7 +4053,7 @@ SiS_DisableBridge(struct SiS_Private *SiS_Pr)
 
     if(SiS_Pr->ChipType < SIS_315H) {
 
-#ifdef SIS300  /* 300 series */
+#ifdef CONFIG_FB_SIS_300       /* 300 series */
 
        if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
           SiS_SetCH700x(SiS_Pr,0x0E,0x09);
@@ -4171,11 +4097,11 @@ SiS_DisableBridge(struct SiS_Private *SiS_Pr)
           SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
        }
 
-#endif  /* SIS300 */
+#endif  /* CONFIG_FB_SIS_300 */
 
     } else {
 
-#ifdef SIS315H /* 315 series */
+#ifdef CONFIG_FB_SIS_315       /* 315 series */
 
        if(!(SiS_IsNotM650orLater(SiS_Pr))) {
           /*if(SiS_Pr->ChipType < SIS_340) { */ /* XGI needs this */
@@ -4288,7 +4214,7 @@ SiS_DisableBridge(struct SiS_Private *SiS_Pr)
           }
         }
 
-#endif  /* SIS315H */
+#endif  /* CONFIG_FB_SIS_315 */
 
     }  /* 315 series */
 
@@ -4304,14 +4230,12 @@ SiS_DisableBridge(struct SiS_Private *SiS_Pr)
  * from outside the context of a mode switch!
  * MUST call getVBType before calling this
  */
-#ifdef SIS_LINUX_KERNEL
 static
-#endif
 void
 SiS_EnableBridge(struct SiS_Private *SiS_Pr)
 {
   unsigned short temp=0, tempah;
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
   unsigned short temp1, pushax=0;
   bool delaylong = false;
 #endif
@@ -4322,7 +4246,7 @@ SiS_EnableBridge(struct SiS_Private *SiS_Pr)
 
       if(SiS_Pr->ChipType < SIS_315H) {
 
-#ifdef SIS300     /* 300 series */
+#ifdef CONFIG_FB_SIS_300     /* 300 series */
 
         if(SiS_CRT2IsLCD(SiS_Pr)) {
            if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
@@ -4385,11 +4309,11 @@ SiS_EnableBridge(struct SiS_Private *SiS_Pr)
         }
 
 
-#endif /* SIS300 */
+#endif /* CONFIG_FB_SIS_300 */
 
       } else {
 
-#ifdef SIS315H    /* 315 series */
+#ifdef CONFIG_FB_SIS_315    /* 315 series */
 
 #ifdef SET_EMI
         unsigned char   r30=0, r31=0, r32=0, r33=0, cr36=0;
@@ -4688,7 +4612,7 @@ SiS_EnableBridge(struct SiS_Private *SiS_Pr)
            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
         }
 
-#endif /* SIS315H */
+#endif /* CONFIG_FB_SIS_315 */
 
       }
 
@@ -4739,7 +4663,7 @@ SiS_EnableBridge(struct SiS_Private *SiS_Pr)
 
     if(SiS_Pr->ChipType < SIS_315H) {
 
-#ifdef SIS300    /* 300 series */
+#ifdef CONFIG_FB_SIS_300    /* 300 series */
 
        if(SiS_CRT2IsLCD(SiS_Pr)) {
          if(SiS_Pr->ChipType == SIS_730) {
@@ -4783,11 +4707,11 @@ SiS_EnableBridge(struct SiS_Private *SiS_Pr)
          }
        }
 
-#endif  /* SIS300 */
+#endif  /* CONFIG_FB_SIS_300 */
 
     } else {
 
-#ifdef SIS315H    /* 315 series */
+#ifdef CONFIG_FB_SIS_315    /* 315 series */
 
        if(!(SiS_IsNotM650orLater(SiS_Pr))) {
          /*if(SiS_Pr->ChipType < SIS_340) {*/  /* XGI needs this */
@@ -4881,7 +4805,7 @@ SiS_EnableBridge(struct SiS_Private *SiS_Pr)
          }
        }
 
-#endif  /* SIS315H */
+#endif  /* CONFIG_FB_SIS_315 */
 
     } /* 310 series */
 
@@ -4971,7 +4895,7 @@ SiS_SetCRT2Sync(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned shor
 
       if(SiS_Pr->ChipType < SIS_315H) {
 
-#ifdef SIS300  /* ---- 300 series --- */
+#ifdef CONFIG_FB_SIS_300  /* ---- 300 series --- */
 
         if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {                        /* 630 - 301B(-DH) */
 
@@ -5000,11 +4924,11 @@ SiS_SetCRT2Sync(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned shor
 
         }
 
-#endif /* SIS300 */
+#endif /* CONFIG_FB_SIS_300 */
 
       } else {
 
-#ifdef SIS315H  /* ------- 315 series ------ */
+#ifdef CONFIG_FB_SIS_315  /* ------- 315 series ------ */
 
         if(SiS_Pr->SiS_VBType & VB_SISLVDS) {                  /* 315 - LVDS */
 
@@ -5076,13 +5000,13 @@ SiS_SetCRT2Sync(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned shor
            }
 
          }
-#endif  /* SIS315H */
+#endif  /* CONFIG_FB_SIS_315 */
       }
    }
 }
 
 /* Set CRT2 FIFO on 300/540/630/730 */
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
 static void
 SiS_SetCRT2FIFO_300(struct SiS_Private *SiS_Pr,unsigned short ModeNo)
 {
@@ -5154,13 +5078,8 @@ SiS_SetCRT2FIFO_300(struct SiS_Private *SiS_Pr,unsigned short ModeNo)
 
      } else {
 
-#ifdef SIS_LINUX_KERNEL
        pci50 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
        pciA0 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xa0);
-#else
-       pci50 = pciReadLong(0x00000000, 0x50);
-       pciA0 = pciReadLong(0x00000000, 0xA0);
-#endif
 
         if(SiS_Pr->ChipType == SIS_730) {
 
@@ -5262,7 +5181,7 @@ SiS_SetCRT2FIFO_300(struct SiS_Private *SiS_Pr,unsigned short ModeNo)
 #endif
 
 /* Set CRT2 FIFO on 315/330 series */
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 static void
 SiS_SetCRT2FIFO_310(struct SiS_Private *SiS_Pr)
 {
@@ -5420,27 +5339,6 @@ SiS_SetGroup1_301(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned sho
 
   temp = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);                 /* ? */
-
-#ifdef SIS_XORG_XF86
-#ifdef TWDEBUG
-   xf86DrvMsg(0, X_INFO, "%d %d %d %d  %d %d %d %d  (%d %d %d %d)\n",
-       SiS_Pr->CHDisplay, SiS_Pr->CHSyncStart, SiS_Pr->CHSyncEnd, SiS_Pr->CHTotal,
-       SiS_Pr->CVDisplay, SiS_Pr->CVSyncStart, SiS_Pr->CVSyncEnd, SiS_Pr->CVTotal,
-       SiS_Pr->CHBlankStart, SiS_Pr->CHBlankEnd, SiS_Pr->CVBlankStart, SiS_Pr->CVBlankEnd);
-
-   xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
-       SiS_Pr->CCRT1CRTC[0], SiS_Pr->CCRT1CRTC[1],
-       SiS_Pr->CCRT1CRTC[2], SiS_Pr->CCRT1CRTC[3],
-       SiS_Pr->CCRT1CRTC[4], SiS_Pr->CCRT1CRTC[5],
-       SiS_Pr->CCRT1CRTC[6], SiS_Pr->CCRT1CRTC[7]);
-   xf86DrvMsg(0, X_INFO, "   0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
-       SiS_Pr->CCRT1CRTC[8], SiS_Pr->CCRT1CRTC[9],
-       SiS_Pr->CCRT1CRTC[10], SiS_Pr->CCRT1CRTC[11],
-       SiS_Pr->CCRT1CRTC[12], SiS_Pr->CCRT1CRTC[13],
-       SiS_Pr->CCRT1CRTC[14], SiS_Pr->CCRT1CRTC[15]);
-   xf86DrvMsg(0, X_INFO, "   0x%02x}},\n", SiS_Pr->CCRT1CRTC[16]);
-#endif
-#endif
 }
 
 /* Setup panel link
@@ -5455,17 +5353,17 @@ SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
   unsigned short push2, tempax, tempbx, tempcx, temp;
   unsigned int   tempeax = 0, tempebx, tempecx, tempvcfact = 0;
   bool islvds = false, issis  = false, chkdclkfirst = false;
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
   unsigned short crt2crtc = 0;
 #endif
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
   unsigned short pushcx;
 #endif
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
      crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
 #endif
   } else if(SiS_Pr->UseCustomMode) {
@@ -5473,7 +5371,7 @@ SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
   } else {
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
      crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
 #endif
   }
@@ -5494,7 +5392,7 @@ SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
      }
   }
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
   if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
      if(IS_SIS330) {
         SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
@@ -5744,7 +5642,7 @@ SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
 
   if(SiS_Pr->ChipType < SIS_315H) {
 
-#ifdef SIS300      /* 300 series */
+#ifdef CONFIG_FB_SIS_300      /* 300 series */
      tempeax = SiS_Pr->SiS_VGAVDE << 6;
      temp = (tempeax % (unsigned int)SiS_Pr->SiS_VDE);
      tempeax = tempeax / (unsigned int)SiS_Pr->SiS_VDE;
@@ -5755,11 +5653,11 @@ SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
      temp = (unsigned short)(tempeax & 0x00FF);
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,temp);              /* BPLVCFACT */
      tempvcfact = temp;
-#endif /* SIS300 */
+#endif /* CONFIG_FB_SIS_300 */
 
   } else {
 
-#ifdef SIS315H  /* 315 series */
+#ifdef CONFIG_FB_SIS_315  /* 315 series */
      tempeax = SiS_Pr->SiS_VGAVDE << 18;
      tempebx = SiS_Pr->SiS_VDE;
      temp = (tempeax % tempebx);
@@ -5845,7 +5743,7 @@ SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
   temp = (unsigned short)(tempecx & 0x00FF);
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
   if(SiS_Pr->ChipType >= SIS_315H) {
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
         if((islvds) || (SiS_Pr->SiS_VBInfo & VB_SISLVDS)) {
@@ -5863,7 +5761,7 @@ SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
   }
 #endif
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
   if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
      unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
      unsigned char *trumpdata;
@@ -5899,7 +5797,7 @@ SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
   }
 #endif
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
   if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x25,0x00);
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x26,0x00);
@@ -5954,7 +5852,7 @@ SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
      temp = tempax & 0x00FF;
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,temp);
      temp = ((tempax & 0xFF00) >> 8) << 3;
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x0F8,temp);
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port, 0x44, 0x07, temp);
 
      tempax = SiS_Pr->SiS_VDE;                                 /* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
      if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
@@ -5968,7 +5866,7 @@ SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
      temp = ((tempeax & 0xFF0000) >> 16) | 0x10;
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,temp);
      temp = ((tempeax & 0x01000000) >> 24) << 7;
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x080,temp);
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port, 0x3C, 0x7F, temp);
 
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x03);
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0x50);
@@ -5999,7 +5897,7 @@ SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,0x0a);
      }
   }
-#endif  /* SIS315H */
+#endif  /* CONFIG_FB_SIS_315 */
 }
 
 /* Set Part 1 */
@@ -6007,12 +5905,12 @@ static void
 SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
                unsigned short RefreshRateTableIndex)
 {
-#if defined(SIS300) || defined(SIS315H)
+#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
   unsigned char   *ROMAddr = SiS_Pr->VirtualRomBase;
 #endif
   unsigned short  temp=0, tempax=0, tempbx=0, tempcx=0, bridgeadd=0;
   unsigned short  pushbx=0, CRT1Index=0, modeflag, resinfo=0;
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
   unsigned short  tempbl=0;
 #endif
 
@@ -6038,11 +5936,11 @@ SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
          (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) {
 
      if(SiS_Pr->ChipType < SIS_315H ) {
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
        SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo);
 #endif
      } else {
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
        SiS_SetCRT2FIFO_310(SiS_Pr);
 #endif
      }
@@ -6051,7 +5949,7 @@ SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
 
      if(SiS_Pr->ChipType < SIS_315H ) {
 
-#ifdef SIS300   /* ------------- 300 series --------------*/
+#ifdef CONFIG_FB_SIS_300   /* ------------- 300 series --------------*/
 
        temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF;                   /* BTVGA2HT 0x08,0x09 */
        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp);              /* CRT2 Horizontal Total */
@@ -6070,11 +5968,11 @@ SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
 
        bridgeadd = 12;
 
-#endif /* SIS300 */
+#endif /* CONFIG_FB_SIS_300 */
 
      } else {
 
-#ifdef SIS315H  /* ------------------- 315/330 series --------------- */
+#ifdef CONFIG_FB_SIS_315  /* ------------------- 315/330 series --------------- */
 
        tempcx = SiS_Pr->SiS_VGAHT;                               /* BTVGA2HT 0x08,0x09 */
        if(modeflag & HalfDCLK) {
@@ -6125,7 +6023,7 @@ SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
           }
         }
 
-#endif  /* SIS315H */
+#endif  /* CONFIG_FB_SIS_315 */
 
      }  /* 315/330 series */
 
@@ -6256,7 +6154,7 @@ SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
 
      if(SiS_Pr->ChipType < SIS_315H) {
 
-#ifdef SIS300  /* ---------- 300 series -------------- */
+#ifdef CONFIG_FB_SIS_300  /* ---------- 300 series -------------- */
 
        if(SiS_Pr->SiS_VBType & VB_SISVB) {
           temp = 0x20;
@@ -6310,11 +6208,11 @@ SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
 
        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);   /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */
 
-#endif  /* SIS300 */
+#endif  /* CONFIG_FB_SIS_300 */
 
      } else {
 
-#ifdef SIS315H   /* --------------- 315/330 series ---------------*/
+#ifdef CONFIG_FB_SIS_315   /* --------------- 315/330 series ---------------*/
 
        if(SiS_Pr->ChipType < SIS_661) {
 
@@ -6349,7 +6247,7 @@ SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
        if(modeflag & HalfDCLK)       tempax |= 0x40;
        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
 
-#endif  /* SIS315H */
+#endif  /* CONFIG_FB_SIS_315 */
 
      }
 
@@ -6381,7 +6279,7 @@ SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
 /*         SET PART 2 REGISTER GROUP         */
 /*********************************************/
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 static unsigned char *
 SiS_GetGroup2CLVXPtr(struct SiS_Private *SiS_Pr, int tabletype)
 {
@@ -6478,7 +6376,7 @@ SiS_GetCRT2Part2Ptr(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned sh
 }
 #endif
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
 static void
 SiS_Group2LCDSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short crt2crtc)
 {
@@ -6690,7 +6588,7 @@ SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
   unsigned int   longtemp, PhaseIndex;
   bool           newtvphase;
   const unsigned char *TimingPoint;
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
   unsigned short resindex, CRT2Index;
   const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
 
@@ -7069,7 +6967,7 @@ SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x17,0xFB);
   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x18,0xDF);
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
   if(SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
                                                &CRT2Index, &resindex)) {
       switch(CRT2Index) {
@@ -7130,12 +7028,6 @@ SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
 
     /* Non-expanding: lcdvdes = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */
 
-#ifdef SIS_XORG_XF86
-#ifdef TWDEBUG
-    xf86DrvMsg(0, X_INFO, "lcdvdes 0x%x lcdvdee 0x%x\n", tempcx, tempbx);
-#endif
-#endif
-
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempcx);     /* lcdvdes  */
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempbx);     /* lcdvdee  */
 
@@ -7184,12 +7076,6 @@ SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
        tempbx = SiS_Pr->CVSyncStart;
     }
 
-#ifdef SIS_XORG_XF86
-#ifdef TWDEBUG
-    xf86DrvMsg(0, X_INFO, "lcdvrs 0x%x\n", tempbx);
-#endif
-#endif
-
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx);         /* lcdvrs */
 
     temp = (tempbx >> 4) & 0xF0;
@@ -7201,15 +7087,9 @@ SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
        temp |= (SiS_Pr->CVSyncEnd & 0x0f);
     }
 
-#ifdef SIS_XORG_XF86
-#ifdef TWDEBUG
-    xf86DrvMsg(0, X_INFO, "lcdvre[3:0] 0x%x\n", (temp & 0x0f));
-#endif
-#endif
-
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
     SiS_Group2LCDSpecial(SiS_Pr, ModeNo, crt2crtc);
 #endif
 
@@ -7245,12 +7125,6 @@ SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
        tempax >>= 1;
     }
 
-#ifdef SIS_XORG_XF86
-#ifdef TWDEBUG
-    xf86DrvMsg(0, X_INFO, "lcdhdee 0x%x\n", tempbx);
-#endif
-#endif
-
     tempbx += bridgeoffset;
 
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,tempbx);         /* lcdhdee */
@@ -7276,12 +7150,6 @@ SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
        tempbx += bridgeoffset;
     }
 
-#ifdef SIS_XORG_XF86
-#ifdef TWDEBUG
-    xf86DrvMsg(0, X_INFO, "lcdhrs 0x%x\n", tempbx);
-#endif
-#endif
-
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,tempbx);         /* lcdhrs */
     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,((tempbx >> 4) & 0xf0));
 
@@ -7300,20 +7168,14 @@ SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
        tempbx += bridgeoffset;
     }
 
-#ifdef SIS_XORG_XF86
-#ifdef TWDEBUG
-    xf86DrvMsg(0, X_INFO, "lcdhre 0x%x\n", tempbx);
-#endif
-#endif
-
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempbx);         /* lcdhre */
 
     SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
     SiS_Set300Part2Regs(SiS_Pr, ModeIdIndex, RefreshRateTableIndex, ModeNo);
 #endif
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
   } /* CRT2-LCD from table */
 #endif
 }
@@ -7382,7 +7244,7 @@ SiS_SetGroup3(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
 /*         SET PART 4 REGISTER GROUP         */
 /*********************************************/
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 #if 0
 static void
 SiS_ShiftXPos(struct SiS_Private *SiS_Pr, int shift)
@@ -8011,7 +7873,7 @@ SiS_SetCHTVReg(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
 
    if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
 
       /* Chrontel 7005 - I assume that it does not come with a 315 series chip */
 
@@ -8124,7 +7986,7 @@ SiS_SetCHTVReg(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
 
       /* Chrontel 7019 - assumed that it does not come with a 300 series chip */
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 
       unsigned short temp;
 
@@ -8175,7 +8037,7 @@ SiS_SetCHTVReg(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
 
 }
 
-#ifdef SIS315H  /* ----------- 315 series only ---------- */
+#ifdef CONFIG_FB_SIS_315  /* ----------- 315 series only ---------- */
 
 void
 SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr)
@@ -8657,7 +8519,7 @@ SiS_ChrontelDoSomething1(struct SiS_Private *SiS_Pr)
 bool
 SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 {
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
    unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
 #endif
    unsigned short ModeIdIndex, RefreshRateTableIndex;
@@ -8703,16 +8565,6 @@ SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
       SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
    }
 
-#ifdef SIS_XORG_XF86
-#ifdef TWDEBUG
-  xf86DrvMsg(0, X_INFO, "(init301: LCDHDES 0x%03x LCDVDES 0x%03x)\n", SiS_Pr->SiS_LCDHDES, SiS_Pr->SiS_LCDVDES);
-  xf86DrvMsg(0, X_INFO, "(init301: HDE     0x%03x VDE     0x%03x)\n", SiS_Pr->SiS_HDE, SiS_Pr->SiS_VDE);
-  xf86DrvMsg(0, X_INFO, "(init301: VGAHDE  0x%03x VGAVDE  0x%03x)\n", SiS_Pr->SiS_VGAHDE, SiS_Pr->SiS_VGAVDE);
-  xf86DrvMsg(0, X_INFO, "(init301: HT      0x%03x VT      0x%03x)\n", SiS_Pr->SiS_HT, SiS_Pr->SiS_VT);
-  xf86DrvMsg(0, X_INFO, "(init301: VGAHT   0x%03x VGAVT   0x%03x)\n", SiS_Pr->SiS_VGAHT, SiS_Pr->SiS_VGAVT);
-#endif
-#endif
-
    if(SiS_Pr->SiS_SetFlag & LowModeTests) {
       SiS_SetGroup1(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
    }
@@ -8722,12 +8574,12 @@ SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
       if(SiS_Pr->SiS_SetFlag & LowModeTests) {
 
         SiS_SetGroup2(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
         SiS_SetGroup2_C_ELV(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
 #endif
         SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex);
         SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
         SiS_SetGroup4_C_ELV(SiS_Pr, ModeNo, ModeIdIndex);
 #endif
         SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex);
@@ -8758,7 +8610,7 @@ SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
         if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
            if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
               if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
                  SiS_SetCH701xForLCD(SiS_Pr);
 #endif
               }
@@ -8771,7 +8623,7 @@ SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 
    }
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
    if(SiS_Pr->ChipType < SIS_315H) {
       if(SiS_Pr->SiS_SetFlag & LowModeTests) {
         if(SiS_Pr->SiS_UseOEM) {
@@ -8794,7 +8646,7 @@ SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
    }
 #endif
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
    if(SiS_Pr->ChipType >= SIS_315H) {
       if(SiS_Pr->SiS_SetFlag & LowModeTests) {
         if(SiS_Pr->ChipType < SIS_661) {
@@ -8873,7 +8725,7 @@ SiS_SetupDDCN(struct SiS_Private *SiS_Pr)
   }
 }
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
 static unsigned char *
 SiS_SetTrumpBlockLoop(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
 {
@@ -8923,11 +8775,6 @@ SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
      dataptr = SiS_SetTrumpBlockLoop(SiS_Pr, dataptr);
      if(!dataptr) return false;
   }
-#ifdef SIS_XORG_XF86
-#ifdef TWDEBUG
-  xf86DrvMsg(0, X_INFO, "Trumpion block success\n");
-#endif
-#endif
   return true;
 }
 #endif
@@ -9002,9 +8849,7 @@ SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
   SiS_SetChReg(SiS_Pr, reg, val, 0);
 }
 
-#ifdef SIS_LINUX_KERNEL
 static
-#endif
 void
 SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
 {
@@ -9091,9 +8936,7 @@ SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
 
 /* Read from Chrontel 70xx */
 /* Parameter is [Register no (S7-S0)] */
-#ifdef SIS_LINUX_KERNEL
 static
-#endif
 unsigned short
 SiS_GetCH70xx(struct SiS_Private *SiS_Pr, unsigned short tempbx)
 {
@@ -9114,9 +8957,7 @@ SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
 }
 
 /* Our own DDC functions */
-#ifndef SIS_XORG_XF86
 static
-#endif
 unsigned short
 SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
                 unsigned short adaptnum, unsigned short DDCdatatype, bool checkcr32,
@@ -9224,12 +9065,6 @@ SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
 
     SiS_SetupDDCN(SiS_Pr);
 
-#ifdef SIS_XORG_XF86
-#ifdef TWDEBUG
-    xf86DrvMsg(0, X_INFO, "DDC Port %x Index %x Shift %d\n",
-               SiS_Pr->SiS_DDC_Port, SiS_Pr->SiS_DDC_Index, temp);
-#endif
-#endif
     return 0;
 }
 
@@ -9292,11 +9127,6 @@ SiS_DoProbeDDC(struct SiS_Private *SiS_Pr)
     SiS_SetSwitchDDC2(SiS_Pr);
     if(SiS_PrepareDDC(SiS_Pr)) {
          SiS_SetStop(SiS_Pr);
-#ifdef SIS_XORG_XF86
-#ifdef TWDEBUG
-         xf86DrvMsg(0, X_INFO, "Probe: Prepare failed\n");
-#endif
-#endif
          return 0xFFFF;
     }
     mask = 0xf0;
@@ -9310,11 +9140,6 @@ SiS_DoProbeDDC(struct SiS_Private *SiS_Pr)
        } else {
            failed = true;
           ret = 0xFFFF;
-#ifdef SIS_XORG_XF86
-#ifdef TWDEBUG
-           xf86DrvMsg(0, X_INFO, "Probe: Read 1 failed\n");
-#endif
-#endif
        }
     }
     if(!failed) {
@@ -9324,11 +9149,6 @@ SiS_DoProbeDDC(struct SiS_Private *SiS_Pr)
        if(temp == value) ret = 0;
        else {
           ret = 0xFFFF;
-#ifdef SIS_XORG_XF86
-#ifdef TWDEBUG
-          xf86DrvMsg(0, X_INFO, "Probe: Read 2 failed\n");
-#endif
-#endif
           if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
              if(temp == 0x30) ret = 0;
           }
@@ -9338,9 +9158,7 @@ SiS_DoProbeDDC(struct SiS_Private *SiS_Pr)
     return ret;
 }
 
-#ifndef SIS_XORG_XF86
 static
-#endif
 unsigned short
 SiS_ProbeDDC(struct SiS_Private *SiS_Pr)
 {
@@ -9357,9 +9175,7 @@ SiS_ProbeDDC(struct SiS_Private *SiS_Pr)
    return flag;
 }
 
-#ifndef SIS_XORG_XF86
 static
-#endif
 unsigned short
 SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype, unsigned char *buffer)
 {
@@ -9606,11 +9422,6 @@ SiS_SetSCLKHigh(struct SiS_Private *SiS_Pr)
     temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
   } while((!(temp & SiS_Pr->SiS_DDC_Clk)) && --watchdog);
   if (!watchdog) {
-#ifdef SIS_XORG_XF86
-#ifdef TWDEBUG
-        xf86DrvMsg(0, X_INFO, "SetClkHigh failed\n");
-#endif
-#endif
        return 0xFFFF;
   }
   SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
@@ -9641,7 +9452,7 @@ SiS_CheckACK(struct SiS_Private *SiS_Pr)
 
 /* =============== SiS 315/330 O.E.M. ================= */
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 
 static unsigned short
 GetRAMDACromptr(struct SiS_Private *SiS_Pr)
@@ -10829,7 +10640,7 @@ SiS_FinalizeLCD(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned shor
 
 /*  =================  SiS 300 O.E.M. ================== */
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
 
 static void
 SetOEMLCDData2(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
index 51d99222375dd9034c94c5a66eba731f60299e05..2112d6d7feda02fb101a3fddf4d99b2c53b23bbb 100644 (file)
 #ifndef  _INIT301_H_
 #define  _INIT301_H_
 
-#include "osdef.h"
 #include "initdef.h"
 
-#ifdef SIS_XORG_XF86
-#include "sis.h"
-#include "sis_regs.h"
-#endif
-
-#ifdef SIS_LINUX_KERNEL
 #include "vgatypes.h"
 #include "vstruct.h"
 #ifdef SIS_CP
@@ -72,7 +65,6 @@
 #include <linux/fb.h>
 #include "sis.h"
 #include <video/sisfb.h>
-#endif
 
 static const unsigned char SiS_YPbPrTable[3][64] = {
   {
@@ -237,7 +229,7 @@ static const unsigned char SiS_Part2CLVX_6[] = {   /* 1080i */
     0xFF,0xFF,
 };
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 /* 661 et al LCD data structure (2.03.00) */
 static const unsigned char SiS_LCDStruct661[] = {
     /* 1024x768 */
@@ -279,7 +271,7 @@ static const unsigned char SiS_LCDStruct661[] = {
 };
 #endif
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
 static unsigned char SiS300_TrumpionData[14][80] = {
   { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
     0x20,0x03,0x0B,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x10,0x00,0x00,0x04,0x23,
@@ -356,9 +348,6 @@ static unsigned char SiS300_TrumpionData[14][80] = {
 #endif
 
 void           SiS_UnLockCRT2(struct SiS_Private *SiS_Pr);
-#ifndef SIS_LINUX_KERNEL
-void           SiS_LockCRT2(struct SiS_Private *SiS_Pr);
-#endif
 void           SiS_EnableCRT2(struct SiS_Private *SiS_Pr);
 unsigned short SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
 void           SiS_WaitRetrace1(struct SiS_Private *SiS_Pr);
@@ -375,9 +364,6 @@ unsigned short      SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo
                        unsigned short RefreshRateTableIndex);
 unsigned short SiS_GetResInfo(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned short ModeIdIndex);
 void           SiS_DisableBridge(struct SiS_Private *SiS_Pr);
-#ifndef SIS_LINUX_KERNEL
-void           SiS_EnableBridge(struct SiS_Private *SiS_Pr);
-#endif
 bool           SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
 void           SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr);
 void           SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr);
@@ -386,13 +372,9 @@ void               SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned cha
 unsigned short SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempax);
 void           SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
 unsigned short SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempax);
-#ifndef SIS_LINUX_KERNEL
-void           SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
-unsigned short SiS_GetCH70xx(struct SiS_Private *SiS_Pr, unsigned short tempax);
-#endif
 void           SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
                        unsigned char orval,unsigned short andval);
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 static void    SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr);
 static void    SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr);
 static void    SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr);
@@ -401,7 +383,7 @@ void                SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr);
 void           SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr);
 #endif /* 315 */
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
 static  bool   SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr);
 void           SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo);
 #endif
@@ -412,21 +394,12 @@ unsigned short    SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, i
                        unsigned short adaptnum, unsigned short DDCdatatype,
                        unsigned char *buffer, unsigned int VBFlags2);
 
-#ifdef SIS_XORG_XF86
-unsigned short         SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags,
-                               int VGAEngine, unsigned short adaptnum, unsigned short DDCdatatype,
-                               bool checkcr32, unsigned int VBFlags2);
-unsigned short         SiS_ProbeDDC(struct SiS_Private *SiS_Pr);
-unsigned short         SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype,
-                               unsigned char *buffer);
-#else
 static unsigned short  SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags,
                                int VGAEngine, unsigned short adaptnum, unsigned short DDCdatatype,
                                bool checkcr32, unsigned int VBFlags2);
 static unsigned short  SiS_ProbeDDC(struct SiS_Private *SiS_Pr);
 static unsigned short  SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype,
                                unsigned char *buffer);
-#endif
 static void            SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr);
 static unsigned short  SiS_SetStart(struct SiS_Private *SiS_Pr);
 static unsigned short  SiS_SetStop(struct SiS_Private *SiS_Pr);
@@ -441,13 +414,13 @@ static unsigned short     SiS_PrepareDDC(struct SiS_Private *SiS_Pr);
 static void            SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno);
 static unsigned short  SiS_DoProbeDDC(struct SiS_Private *SiS_Pr);
 
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
 static void            SiS_OEM300Setting(struct SiS_Private *SiS_Pr,
                                unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefTabindex);
 static void            SetOEMLCDData2(struct SiS_Private *SiS_Pr,
                                unsigned short ModeNo, unsigned short ModeIdIndex,unsigned short RefTableIndex);
 #endif
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
 static void            SiS_OEM310Setting(struct SiS_Private *SiS_Pr,
                                unsigned short ModeNo,unsigned short ModeIdIndex, unsigned short RRTI);
 static void            SiS_OEM661Setting(struct SiS_Private *SiS_Pr,
@@ -455,17 +428,6 @@ static void                SiS_OEM661Setting(struct SiS_Private *SiS_Pr,
 static void            SiS_FinalizeLCD(struct SiS_Private *, unsigned short, unsigned short);
 #endif
 
-extern void            SiS_SetReg(SISIOADDRESS, unsigned short, unsigned short);
-extern void            SiS_SetRegByte(SISIOADDRESS, unsigned short);
-extern void            SiS_SetRegShort(SISIOADDRESS, unsigned short);
-extern void            SiS_SetRegLong(SISIOADDRESS, unsigned int);
-extern unsigned char   SiS_GetReg(SISIOADDRESS, unsigned short);
-extern unsigned char   SiS_GetRegByte(SISIOADDRESS);
-extern unsigned short  SiS_GetRegShort(SISIOADDRESS);
-extern unsigned int    SiS_GetRegLong(SISIOADDRESS);
-extern void            SiS_SetRegANDOR(SISIOADDRESS, unsigned short, unsigned short, unsigned short);
-extern void            SiS_SetRegOR(SISIOADDRESS, unsigned short, unsigned short);
-extern void            SiS_SetRegAND(SISIOADDRESS, unsigned short, unsigned short);
 extern void            SiS_DisplayOff(struct SiS_Private *SiS_Pr);
 extern void            SiS_DisplayOn(struct SiS_Private *SiS_Pr);
 extern bool            SiS_SearchModeID(struct SiS_Private *, unsigned short *, unsigned short *);
@@ -482,15 +444,13 @@ extern void               SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short M
 extern void            SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth);
 extern unsigned short  SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
 extern unsigned short  SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
-#ifdef SIS300
+#ifdef CONFIG_FB_SIS_300
 extern void            SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *tempbx,
                                unsigned short *tempcl);
 extern unsigned short  SiS_GetFIFOThresholdB300(unsigned short tempbx, unsigned short tempcl);
 extern unsigned short  SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index);
-#ifdef SIS_LINUX_KERNEL
 extern unsigned int    sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
 extern unsigned int    sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg);
 #endif
-#endif
 
 #endif
index 99c04a4855d13671925301f1f219a2d991160f86..9dec64da401593097b4432e6bf846187ca864ddc 100644 (file)
@@ -25,7 +25,6 @@
  * Author:     Thomas Winischhofer <thomas@winischhofer.net>
  */
 
-#include "osdef.h"
 #include "initdef.h"
 #include "vgatypes.h"
 #include "vstruct.h"
@@ -59,7 +58,7 @@ sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr, unsigned char modeno,
 
     if(rateindex > 0) rateindex--;
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
     switch(ModeNo) {
     case 0x5a: ModeNo = 0x50; break;
     case 0x5b: ModeNo = 0x56;
@@ -103,7 +102,7 @@ sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno,
 
     if(rateindex > 0) rateindex--;
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
     switch(ModeNo) {
        case 0x5a: ModeNo = 0x50; break;
        case 0x5b: ModeNo = 0x56;
@@ -187,7 +186,7 @@ sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno, int *ht
 
     if(rateindex > 0) rateindex--;
 
-#ifdef SIS315H
+#ifdef CONFIG_FB_SIS_315
     switch(ModeNo) {
        case 0x5a: ModeNo = 0x50; break;
        case 0x5b: ModeNo = 0x56;
diff --git a/drivers/video/sis/osdef.h b/drivers/video/sis/osdef.h
deleted file mode 100644 (file)
index 6ff8f98..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/* $XFree86$ */
-/* $XdotOrg$ */
-/*
- * OS depending defines
- *
- * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
- *
- * If distributed as part of the Linux kernel, the following license terms
- * apply:
- *
- * * 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 named License,
- * * or 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
- *
- * Otherwise, the following license terms apply:
- *
- * * 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 name of the author may not be used to endorse or promote products
- * *    derived from this software without specific prior written permission.
- * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- *
- * Author:     Thomas Winischhofer <thomas@winischhofer.net>
- *             Silicon Integrated Systems, Inc. (used by permission)
- *
- */
-
-#ifndef _SIS_OSDEF_H_
-#define _SIS_OSDEF_H_
-
-/* The choices are: */
-#define SIS_LINUX_KERNEL               /* Linux kernel framebuffer */
-#undef  SIS_XORG_XF86                  /* XFree86/X.org */
-
-#ifdef OutPortByte
-#undef OutPortByte
-#endif
-
-#ifdef OutPortWord
-#undef OutPortWord
-#endif
-
-#ifdef OutPortLong
-#undef OutPortLong
-#endif
-
-#ifdef InPortByte
-#undef InPortByte
-#endif
-
-#ifdef InPortWord
-#undef InPortWord
-#endif
-
-#ifdef InPortLong
-#undef InPortLong
-#endif
-
-/**********************************************************************/
-/*  LINUX KERNEL                                                      */
-/**********************************************************************/
-
-#ifdef SIS_LINUX_KERNEL
-
-#ifdef CONFIG_FB_SIS_300
-#define SIS300
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-#define SIS315H
-#endif
-
-#if !defined(SIS300) && !defined(SIS315H)
-#warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
-#warning sisfb will not work!
-#endif
-
-#define OutPortByte(p,v) outb((u8)(v),(SISIOADDRESS)(p))
-#define OutPortWord(p,v) outw((u16)(v),(SISIOADDRESS)(p))
-#define OutPortLong(p,v) outl((u32)(v),(SISIOADDRESS)(p))
-#define InPortByte(p)    inb((SISIOADDRESS)(p))
-#define InPortWord(p)    inw((SISIOADDRESS)(p))
-#define InPortLong(p)    inl((SISIOADDRESS)(p))
-#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset_io(MemoryAddress, value, MemorySize)
-
-#endif /* LINUX_KERNEL */
-
-/**********************************************************************/
-/*  XFree86/X.org                                                    */
-/**********************************************************************/
-
-#ifdef SIS_XORG_XF86
-
-#define SIS300
-#define SIS315H
-
-#define OutPortByte(p,v) outSISREG((IOADDRESS)(p),(CARD8)(v))
-#define OutPortWord(p,v) outSISREGW((IOADDRESS)(p),(CARD16)(v))
-#define OutPortLong(p,v) outSISREGL((IOADDRESS)(p),(CARD32)(v))
-#define InPortByte(p)    inSISREG((IOADDRESS)(p))
-#define InPortWord(p)    inSISREGW((IOADDRESS)(p))
-#define InPortLong(p)    inSISREGL((IOADDRESS)(p))
-#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
-
-#endif /* XF86 */
-
-#endif  /* _OSDEF_H_ */
index 7c5710e3fb567272dc0952778bef930c8f2ba70b..eac7a01925f3d26e03ab33cc2650a76278993391 100644 (file)
@@ -24,7 +24,6 @@
 #ifndef _SIS_H_
 #define _SIS_H_
 
-#include "osdef.h"
 #include <video/sisfb.h>
 
 #include "vgatypes.h"
 #define VB2_LCDOVER1600BRIDGE  (VB2_307T  | VB2_307LV)
 #define VB2_RAMDAC202MHZBRIDGE (VB2_301C  | VB2_307T)
 
-/* I/O port access macros */
-#define inSISREG(base)         inb(base)
-
-#define outSISREG(base,val)    outb(val,base)
-
-#define orSISREG(base,val)                             \
-               do {                                    \
-                       u8 __Temp = inSISREG(base);     \
-                       outSISREG(base, __Temp | (val));\
-               } while (0)
-
-#define andSISREG(base,val)                            \
-               do {                                    \
-                       u8 __Temp = inSISREG(base);     \
-                       outSISREG(base, __Temp & (val));\
-               } while (0)
-
-#define inSISIDXREG(base,idx,var)                      \
-               do {                                    \
-                       outSISREG(base, idx);           \
-                       var = inSISREG((base)+1);       \
-               } while (0)
-
-#define outSISIDXREG(base,idx,val)                     \
-               do {                                    \
-                       outSISREG(base, idx);           \
-                       outSISREG((base)+1, val);       \
-               } while (0)
-
-#define orSISIDXREG(base,idx,val)                              \
-               do {                                            \
-                       u8 __Temp;                              \
-                       outSISREG(base, idx);                   \
-                       __Temp = inSISREG((base)+1) | (val);    \
-                       outSISREG((base)+1, __Temp);            \
-               } while (0)
-
-#define andSISIDXREG(base,idx,and)                             \
-               do {                                            \
-                       u8 __Temp;                              \
-                       outSISREG(base, idx);                   \
-                       __Temp = inSISREG((base)+1) & (and);    \
-                       outSISREG((base)+1, __Temp);            \
-               } while (0)
-
-#define setSISIDXREG(base,idx,and,or)                                  \
-               do {                                                    \
-                       u8 __Temp;                                      \
-                       outSISREG(base, idx);                           \
-                       __Temp = (inSISREG((base)+1) & (and)) | (or);   \
-                       outSISREG((base)+1, __Temp);                    \
-               } while (0)
+/* I/O port access functions */
+
+void SiS_SetReg(SISIOADDRESS, u8, u8);
+void SiS_SetRegByte(SISIOADDRESS, u8);
+void SiS_SetRegShort(SISIOADDRESS, u16);
+void SiS_SetRegLong(SISIOADDRESS, u32);
+void SiS_SetRegANDOR(SISIOADDRESS, u8, u8, u8);
+void SiS_SetRegAND(SISIOADDRESS, u8, u8);
+void SiS_SetRegOR(SISIOADDRESS, u8, u8);
+u8 SiS_GetReg(SISIOADDRESS, u8);
+u8 SiS_GetRegByte(SISIOADDRESS);
+u16 SiS_GetRegShort(SISIOADDRESS);
+u32 SiS_GetRegLong(SISIOADDRESS);
 
 /* MMIO access macros */
 #define MMIO_IN8(base, offset)  readb((base+offset))
index 3dde12b0ab06420c58b0e6a41fc5f23350b28a75..2fb8c5a660fb88ebd42c10f90739ee233648b974 100644 (file)
 #include "sis.h"
 #include "sis_main.h"
 
+#if !defined(CONFIG_FB_SIS_300) && !defined(CONFIG_FB_SIS_315)
+#warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
+#warning sisfb will not work!
+#endif
+
 static void sisfb_handle_command(struct sis_video_info *ivideo,
                                 struct sisfb_cmd *sisfb_command);
 
@@ -732,7 +737,7 @@ sisfb_bridgeisslave(struct sis_video_info *ivideo)
        if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
                return false;
 
-       inSISIDXREG(SISPART1,0x00,P1_00);
+       P1_00 = SiS_GetReg(SISPART1, 0x00);
        if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
            ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
                return true;
@@ -746,11 +751,11 @@ sisfballowretracecrt1(struct sis_video_info *ivideo)
 {
        u8 temp;
 
-       inSISIDXREG(SISCR,0x17,temp);
+       temp = SiS_GetReg(SISCR, 0x17);
        if(!(temp & 0x80))
                return false;
 
-       inSISIDXREG(SISSR,0x1f,temp);
+       temp = SiS_GetReg(SISSR, 0x1f);
        if(temp & 0xc0)
                return false;
 
@@ -763,7 +768,7 @@ sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
        if(!sisfballowretracecrt1(ivideo))
                return false;
 
-       if(inSISREG(SISINPSTAT) & 0x08)
+       if (SiS_GetRegByte(SISINPSTAT) & 0x08)
                return true;
        else
                return false;
@@ -778,9 +783,9 @@ sisfbwaitretracecrt1(struct sis_video_info *ivideo)
                return;
 
        watchdog = 65536;
-       while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog);
+       while ((!(SiS_GetRegByte(SISINPSTAT) & 0x08)) && --watchdog);
        watchdog = 65536;
-       while((inSISREG(SISINPSTAT) & 0x08) && --watchdog);
+       while ((SiS_GetRegByte(SISINPSTAT) & 0x08) && --watchdog);
 }
 
 static bool
@@ -794,7 +799,7 @@ sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
        default:          return false;
        }
 
-       inSISIDXREG(SISPART1, reg, temp);
+       temp = SiS_GetReg(SISPART1, reg);
        if(temp & 0x02)
                return true;
        else
@@ -832,10 +837,10 @@ sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
                        default:
                        case SIS_315_VGA: idx = 0x30; break;
                }
-               inSISIDXREG(SISPART1,(idx+0),reg1); /* 30 */
-               inSISIDXREG(SISPART1,(idx+1),reg2); /* 31 */
-               inSISIDXREG(SISPART1,(idx+2),reg3); /* 32 */
-               inSISIDXREG(SISPART1,(idx+3),reg4); /* 33 */
+               reg1 = SiS_GetReg(SISPART1, (idx+0)); /* 30 */
+               reg2 = SiS_GetReg(SISPART1, (idx+1)); /* 31 */
+               reg3 = SiS_GetReg(SISPART1, (idx+2)); /* 32 */
+               reg4 = SiS_GetReg(SISPART1, (idx+3)); /* 33 */
                if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
                if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
                if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
@@ -848,13 +853,13 @@ sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
                        FB_VBLANK_HAVE_VBLANK |
                        FB_VBLANK_HAVE_VCOUNT |
                        FB_VBLANK_HAVE_HCOUNT);
-               reg1 = inSISREG(SISINPSTAT);
+               reg1 = SiS_GetRegByte(SISINPSTAT);
                if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
                if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
-               inSISIDXREG(SISCR,0x20,reg1);
-               inSISIDXREG(SISCR,0x1b,reg1);
-               inSISIDXREG(SISCR,0x1c,reg2);
-               inSISIDXREG(SISCR,0x1d,reg3);
+               reg1 = SiS_GetReg(SISCR, 0x20);
+               reg1 = SiS_GetReg(SISCR, 0x1b);
+               reg2 = SiS_GetReg(SISCR, 0x1c);
+               reg3 = SiS_GetReg(SISCR, 0x1d);
                (*vcount) = reg2 | ((reg3 & 0x07) << 8);
                (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
        }
@@ -925,12 +930,12 @@ sisfb_myblank(struct sis_video_info *ivideo, int blank)
                     (ivideo->sisfb_thismonitor.feature & 0xe0))) {
 
                        if(ivideo->sisvga_engine == SIS_315_VGA) {
-                               setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
+                               SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
                        }
 
                        if(!(sisfb_bridgeisslave(ivideo))) {
-                               setSISIDXREG(SISSR, 0x01, ~0x20, sr01);
-                               setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f);
+                               SiS_SetRegANDOR(SISSR, 0x01, ~0x20, sr01);
+                               SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, sr1f);
                        }
                }
 
@@ -960,25 +965,25 @@ sisfb_myblank(struct sis_video_info *ivideo, int blank)
                    (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) ||
                   ((ivideo->sisvga_engine == SIS_315_VGA) &&
                    ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) {
-                       setSISIDXREG(SISSR, 0x11, ~0x0c, sr11);
+                       SiS_SetRegANDOR(SISSR, 0x11, ~0x0c, sr11);
                }
 
                if(ivideo->sisvga_engine == SIS_300_VGA) {
                        if((ivideo->vbflags2 & VB2_30xB) &&
                           (!(ivideo->vbflags2 & VB2_30xBDH))) {
-                               setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13);
+                               SiS_SetRegANDOR(SISPART1, 0x13, 0x3f, p1_13);
                        }
                } else if(ivideo->sisvga_engine == SIS_315_VGA) {
                        if((ivideo->vbflags2 & VB2_30xB) &&
                           (!(ivideo->vbflags2 & VB2_30xBDH))) {
-                               setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
+                               SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
                        }
                }
 
        } else if(ivideo->currentvbflags & CRT2_VGA) {
 
                if(ivideo->vbflags2 & VB2_30xB) {
-                       setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
+                       SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
                }
 
        }
@@ -1109,15 +1114,15 @@ sisfb_set_pitch(struct sis_video_info *ivideo)
 
        /* We need to set pitch for CRT1 if bridge is in slave mode, too */
        if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
-               outSISIDXREG(SISCR,0x13,(HDisplay1 & 0xFF));
-               setSISIDXREG(SISSR,0x0E,0xF0,(HDisplay1 >> 8));
+               SiS_SetReg(SISCR, 0x13, (HDisplay1 & 0xFF));
+               SiS_SetRegANDOR(SISSR, 0x0E, 0xF0, (HDisplay1 >> 8));
        }
 
        /* We must not set the pitch for CRT2 if bridge is in slave mode */
        if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
-               orSISIDXREG(SISPART1,ivideo->CRT2_write_enable,0x01);
-               outSISIDXREG(SISPART1,0x07,(HDisplay2 & 0xFF));
-               setSISIDXREG(SISPART1,0x09,0xF0,(HDisplay2 >> 8));
+               SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
+               SiS_SetReg(SISPART1, 0x07, (HDisplay2 & 0xFF));
+               SiS_SetRegANDOR(SISPART1, 0x09, 0xF0, (HDisplay2 >> 8));
        }
 }
 
@@ -1162,7 +1167,7 @@ sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
        /* >=2.6.12's fbcon clears the screen anyway */
        modeno |= 0x80;
 
-       outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
+       SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
 
        sisfb_pre_setmode(ivideo);
 
@@ -1171,7 +1176,7 @@ sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
                return -EINVAL;
        }
 
-       outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
+       SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
 
        sisfb_post_setmode(ivideo);
 
@@ -1303,13 +1308,13 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
 static void
 sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base)
 {
-       outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
+       SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
 
-       outSISIDXREG(SISCR, 0x0D, base & 0xFF);
-       outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF);
-       outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF);
+       SiS_SetReg(SISCR, 0x0D, base & 0xFF);
+       SiS_SetReg(SISCR, 0x0C, (base >> 8) & 0xFF);
+       SiS_SetReg(SISSR, 0x0D, (base >> 16) & 0xFF);
        if(ivideo->sisvga_engine == SIS_315_VGA) {
-               setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
+               SiS_SetRegANDOR(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
        }
 }
 
@@ -1317,12 +1322,12 @@ static void
 sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
 {
        if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
-               orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01);
-               outSISIDXREG(SISPART1, 0x06, (base & 0xFF));
-               outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF));
-               outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF));
+               SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
+               SiS_SetReg(SISPART1, 0x06, (base & 0xFF));
+               SiS_SetReg(SISPART1, 0x05, ((base >> 8) & 0xFF));
+               SiS_SetReg(SISPART1, 0x04, ((base >> 16) & 0xFF));
                if(ivideo->sisvga_engine == SIS_315_VGA) {
-                       setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
+                       SiS_SetRegANDOR(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
                }
        }
 }
@@ -1383,15 +1388,15 @@ sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
 
        switch(info->var.bits_per_pixel) {
        case 8:
-               outSISREG(SISDACA, regno);
-               outSISREG(SISDACD, (red >> 10));
-               outSISREG(SISDACD, (green >> 10));
-               outSISREG(SISDACD, (blue >> 10));
+               SiS_SetRegByte(SISDACA, regno);
+               SiS_SetRegByte(SISDACD, (red >> 10));
+               SiS_SetRegByte(SISDACD, (green >> 10));
+               SiS_SetRegByte(SISDACD, (blue >> 10));
                if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
-                       outSISREG(SISDAC2A, regno);
-                       outSISREG(SISDAC2D, (red >> 8));
-                       outSISREG(SISDAC2D, (green >> 8));
-                       outSISREG(SISDAC2D, (blue >> 8));
+                       SiS_SetRegByte(SISDAC2A, regno);
+                       SiS_SetRegByte(SISDAC2D, (red >> 8));
+                       SiS_SetRegByte(SISDAC2D, (green >> 8));
+                       SiS_SetRegByte(SISDAC2D, (blue >> 8));
                }
                break;
        case 16:
@@ -1956,7 +1961,7 @@ sisfb_get_dram_size(struct sis_video_info *ivideo)
        switch(ivideo->chip) {
 #ifdef CONFIG_FB_SIS_300
        case SIS_300:
-               inSISIDXREG(SISSR, 0x14, reg);
+               reg = SiS_GetReg(SISSR, 0x14);
                ivideo->video_size = ((reg & 0x3F) + 1) << 20;
                break;
        case SIS_540:
@@ -1972,7 +1977,7 @@ sisfb_get_dram_size(struct sis_video_info *ivideo)
        case SIS_315H:
        case SIS_315PRO:
        case SIS_315:
-               inSISIDXREG(SISSR, 0x14, reg);
+               reg = SiS_GetReg(SISSR, 0x14);
                ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
                switch((reg >> 2) & 0x03) {
                case 0x01:
@@ -1984,31 +1989,31 @@ sisfb_get_dram_size(struct sis_video_info *ivideo)
                }
                break;
        case SIS_330:
-               inSISIDXREG(SISSR, 0x14, reg);
+               reg = SiS_GetReg(SISSR, 0x14);
                ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
                if(reg & 0x0c) ivideo->video_size <<= 1;
                break;
        case SIS_550:
        case SIS_650:
        case SIS_740:
-               inSISIDXREG(SISSR, 0x14, reg);
+               reg = SiS_GetReg(SISSR, 0x14);
                ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
                break;
        case SIS_661:
        case SIS_741:
-               inSISIDXREG(SISCR, 0x79, reg);
+               reg = SiS_GetReg(SISCR, 0x79);
                ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
                break;
        case SIS_660:
        case SIS_760:
        case SIS_761:
-               inSISIDXREG(SISCR, 0x79, reg);
+               reg = SiS_GetReg(SISCR, 0x79);
                reg = (reg & 0xf0) >> 4;
                if(reg) {
                        ivideo->video_size = (1 << reg) << 20;
                        ivideo->UMAsize = ivideo->video_size;
                }
-               inSISIDXREG(SISCR, 0x78, reg);
+               reg = SiS_GetReg(SISCR, 0x78);
                reg &= 0x30;
                if(reg) {
                        if(reg == 0x10) {
@@ -2022,7 +2027,7 @@ sisfb_get_dram_size(struct sis_video_info *ivideo)
        case SIS_340:
        case XGI_20:
        case XGI_40:
-               inSISIDXREG(SISSR, 0x14, reg);
+               reg = SiS_GetReg(SISSR, 0x14);
                ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
                if(ivideo->chip != XGI_20) {
                        reg = (reg & 0x0c) >> 2;
@@ -2056,11 +2061,11 @@ sisfb_detect_VB_connect(struct sis_video_info *ivideo)
 
 #ifdef CONFIG_FB_SIS_300
        if(ivideo->sisvga_engine == SIS_300_VGA) {
-               inSISIDXREG(SISSR, 0x17, temp);
+               temp = SiS_GetReg(SISSR, 0x17);
                if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
                        /* PAL/NTSC is stored on SR16 on such machines */
                        if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
-                               inSISIDXREG(SISSR, 0x16, temp);
+                               temp = SiS_GetReg(SISSR, 0x16);
                                if(temp & 0x20)
                                        ivideo->vbflags |= TV_PAL;
                                else
@@ -2070,7 +2075,7 @@ sisfb_detect_VB_connect(struct sis_video_info *ivideo)
        }
 #endif
 
-       inSISIDXREG(SISCR, 0x32, cr32);
+       cr32 = SiS_GetReg(SISCR, 0x32);
 
        if(cr32 & SIS_CRT1) {
                ivideo->sisfb_crt1off = 0;
@@ -2146,15 +2151,15 @@ sisfb_detect_VB_connect(struct sis_video_info *ivideo)
            }
            if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
                if(ivideo->sisvga_engine == SIS_300_VGA) {
-                       inSISIDXREG(SISSR, 0x38, temp);
+                       temp = SiS_GetReg(SISSR, 0x38);
                        if(temp & 0x01) ivideo->vbflags |= TV_PAL;
                        else            ivideo->vbflags |= TV_NTSC;
                } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
-                       inSISIDXREG(SISSR, 0x38, temp);
+                       temp = SiS_GetReg(SISSR, 0x38);
                        if(temp & 0x01) ivideo->vbflags |= TV_PAL;
                        else            ivideo->vbflags |= TV_NTSC;
                } else {
-                       inSISIDXREG(SISCR, 0x79, temp);
+                       temp = SiS_GetReg(SISCR, 0x79);
                        if(temp & 0x20) ivideo->vbflags |= TV_PAL;
                        else            ivideo->vbflags |= TV_NTSC;
                }
@@ -2193,26 +2198,26 @@ sisfb_sense_crt1(struct sis_video_info *ivideo)
     u16 temp = 0xffff;
     int i;
 
-    inSISIDXREG(SISSR,0x1F,sr1F);
-    orSISIDXREG(SISSR,0x1F,0x04);
-    andSISIDXREG(SISSR,0x1F,0x3F);
+    sr1F = SiS_GetReg(SISSR, 0x1F);
+    SiS_SetRegOR(SISSR, 0x1F, 0x04);
+    SiS_SetRegAND(SISSR, 0x1F, 0x3F);
     if(sr1F & 0xc0) mustwait = true;
 
 #ifdef CONFIG_FB_SIS_315
     if(ivideo->sisvga_engine == SIS_315_VGA) {
-       inSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,cr63);
+       cr63 = SiS_GetReg(SISCR, ivideo->SiS_Pr.SiS_MyCR63);
        cr63 &= 0x40;
-       andSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF);
+       SiS_SetRegAND(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF);
     }
 #endif
 
-    inSISIDXREG(SISCR,0x17,cr17);
+    cr17 = SiS_GetReg(SISCR, 0x17);
     cr17 &= 0x80;
     if(!cr17) {
-       orSISIDXREG(SISCR,0x17,0x80);
+       SiS_SetRegOR(SISCR, 0x17, 0x80);
        mustwait = true;
-       outSISIDXREG(SISSR, 0x00, 0x01);
-       outSISIDXREG(SISSR, 0x00, 0x03);
+       SiS_SetReg(SISSR, 0x00, 0x01);
+       SiS_SetReg(SISSR, 0x00, 0x03);
     }
 
     if(mustwait) {
@@ -2221,18 +2226,18 @@ sisfb_sense_crt1(struct sis_video_info *ivideo)
 
 #ifdef CONFIG_FB_SIS_315
     if(ivideo->chip >= SIS_330) {
-       andSISIDXREG(SISCR,0x32,~0x20);
+       SiS_SetRegAND(SISCR, 0x32, ~0x20);
        if(ivideo->chip >= SIS_340) {
-          outSISIDXREG(SISCR, 0x57, 0x4a);
+          SiS_SetReg(SISCR, 0x57, 0x4a);
        } else {
-          outSISIDXREG(SISCR, 0x57, 0x5f);
+          SiS_SetReg(SISCR, 0x57, 0x5f);
        }
-       orSISIDXREG(SISCR, 0x53, 0x02);
-       while((inSISREG(SISINPSTAT)) & 0x01)    break;
-       while(!((inSISREG(SISINPSTAT)) & 0x01)) break;
-       if((inSISREG(SISMISCW)) & 0x10) temp = 1;
-       andSISIDXREG(SISCR, 0x53, 0xfd);
-       andSISIDXREG(SISCR, 0x57, 0x00);
+       SiS_SetRegOR(SISCR, 0x53, 0x02);
+       while ((SiS_GetRegByte(SISINPSTAT)) & 0x01)    break;
+       while (!((SiS_GetRegByte(SISINPSTAT)) & 0x01)) break;
+       if ((SiS_GetRegByte(SISMISCW)) & 0x10) temp = 1;
+       SiS_SetRegAND(SISCR, 0x53, 0xfd);
+       SiS_SetRegAND(SISCR, 0x57, 0x00);
     }
 #endif
 
@@ -2249,18 +2254,18 @@ sisfb_sense_crt1(struct sis_video_info *ivideo)
     }
 
     if((temp) && (temp != 0xffff)) {
-       orSISIDXREG(SISCR,0x32,0x20);
+       SiS_SetRegOR(SISCR, 0x32, 0x20);
     }
 
 #ifdef CONFIG_FB_SIS_315
     if(ivideo->sisvga_engine == SIS_315_VGA) {
-       setSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF,cr63);
+       SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF, cr63);
     }
 #endif
 
-    setSISIDXREG(SISCR,0x17,0x7F,cr17);
+    SiS_SetRegANDOR(SISCR, 0x17, 0x7F, cr17);
 
-    outSISIDXREG(SISSR,0x1F,sr1F);
+    SiS_SetReg(SISSR, 0x1F, sr1F);
 }
 
 /* Determine and detect attached devices on SiS30x */
@@ -2281,7 +2286,7 @@ SiS_SenseLCD(struct sis_video_info *ivideo)
                return;
 
        /* If LCD already set up by BIOS, skip it */
-       inSISIDXREG(SISCR, 0x32, reg);
+       reg = SiS_GetReg(SISCR, 0x32);
        if(reg & 0x08)
                return;
 
@@ -2344,10 +2349,10 @@ SiS_SenseLCD(struct sis_video_info *ivideo)
        else
                cr37 |= 0xc0;
 
-       outSISIDXREG(SISCR, 0x36, paneltype);
+       SiS_SetReg(SISCR, 0x36, paneltype);
        cr37 &= 0xf1;
-       setSISIDXREG(SISCR, 0x37, 0x0c, cr37);
-       orSISIDXREG(SISCR, 0x32, 0x08);
+       SiS_SetRegANDOR(SISCR, 0x37, 0x0c, cr37);
+       SiS_SetRegOR(SISCR, 0x32, 0x08);
 
        ivideo->SiS_Pr.PanelSelfDetected = true;
 }
@@ -2361,19 +2366,19 @@ SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
        result = 0;
        for(i = 0; i < 3; i++) {
           mytest = test;
-          outSISIDXREG(SISPART4,0x11,(type & 0x00ff));
+          SiS_SetReg(SISPART4, 0x11, (type & 0x00ff));
           temp = (type >> 8) | (mytest & 0x00ff);
-          setSISIDXREG(SISPART4,0x10,0xe0,temp);
+         SiS_SetRegANDOR(SISPART4, 0x10, 0xe0, temp);
           SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
           mytest >>= 8;
           mytest &= 0x7f;
-          inSISIDXREG(SISPART4,0x03,temp);
+          temp = SiS_GetReg(SISPART4, 0x03);
           temp ^= 0x0e;
           temp &= mytest;
           if(temp == mytest) result++;
 #if 1
-         outSISIDXREG(SISPART4,0x11,0x00);
-         andSISIDXREG(SISPART4,0x10,0xe0);
+         SiS_SetReg(SISPART4, 0x11, 0x00);
+         SiS_SetRegAND(SISPART4, 0x10, 0xe0);
          SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
 #endif
        }
@@ -2395,7 +2400,7 @@ SiS_Sense30x(struct sis_video_info *ivideo)
 
     if(ivideo->vbflags2 & VB2_301) {
        svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
-       inSISIDXREG(SISPART4,0x01,myflag);
+       myflag = SiS_GetReg(SISPART4, 0x01);
        if(myflag & 0x04) {
          svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
        }
@@ -2425,7 +2430,7 @@ SiS_Sense30x(struct sis_video_info *ivideo)
     }
 
     if(ivideo->chip == SIS_300) {
-       inSISIDXREG(SISSR,0x3b,myflag);
+       myflag = SiS_GetReg(SISSR, 0x3b);
        if(!(myflag & 0x01)) vga2 = vga2_c = 0;
     }
 
@@ -2433,93 +2438,93 @@ SiS_Sense30x(struct sis_video_info *ivideo)
        vga2 = vga2_c = 0;
     }
 
-    inSISIDXREG(SISSR,0x1e,backupSR_1e);
-    orSISIDXREG(SISSR,0x1e,0x20);
+    backupSR_1e = SiS_GetReg(SISSR, 0x1e);
+    SiS_SetRegOR(SISSR, 0x1e, 0x20);
 
-    inSISIDXREG(SISPART4,0x0d,backupP4_0d);
+    backupP4_0d = SiS_GetReg(SISPART4, 0x0d);
     if(ivideo->vbflags2 & VB2_30xC) {
-       setSISIDXREG(SISPART4,0x0d,~0x07,0x01);
+       SiS_SetRegANDOR(SISPART4, 0x0d, ~0x07, 0x01);
     } else {
-       orSISIDXREG(SISPART4,0x0d,0x04);
+       SiS_SetRegOR(SISPART4, 0x0d, 0x04);
     }
     SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
 
-    inSISIDXREG(SISPART2,0x00,backupP2_00);
-    outSISIDXREG(SISPART2,0x00,((backupP2_00 | 0x1c) & 0xfc));
+    backupP2_00 = SiS_GetReg(SISPART2, 0x00);
+    SiS_SetReg(SISPART2, 0x00, ((backupP2_00 | 0x1c) & 0xfc));
 
-    inSISIDXREG(SISPART2,0x4d,backupP2_4d);
+    backupP2_4d = SiS_GetReg(SISPART2, 0x4d);
     if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
-       outSISIDXREG(SISPART2,0x4d,(backupP2_4d & ~0x10));
+       SiS_SetReg(SISPART2, 0x4d, (backupP2_4d & ~0x10));
     }
 
     if(!(ivideo->vbflags2 & VB2_30xCLV)) {
        SISDoSense(ivideo, 0, 0);
     }
 
-    andSISIDXREG(SISCR, 0x32, ~0x14);
+    SiS_SetRegAND(SISCR, 0x32, ~0x14);
 
     if(vga2_c || vga2) {
        if(SISDoSense(ivideo, vga2, vga2_c)) {
           if(biosflag & 0x01) {
             printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);
-            orSISIDXREG(SISCR, 0x32, 0x04);
+            SiS_SetRegOR(SISCR, 0x32, 0x04);
          } else {
             printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
-            orSISIDXREG(SISCR, 0x32, 0x10);
+            SiS_SetRegOR(SISCR, 0x32, 0x10);
          }
        }
     }
 
-    andSISIDXREG(SISCR, 0x32, 0x3f);
+    SiS_SetRegAND(SISCR, 0x32, 0x3f);
 
     if(ivideo->vbflags2 & VB2_30xCLV) {
-       orSISIDXREG(SISPART4,0x0d,0x04);
+       SiS_SetRegOR(SISPART4, 0x0d, 0x04);
     }
 
     if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
-       outSISIDXREG(SISPART2,0x4d,(backupP2_4d | 0x10));
+       SiS_SetReg(SISPART2, 0x4d, (backupP2_4d | 0x10));
        SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
        if((result = SISDoSense(ivideo, svhs, 0x0604))) {
           if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
             printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);
-            orSISIDXREG(SISCR,0x32,0x80);
+            SiS_SetRegOR(SISCR, 0x32, 0x80);
          }
        }
-       outSISIDXREG(SISPART2,0x4d,backupP2_4d);
+       SiS_SetReg(SISPART2, 0x4d, backupP2_4d);
     }
 
-    andSISIDXREG(SISCR, 0x32, ~0x03);
+    SiS_SetRegAND(SISCR, 0x32, ~0x03);
 
     if(!(ivideo->vbflags & TV_YPBPR)) {
        if((result = SISDoSense(ivideo, svhs, svhs_c))) {
           printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
-          orSISIDXREG(SISCR, 0x32, 0x02);
+          SiS_SetRegOR(SISCR, 0x32, 0x02);
        }
        if((biosflag & 0x02) || (!result)) {
           if(SISDoSense(ivideo, cvbs, cvbs_c)) {
             printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
-            orSISIDXREG(SISCR, 0x32, 0x01);
+            SiS_SetRegOR(SISCR, 0x32, 0x01);
           }
        }
     }
 
     SISDoSense(ivideo, 0, 0);
 
-    outSISIDXREG(SISPART2,0x00,backupP2_00);
-    outSISIDXREG(SISPART4,0x0d,backupP4_0d);
-    outSISIDXREG(SISSR,0x1e,backupSR_1e);
+    SiS_SetReg(SISPART2, 0x00, backupP2_00);
+    SiS_SetReg(SISPART4, 0x0d, backupP4_0d);
+    SiS_SetReg(SISSR, 0x1e, backupSR_1e);
 
     if(ivideo->vbflags2 & VB2_30xCLV) {
-       inSISIDXREG(SISPART2,0x00,biosflag);
+       biosflag = SiS_GetReg(SISPART2, 0x00);
        if(biosflag & 0x20) {
           for(myflag = 2; myflag > 0; myflag--) {
             biosflag ^= 0x20;
-            outSISIDXREG(SISPART2,0x00,biosflag);
+            SiS_SetReg(SISPART2, 0x00, biosflag);
          }
        }
     }
 
-    outSISIDXREG(SISPART2,0x00,backupP2_00);
+    SiS_SetReg(SISPART2, 0x00, backupP2_00);
 }
 
 /* Determine and detect attached TV's on Chrontel */
@@ -2583,20 +2588,20 @@ SiS_SenseCh(struct sis_video_info *ivideo)
           if(temp1 == 0x02) {
                printk(KERN_INFO "%s SVIDEO output\n", stdstr);
                ivideo->vbflags |= TV_SVIDEO;
-               orSISIDXREG(SISCR, 0x32, 0x02);
-               andSISIDXREG(SISCR, 0x32, ~0x05);
+               SiS_SetRegOR(SISCR, 0x32, 0x02);
+               SiS_SetRegAND(SISCR, 0x32, ~0x05);
           } else if (temp1 == 0x01) {
                printk(KERN_INFO "%s CVBS output\n", stdstr);
                ivideo->vbflags |= TV_AVIDEO;
-               orSISIDXREG(SISCR, 0x32, 0x01);
-               andSISIDXREG(SISCR, 0x32, ~0x06);
+               SiS_SetRegOR(SISCR, 0x32, 0x01);
+               SiS_SetRegAND(SISCR, 0x32, ~0x06);
           } else {
                SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
-               andSISIDXREG(SISCR, 0x32, ~0x07);
+               SiS_SetRegAND(SISCR, 0x32, ~0x07);
           }
        } else if(temp1 == 0) {
          SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
-         andSISIDXREG(SISCR, 0x32, ~0x07);
+         SiS_SetRegAND(SISCR, 0x32, ~0x07);
        }
        /* Set general purpose IO for Chrontel communication */
        SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
@@ -2627,22 +2632,22 @@ SiS_SenseCh(struct sis_video_info *ivideo)
        case 0x01:
             printk(KERN_INFO "%s CVBS output\n", stdstr);
             ivideo->vbflags |= TV_AVIDEO;
-            orSISIDXREG(SISCR, 0x32, 0x01);
-            andSISIDXREG(SISCR, 0x32, ~0x06);
+            SiS_SetRegOR(SISCR, 0x32, 0x01);
+            SiS_SetRegAND(SISCR, 0x32, ~0x06);
             break;
        case 0x02:
             printk(KERN_INFO "%s SVIDEO output\n", stdstr);
             ivideo->vbflags |= TV_SVIDEO;
-            orSISIDXREG(SISCR, 0x32, 0x02);
-            andSISIDXREG(SISCR, 0x32, ~0x05);
+            SiS_SetRegOR(SISCR, 0x32, 0x02);
+            SiS_SetRegAND(SISCR, 0x32, ~0x05);
             break;
        case 0x04:
             printk(KERN_INFO "%s SCART output\n", stdstr);
-            orSISIDXREG(SISCR, 0x32, 0x04);
-            andSISIDXREG(SISCR, 0x32, ~0x03);
+            SiS_SetRegOR(SISCR, 0x32, 0x04);
+            SiS_SetRegAND(SISCR, 0x32, ~0x03);
             break;
        default:
-            andSISIDXREG(SISCR, 0x32, ~0x07);
+            SiS_SetRegAND(SISCR, 0x32, ~0x07);
        }
 #endif
     }
@@ -2660,10 +2665,10 @@ sisfb_get_VB_type(struct sis_video_info *ivideo)
        if(ivideo->chip == XGI_20)
                return;
 
-       inSISIDXREG(SISPART4, 0x00, vb_chipid);
+       vb_chipid = SiS_GetReg(SISPART4, 0x00);
        switch(vb_chipid) {
        case 0x01:
-               inSISIDXREG(SISPART4, 0x01, reg);
+               reg = SiS_GetReg(SISPART4, 0x01);
                if(reg < 0xb0) {
                        ivideo->vbflags |= VB_301;      /* Deprecated */
                        ivideo->vbflags2 |= VB2_301;
@@ -2671,7 +2676,7 @@ sisfb_get_VB_type(struct sis_video_info *ivideo)
                } else if(reg < 0xc0) {
                        ivideo->vbflags |= VB_301B;     /* Deprecated */
                        ivideo->vbflags2 |= VB2_301B;
-                       inSISIDXREG(SISPART4,0x23,reg);
+                       reg = SiS_GetReg(SISPART4, 0x23);
                        if(!(reg & 0x02)) {
                           ivideo->vbflags |= VB_30xBDH;        /* Deprecated */
                           ivideo->vbflags2 |= VB2_30xBDH;
@@ -2688,7 +2693,7 @@ sisfb_get_VB_type(struct sis_video_info *ivideo)
                        ivideo->vbflags2 |= VB2_301LV;
                        printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
                } else if(reg <= 0xe1) {
-                       inSISIDXREG(SISPART4,0x39,reg);
+                       reg = SiS_GetReg(SISPART4, 0x39);
                        if(reg == 0xff) {
                           ivideo->vbflags |= VB_302LV; /* Deprecated */
                           ivideo->vbflags2 |= VB2_302LV;
@@ -2713,7 +2718,7 @@ sisfb_get_VB_type(struct sis_video_info *ivideo)
        }
 
        if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
-               inSISIDXREG(SISCR, 0x37, reg);
+               reg = SiS_GetReg(SISCR, 0x37);
                reg &= SIS_EXTERNAL_CHIP_MASK;
                reg >>= 1;
                if(ivideo->sisvga_engine == SIS_300_VGA) {
@@ -2754,7 +2759,7 @@ sisfb_get_VB_type(struct sis_video_info *ivideo)
 #endif
                } else if(ivideo->chip >= SIS_661) {
 #ifdef CONFIG_FB_SIS_315
-                       inSISIDXREG(SISCR, 0x38, reg);
+                       reg = SiS_GetReg(SISCR, 0x38);
                        reg >>= 5;
                        switch(reg) {
                           case 0x02:
@@ -2817,13 +2822,13 @@ sisfb_engine_init(struct sis_video_info *ivideo)
 
                tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
 
-               inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
+               tq_state = SiS_GetReg(SISSR, IND_SIS_TURBOQUEUE_SET);
                tq_state |= 0xf0;
                tq_state &= 0xfc;
                tq_state |= (u8)(tqueue_pos >> 8);
-               outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
+               SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
 
-               outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
+               SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
 
                ivideo->caps |= TURBO_QUEUE_CAP;
        }
@@ -2860,8 +2865,8 @@ sisfb_engine_init(struct sis_video_info *ivideo)
                        }
                }
 
-               outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
-               outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
+               SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
+               SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
 
                if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
                        /* Must disable dual pipe on XGI_40. Can't do
@@ -2873,7 +2878,7 @@ sisfb_engine_init(struct sis_video_info *ivideo)
 
                                MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
 
-                               outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
+                               SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
 
                                tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
                                MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
@@ -2890,7 +2895,7 @@ sisfb_engine_init(struct sis_video_info *ivideo)
 
                                sisfb_syncaccel(ivideo);
 
-                               outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
+                               SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
 
                        }
                }
@@ -2899,7 +2904,7 @@ sisfb_engine_init(struct sis_video_info *ivideo)
                MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
 
                temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
-               outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
+               SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, temp);
 
                tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
                MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
@@ -2917,7 +2922,7 @@ sisfb_detect_lcd_type(struct sis_video_info *ivideo)
        u8 reg;
        int i;
 
-       inSISIDXREG(SISCR, 0x36, reg);
+       reg = SiS_GetReg(SISCR, 0x36);
        reg &= 0x0f;
        if(ivideo->sisvga_engine == SIS_300_VGA) {
                ivideo->CRT2LCDType = sis300paneltype[reg];
@@ -2936,8 +2941,8 @@ sisfb_detect_lcd_type(struct sis_video_info *ivideo)
        if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
                /* For broken BIOSes: Assume 1024x768, RGB18 */
                ivideo->CRT2LCDType = LCD_1024x768;
-               setSISIDXREG(SISCR,0x36,0xf0,0x02);
-               setSISIDXREG(SISCR,0x37,0xee,0x01);
+               SiS_SetRegANDOR(SISCR, 0x36, 0xf0, 0x02);
+               SiS_SetRegANDOR(SISCR, 0x37, 0xee, 0x01);
                printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
        }
 
@@ -2975,10 +2980,10 @@ sisfb_save_pdc_emi(struct sis_video_info *ivideo)
        if(ivideo->sisvga_engine == SIS_300_VGA) {
                if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
                        int tmp;
-                       inSISIDXREG(SISCR,0x30,tmp);
+                       tmp = SiS_GetReg(SISCR, 0x30);
                        if(tmp & 0x20) {
                                /* Currently on LCD? If yes, read current pdc */
-                               inSISIDXREG(SISPART1,0x13,ivideo->detectedpdc);
+                               ivideo->detectedpdc = SiS_GetReg(SISPART1, 0x13);
                                ivideo->detectedpdc &= 0x3c;
                                if(ivideo->SiS_Pr.PDC == -1) {
                                        /* Let option override detection */
@@ -3002,7 +3007,7 @@ sisfb_save_pdc_emi(struct sis_video_info *ivideo)
                /* Try to find about LCDA */
                if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
                        int tmp;
-                       inSISIDXREG(SISPART1,0x13,tmp);
+                       tmp = SiS_GetReg(SISPART1, 0x13);
                        if(tmp & 0x04) {
                                ivideo->SiS_Pr.SiS_UseLCDA = true;
                                ivideo->detectedlcda = 0x03;
@@ -3012,16 +3017,16 @@ sisfb_save_pdc_emi(struct sis_video_info *ivideo)
                /* Save PDC */
                if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
                        int tmp;
-                       inSISIDXREG(SISCR,0x30,tmp);
+                       tmp = SiS_GetReg(SISCR, 0x30);
                        if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
                                /* Currently on LCD? If yes, read current pdc */
                                u8 pdc;
-                               inSISIDXREG(SISPART1,0x2D,pdc);
+                               pdc = SiS_GetReg(SISPART1, 0x2D);
                                ivideo->detectedpdc  = (pdc & 0x0f) << 1;
                                ivideo->detectedpdca = (pdc & 0xf0) >> 3;
-                               inSISIDXREG(SISPART1,0x35,pdc);
+                               pdc = SiS_GetReg(SISPART1, 0x35);
                                ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
-                               inSISIDXREG(SISPART1,0x20,pdc);
+                               pdc = SiS_GetReg(SISPART1, 0x20);
                                ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
                                if(ivideo->newrom) {
                                        /* New ROM invalidates other PDC resp. */
@@ -3055,10 +3060,10 @@ sisfb_save_pdc_emi(struct sis_video_info *ivideo)
 
                        /* Save EMI */
                        if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
-                               inSISIDXREG(SISPART4,0x30,ivideo->SiS_Pr.EMI_30);
-                               inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31);
-                               inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32);
-                               inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33);
+                               ivideo->SiS_Pr.EMI_30 = SiS_GetReg(SISPART4, 0x30);
+                               ivideo->SiS_Pr.EMI_31 = SiS_GetReg(SISPART4, 0x31);
+                               ivideo->SiS_Pr.EMI_32 = SiS_GetReg(SISPART4, 0x32);
+                               ivideo->SiS_Pr.EMI_33 = SiS_GetReg(SISPART4, 0x33);
                                ivideo->SiS_Pr.HaveEMI = true;
                                if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
                                        ivideo->SiS_Pr.HaveEMILCD = true;
@@ -3483,8 +3488,8 @@ sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
         * ivideo->accel here, as this might have
         * been changed before this is called.
         */
-       inSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, cr30);
-       inSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, cr31);
+       cr30 = SiS_GetReg(SISSR, IND_SIS_PCI_ADDRESS_SET);
+       cr31 = SiS_GetReg(SISSR, IND_SIS_MODULE_ENABLE);
        /* MMIO and 2D/3D engine enabled? */
        if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
 #ifdef CONFIG_FB_SIS_300
@@ -3502,7 +3507,7 @@ sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
                         * enabled, and that the queue
                         * is not in the state of "reset"
                         */
-                       inSISIDXREG(SISSR, 0x26, cr30);
+                       cr30 = SiS_GetReg(SISSR, 0x26);
                        if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
                                sisfb_syncaccel(ivideo);
                        }
@@ -3519,9 +3524,9 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
 
        ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
 
-       outSISIDXREG(SISSR, 0x05, 0x86);
+       SiS_SetReg(SISSR, 0x05, 0x86);
 
-       inSISIDXREG(SISCR, 0x31, cr31);
+       cr31 = SiS_GetReg(SISCR, 0x31);
        cr31 &= ~0x60;
        cr31 |= 0x04;
 
@@ -3530,11 +3535,11 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
 #ifdef CONFIG_FB_SIS_315
        if(ivideo->sisvga_engine == SIS_315_VGA) {
           if(ivideo->chip >= SIS_661) {
-             inSISIDXREG(SISCR, 0x38, cr38);
+             cr38 = SiS_GetReg(SISCR, 0x38);
              cr38 &= ~0x07;  /* Clear LCDA/DualEdge and YPbPr bits */
           } else {
              tvregnum = 0x38;
-             inSISIDXREG(SISCR, tvregnum, cr38);
+             cr38 = SiS_GetReg(SISCR, tvregnum);
              cr38 &= ~0x3b;  /* Clear LCDA/DualEdge and YPbPr bits */
           }
        }
@@ -3542,7 +3547,7 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
 #ifdef CONFIG_FB_SIS_300
        if(ivideo->sisvga_engine == SIS_300_VGA) {
           tvregnum = 0x35;
-          inSISIDXREG(SISCR, tvregnum, cr38);
+          cr38 = SiS_GetReg(SISCR, tvregnum);
        }
 #endif
 
@@ -3649,20 +3654,20 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
              cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
        }
 
-       outSISIDXREG(SISCR, 0x30, cr30);
-       outSISIDXREG(SISCR, 0x33, cr33);
+       SiS_SetReg(SISCR, 0x30, cr30);
+       SiS_SetReg(SISCR, 0x33, cr33);
 
        if(ivideo->chip >= SIS_661) {
 #ifdef CONFIG_FB_SIS_315
           cr31 &= ~0x01;                          /* Clear PAL flag (now in CR35) */
-          setSISIDXREG(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
+          SiS_SetRegANDOR(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
           cr38 &= 0x07;                           /* Use only LCDA and HiVision/YPbPr bits */
-          setSISIDXREG(SISCR, 0x38, 0xf8, cr38);
+          SiS_SetRegANDOR(SISCR, 0x38, 0xf8, cr38);
 #endif
        } else if(ivideo->chip != SIS_300) {
-          outSISIDXREG(SISCR, tvregnum, cr38);
+          SiS_SetReg(SISCR, tvregnum, cr38);
        }
-       outSISIDXREG(SISCR, 0x31, cr31);
+       SiS_SetReg(SISCR, 0x31, cr31);
 
        ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
 
@@ -3677,15 +3682,15 @@ sisfb_fixup_SR11(struct sis_video_info *ivideo)
        u8  tmpreg;
 
        if(ivideo->chip >= SIS_661) {
-               inSISIDXREG(SISSR,0x11,tmpreg);
+               tmpreg = SiS_GetReg(SISSR, 0x11);
                if(tmpreg & 0x20) {
-                       inSISIDXREG(SISSR,0x3e,tmpreg);
+                       tmpreg = SiS_GetReg(SISSR, 0x3e);
                        tmpreg = (tmpreg + 1) & 0xff;
-                       outSISIDXREG(SISSR,0x3e,tmpreg);
-                       inSISIDXREG(SISSR,0x11,tmpreg);
+                       SiS_SetReg(SISSR, 0x3e, tmpreg);
+                       tmpreg = SiS_GetReg(SISSR, 0x11);
                }
                if(tmpreg & 0xf0) {
-                       andSISIDXREG(SISSR,0x11,0x0f);
+                       SiS_SetRegAND(SISSR, 0x11, 0x0f);
                }
        }
 }
@@ -3711,7 +3716,7 @@ sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
                        case 1:
                                x += val;
                                if(x < 0) x = 0;
-                               outSISIDXREG(SISSR,0x05,0x86);
+                               SiS_SetReg(SISSR, 0x05, 0x86);
                                SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff));
                                SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD);
                                break;
@@ -3740,11 +3745,11 @@ sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
                        temp += (val * 2);
                        p2_43 = temp & 0xff;
                        p2_42 = (temp & 0xf00) >> 4;
-                       outSISIDXREG(SISPART2,0x1f,p2_1f);
-                       setSISIDXREG(SISPART2,0x20,0x0F,p2_20);
-                       setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b);
-                       setSISIDXREG(SISPART2,0x42,0x0F,p2_42);
-                       outSISIDXREG(SISPART2,0x43,p2_43);
+                       SiS_SetReg(SISPART2, 0x1f, p2_1f);
+                       SiS_SetRegANDOR(SISPART2, 0x20, 0x0F, p2_20);
+                       SiS_SetRegANDOR(SISPART2, 0x2b, 0xF0, p2_2b);
+                       SiS_SetRegANDOR(SISPART2, 0x42, 0x0F, p2_42);
+                       SiS_SetReg(SISPART2, 0x43, p2_43);
                }
        }
 }
@@ -3769,7 +3774,7 @@ sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
                        case 1:
                                y -= val;
                                if(y < 0) y = 0;
-                               outSISIDXREG(SISSR,0x05,0x86);
+                               SiS_SetReg(SISSR, 0x05, 0x86);
                                SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff));
                                SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE);
                                break;
@@ -3793,8 +3798,8 @@ sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
                                        p2_02 += 2;
                                }
                        }
-                       outSISIDXREG(SISPART2,0x01,p2_01);
-                       outSISIDXREG(SISPART2,0x02,p2_02);
+                       SiS_SetReg(SISPART2, 0x01, p2_01);
+                       SiS_SetReg(SISPART2, 0x02, p2_02);
                }
        }
 }
@@ -3811,7 +3816,7 @@ sisfb_post_setmode(struct sis_video_info *ivideo)
        u8 reg1;
 #endif
 
-       outSISIDXREG(SISSR, 0x05, 0x86);
+       SiS_SetReg(SISSR, 0x05, 0x86);
 
 #ifdef CONFIG_FB_SIS_315
        sisfb_fixup_SR11(ivideo);
@@ -3835,7 +3840,7 @@ sisfb_post_setmode(struct sis_video_info *ivideo)
                        crt1isoff = false;
                        reg = 0x80;
                }
-               setSISIDXREG(SISCR, 0x17, 0x7f, reg);
+               SiS_SetRegANDOR(SISCR, 0x17, 0x7f, reg);
        }
 #endif
 #ifdef CONFIG_FB_SIS_315
@@ -3849,8 +3854,8 @@ sisfb_post_setmode(struct sis_video_info *ivideo)
                        reg  = 0x00;
                        reg1 = 0x00;
                }
-               setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
-               setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1);
+               SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
+               SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, reg1);
        }
 #endif
 
@@ -3866,17 +3871,17 @@ sisfb_post_setmode(struct sis_video_info *ivideo)
                }
        }
 
-       andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
+       SiS_SetRegAND(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
 
        if(ivideo->currentvbflags & CRT2_TV) {
                if(ivideo->vbflags2 & VB2_SISBRIDGE) {
-                       inSISIDXREG(SISPART2,0x1f,ivideo->p2_1f);
-                       inSISIDXREG(SISPART2,0x20,ivideo->p2_20);
-                       inSISIDXREG(SISPART2,0x2b,ivideo->p2_2b);
-                       inSISIDXREG(SISPART2,0x42,ivideo->p2_42);
-                       inSISIDXREG(SISPART2,0x43,ivideo->p2_43);
-                       inSISIDXREG(SISPART2,0x01,ivideo->p2_01);
-                       inSISIDXREG(SISPART2,0x02,ivideo->p2_02);
+                       ivideo->p2_1f = SiS_GetReg(SISPART2, 0x1f);
+                       ivideo->p2_20 = SiS_GetReg(SISPART2, 0x20);
+                       ivideo->p2_2b = SiS_GetReg(SISPART2, 0x2b);
+                       ivideo->p2_42 = SiS_GetReg(SISPART2, 0x42);
+                       ivideo->p2_43 = SiS_GetReg(SISPART2, 0x43);
+                       ivideo->p2_01 = SiS_GetReg(SISPART2, 0x01);
+                       ivideo->p2_02 = SiS_GetReg(SISPART2, 0x02);
                } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
                        if(ivideo->chronteltype == 1) {
                                ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
@@ -4100,7 +4105,6 @@ sisfb_find_rom(struct pci_dev *pdev)
        struct sis_video_info *ivideo = pci_get_drvdata(pdev);
        void __iomem *rom_base;
        unsigned char *myrombase = NULL;
-       u32 temp;
        size_t romsize;
 
        /* First, try the official pci ROM functions (except
@@ -4114,14 +4118,6 @@ sisfb_find_rom(struct pci_dev *pdev)
                        if(sisfb_check_rom(rom_base, ivideo)) {
 
                                if((myrombase = vmalloc(65536))) {
-
-                                       /* Work around bug in pci/rom.c: Folks forgot to check
-                                        * whether the size retrieved from the BIOS image eventually
-                                        * is larger than the mapped size
-                                        */
-                                       if(pci_resource_len(pdev, PCI_ROM_RESOURCE) < romsize)
-                                               romsize = pci_resource_len(pdev, PCI_ROM_RESOURCE);
-
                                        memcpy_fromio(myrombase, rom_base,
                                                        (romsize > 65536) ? 65536 : romsize);
                                }
@@ -4135,43 +4131,29 @@ sisfb_find_rom(struct pci_dev *pdev)
        /* Otherwise do it the conventional way. */
 
 #if defined(__i386__) || defined(__x86_64__)
+       {
+               u32 temp;
 
-       for(temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
+               for (temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
 
-               rom_base = ioremap(temp, 65536);
-               if(!rom_base)
-                       continue;
+                       rom_base = ioremap(temp, 65536);
+                       if (!rom_base)
+                               continue;
 
-               if(!sisfb_check_rom(rom_base, ivideo)) {
-                       iounmap(rom_base);
-                       continue;
-               }
-
-               if((myrombase = vmalloc(65536)))
-                       memcpy_fromio(myrombase, rom_base, 65536);
-
-               iounmap(rom_base);
-               break;
-
-        }
+                       if (!sisfb_check_rom(rom_base, ivideo)) {
+                               iounmap(rom_base);
+                               continue;
+                       }
 
-#else
+                       if ((myrombase = vmalloc(65536)))
+                               memcpy_fromio(myrombase, rom_base, 65536);
 
-       pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &temp);
-       pci_write_config_dword(pdev, PCI_ROM_ADDRESS,
-                       (ivideo->video_base & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE);
+                       iounmap(rom_base);
+                       break;
 
-       rom_base = ioremap(ivideo->video_base, 65536);
-       if(rom_base) {
-               if(sisfb_check_rom(rom_base, ivideo)) {
-                       if((myrombase = vmalloc(65536)))
-                               memcpy_fromio(myrombase, rom_base, 65536);
                }
-               iounmap(rom_base);
-       }
-
-       pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp);
 
+       }
 #endif
 
        return myrombase;
@@ -4212,10 +4194,10 @@ sisfb_post_300_buswidth(struct sis_video_info *ivideo)
        unsigned char reg;
        int i, j;
 
-       andSISIDXREG(SISSR, 0x15, 0xFB);
-       orSISIDXREG(SISSR, 0x15, 0x04);
-       outSISIDXREG(SISSR, 0x13, 0x00);
-       outSISIDXREG(SISSR, 0x14, 0xBF);
+       SiS_SetRegAND(SISSR, 0x15, 0xFB);
+       SiS_SetRegOR(SISSR, 0x15, 0x04);
+       SiS_SetReg(SISSR, 0x13, 0x00);
+       SiS_SetReg(SISSR, 0x14, 0xBF);
 
        for(i = 0; i < 2; i++) {
                temp = 0x1234;
@@ -4223,12 +4205,12 @@ sisfb_post_300_buswidth(struct sis_video_info *ivideo)
                        writew(temp, FBAddress);
                        if(readw(FBAddress) == temp)
                                break;
-                       orSISIDXREG(SISSR, 0x3c, 0x01);
-                       inSISIDXREG(SISSR, 0x05, reg);
-                       inSISIDXREG(SISSR, 0x05, reg);
-                       andSISIDXREG(SISSR, 0x3c, 0xfe);
-                       inSISIDXREG(SISSR, 0x05, reg);
-                       inSISIDXREG(SISSR, 0x05, reg);
+                       SiS_SetRegOR(SISSR, 0x3c, 0x01);
+                       reg = SiS_GetReg(SISSR, 0x05);
+                       reg = SiS_GetReg(SISSR, 0x05);
+                       SiS_SetRegAND(SISSR, 0x3c, 0xfe);
+                       reg = SiS_GetReg(SISSR, 0x05);
+                       reg = SiS_GetReg(SISSR, 0x05);
                        temp++;
                }
        }
@@ -4238,7 +4220,7 @@ sisfb_post_300_buswidth(struct sis_video_info *ivideo)
        writel(0x89ABCDEFL, (FBAddress + 8));
        writel(0xCDEF0123L, (FBAddress + 12));
 
-       inSISIDXREG(SISSR, 0x3b, reg);
+       reg = SiS_GetReg(SISSR, 0x3b);
        if(reg & 0x01) {
                if(readl((FBAddress + 12)) == 0xCDEF0123L)
                        return 4;       /* Channel A 128bit */
@@ -4301,13 +4283,13 @@ sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth
                PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
                PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
 
-               andSISIDXREG(SISSR, 0x15, 0xFB); /* Test */
-               orSISIDXREG(SISSR, 0x15, 0x04);  /* Test */
+               SiS_SetRegAND(SISSR, 0x15, 0xFB); /* Test */
+               SiS_SetRegOR(SISSR, 0x15, 0x04);  /* Test */
                sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
                if(buswidth == 4)      sr14 |= 0x80;
                else if(buswidth == 2) sr14 |= 0x40;
-               outSISIDXREG(SISSR, 0x13, SiS_DRAMType[k][4]);
-               outSISIDXREG(SISSR, 0x14, sr14);
+               SiS_SetReg(SISSR, 0x13, SiS_DRAMType[k][4]);
+               SiS_SetReg(SISSR, 0x14, sr14);
 
                BankNumHigh <<= 16;
                BankNumMid <<= 16;
@@ -4374,13 +4356,13 @@ sisfb_post_sis300(struct pci_dev *pdev)
        if(!ivideo->SiS_Pr.UseROM)
                bios = NULL;
 
-       outSISIDXREG(SISSR, 0x05, 0x86);
+       SiS_SetReg(SISSR, 0x05, 0x86);
 
        if(bios) {
                if(bios[0x52] & 0x80) {
                        memtype = bios[0x52];
                } else {
-                       inSISIDXREG(SISSR, 0x3a, memtype);
+                       memtype = SiS_GetReg(SISSR, 0x3a);
                }
                memtype &= 0x07;
        }
@@ -4404,19 +4386,19 @@ sisfb_post_sis300(struct pci_dev *pdev)
                        v6 = bios[rindex++];
                }
        }
-       outSISIDXREG(SISSR, 0x28, v1);
-       outSISIDXREG(SISSR, 0x29, v2);
-       outSISIDXREG(SISSR, 0x2a, v3);
-       outSISIDXREG(SISSR, 0x2e, v4);
-       outSISIDXREG(SISSR, 0x2f, v5);
-       outSISIDXREG(SISSR, 0x30, v6);
+       SiS_SetReg(SISSR, 0x28, v1);
+       SiS_SetReg(SISSR, 0x29, v2);
+       SiS_SetReg(SISSR, 0x2a, v3);
+       SiS_SetReg(SISSR, 0x2e, v4);
+       SiS_SetReg(SISSR, 0x2f, v5);
+       SiS_SetReg(SISSR, 0x30, v6);
 
        v1 = 0x10;
        if(bios)
                v1 = bios[0xa4];
-       outSISIDXREG(SISSR, 0x07, v1);       /* DAC speed */
+       SiS_SetReg(SISSR, 0x07, v1);       /* DAC speed */
 
-       outSISIDXREG(SISSR, 0x11, 0x0f);     /* DDC, power save */
+       SiS_SetReg(SISSR, 0x11, 0x0f);     /* DDC, power save */
 
        v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
        v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
@@ -4433,87 +4415,87 @@ sisfb_post_sis300(struct pci_dev *pdev)
        }
        if(ivideo->revision_id >= 0x80)
                v3 &= 0xfd;
-       outSISIDXREG(SISSR, 0x15, v1);       /* Ram type (assuming 0, BIOS 0xa5 step 8) */
-       outSISIDXREG(SISSR, 0x16, v2);
-       outSISIDXREG(SISSR, 0x17, v3);
-       outSISIDXREG(SISSR, 0x18, v4);
-       outSISIDXREG(SISSR, 0x19, v5);
-       outSISIDXREG(SISSR, 0x1a, v6);
-       outSISIDXREG(SISSR, 0x1b, v7);
-       outSISIDXREG(SISSR, 0x1c, v8);     /* ---- */
-       andSISIDXREG(SISSR, 0x15 ,0xfb);
-       orSISIDXREG(SISSR, 0x15, 0x04);
+       SiS_SetReg(SISSR, 0x15, v1);       /* Ram type (assuming 0, BIOS 0xa5 step 8) */
+       SiS_SetReg(SISSR, 0x16, v2);
+       SiS_SetReg(SISSR, 0x17, v3);
+       SiS_SetReg(SISSR, 0x18, v4);
+       SiS_SetReg(SISSR, 0x19, v5);
+       SiS_SetReg(SISSR, 0x1a, v6);
+       SiS_SetReg(SISSR, 0x1b, v7);
+       SiS_SetReg(SISSR, 0x1c, v8);       /* ---- */
+       SiS_SetRegAND(SISSR, 0x15, 0xfb);
+       SiS_SetRegOR(SISSR, 0x15, 0x04);
        if(bios) {
                if(bios[0x53] & 0x02) {
-                       orSISIDXREG(SISSR, 0x19, 0x20);
+                       SiS_SetRegOR(SISSR, 0x19, 0x20);
                }
        }
        v1 = 0x04;                         /* DAC pedestal (BIOS 0xe5) */
        if(ivideo->revision_id >= 0x80)
                v1 |= 0x01;
-       outSISIDXREG(SISSR, 0x1f, v1);
-       outSISIDXREG(SISSR, 0x20, 0xa4);     /* linear & relocated io & disable a0000 */
+       SiS_SetReg(SISSR, 0x1f, v1);
+       SiS_SetReg(SISSR, 0x20, 0xa4);     /* linear & relocated io & disable a0000 */
        v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
        if(bios) {
                v1 = bios[0xe8];
                v2 = bios[0xe9];
                v3 = bios[0xea];
        }
-       outSISIDXREG(SISSR, 0x23, v1);
-       outSISIDXREG(SISSR, 0x24, v2);
-       outSISIDXREG(SISSR, 0x25, v3);
-       outSISIDXREG(SISSR, 0x21, 0x84);
-       outSISIDXREG(SISSR, 0x22, 0x00);
-       outSISIDXREG(SISCR, 0x37, 0x00);
-       orSISIDXREG(SISPART1, 0x24, 0x01);   /* unlock crt2 */
-       outSISIDXREG(SISPART1, 0x00, 0x00);
+       SiS_SetReg(SISSR, 0x23, v1);
+       SiS_SetReg(SISSR, 0x24, v2);
+       SiS_SetReg(SISSR, 0x25, v3);
+       SiS_SetReg(SISSR, 0x21, 0x84);
+       SiS_SetReg(SISSR, 0x22, 0x00);
+       SiS_SetReg(SISCR, 0x37, 0x00);
+       SiS_SetRegOR(SISPART1, 0x24, 0x01);   /* unlock crt2 */
+       SiS_SetReg(SISPART1, 0x00, 0x00);
        v1 = 0x40; v2 = 0x11;
        if(bios) {
                v1 = bios[0xec];
                v2 = bios[0xeb];
        }
-       outSISIDXREG(SISPART1, 0x02, v1);
+       SiS_SetReg(SISPART1, 0x02, v1);
 
        if(ivideo->revision_id >= 0x80)
                v2 &= ~0x01;
 
-       inSISIDXREG(SISPART4, 0x00, reg);
+       reg = SiS_GetReg(SISPART4, 0x00);
        if((reg == 1) || (reg == 2)) {
-               outSISIDXREG(SISCR, 0x37, 0x02);
-               outSISIDXREG(SISPART2, 0x00, 0x1c);
+               SiS_SetReg(SISCR, 0x37, 0x02);
+               SiS_SetReg(SISPART2, 0x00, 0x1c);
                v4 = 0x00; v5 = 0x00; v6 = 0x10;
                if(ivideo->SiS_Pr.UseROM) {
                        v4 = bios[0xf5];
                        v5 = bios[0xf6];
                        v6 = bios[0xf7];
                }
-               outSISIDXREG(SISPART4, 0x0d, v4);
-               outSISIDXREG(SISPART4, 0x0e, v5);
-               outSISIDXREG(SISPART4, 0x10, v6);
-               outSISIDXREG(SISPART4, 0x0f, 0x3f);
-               inSISIDXREG(SISPART4, 0x01, reg);
+               SiS_SetReg(SISPART4, 0x0d, v4);
+               SiS_SetReg(SISPART4, 0x0e, v5);
+               SiS_SetReg(SISPART4, 0x10, v6);
+               SiS_SetReg(SISPART4, 0x0f, 0x3f);
+               reg = SiS_GetReg(SISPART4, 0x01);
                if(reg >= 0xb0) {
-                       inSISIDXREG(SISPART4, 0x23, reg);
+                       reg = SiS_GetReg(SISPART4, 0x23);
                        reg &= 0x20;
                        reg <<= 1;
-                       outSISIDXREG(SISPART4, 0x23, reg);
+                       SiS_SetReg(SISPART4, 0x23, reg);
                }
        } else {
                v2 &= ~0x10;
        }
-       outSISIDXREG(SISSR, 0x32, v2);
+       SiS_SetReg(SISSR, 0x32, v2);
 
-       andSISIDXREG(SISPART1, 0x24, 0xfe);  /* Lock CRT2 */
+       SiS_SetRegAND(SISPART1, 0x24, 0xfe);  /* Lock CRT2 */
 
-       inSISIDXREG(SISSR, 0x16, reg);
+       reg = SiS_GetReg(SISSR, 0x16);
        reg &= 0xc3;
-       outSISIDXREG(SISCR, 0x35, reg);
-       outSISIDXREG(SISCR, 0x83, 0x00);
+       SiS_SetReg(SISCR, 0x35, reg);
+       SiS_SetReg(SISCR, 0x83, 0x00);
 #if !defined(__i386__) && !defined(__x86_64__)
        if(sisfb_videoram) {
-               outSISIDXREG(SISSR, 0x13, 0x28);  /* ? */
+               SiS_SetReg(SISSR, 0x13, 0x28);  /* ? */
                reg = ((sisfb_videoram >> 10) - 1) | 0x40;
-               outSISIDXREG(SISSR, 0x14, reg);
+               SiS_SetReg(SISSR, 0x14, reg);
        } else {
 #endif
                /* Need to map max FB size for finding out about RAM size */
@@ -4526,8 +4508,8 @@ sisfb_post_sis300(struct pci_dev *pdev)
                } else {
                        printk(KERN_DEBUG
                                "sisfb: Failed to map memory for size detection, assuming 8MB\n");
-                       outSISIDXREG(SISSR, 0x13, 0x28);  /* ? */
-                       outSISIDXREG(SISSR, 0x14, 0x47);  /* 8MB, 64bit default */
+                       SiS_SetReg(SISSR, 0x13, 0x28);  /* ? */
+                       SiS_SetReg(SISSR, 0x14, 0x47);  /* 8MB, 64bit default */
                }
 #if !defined(__i386__) && !defined(__x86_64__)
        }
@@ -4536,7 +4518,7 @@ sisfb_post_sis300(struct pci_dev *pdev)
                v1 = bios[0xe6];
                v2 = bios[0xe7];
        } else {
-               inSISIDXREG(SISSR, 0x3a, reg);
+               reg = SiS_GetReg(SISSR, 0x3a);
                if((reg & 0x30) == 0x30) {
                        v1 = 0x04; /* PCI */
                        v2 = 0x92;
@@ -4545,8 +4527,8 @@ sisfb_post_sis300(struct pci_dev *pdev)
                        v2 = 0xb2;
                }
        }
-       outSISIDXREG(SISSR, 0x21, v1);
-       outSISIDXREG(SISSR, 0x22, v2);
+       SiS_SetReg(SISSR, 0x21, v1);
+       SiS_SetReg(SISSR, 0x22, v2);
 
        /* Sense CRT1 */
        sisfb_sense_crt1(ivideo);
@@ -4559,13 +4541,13 @@ sisfb_post_sis300(struct pci_dev *pdev)
        ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
        SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
 
-       outSISIDXREG(SISSR, 0x05, 0x86);
+       SiS_SetReg(SISSR, 0x05, 0x86);
 
        /* Display off */
-       orSISIDXREG(SISSR, 0x01, 0x20);
+       SiS_SetRegOR(SISSR, 0x01, 0x20);
 
        /* Save mode number in CR34 */
-       outSISIDXREG(SISCR, 0x34, 0x2e);
+       SiS_SetReg(SISCR, 0x34, 0x2e);
 
        /* Let everyone know what the current mode is */
        ivideo->modeprechange = 0x2e;
@@ -4588,7 +4570,7 @@ sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
        u8 reg;
 
        for(i = 0; i <= (delay * 10 * 36); i++) {
-               inSISIDXREG(SISSR, 0x05, reg);
+               reg = SiS_GetReg(SISSR, 0x05);
                reg++;
        }
 }
@@ -4680,7 +4662,7 @@ sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
         * - if running on non-x86, there usually is no VGA window
         *   at a0000.
         */
-       orSISIDXREG(SISSR, 0x20, (0x80 | 0x04));
+       SiS_SetRegOR(SISSR, 0x20, (0x80 | 0x04));
 
        /* Need to map max FB size for finding out about RAM size */
        mapsize = ivideo->video_size;
@@ -4688,76 +4670,76 @@ sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
 
        if(!ivideo->video_vbase) {
                printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
-               outSISIDXREG(SISSR, 0x13, 0x35);
-               outSISIDXREG(SISSR, 0x14, 0x41);
+               SiS_SetReg(SISSR, 0x13, 0x35);
+               SiS_SetReg(SISSR, 0x14, 0x41);
                /* TODO */
                return;
        }
 
        /* Non-interleaving */
-       outSISIDXREG(SISSR, 0x15, 0x00);
+       SiS_SetReg(SISSR, 0x15, 0x00);
        /* No tiling */
-       outSISIDXREG(SISSR, 0x1c, 0x00);
+       SiS_SetReg(SISSR, 0x1c, 0x00);
 
        if(ivideo->chip == XGI_20) {
 
                channelab = 1;
-               inSISIDXREG(SISCR, 0x97, reg);
+               reg = SiS_GetReg(SISCR, 0x97);
                if(!(reg & 0x01)) {     /* Single 32/16 */
                        buswidth = 32;
-                       outSISIDXREG(SISSR, 0x13, 0xb1);
-                       outSISIDXREG(SISSR, 0x14, 0x52);
+                       SiS_SetReg(SISSR, 0x13, 0xb1);
+                       SiS_SetReg(SISSR, 0x14, 0x52);
                        sisfb_post_xgi_delay(ivideo, 1);
                        sr14 = 0x02;
                        if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
                                goto bail_out;
 
-                       outSISIDXREG(SISSR, 0x13, 0x31);
-                       outSISIDXREG(SISSR, 0x14, 0x42);
+                       SiS_SetReg(SISSR, 0x13, 0x31);
+                       SiS_SetReg(SISSR, 0x14, 0x42);
                        sisfb_post_xgi_delay(ivideo, 1);
                        if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize))
                                goto bail_out;
 
                        buswidth = 16;
-                       outSISIDXREG(SISSR, 0x13, 0xb1);
-                       outSISIDXREG(SISSR, 0x14, 0x41);
+                       SiS_SetReg(SISSR, 0x13, 0xb1);
+                       SiS_SetReg(SISSR, 0x14, 0x41);
                        sisfb_post_xgi_delay(ivideo, 1);
                        sr14 = 0x01;
                        if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
                                goto bail_out;
                        else
-                               outSISIDXREG(SISSR, 0x13, 0x31);
+                               SiS_SetReg(SISSR, 0x13, 0x31);
                } else {                /* Dual 16/8 */
                        buswidth = 16;
-                       outSISIDXREG(SISSR, 0x13, 0xb1);
-                       outSISIDXREG(SISSR, 0x14, 0x41);
+                       SiS_SetReg(SISSR, 0x13, 0xb1);
+                       SiS_SetReg(SISSR, 0x14, 0x41);
                        sisfb_post_xgi_delay(ivideo, 1);
                        sr14 = 0x01;
                        if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
                                goto bail_out;
 
-                       outSISIDXREG(SISSR, 0x13, 0x31);
-                       outSISIDXREG(SISSR, 0x14, 0x31);
+                       SiS_SetReg(SISSR, 0x13, 0x31);
+                       SiS_SetReg(SISSR, 0x14, 0x31);
                        sisfb_post_xgi_delay(ivideo, 1);
                        if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize))
                                goto bail_out;
 
                        buswidth = 8;
-                       outSISIDXREG(SISSR, 0x13, 0xb1);
-                       outSISIDXREG(SISSR, 0x14, 0x30);
+                       SiS_SetReg(SISSR, 0x13, 0xb1);
+                       SiS_SetReg(SISSR, 0x14, 0x30);
                        sisfb_post_xgi_delay(ivideo, 1);
                        sr14 = 0x00;
                        if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize))
                                goto bail_out;
                        else
-                               outSISIDXREG(SISSR, 0x13, 0x31);
+                               SiS_SetReg(SISSR, 0x13, 0x31);
                }
 
        } else {        /* XGI_40 */
 
-               inSISIDXREG(SISCR, 0x97, reg);
+               reg = SiS_GetReg(SISCR, 0x97);
                if(!(reg & 0x10)) {
-                       inSISIDXREG(SISSR, 0x39, reg);
+                       reg = SiS_GetReg(SISSR, 0x39);
                        reg >>= 1;
                }
 
@@ -4765,52 +4747,52 @@ sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
                        buswidth = 32;
                        if(ivideo->revision_id == 2) {
                                channelab = 2;
-                               outSISIDXREG(SISSR, 0x13, 0xa1);
-                               outSISIDXREG(SISSR, 0x14, 0x44);
+                               SiS_SetReg(SISSR, 0x13, 0xa1);
+                               SiS_SetReg(SISSR, 0x14, 0x44);
                                sr14 = 0x04;
                                sisfb_post_xgi_delay(ivideo, 1);
                                if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
                                        goto bail_out;
 
-                               outSISIDXREG(SISSR, 0x13, 0x21);
-                               outSISIDXREG(SISSR, 0x14, 0x34);
+                               SiS_SetReg(SISSR, 0x13, 0x21);
+                               SiS_SetReg(SISSR, 0x14, 0x34);
                                if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
                                        goto bail_out;
 
                                channelab = 1;
-                               outSISIDXREG(SISSR, 0x13, 0xa1);
-                               outSISIDXREG(SISSR, 0x14, 0x40);
+                               SiS_SetReg(SISSR, 0x13, 0xa1);
+                               SiS_SetReg(SISSR, 0x14, 0x40);
                                sr14 = 0x00;
                                if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
                                        goto bail_out;
 
-                               outSISIDXREG(SISSR, 0x13, 0x21);
-                               outSISIDXREG(SISSR, 0x14, 0x30);
+                               SiS_SetReg(SISSR, 0x13, 0x21);
+                               SiS_SetReg(SISSR, 0x14, 0x30);
                        } else {
                                channelab = 3;
-                               outSISIDXREG(SISSR, 0x13, 0xa1);
-                               outSISIDXREG(SISSR, 0x14, 0x4c);
+                               SiS_SetReg(SISSR, 0x13, 0xa1);
+                               SiS_SetReg(SISSR, 0x14, 0x4c);
                                sr14 = 0x0c;
                                sisfb_post_xgi_delay(ivideo, 1);
                                if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize))
                                        goto bail_out;
 
                                channelab = 2;
-                               outSISIDXREG(SISSR, 0x14, 0x48);
+                               SiS_SetReg(SISSR, 0x14, 0x48);
                                sisfb_post_xgi_delay(ivideo, 1);
                                sr14 = 0x08;
                                if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
                                        goto bail_out;
 
-                               outSISIDXREG(SISSR, 0x13, 0x21);
-                               outSISIDXREG(SISSR, 0x14, 0x3c);
+                               SiS_SetReg(SISSR, 0x13, 0x21);
+                               SiS_SetReg(SISSR, 0x14, 0x3c);
                                sr14 = 0x0c;
 
                                if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) {
                                        channelab = 3;
                                } else {
                                        channelab = 2;
-                                       outSISIDXREG(SISSR, 0x14, 0x38);
+                                       SiS_SetReg(SISSR, 0x14, 0x38);
                                        sr14 = 0x08;
                                }
                        }
@@ -4821,26 +4803,26 @@ sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
                        buswidth = 64;
                        if(ivideo->revision_id == 2) {
                                channelab = 1;
-                               outSISIDXREG(SISSR, 0x13, 0xa1);
-                               outSISIDXREG(SISSR, 0x14, 0x52);
+                               SiS_SetReg(SISSR, 0x13, 0xa1);
+                               SiS_SetReg(SISSR, 0x14, 0x52);
                                sisfb_post_xgi_delay(ivideo, 1);
                                sr14 = 0x02;
                                if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
                                        goto bail_out;
 
-                               outSISIDXREG(SISSR, 0x13, 0x21);
-                               outSISIDXREG(SISSR, 0x14, 0x42);
+                               SiS_SetReg(SISSR, 0x13, 0x21);
+                               SiS_SetReg(SISSR, 0x14, 0x42);
                        } else {
                                channelab = 2;
-                               outSISIDXREG(SISSR, 0x13, 0xa1);
-                               outSISIDXREG(SISSR, 0x14, 0x5a);
+                               SiS_SetReg(SISSR, 0x13, 0xa1);
+                               SiS_SetReg(SISSR, 0x14, 0x5a);
                                sisfb_post_xgi_delay(ivideo, 1);
                                sr14 = 0x0a;
                                if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize))
                                        goto bail_out;
 
-                               outSISIDXREG(SISSR, 0x13, 0x21);
-                               outSISIDXREG(SISSR, 0x14, 0x4a);
+                               SiS_SetReg(SISSR, 0x13, 0x21);
+                               SiS_SetReg(SISSR, 0x14, 0x4a);
                        }
                        sisfb_post_xgi_delay(ivideo, 1);
 
@@ -4848,7 +4830,7 @@ sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
        }
 
 bail_out:
-       setSISIDXREG(SISSR, 0x14, 0xf0, sr14);
+       SiS_SetRegANDOR(SISSR, 0x14, 0xf0, sr14);
        sisfb_post_xgi_delay(ivideo, 1);
 
        j = (ivideo->chip == XGI_20) ? 5 : 9;
@@ -4858,13 +4840,13 @@ bail_out:
 
                reg = (ivideo->chip == XGI_20) ?
                                dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
-               setSISIDXREG(SISSR, 0x13, 0x80, reg);
+               SiS_SetRegANDOR(SISSR, 0x13, 0x80, reg);
                sisfb_post_xgi_delay(ivideo, 50);
 
                ranksize = (ivideo->chip == XGI_20) ?
                                dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
 
-               inSISIDXREG(SISSR, 0x13, reg);
+               reg = SiS_GetReg(SISSR, 0x13);
                if(reg & 0x80) ranksize <<= 1;
 
                if(ivideo->chip == XGI_20) {
@@ -4883,7 +4865,7 @@ bail_out:
 
                if(!reg) continue;
 
-               setSISIDXREG(SISSR, 0x14, 0x0f, (reg & 0xf0));
+               SiS_SetRegANDOR(SISSR, 0x14, 0x0f, (reg & 0xf0));
                sisfb_post_xgi_delay(ivideo, 1);
 
                if(sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize))
@@ -4928,9 +4910,9 @@ sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
                v2 = ivideo->bios_abase[0x90 + index + 1];
                v3 = ivideo->bios_abase[0x90 + index + 2];
        }
-       outSISIDXREG(SISSR, 0x28, v1);
-       outSISIDXREG(SISSR, 0x29, v2);
-       outSISIDXREG(SISSR, 0x2a, v3);
+       SiS_SetReg(SISSR, 0x28, v1);
+       SiS_SetReg(SISSR, 0x29, v2);
+       SiS_SetReg(SISSR, 0x2a, v3);
        sisfb_post_xgi_delay(ivideo, 0x43);
        sisfb_post_xgi_delay(ivideo, 0x43);
        sisfb_post_xgi_delay(ivideo, 0x43);
@@ -4941,9 +4923,9 @@ sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
                v2 = ivideo->bios_abase[0xb8 + index + 1];
                v3 = ivideo->bios_abase[0xb8 + index + 2];
        }
-       outSISIDXREG(SISSR, 0x2e, v1);
-       outSISIDXREG(SISSR, 0x2f, v2);
-       outSISIDXREG(SISSR, 0x30, v3);
+       SiS_SetReg(SISSR, 0x2e, v1);
+       SiS_SetReg(SISSR, 0x2f, v2);
+       SiS_SetReg(SISSR, 0x30, v3);
        sisfb_post_xgi_delay(ivideo, 0x43);
        sisfb_post_xgi_delay(ivideo, 0x43);
        sisfb_post_xgi_delay(ivideo, 0x43);
@@ -5016,29 +4998,29 @@ sisfb_post_xgi(struct pci_dev *pdev)
        };
 
        /* VGA enable */
-       reg = inSISREG(SISVGAENABLE) | 0x01;
-       outSISREG(SISVGAENABLE, reg);
+       reg = SiS_GetRegByte(SISVGAENABLE) | 0x01;
+       SiS_SetRegByte(SISVGAENABLE, reg);
 
        /* Misc */
-       reg = inSISREG(SISMISCR) | 0x01;
-       outSISREG(SISMISCW, reg);
+       reg = SiS_GetRegByte(SISMISCR) | 0x01;
+       SiS_SetRegByte(SISMISCW, reg);
 
        /* Unlock SR */
-       outSISIDXREG(SISSR, 0x05, 0x86);
-       inSISIDXREG(SISSR, 0x05, reg);
+       SiS_SetReg(SISSR, 0x05, 0x86);
+       reg = SiS_GetReg(SISSR, 0x05);
        if(reg != 0xa1)
                return 0;
 
        /* Clear some regs */
        for(i = 0; i < 0x22; i++) {
                if(0x06 + i == 0x20) continue;
-               outSISIDXREG(SISSR, 0x06 + i, 0x00);
+               SiS_SetReg(SISSR, 0x06 + i, 0x00);
        }
        for(i = 0; i < 0x0b; i++) {
-               outSISIDXREG(SISSR, 0x31 + i, 0x00);
+               SiS_SetReg(SISSR, 0x31 + i, 0x00);
        }
        for(i = 0; i < 0x10; i++) {
-               outSISIDXREG(SISCR, 0x30 + i, 0x00);
+               SiS_SetReg(SISCR, 0x30 + i, 0x00);
        }
 
        ptr = cs78;
@@ -5046,7 +5028,7 @@ sisfb_post_xgi(struct pci_dev *pdev)
                ptr = (const u8 *)&bios[0x78];
        }
        for(i = 0; i < 3; i++) {
-               outSISIDXREG(SISSR, 0x23 + i, ptr[i]);
+               SiS_SetReg(SISSR, 0x23 + i, ptr[i]);
        }
 
        ptr = cs76;
@@ -5054,7 +5036,7 @@ sisfb_post_xgi(struct pci_dev *pdev)
                ptr = (const u8 *)&bios[0x76];
        }
        for(i = 0; i < 2; i++) {
-               outSISIDXREG(SISSR, 0x21 + i, ptr[i]);
+               SiS_SetReg(SISSR, 0x21 + i, ptr[i]);
        }
 
        v1 = 0x18; v2 = 0x00;
@@ -5062,83 +5044,83 @@ sisfb_post_xgi(struct pci_dev *pdev)
                v1 = bios[0x74];
                v2 = bios[0x75];
        }
-       outSISIDXREG(SISSR, 0x07, v1);
-       outSISIDXREG(SISSR, 0x11, 0x0f);
-       outSISIDXREG(SISSR, 0x1f, v2);
+       SiS_SetReg(SISSR, 0x07, v1);
+       SiS_SetReg(SISSR, 0x11, 0x0f);
+       SiS_SetReg(SISSR, 0x1f, v2);
        /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
-       outSISIDXREG(SISSR, 0x20, 0x80 | 0x20 | 0x04);
-       outSISIDXREG(SISSR, 0x27, 0x74);
+       SiS_SetReg(SISSR, 0x20, 0x80 | 0x20 | 0x04);
+       SiS_SetReg(SISSR, 0x27, 0x74);
 
        ptr = cs7b;
        if(ivideo->haveXGIROM) {
                ptr = (const u8 *)&bios[0x7b];
        }
        for(i = 0; i < 3; i++) {
-               outSISIDXREG(SISSR, 0x31 + i, ptr[i]);
+               SiS_SetReg(SISSR, 0x31 + i, ptr[i]);
        }
 
        if(ivideo->chip == XGI_40) {
                if(ivideo->revision_id == 2) {
-                       setSISIDXREG(SISSR, 0x3b, 0x3f, 0xc0);
+                       SiS_SetRegANDOR(SISSR, 0x3b, 0x3f, 0xc0);
                }
-               outSISIDXREG(SISCR, 0x7d, 0xfe);
-               outSISIDXREG(SISCR, 0x7e, 0x0f);
+               SiS_SetReg(SISCR, 0x7d, 0xfe);
+               SiS_SetReg(SISCR, 0x7e, 0x0f);
        }
        if(ivideo->revision_id == 0) {  /* 40 *and* 20? */
-               andSISIDXREG(SISCR, 0x58, 0xd7);
-               inSISIDXREG(SISCR, 0xcb, reg);
+               SiS_SetRegAND(SISCR, 0x58, 0xd7);
+               reg = SiS_GetReg(SISCR, 0xcb);
                if(reg & 0x20) {
-                       setSISIDXREG(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
+                       SiS_SetRegANDOR(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
                }
        }
 
        reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
-       setSISIDXREG(SISCR, 0x38, 0x1f, reg);
+       SiS_SetRegANDOR(SISCR, 0x38, 0x1f, reg);
 
        if(ivideo->chip == XGI_20) {
-               outSISIDXREG(SISSR, 0x36, 0x70);
+               SiS_SetReg(SISSR, 0x36, 0x70);
        } else {
-               outSISIDXREG(SISVID, 0x00, 0x86);
-               outSISIDXREG(SISVID, 0x32, 0x00);
-               outSISIDXREG(SISVID, 0x30, 0x00);
-               outSISIDXREG(SISVID, 0x32, 0x01);
-               outSISIDXREG(SISVID, 0x30, 0x00);
-               andSISIDXREG(SISVID, 0x2f, 0xdf);
-               andSISIDXREG(SISCAP, 0x00, 0x3f);
-
-               outSISIDXREG(SISPART1, 0x2f, 0x01);
-               outSISIDXREG(SISPART1, 0x00, 0x00);
-               outSISIDXREG(SISPART1, 0x02, bios[0x7e]);
-               outSISIDXREG(SISPART1, 0x2e, 0x08);
-               andSISIDXREG(SISPART1, 0x35, 0x7f);
-               andSISIDXREG(SISPART1, 0x50, 0xfe);
-
-               inSISIDXREG(SISPART4, 0x00, reg);
+               SiS_SetReg(SISVID, 0x00, 0x86);
+               SiS_SetReg(SISVID, 0x32, 0x00);
+               SiS_SetReg(SISVID, 0x30, 0x00);
+               SiS_SetReg(SISVID, 0x32, 0x01);
+               SiS_SetReg(SISVID, 0x30, 0x00);
+               SiS_SetRegAND(SISVID, 0x2f, 0xdf);
+               SiS_SetRegAND(SISCAP, 0x00, 0x3f);
+
+               SiS_SetReg(SISPART1, 0x2f, 0x01);
+               SiS_SetReg(SISPART1, 0x00, 0x00);
+               SiS_SetReg(SISPART1, 0x02, bios[0x7e]);
+               SiS_SetReg(SISPART1, 0x2e, 0x08);
+               SiS_SetRegAND(SISPART1, 0x35, 0x7f);
+               SiS_SetRegAND(SISPART1, 0x50, 0xfe);
+
+               reg = SiS_GetReg(SISPART4, 0x00);
                if(reg == 1 || reg == 2) {
-                       outSISIDXREG(SISPART2, 0x00, 0x1c);
-                       outSISIDXREG(SISPART4, 0x0d, bios[0x7f]);
-                       outSISIDXREG(SISPART4, 0x0e, bios[0x80]);
-                       outSISIDXREG(SISPART4, 0x10, bios[0x81]);
-                       andSISIDXREG(SISPART4, 0x0f, 0x3f);
+                       SiS_SetReg(SISPART2, 0x00, 0x1c);
+                       SiS_SetReg(SISPART4, 0x0d, bios[0x7f]);
+                       SiS_SetReg(SISPART4, 0x0e, bios[0x80]);
+                       SiS_SetReg(SISPART4, 0x10, bios[0x81]);
+                       SiS_SetRegAND(SISPART4, 0x0f, 0x3f);
 
-                       inSISIDXREG(SISPART4, 0x01, reg);
+                       reg = SiS_GetReg(SISPART4, 0x01);
                        if((reg & 0xf0) >= 0xb0) {
-                               inSISIDXREG(SISPART4, 0x23, reg);
+                               reg = SiS_GetReg(SISPART4, 0x23);
                                if(reg & 0x20) reg |= 0x40;
-                               outSISIDXREG(SISPART4, 0x23, reg);
+                               SiS_SetReg(SISPART4, 0x23, reg);
                                reg = (reg & 0x20) ? 0x02 : 0x00;
-                               setSISIDXREG(SISPART1, 0x1e, 0xfd, reg);
+                               SiS_SetRegANDOR(SISPART1, 0x1e, 0xfd, reg);
                        }
                }
 
                v1 = bios[0x77];
 
-               inSISIDXREG(SISSR, 0x3b, reg);
+               reg = SiS_GetReg(SISSR, 0x3b);
                if(reg & 0x02) {
-                       inSISIDXREG(SISSR, 0x3a, reg);
+                       reg = SiS_GetReg(SISSR, 0x3a);
                        v2 = (reg & 0x30) >> 3;
                        if(!(v2 & 0x04)) v2 ^= 0x02;
-                       inSISIDXREG(SISSR, 0x39, reg);
+                       reg = SiS_GetReg(SISSR, 0x39);
                        if(reg & 0x80) v2 |= 0x80;
                        v2 |= 0x01;
 
@@ -5171,36 +5153,36 @@ sisfb_post_xgi(struct pci_dev *pdev)
                                        v2 |= 0x08;
                                }
                        }
-                       setSISIDXREG(SISCR, 0x5f, 0xf0, v2);
+                       SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, v2);
                }
-               outSISIDXREG(SISSR, 0x22, v1);
+               SiS_SetReg(SISSR, 0x22, v1);
 
                if(ivideo->revision_id == 2) {
-                       inSISIDXREG(SISSR, 0x3b, v1);
-                       inSISIDXREG(SISSR, 0x3a, v2);
+                       v1 = SiS_GetReg(SISSR, 0x3b);
+                       v2 = SiS_GetReg(SISSR, 0x3a);
                        regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8);
                        if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
-                               setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01);
+                               SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
 
                        if((mypdev = pci_get_device(0x10de, 0x01e0, NULL))) {
                                /* TODO: set CR5f &0xf1 | 0x01 for version 6570
                                 * of nforce 2 ROM
                                 */
                                if(0)
-                                       setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01);
+                                       SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
                                pci_dev_put(mypdev);
                        }
                }
 
                v1 = 0x30;
-               inSISIDXREG(SISSR, 0x3b, reg);
-               inSISIDXREG(SISCR, 0x5f, v2);
+               reg = SiS_GetReg(SISSR, 0x3b);
+               v2 = SiS_GetReg(SISCR, 0x5f);
                if((!(reg & 0x02)) && (v2 & 0x0e))
                        v1 |= 0x08;
-               outSISIDXREG(SISSR, 0x27, v1);
+               SiS_SetReg(SISSR, 0x27, v1);
 
                if(bios[0x64] & 0x01) {
-                       setSISIDXREG(SISCR, 0x5f, 0xf0, bios[0x64]);
+                       SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, bios[0x64]);
                }
 
                v1 = bios[0x4f7];
@@ -5208,27 +5190,27 @@ sisfb_post_xgi(struct pci_dev *pdev)
                regd = (regd >> 20) & 0x0f;
                if(regd == 1) {
                        v1 &= 0xfc;
-                       orSISIDXREG(SISCR, 0x5f, 0x08);
-               }
-               outSISIDXREG(SISCR, 0x48, v1);
-
-               setSISIDXREG(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
-               setSISIDXREG(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
-               setSISIDXREG(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
-               setSISIDXREG(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
-               setSISIDXREG(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
-               outSISIDXREG(SISCR, 0x70, bios[0x4fc]);
-               setSISIDXREG(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
-               outSISIDXREG(SISCR, 0x74, 0xd0);
-               setSISIDXREG(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
-               setSISIDXREG(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
-               setSISIDXREG(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
+                       SiS_SetRegOR(SISCR, 0x5f, 0x08);
+               }
+               SiS_SetReg(SISCR, 0x48, v1);
+
+               SiS_SetRegANDOR(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
+               SiS_SetRegANDOR(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
+               SiS_SetRegANDOR(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
+               SiS_SetRegANDOR(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
+               SiS_SetRegANDOR(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
+               SiS_SetReg(SISCR, 0x70, bios[0x4fc]);
+               SiS_SetRegANDOR(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
+               SiS_SetReg(SISCR, 0x74, 0xd0);
+               SiS_SetRegANDOR(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
+               SiS_SetRegANDOR(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
+               SiS_SetRegANDOR(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
                v1 = bios[0x501];
                if((mypdev = pci_get_device(0x8086, 0x2530, NULL))) {
                        v1 = 0xf0;
                        pci_dev_put(mypdev);
                }
-               outSISIDXREG(SISCR, 0x77, v1);
+               SiS_SetReg(SISCR, 0x77, v1);
        }
 
        /* RAM type */
@@ -5239,14 +5221,14 @@ sisfb_post_xgi(struct pci_dev *pdev)
        if(ivideo->haveXGIROM) {
                v1 = bios[0x140 + regb];
        }
-       outSISIDXREG(SISCR, 0x6d, v1);
+       SiS_SetReg(SISCR, 0x6d, v1);
 
        ptr = cs128;
        if(ivideo->haveXGIROM) {
                ptr = (const u8 *)&bios[0x128];
        }
        for(i = 0, j = 0; i < 3; i++, j += 8) {
-               outSISIDXREG(SISCR, 0x68 + i, ptr[j + regb]);
+               SiS_SetReg(SISCR, 0x68 + i, ptr[j + regb]);
        }
 
        ptr  = cs31a;
@@ -5270,14 +5252,14 @@ sisfb_post_xgi(struct pci_dev *pdev)
                        if(regd & 0x01) reg |= 0x04;
                        if(regd & 0x02) reg |= 0x08;
                        regd >>= 2;
-                       outSISIDXREG(SISCR, rega, reg);
-                       inSISIDXREG(SISCR, rega, reg);
-                       inSISIDXREG(SISCR, rega, reg);
+                       SiS_SetReg(SISCR, rega, reg);
+                       reg = SiS_GetReg(SISCR, rega);
+                       reg = SiS_GetReg(SISCR, rega);
                        reg += 0x10;
                }
        }
 
-       andSISIDXREG(SISCR, 0x6e, 0xfc);
+       SiS_SetRegAND(SISCR, 0x6e, 0xfc);
 
        ptr  = NULL;
        if(ivideo->haveXGIROM) {
@@ -5285,7 +5267,7 @@ sisfb_post_xgi(struct pci_dev *pdev)
                ptr  = (const u8 *)&bios[index];
        }
        for(i = 0; i < 4; i++) {
-               setSISIDXREG(SISCR, 0x6e, 0xfc, i);
+               SiS_SetRegANDOR(SISCR, 0x6e, 0xfc, i);
                reg = 0x00;
                for(j = 0; j < 2; j++) {
                        regd = 0;
@@ -5299,9 +5281,9 @@ sisfb_post_xgi(struct pci_dev *pdev)
                                if(regd & 0x01) reg |= 0x01;
                                if(regd & 0x02) reg |= 0x02;
                                regd >>= 2;
-                               outSISIDXREG(SISCR, 0x6f, reg);
-                               inSISIDXREG(SISCR, 0x6f, reg);
-                               inSISIDXREG(SISCR, 0x6f, reg);
+                               SiS_SetReg(SISCR, 0x6f, reg);
+                               reg = SiS_GetReg(SISCR, 0x6f);
+                               reg = SiS_GetReg(SISCR, 0x6f);
                                reg += 0x08;
                        }
                }
@@ -5312,10 +5294,10 @@ sisfb_post_xgi(struct pci_dev *pdev)
                ptr  = (const u8 *)&bios[0x148];
        }
        for(i = 0, j = 0; i < 2; i++, j += 8) {
-               outSISIDXREG(SISCR, 0x80 + i, ptr[j + regb]);
+               SiS_SetReg(SISCR, 0x80 + i, ptr[j + regb]);
        }
 
-       andSISIDXREG(SISCR, 0x89, 0x8f);
+       SiS_SetRegAND(SISCR, 0x89, 0x8f);
 
        ptr  = cs45a;
        if(ivideo->haveXGIROM) {
@@ -5329,9 +5311,9 @@ sisfb_post_xgi(struct pci_dev *pdev)
                if(regd & 0x01) reg |= 0x01;
                if(regd & 0x02) reg |= 0x02;
                regd >>= 2;
-               outSISIDXREG(SISCR, 0x89, reg);
-               inSISIDXREG(SISCR, 0x89, reg);
-               inSISIDXREG(SISCR, 0x89, reg);
+               SiS_SetReg(SISCR, 0x89, reg);
+               reg = SiS_GetReg(SISCR, 0x89);
+               reg = SiS_GetReg(SISCR, 0x89);
                reg += 0x10;
        }
 
@@ -5342,27 +5324,27 @@ sisfb_post_xgi(struct pci_dev *pdev)
                v3 = bios[0x120 + regb];
                v4 = bios[0x1ca];
        }
-       outSISIDXREG(SISCR, 0x45, v1 & 0x0f);
-       outSISIDXREG(SISCR, 0x99, (v1 >> 4) & 0x07);
-       orSISIDXREG(SISCR, 0x40, v1 & 0x80);
-       outSISIDXREG(SISCR, 0x41, v2);
+       SiS_SetReg(SISCR, 0x45, v1 & 0x0f);
+       SiS_SetReg(SISCR, 0x99, (v1 >> 4) & 0x07);
+       SiS_SetRegOR(SISCR, 0x40, v1 & 0x80);
+       SiS_SetReg(SISCR, 0x41, v2);
 
        ptr  = cs170;
        if(ivideo->haveXGIROM) {
                ptr  = (const u8 *)&bios[0x170];
        }
        for(i = 0, j = 0; i < 7; i++, j += 8) {
-               outSISIDXREG(SISCR, 0x90 + i, ptr[j + regb]);
+               SiS_SetReg(SISCR, 0x90 + i, ptr[j + regb]);
        }
 
-       outSISIDXREG(SISCR, 0x59, v3);
+       SiS_SetReg(SISCR, 0x59, v3);
 
        ptr  = cs1a8;
        if(ivideo->haveXGIROM) {
                ptr  = (const u8 *)&bios[0x1a8];
        }
        for(i = 0, j = 0; i < 3; i++, j += 8) {
-               outSISIDXREG(SISCR, 0xc3 + i, ptr[j + regb]);
+               SiS_SetReg(SISCR, 0xc3 + i, ptr[j + regb]);
        }
 
        ptr  = cs100;
@@ -5370,27 +5352,27 @@ sisfb_post_xgi(struct pci_dev *pdev)
                ptr  = (const u8 *)&bios[0x100];
        }
        for(i = 0, j = 0; i < 2; i++, j += 8) {
-               outSISIDXREG(SISCR, 0x8a + i, ptr[j + regb]);
+               SiS_SetReg(SISCR, 0x8a + i, ptr[j + regb]);
        }
 
-       outSISIDXREG(SISCR, 0xcf, v4);
+       SiS_SetReg(SISCR, 0xcf, v4);
 
-       outSISIDXREG(SISCR, 0x83, 0x09);
-       outSISIDXREG(SISCR, 0x87, 0x00);
+       SiS_SetReg(SISCR, 0x83, 0x09);
+       SiS_SetReg(SISCR, 0x87, 0x00);
 
        if(ivideo->chip == XGI_40) {
                if( (ivideo->revision_id == 1) ||
                    (ivideo->revision_id == 2) ) {
-                       outSISIDXREG(SISCR, 0x8c, 0x87);
+                       SiS_SetReg(SISCR, 0x8c, 0x87);
                }
        }
 
-       outSISIDXREG(SISSR, 0x17, 0x00);
-       outSISIDXREG(SISSR, 0x1a, 0x87);
+       SiS_SetReg(SISSR, 0x17, 0x00);
+       SiS_SetReg(SISSR, 0x1a, 0x87);
 
        if(ivideo->chip == XGI_20) {
-               outSISIDXREG(SISSR, 0x15, 0x00);
-               outSISIDXREG(SISSR, 0x1c, 0x00);
+               SiS_SetReg(SISSR, 0x15, 0x00);
+               SiS_SetReg(SISSR, 0x1c, 0x00);
        }
 
        ramtype = 0x00; v1 = 0x10;
@@ -5400,16 +5382,16 @@ sisfb_post_xgi(struct pci_dev *pdev)
        }
        if(!(ramtype & 0x80)) {
                if(ivideo->chip == XGI_20) {
-                       outSISIDXREG(SISCR, 0x97, v1);
-                       inSISIDXREG(SISCR, 0x97, reg);
+                       SiS_SetReg(SISCR, 0x97, v1);
+                       reg = SiS_GetReg(SISCR, 0x97);
                        if(reg & 0x10) {
                                ramtype = (reg & 0x01) << 1;
                        }
                } else {
-                       inSISIDXREG(SISSR, 0x39, reg);
+                       reg = SiS_GetReg(SISSR, 0x39);
                        ramtype = reg & 0x02;
                        if(!(ramtype)) {
-                               inSISIDXREG(SISSR, 0x3a, reg);
+                               reg = SiS_GetReg(SISSR, 0x3a);
                                ramtype = (reg >> 1) & 0x01;
                        }
                }
@@ -5430,55 +5412,55 @@ sisfb_post_xgi(struct pci_dev *pdev)
                                v2 = bios[regb + 0x160];
                                v3 = bios[regb + 0x168];
                        }
-                       outSISIDXREG(SISCR, 0x82, v1);
-                       outSISIDXREG(SISCR, 0x85, v2);
-                       outSISIDXREG(SISCR, 0x86, v3);
+                       SiS_SetReg(SISCR, 0x82, v1);
+                       SiS_SetReg(SISCR, 0x85, v2);
+                       SiS_SetReg(SISCR, 0x86, v3);
                } else {
-                       outSISIDXREG(SISCR, 0x82, 0x88);
-                       outSISIDXREG(SISCR, 0x86, 0x00);
-                       inSISIDXREG(SISCR, 0x86, reg);
-                       outSISIDXREG(SISCR, 0x86, 0x88);
-                       inSISIDXREG(SISCR, 0x86, reg);
-                       outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]);
-                       outSISIDXREG(SISCR, 0x82, 0x77);
-                       outSISIDXREG(SISCR, 0x85, 0x00);
-                       inSISIDXREG(SISCR, 0x85, reg);
-                       outSISIDXREG(SISCR, 0x85, 0x88);
-                       inSISIDXREG(SISCR, 0x85, reg);
-                       outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]);
-                       outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]);
+                       SiS_SetReg(SISCR, 0x82, 0x88);
+                       SiS_SetReg(SISCR, 0x86, 0x00);
+                       reg = SiS_GetReg(SISCR, 0x86);
+                       SiS_SetReg(SISCR, 0x86, 0x88);
+                       reg = SiS_GetReg(SISCR, 0x86);
+                       SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
+                       SiS_SetReg(SISCR, 0x82, 0x77);
+                       SiS_SetReg(SISCR, 0x85, 0x00);
+                       reg = SiS_GetReg(SISCR, 0x85);
+                       SiS_SetReg(SISCR, 0x85, 0x88);
+                       reg = SiS_GetReg(SISCR, 0x85);
+                       SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
+                       SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
                }
                if(ivideo->chip == XGI_40) {
-                       outSISIDXREG(SISCR, 0x97, 0x00);
+                       SiS_SetReg(SISCR, 0x97, 0x00);
                }
-               outSISIDXREG(SISCR, 0x98, 0x01);
-               outSISIDXREG(SISCR, 0x9a, 0x02);
+               SiS_SetReg(SISCR, 0x98, 0x01);
+               SiS_SetReg(SISCR, 0x9a, 0x02);
 
-               outSISIDXREG(SISSR, 0x18, 0x01);
+               SiS_SetReg(SISSR, 0x18, 0x01);
                if((ivideo->chip == XGI_20) ||
                   (ivideo->revision_id == 2)) {
-                       outSISIDXREG(SISSR, 0x19, 0x40);
+                       SiS_SetReg(SISSR, 0x19, 0x40);
                } else {
-                       outSISIDXREG(SISSR, 0x19, 0x20);
+                       SiS_SetReg(SISSR, 0x19, 0x20);
                }
-               outSISIDXREG(SISSR, 0x16, 0x00);
-               outSISIDXREG(SISSR, 0x16, 0x80);
+               SiS_SetReg(SISSR, 0x16, 0x00);
+               SiS_SetReg(SISSR, 0x16, 0x80);
                if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) {
                        sisfb_post_xgi_delay(ivideo, 0x43);
                        sisfb_post_xgi_delay(ivideo, 0x43);
                        sisfb_post_xgi_delay(ivideo, 0x43);
-                       outSISIDXREG(SISSR, 0x18, 0x00);
+                       SiS_SetReg(SISSR, 0x18, 0x00);
                        if((ivideo->chip == XGI_20) ||
                           (ivideo->revision_id == 2)) {
-                               outSISIDXREG(SISSR, 0x19, 0x40);
+                               SiS_SetReg(SISSR, 0x19, 0x40);
                        } else {
-                               outSISIDXREG(SISSR, 0x19, 0x20);
+                               SiS_SetReg(SISSR, 0x19, 0x20);
                        }
                } else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) {
-                       /* outSISIDXREG(SISSR, 0x16, 0x0c); */ /* ? */
+                       /* SiS_SetReg(SISSR, 0x16, 0x0c); */ /* ? */
                }
-               outSISIDXREG(SISSR, 0x16, 0x00);
-               outSISIDXREG(SISSR, 0x16, 0x80);
+               SiS_SetReg(SISSR, 0x16, 0x00);
+               SiS_SetReg(SISSR, 0x16, 0x80);
                sisfb_post_xgi_delay(ivideo, 4);
                v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83;
                if(ivideo->haveXGIROM) {
@@ -5489,74 +5471,74 @@ sisfb_post_xgi(struct pci_dev *pdev)
                        v4 = bios[index + 2];
                        v5 = bios[index + 3];
                }
-               outSISIDXREG(SISSR, 0x18, v1);
-               outSISIDXREG(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
-               outSISIDXREG(SISSR, 0x16, v2);
-               outSISIDXREG(SISSR, 0x16, v3);
+               SiS_SetReg(SISSR, 0x18, v1);
+               SiS_SetReg(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
+               SiS_SetReg(SISSR, 0x16, v2);
+               SiS_SetReg(SISSR, 0x16, v3);
                sisfb_post_xgi_delay(ivideo, 0x43);
-               outSISIDXREG(SISSR, 0x1b, 0x03);
+               SiS_SetReg(SISSR, 0x1b, 0x03);
                sisfb_post_xgi_delay(ivideo, 0x22);
-               outSISIDXREG(SISSR, 0x18, v1);
-               outSISIDXREG(SISSR, 0x19, 0x00);
-               outSISIDXREG(SISSR, 0x16, v4);
-               outSISIDXREG(SISSR, 0x16, v5);
-               outSISIDXREG(SISSR, 0x1b, 0x00);
+               SiS_SetReg(SISSR, 0x18, v1);
+               SiS_SetReg(SISSR, 0x19, 0x00);
+               SiS_SetReg(SISSR, 0x16, v4);
+               SiS_SetReg(SISSR, 0x16, v5);
+               SiS_SetReg(SISSR, 0x1b, 0x00);
                break;
        case 1:
-               outSISIDXREG(SISCR, 0x82, 0x77);
-               outSISIDXREG(SISCR, 0x86, 0x00);
-               inSISIDXREG(SISCR, 0x86, reg);
-               outSISIDXREG(SISCR, 0x86, 0x88);
-               inSISIDXREG(SISCR, 0x86, reg);
+               SiS_SetReg(SISCR, 0x82, 0x77);
+               SiS_SetReg(SISCR, 0x86, 0x00);
+               reg = SiS_GetReg(SISCR, 0x86);
+               SiS_SetReg(SISCR, 0x86, 0x88);
+               reg = SiS_GetReg(SISCR, 0x86);
                v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
                if(ivideo->haveXGIROM) {
                        v1 = bios[regb + 0x168];
                        v2 = bios[regb + 0x160];
                        v3 = bios[regb + 0x158];
                }
-               outSISIDXREG(SISCR, 0x86, v1);
-               outSISIDXREG(SISCR, 0x82, 0x77);
-               outSISIDXREG(SISCR, 0x85, 0x00);
-               inSISIDXREG(SISCR, 0x85, reg);
-               outSISIDXREG(SISCR, 0x85, 0x88);
-               inSISIDXREG(SISCR, 0x85, reg);
-               outSISIDXREG(SISCR, 0x85, v2);
-               outSISIDXREG(SISCR, 0x82, v3);
-               outSISIDXREG(SISCR, 0x98, 0x01);
-               outSISIDXREG(SISCR, 0x9a, 0x02);
-
-               outSISIDXREG(SISSR, 0x28, 0x64);
-               outSISIDXREG(SISSR, 0x29, 0x63);
+               SiS_SetReg(SISCR, 0x86, v1);
+               SiS_SetReg(SISCR, 0x82, 0x77);
+               SiS_SetReg(SISCR, 0x85, 0x00);
+               reg = SiS_GetReg(SISCR, 0x85);
+               SiS_SetReg(SISCR, 0x85, 0x88);
+               reg = SiS_GetReg(SISCR, 0x85);
+               SiS_SetReg(SISCR, 0x85, v2);
+               SiS_SetReg(SISCR, 0x82, v3);
+               SiS_SetReg(SISCR, 0x98, 0x01);
+               SiS_SetReg(SISCR, 0x9a, 0x02);
+
+               SiS_SetReg(SISSR, 0x28, 0x64);
+               SiS_SetReg(SISSR, 0x29, 0x63);
                sisfb_post_xgi_delay(ivideo, 15);
-               outSISIDXREG(SISSR, 0x18, 0x00);
-               outSISIDXREG(SISSR, 0x19, 0x20);
-               outSISIDXREG(SISSR, 0x16, 0x00);
-               outSISIDXREG(SISSR, 0x16, 0x80);
-               outSISIDXREG(SISSR, 0x18, 0xc5);
-               outSISIDXREG(SISSR, 0x19, 0x23);
-               outSISIDXREG(SISSR, 0x16, 0x00);
-               outSISIDXREG(SISSR, 0x16, 0x80);
+               SiS_SetReg(SISSR, 0x18, 0x00);
+               SiS_SetReg(SISSR, 0x19, 0x20);
+               SiS_SetReg(SISSR, 0x16, 0x00);
+               SiS_SetReg(SISSR, 0x16, 0x80);
+               SiS_SetReg(SISSR, 0x18, 0xc5);
+               SiS_SetReg(SISSR, 0x19, 0x23);
+               SiS_SetReg(SISSR, 0x16, 0x00);
+               SiS_SetReg(SISSR, 0x16, 0x80);
                sisfb_post_xgi_delay(ivideo, 1);
-               outSISIDXREG(SISCR, 0x97,0x11);
+               SiS_SetReg(SISCR, 0x97, 0x11);
                sisfb_post_xgi_setclocks(ivideo, regb);
                sisfb_post_xgi_delay(ivideo, 0x46);
-               outSISIDXREG(SISSR, 0x18, 0xc5);
-               outSISIDXREG(SISSR, 0x19, 0x23);
-               outSISIDXREG(SISSR, 0x16, 0x00);
-               outSISIDXREG(SISSR, 0x16, 0x80);
+               SiS_SetReg(SISSR, 0x18, 0xc5);
+               SiS_SetReg(SISSR, 0x19, 0x23);
+               SiS_SetReg(SISSR, 0x16, 0x00);
+               SiS_SetReg(SISSR, 0x16, 0x80);
                sisfb_post_xgi_delay(ivideo, 1);
-               outSISIDXREG(SISSR, 0x1b, 0x04);
+               SiS_SetReg(SISSR, 0x1b, 0x04);
                sisfb_post_xgi_delay(ivideo, 1);
-               outSISIDXREG(SISSR, 0x1b, 0x00);
+               SiS_SetReg(SISSR, 0x1b, 0x00);
                sisfb_post_xgi_delay(ivideo, 1);
                v1 = 0x31;
                if(ivideo->haveXGIROM) {
                        v1 = bios[0xf0];
                }
-               outSISIDXREG(SISSR, 0x18, v1);
-               outSISIDXREG(SISSR, 0x19, 0x06);
-               outSISIDXREG(SISSR, 0x16, 0x04);
-               outSISIDXREG(SISSR, 0x16, 0x84);
+               SiS_SetReg(SISSR, 0x18, v1);
+               SiS_SetReg(SISSR, 0x19, 0x06);
+               SiS_SetReg(SISSR, 0x16, 0x04);
+               SiS_SetReg(SISSR, 0x16, 0x84);
                sisfb_post_xgi_delay(ivideo, 1);
                break;
        default:
@@ -5564,85 +5546,85 @@ sisfb_post_xgi(struct pci_dev *pdev)
                if((ivideo->chip == XGI_40) &&
                   ((ivideo->revision_id == 1) ||
                    (ivideo->revision_id == 2))) {
-                       outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]);
-                       outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]);
-                       outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]);
+                       SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
+                       SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
+                       SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
                } else {
-                       outSISIDXREG(SISCR, 0x82, 0x88);
-                       outSISIDXREG(SISCR, 0x86, 0x00);
-                       inSISIDXREG(SISCR, 0x86, reg);
-                       outSISIDXREG(SISCR, 0x86, 0x88);
-                       outSISIDXREG(SISCR, 0x82, 0x77);
-                       outSISIDXREG(SISCR, 0x85, 0x00);
-                       inSISIDXREG(SISCR, 0x85, reg);
-                       outSISIDXREG(SISCR, 0x85, 0x88);
-                       inSISIDXREG(SISCR, 0x85, reg);
+                       SiS_SetReg(SISCR, 0x82, 0x88);
+                       SiS_SetReg(SISCR, 0x86, 0x00);
+                       reg = SiS_GetReg(SISCR, 0x86);
+                       SiS_SetReg(SISCR, 0x86, 0x88);
+                       SiS_SetReg(SISCR, 0x82, 0x77);
+                       SiS_SetReg(SISCR, 0x85, 0x00);
+                       reg = SiS_GetReg(SISCR, 0x85);
+                       SiS_SetReg(SISCR, 0x85, 0x88);
+                       reg = SiS_GetReg(SISCR, 0x85);
                        v1 = cs160[regb]; v2 = cs158[regb];
                        if(ivideo->haveXGIROM) {
                                v1 = bios[regb + 0x160];
                                v2 = bios[regb + 0x158];
                        }
-                       outSISIDXREG(SISCR, 0x85, v1);
-                       outSISIDXREG(SISCR, 0x82, v2);
+                       SiS_SetReg(SISCR, 0x85, v1);
+                       SiS_SetReg(SISCR, 0x82, v2);
                }
                if(ivideo->chip == XGI_40) {
-                       outSISIDXREG(SISCR, 0x97, 0x11);
+                       SiS_SetReg(SISCR, 0x97, 0x11);
                }
                if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) {
-                       outSISIDXREG(SISCR, 0x98, 0x01);
+                       SiS_SetReg(SISCR, 0x98, 0x01);
                } else {
-                       outSISIDXREG(SISCR, 0x98, 0x03);
+                       SiS_SetReg(SISCR, 0x98, 0x03);
                }
-               outSISIDXREG(SISCR, 0x9a, 0x02);
+               SiS_SetReg(SISCR, 0x9a, 0x02);
 
                if(ivideo->chip == XGI_40) {
-                       outSISIDXREG(SISSR, 0x18, 0x01);
+                       SiS_SetReg(SISSR, 0x18, 0x01);
                } else {
-                       outSISIDXREG(SISSR, 0x18, 0x00);
+                       SiS_SetReg(SISSR, 0x18, 0x00);
                }
-               outSISIDXREG(SISSR, 0x19, 0x40);
-               outSISIDXREG(SISSR, 0x16, 0x00);
-               outSISIDXREG(SISSR, 0x16, 0x80);
+               SiS_SetReg(SISSR, 0x19, 0x40);
+               SiS_SetReg(SISSR, 0x16, 0x00);
+               SiS_SetReg(SISSR, 0x16, 0x80);
                if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) {
                        sisfb_post_xgi_delay(ivideo, 0x43);
                        sisfb_post_xgi_delay(ivideo, 0x43);
                        sisfb_post_xgi_delay(ivideo, 0x43);
-                       outSISIDXREG(SISSR, 0x18, 0x00);
-                       outSISIDXREG(SISSR, 0x19, 0x40);
-                       outSISIDXREG(SISSR, 0x16, 0x00);
-                       outSISIDXREG(SISSR, 0x16, 0x80);
+                       SiS_SetReg(SISSR, 0x18, 0x00);
+                       SiS_SetReg(SISSR, 0x19, 0x40);
+                       SiS_SetReg(SISSR, 0x16, 0x00);
+                       SiS_SetReg(SISSR, 0x16, 0x80);
                }
                sisfb_post_xgi_delay(ivideo, 4);
                v1 = 0x31;
                if(ivideo->haveXGIROM) {
                        v1 = bios[0xf0];
                }
-               outSISIDXREG(SISSR, 0x18, v1);
-               outSISIDXREG(SISSR, 0x19, 0x01);
+               SiS_SetReg(SISSR, 0x18, v1);
+               SiS_SetReg(SISSR, 0x19, 0x01);
                if(ivideo->chip == XGI_40) {
-                       outSISIDXREG(SISSR, 0x16, bios[0x53e]);
-                       outSISIDXREG(SISSR, 0x16, bios[0x53f]);
+                       SiS_SetReg(SISSR, 0x16, bios[0x53e]);
+                       SiS_SetReg(SISSR, 0x16, bios[0x53f]);
                } else {
-                       outSISIDXREG(SISSR, 0x16, 0x05);
-                       outSISIDXREG(SISSR, 0x16, 0x85);
+                       SiS_SetReg(SISSR, 0x16, 0x05);
+                       SiS_SetReg(SISSR, 0x16, 0x85);
                }
                sisfb_post_xgi_delay(ivideo, 0x43);
                if(ivideo->chip == XGI_40) {
-                       outSISIDXREG(SISSR, 0x1b, 0x01);
+                       SiS_SetReg(SISSR, 0x1b, 0x01);
                } else {
-                       outSISIDXREG(SISSR, 0x1b, 0x03);
+                       SiS_SetReg(SISSR, 0x1b, 0x03);
                }
                sisfb_post_xgi_delay(ivideo, 0x22);
-               outSISIDXREG(SISSR, 0x18, v1);
-               outSISIDXREG(SISSR, 0x19, 0x00);
+               SiS_SetReg(SISSR, 0x18, v1);
+               SiS_SetReg(SISSR, 0x19, 0x00);
                if(ivideo->chip == XGI_40) {
-                       outSISIDXREG(SISSR, 0x16, bios[0x540]);
-                       outSISIDXREG(SISSR, 0x16, bios[0x541]);
+                       SiS_SetReg(SISSR, 0x16, bios[0x540]);
+                       SiS_SetReg(SISSR, 0x16, bios[0x541]);
                } else {
-                       outSISIDXREG(SISSR, 0x16, 0x05);
-                       outSISIDXREG(SISSR, 0x16, 0x85);
+                       SiS_SetReg(SISSR, 0x16, 0x05);
+                       SiS_SetReg(SISSR, 0x16, 0x85);
                }
-               outSISIDXREG(SISSR, 0x1b, 0x00);
+               SiS_SetReg(SISSR, 0x1b, 0x00);
        }
 
        regb = 0;       /* ! */
@@ -5650,7 +5632,7 @@ sisfb_post_xgi(struct pci_dev *pdev)
        if(ivideo->haveXGIROM) {
                v1 = bios[0x110 + regb];
        }
-       outSISIDXREG(SISSR, 0x1b, v1);
+       SiS_SetReg(SISSR, 0x1b, v1);
 
        /* RAM size */
        v1 = 0x00; v2 = 0x00;
@@ -5662,8 +5644,8 @@ sisfb_post_xgi(struct pci_dev *pdev)
        regd = 1 << regb;
        if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) {
 
-               outSISIDXREG(SISSR, 0x13, bios[regb + 0xe0]);
-               outSISIDXREG(SISSR, 0x14, bios[regb + 0xe0 + 8]);
+               SiS_SetReg(SISSR, 0x13, bios[regb + 0xe0]);
+               SiS_SetReg(SISSR, 0x14, bios[regb + 0xe0 + 8]);
 
        } else {
 
@@ -5675,24 +5657,24 @@ sisfb_post_xgi(struct pci_dev *pdev)
                ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
                SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
 
-               outSISIDXREG(SISSR, 0x05, 0x86);
+               SiS_SetReg(SISSR, 0x05, 0x86);
 
                /* Disable read-cache */
-               andSISIDXREG(SISSR, 0x21, 0xdf);
+               SiS_SetRegAND(SISSR, 0x21, 0xdf);
                sisfb_post_xgi_ramsize(ivideo);
                /* Enable read-cache */
-               orSISIDXREG(SISSR, 0x21, 0x20);
+               SiS_SetRegOR(SISSR, 0x21, 0x20);
 
        }
 
 #if 0
        printk(KERN_DEBUG "-----------------\n");
        for(i = 0; i < 0xff; i++) {
-               inSISIDXREG(SISCR, i, reg);
+               reg = SiS_GetReg(SISCR, i);
                printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg);
        }
        for(i = 0; i < 0x40; i++) {
-               inSISIDXREG(SISSR, i, reg);
+               reg = SiS_GetReg(SISSR, i);
                printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg);
        }
        printk(KERN_DEBUG "-----------------\n");
@@ -5700,13 +5682,13 @@ sisfb_post_xgi(struct pci_dev *pdev)
 
        /* Sense CRT1 */
        if(ivideo->chip == XGI_20) {
-               orSISIDXREG(SISCR, 0x32, 0x20);
+               SiS_SetRegOR(SISCR, 0x32, 0x20);
        } else {
-               inSISIDXREG(SISPART4, 0x00, reg);
+               reg = SiS_GetReg(SISPART4, 0x00);
                if((reg == 1) || (reg == 2)) {
                        sisfb_sense_crt1(ivideo);
                } else {
-                       orSISIDXREG(SISCR, 0x32, 0x20);
+                       SiS_SetRegOR(SISCR, 0x32, 0x20);
                }
        }
 
@@ -5717,20 +5699,20 @@ sisfb_post_xgi(struct pci_dev *pdev)
        ivideo->curFSTN = ivideo->curDSTN = 0;
        SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
 
-       outSISIDXREG(SISSR, 0x05, 0x86);
+       SiS_SetReg(SISSR, 0x05, 0x86);
 
        /* Display off */
-       orSISIDXREG(SISSR, 0x01, 0x20);
+       SiS_SetRegOR(SISSR, 0x01, 0x20);
 
        /* Save mode number in CR34 */
-       outSISIDXREG(SISCR, 0x34, 0x2e);
+       SiS_SetReg(SISCR, 0x34, 0x2e);
 
        /* Let everyone know what the current mode is */
        ivideo->modeprechange = 0x2e;
 
        if(ivideo->chip == XGI_40) {
-               inSISIDXREG(SISCR, 0xca, reg);
-               inSISIDXREG(SISCR, 0xcc, v1);
+               reg = SiS_GetReg(SISCR, 0xca);
+               v1 = SiS_GetReg(SISCR, 0xcc);
                if((reg & 0x10) && (!(v1 & 0x04))) {
                        printk(KERN_ERR
                                "sisfb: Please connect power to the card.\n");
@@ -5973,7 +5955,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
 #endif
 
-       outSISIDXREG(SISSR, 0x05, 0x86);
+       SiS_SetReg(SISSR, 0x05, 0x86);
 
        if( (!ivideo->sisvga_enabled)
 #if !defined(__i386__) && !defined(__x86_64__)
@@ -5981,13 +5963,13 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 #endif
                                                   ) {
                for(i = 0x30; i <= 0x3f; i++) {
-                       outSISIDXREG(SISCR, i, 0x00);
+                       SiS_SetReg(SISCR, i, 0x00);
                }
        }
 
        /* Find out about current video mode */
        ivideo->modeprechange = 0x03;
-       inSISIDXREG(SISCR, 0x34, reg);
+       reg = SiS_GetReg(SISCR, 0x34);
        if(reg & 0x7f) {
                ivideo->modeprechange = reg & 0x7f;
        } else if(ivideo->sisvga_enabled) {
@@ -6084,9 +6066,9 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if((ivideo->sisfb_mode_idx < 0) ||
           ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
                /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE  */
-               orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
+               SiS_SetRegOR(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
                /* Enable 2D accelerator engine */
-               orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
+               SiS_SetRegOR(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
        }
 
        if(sisfb_pdc != 0xff) {
index 81a22eaabfde0f43abced33a8c4a0cd998acdc0d..12c0dfaf251876baf61b54ce5fe848e73151d371 100644 (file)
 
 #define SISIOMEMTYPE
 
-#ifdef SIS_LINUX_KERNEL
 typedef unsigned long SISIOADDRESS;
 #include <linux/types.h>  /* Need __iomem */
 #undef SISIOMEMTYPE
 #define SISIOMEMTYPE __iomem
-#endif
-
-#ifdef SIS_XORG_XF86
-#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,0,0,0)
-typedef unsigned long IOADDRESS;
-typedef unsigned long SISIOADDRESS;
-#else
-typedef IOADDRESS SISIOADDRESS;
-#endif
-#endif
 
 typedef enum _SIS_CHIP_TYPE {
     SIS_VGALegacy = 0,
index bef4aae388d0fb98305c6dd2d9143cd7c862a491..ea94d214dcff575d4d1945518287c462852c5ac3 100644 (file)
@@ -233,24 +233,15 @@ struct SiS_Private
 {
        unsigned char                   ChipType;
        unsigned char                   ChipRevision;
-#ifdef SIS_XORG_XF86
-       PCITAG                          PciTag;
-#endif
-#ifdef SIS_LINUX_KERNEL
        void                            *ivideo;
-#endif
        unsigned char                   *VirtualRomBase;
        bool                            UseROM;
-#ifdef SIS_LINUX_KERNEL
        unsigned char SISIOMEMTYPE      *VideoMemoryAddress;
        unsigned int                    VideoMemorySize;
-#endif
        SISIOADDRESS                    IOAddress;
        SISIOADDRESS                    IOAddress2;  /* For dual chip XGI volari */
 
-#ifdef SIS_LINUX_KERNEL
        SISIOADDRESS                    RelIO;
-#endif
        SISIOADDRESS                    SiS_P3c4;
        SISIOADDRESS                    SiS_P3d4;
        SISIOADDRESS                    SiS_P3c0;
@@ -280,9 +271,6 @@ struct SiS_Private
        unsigned short                  SiS_IF_DEF_FSTN;
        unsigned short                  SiS_SysFlags;
        unsigned char                   SiS_VGAINFO;
-#ifdef SIS_XORG_XF86
-       unsigned short                  SiS_CP1, SiS_CP2, SiS_CP3, SiS_CP4;
-#endif
        bool                            SiS_UseROM;
        bool                            SiS_ROMNew;
        bool                            SiS_XGIROM;
index a3aa917095038d4afa8515a2d79d1184520e8c6e..6723d6910cde7831175df8932f9adbc5c45f9c76 100644 (file)
@@ -15,6 +15,9 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/list.h>
+#include <linux/pm.h>
+#include <asm/olpc.h>
 
 /*
  * The default port config.
@@ -28,6 +31,19 @@ static struct via_port_cfg adap_configs[] = {
        { 0, 0, 0, 0 }
 };
 
+/*
+ * The OLPC XO-1.5 puts the camera power and reset lines onto
+ * GPIO 2C.
+ */
+static const struct via_port_cfg olpc_adap_configs[] = {
+       [VIA_PORT_26]   = { VIA_PORT_I2C,  VIA_MODE_I2C, VIASR, 0x26 },
+       [VIA_PORT_31]   = { VIA_PORT_I2C,  VIA_MODE_I2C, VIASR, 0x31 },
+       [VIA_PORT_25]   = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 },
+       [VIA_PORT_2C]   = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x2c },
+       [VIA_PORT_3D]   = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x3d },
+       { 0, 0, 0, 0 }
+};
+
 /*
  * We currently only support one viafb device (will there ever be
  * more than one?), so just declare it globally here.
@@ -575,6 +591,78 @@ static void via_teardown_subdevs(void)
                }
 }
 
+/*
+ * Power management functions
+ */
+#ifdef CONFIG_PM
+static LIST_HEAD(viafb_pm_hooks);
+static DEFINE_MUTEX(viafb_pm_hooks_lock);
+
+void viafb_pm_register(struct viafb_pm_hooks *hooks)
+{
+       INIT_LIST_HEAD(&hooks->list);
+
+       mutex_lock(&viafb_pm_hooks_lock);
+       list_add_tail(&hooks->list, &viafb_pm_hooks);
+       mutex_unlock(&viafb_pm_hooks_lock);
+}
+EXPORT_SYMBOL_GPL(viafb_pm_register);
+
+void viafb_pm_unregister(struct viafb_pm_hooks *hooks)
+{
+       mutex_lock(&viafb_pm_hooks_lock);
+       list_del(&hooks->list);
+       mutex_unlock(&viafb_pm_hooks_lock);
+}
+EXPORT_SYMBOL_GPL(viafb_pm_unregister);
+
+static int via_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct viafb_pm_hooks *hooks;
+
+       if (state.event != PM_EVENT_SUSPEND)
+               return 0;
+       /*
+        * "I've occasionally hit a few drivers that caused suspend
+        * failures, and each and every time it was a driver bug, and
+        * the right thing to do was to just ignore the error and suspend
+        * anyway - returning an error code and trying to undo the suspend
+        * is not what anybody ever really wants, even if our model
+        *_allows_ for it."
+        * -- Linus Torvalds, Dec. 7, 2009
+        */
+       mutex_lock(&viafb_pm_hooks_lock);
+       list_for_each_entry_reverse(hooks, &viafb_pm_hooks, list)
+               hooks->suspend(hooks->private);
+       mutex_unlock(&viafb_pm_hooks_lock);
+
+       pci_save_state(pdev);
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, pci_choose_state(pdev, state));
+       return 0;
+}
+
+static int via_resume(struct pci_dev *pdev)
+{
+       struct viafb_pm_hooks *hooks;
+
+       /* Get the bus side powered up */
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+       if (pci_enable_device(pdev))
+               return 0;
+
+       pci_set_master(pdev);
+
+       /* Now bring back any subdevs */
+       mutex_lock(&viafb_pm_hooks_lock);
+       list_for_each_entry(hooks, &viafb_pm_hooks, list)
+               hooks->resume(hooks->private);
+       mutex_unlock(&viafb_pm_hooks_lock);
+
+       return 0;
+}
+#endif /* CONFIG_PM */
 
 static int __devinit via_pci_probe(struct pci_dev *pdev,
                const struct pci_device_id *ent)
@@ -584,6 +672,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
        ret = pci_enable_device(pdev);
        if (ret)
                return ret;
+
        /*
         * Global device initialization.
         */
@@ -591,6 +680,9 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
        global_dev.pdev = pdev;
        global_dev.chip_type = ent->driver_data;
        global_dev.port_cfg = adap_configs;
+       if (machine_is_olpc())
+               global_dev.port_cfg = olpc_adap_configs;
+
        spin_lock_init(&global_dev.reg_lock);
        ret = via_pci_setup_mmio(&global_dev);
        if (ret)
@@ -663,8 +755,8 @@ static struct pci_driver via_driver = {
        .probe          = via_pci_probe,
        .remove         = __devexit_p(via_pci_remove),
 #ifdef CONFIG_PM
-       .suspend        = viafb_suspend,
-       .resume         = viafb_resume,
+       .suspend        = via_suspend,
+       .resume         = via_resume,
 #endif
 };
 
index 39acb37e7a1d2bd333003679b9b322e4a6feb291..c2a0a1cfd3b3fe6c9f2da44e8574fe9a20591be5 100644 (file)
@@ -172,6 +172,28 @@ static void viafb_gpio_disable(struct viafb_gpio *gpio)
        via_write_reg_mask(VIASR, gpio->vg_port_index, 0, 0x02);
 }
 
+#ifdef CONFIG_PM
+
+static int viafb_gpio_suspend(void *private)
+{
+       return 0;
+}
+
+static int viafb_gpio_resume(void *private)
+{
+       int i;
+
+       for (i = 0; i < gpio_config.gpio_chip.ngpio; i += 2)
+               viafb_gpio_enable(gpio_config.active_gpios[i]);
+       return 0;
+}
+
+static struct viafb_pm_hooks viafb_gpio_pm_hooks = {
+       .suspend = viafb_gpio_suspend,
+       .resume = viafb_gpio_resume
+};
+#endif /* CONFIG_PM */
+
 /*
  * Look up a specific gpio and return the number it was assigned.
  */
@@ -236,6 +258,9 @@ static __devinit int viafb_gpio_probe(struct platform_device *platdev)
                printk(KERN_ERR "viafb: failed to add gpios (%d)\n", ret);
                gpio_config.gpio_chip.ngpio = 0;
        }
+#ifdef CONFIG_PM
+       viafb_pm_register(&viafb_gpio_pm_hooks);
+#endif
        return ret;
 }
 
@@ -245,6 +270,10 @@ static int viafb_gpio_remove(struct platform_device *platdev)
        unsigned long flags;
        int ret = 0, i;
 
+#ifdef CONFIG_PM
+       viafb_pm_unregister(&viafb_gpio_pm_hooks);
+#endif
+
        /*
         * Get unregistered.
         */
index d298cfccd6fc24bb842f69a9c8cf9945bdc8c8ae..289edd519527ff948570261db01747be8c26e20f 100644 (file)
@@ -1672,31 +1672,19 @@ static int parse_mode(const char *str, u32 *xres, u32 *yres)
 
 
 #ifdef CONFIG_PM
-int viafb_suspend(struct pci_dev *pdev, pm_message_t state)
+static int viafb_suspend(void *unused)
 {
-       if (state.event == PM_EVENT_SUSPEND) {
-               acquire_console_sem();
-               fb_set_suspend(viafbinfo, 1);
-
-               viafb_sync(viafbinfo);
-
-               pci_save_state(pdev);
-               pci_disable_device(pdev);
-               pci_set_power_state(pdev, pci_choose_state(pdev, state));
-               release_console_sem();
-       }
+       acquire_console_sem();
+       fb_set_suspend(viafbinfo, 1);
+       viafb_sync(viafbinfo);
+       release_console_sem();
 
        return 0;
 }
 
-int viafb_resume(struct pci_dev *pdev)
+static int viafb_resume(void *unused)
 {
        acquire_console_sem();
-       pci_set_power_state(pdev, PCI_D0);
-       pci_restore_state(pdev);
-       if (pci_enable_device(pdev))
-               goto fail;
-       pci_set_master(pdev);
        if (viaparinfo->shared->vdev->engine_mmio)
                viafb_reset_engine(viaparinfo);
        viafb_set_par(viafbinfo);
@@ -1704,11 +1692,15 @@ int viafb_resume(struct pci_dev *pdev)
                viafb_set_par(viafbinfo1);
        fb_set_suspend(viafbinfo, 0);
 
-fail:
        release_console_sem();
        return 0;
 }
 
+static struct viafb_pm_hooks viafb_fb_pm_hooks = {
+       .suspend = viafb_suspend,
+       .resume = viafb_resume
+};
+
 #endif
 
 
@@ -1899,6 +1891,10 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
 
        viafb_init_proc(viaparinfo->shared);
        viafb_init_dac(IGA2);
+
+#ifdef CONFIG_PM
+       viafb_pm_register(&viafb_fb_pm_hooks);
+#endif
        return 0;
 
 out_fb_unreg:
index 4960e3da6645a8d51e73f50754a71536cc15e327..d66f963e930e3d2791e004b120b6a98b8b5dec92 100644 (file)
@@ -108,6 +108,4 @@ void via_fb_pci_remove(struct pci_dev *pdev);
 /* Temporary */
 int viafb_init(void);
 void viafb_exit(void);
-int viafb_suspend(struct pci_dev *pdev, pm_message_t state);
-int viafb_resume(struct pci_dev *pdev);
 #endif /* __VIAFBDEV_H__ */
diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/vt8500lcdfb.c
new file mode 100644 (file)
index 0000000..7617f12
--- /dev/null
@@ -0,0 +1,447 @@
+/*
+ *  linux/drivers/video/vt8500lcdfb.c
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * Based on skeletonfb.c and pxafb.c
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/wait.h>
+
+#include <mach/vt8500fb.h>
+
+#include "vt8500lcdfb.h"
+#include "wmt_ge_rops.h"
+
+#define to_vt8500lcd_info(__info) container_of(__info, \
+                                               struct vt8500lcd_info, fb)
+
+static int vt8500lcd_set_par(struct fb_info *info)
+{
+       struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
+       int reg_bpp = 5; /* 16bpp */
+       int i;
+       unsigned long control0;
+
+       if (!fbi)
+               return -EINVAL;
+
+       if (info->var.bits_per_pixel <= 8) {
+               /* palettized */
+               info->var.red.offset    = 0;
+               info->var.red.length    = info->var.bits_per_pixel;
+               info->var.red.msb_right = 0;
+
+               info->var.green.offset  = 0;
+               info->var.green.length  = info->var.bits_per_pixel;
+               info->var.green.msb_right = 0;
+
+               info->var.blue.offset   = 0;
+               info->var.blue.length   = info->var.bits_per_pixel;
+               info->var.blue.msb_right = 0;
+
+               info->var.transp.offset = 0;
+               info->var.transp.length = 0;
+               info->var.transp.msb_right = 0;
+
+               info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+               info->fix.line_length = info->var.xres_virtual /
+                                               (8/info->var.bits_per_pixel);
+       } else {
+               /* non-palettized */
+               info->var.transp.offset = 0;
+               info->var.transp.length = 0;
+               info->var.transp.msb_right = 0;
+
+               if (info->var.bits_per_pixel == 16) {
+                       /* RGB565 */
+                       info->var.red.offset = 11;
+                       info->var.red.length = 5;
+                       info->var.red.msb_right = 0;
+                       info->var.green.offset = 5;
+                       info->var.green.length = 6;
+                       info->var.green.msb_right = 0;
+                       info->var.blue.offset = 0;
+                       info->var.blue.length = 5;
+                       info->var.blue.msb_right = 0;
+               } else {
+                       /* Equal depths per channel */
+                       info->var.red.offset = info->var.bits_per_pixel
+                                                       * 2 / 3;
+                       info->var.red.length = info->var.bits_per_pixel / 3;
+                       info->var.red.msb_right = 0;
+                       info->var.green.offset = info->var.bits_per_pixel / 3;
+                       info->var.green.length = info->var.bits_per_pixel / 3;
+                       info->var.green.msb_right = 0;
+                       info->var.blue.offset = 0;
+                       info->var.blue.length = info->var.bits_per_pixel / 3;
+                       info->var.blue.msb_right = 0;
+               }
+
+               info->fix.visual = FB_VISUAL_TRUECOLOR;
+               info->fix.line_length = info->var.bits_per_pixel > 16 ?
+                                       info->var.xres_virtual << 2 :
+                                       info->var.xres_virtual << 1;
+       }
+
+       for (i = 0; i < 8; i++) {
+               if (bpp_values[i] == info->var.bits_per_pixel) {
+                       reg_bpp = i;
+                       continue;
+               }
+       }
+
+       control0 = readl(fbi->regbase) & ~0xf;
+       writel(0, fbi->regbase);
+       while (readl(fbi->regbase + 0x38) & 0x10)
+               /* wait */;
+       writel((((info->var.hsync_len - 1) & 0x3f) << 26)
+               | ((info->var.left_margin & 0xff) << 18)
+               | (((info->var.xres - 1) & 0x3ff) << 8)
+               | (info->var.right_margin & 0xff), fbi->regbase + 0x4);
+       writel((((info->var.vsync_len - 1) & 0x3f) << 26)
+               | ((info->var.upper_margin & 0xff) << 18)
+               | (((info->var.yres - 1) & 0x3ff) << 8)
+               | (info->var.lower_margin & 0xff), fbi->regbase + 0x8);
+       writel((((info->var.yres - 1) & 0x400) << 2)
+               | ((info->var.xres - 1) & 0x400), fbi->regbase + 0x10);
+       writel(0x80000000, fbi->regbase + 0x20);
+       writel(control0 | (reg_bpp << 1) | 0x100, fbi->regbase);
+
+       return 0;
+}
+
+static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+       chan &= 0xffff;
+       chan >>= 16 - bf->length;
+       return chan << bf->offset;
+}
+
+static int vt8500lcd_setcolreg(unsigned regno, unsigned red, unsigned green,
+                          unsigned blue, unsigned transp,
+                          struct fb_info *info) {
+       struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
+       int ret = 1;
+       unsigned int val;
+       if (regno >= 256)
+               return -EINVAL;
+
+       if (info->var.grayscale)
+               red = green = blue =
+                       (19595 * red + 38470 * green + 7471 * blue) >> 16;
+
+       switch (fbi->fb.fix.visual) {
+       case FB_VISUAL_TRUECOLOR:
+               if (regno < 16) {
+                       u32 *pal = fbi->fb.pseudo_palette;
+
+                       val  = chan_to_field(red, &fbi->fb.var.red);
+                       val |= chan_to_field(green, &fbi->fb.var.green);
+                       val |= chan_to_field(blue, &fbi->fb.var.blue);
+
+                       pal[regno] = val;
+                       ret = 0;
+               }
+               break;
+
+       case FB_VISUAL_STATIC_PSEUDOCOLOR:
+       case FB_VISUAL_PSEUDOCOLOR:
+               writew((red & 0xf800)
+                     | ((green >> 5) & 0x7e0)
+                     | ((blue >> 11) & 0x1f),
+                      fbi->palette_cpu + sizeof(u16) * regno);
+               break;
+       }
+
+       return ret;
+}
+
+static int vt8500lcd_ioctl(struct fb_info *info, unsigned int cmd,
+                        unsigned long arg)
+{
+       int ret = 0;
+       struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
+
+       if (cmd == FBIO_WAITFORVSYNC) {
+               /* Unmask End of Frame interrupt */
+               writel(0xffffffff ^ (1 << 3), fbi->regbase + 0x3c);
+               ret = wait_event_interruptible_timeout(fbi->wait,
+                       readl(fbi->regbase + 0x38) & (1 << 3), HZ / 10);
+               /* Mask back to reduce unwanted interrupt traffic */
+               writel(0xffffffff, fbi->regbase + 0x3c);
+               if (ret < 0)
+                       return ret;
+               if (ret == 0)
+                       return -ETIMEDOUT;
+       }
+
+       return ret;
+}
+
+static int vt8500lcd_pan_display(struct fb_var_screeninfo *var,
+                               struct fb_info *info)
+{
+       unsigned pixlen = info->fix.line_length / info->var.xres_virtual;
+       unsigned off = pixlen * var->xoffset
+                     + info->fix.line_length * var->yoffset;
+       struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
+
+       writel((1 << 31)
+               | (((var->xres_virtual - var->xres) * pixlen / 4) << 20)
+               | (off >> 2), fbi->regbase + 0x20);
+       return 0;
+}
+
+static struct fb_ops vt8500lcd_ops = {
+       .owner          = THIS_MODULE,
+       .fb_set_par     = vt8500lcd_set_par,
+       .fb_setcolreg   = vt8500lcd_setcolreg,
+       .fb_fillrect    = wmt_ge_fillrect,
+       .fb_copyarea    = wmt_ge_copyarea,
+       .fb_imageblit   = sys_imageblit,
+       .fb_sync        = wmt_ge_sync,
+       .fb_ioctl       = vt8500lcd_ioctl,
+       .fb_pan_display = vt8500lcd_pan_display,
+};
+
+static irqreturn_t vt8500lcd_handle_irq(int irq, void *dev_id)
+{
+       struct vt8500lcd_info *fbi = dev_id;
+
+       if (readl(fbi->regbase + 0x38) & (1 << 3))
+               wake_up_interruptible(&fbi->wait);
+
+       writel(0xffffffff, fbi->regbase + 0x38);
+       return IRQ_HANDLED;
+}
+
+static int __devinit vt8500lcd_probe(struct platform_device *pdev)
+{
+       struct vt8500lcd_info *fbi;
+       struct resource *res;
+       struct vt8500fb_platform_data *pdata = pdev->dev.platform_data;
+       void *addr;
+       int irq, ret;
+
+       ret = -ENOMEM;
+       fbi = NULL;
+
+       fbi = kzalloc(sizeof(struct vt8500lcd_info) + sizeof(u32) * 16,
+                                                       GFP_KERNEL);
+       if (!fbi) {
+               dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
+               ret = -ENOMEM;
+               goto failed;
+       }
+
+       strcpy(fbi->fb.fix.id, "VT8500 LCD");
+
+       fbi->fb.fix.type        = FB_TYPE_PACKED_PIXELS;
+       fbi->fb.fix.xpanstep    = 0;
+       fbi->fb.fix.ypanstep    = 1;
+       fbi->fb.fix.ywrapstep   = 0;
+       fbi->fb.fix.accel       = FB_ACCEL_NONE;
+
+       fbi->fb.var.nonstd      = 0;
+       fbi->fb.var.activate    = FB_ACTIVATE_NOW;
+       fbi->fb.var.height      = -1;
+       fbi->fb.var.width       = -1;
+       fbi->fb.var.vmode       = FB_VMODE_NONINTERLACED;
+
+       fbi->fb.fbops           = &vt8500lcd_ops;
+       fbi->fb.flags           = FBINFO_DEFAULT
+                               | FBINFO_HWACCEL_COPYAREA
+                               | FBINFO_HWACCEL_FILLRECT
+                               | FBINFO_HWACCEL_YPAN
+                               | FBINFO_VIRTFB
+                               | FBINFO_PARTIAL_PAN_OK;
+       fbi->fb.node            = -1;
+
+       addr = fbi;
+       addr = addr + sizeof(struct vt8500lcd_info);
+       fbi->fb.pseudo_palette  = addr;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "no I/O memory resource defined\n");
+               ret = -ENODEV;
+               goto failed_fbi;
+       }
+
+       res = request_mem_region(res->start, resource_size(res), "vt8500lcd");
+       if (res == NULL) {
+               dev_err(&pdev->dev, "failed to request I/O memory\n");
+               ret = -EBUSY;
+               goto failed_fbi;
+       }
+
+       fbi->regbase = ioremap(res->start, resource_size(res));
+       if (fbi->regbase == NULL) {
+               dev_err(&pdev->dev, "failed to map I/O memory\n");
+               ret = -EBUSY;
+               goto failed_free_res;
+       }
+
+       fbi->fb.fix.smem_start  = pdata->video_mem_phys;
+       fbi->fb.fix.smem_len    = pdata->video_mem_len;
+       fbi->fb.screen_base     = pdata->video_mem_virt;
+
+       fbi->palette_size       = PAGE_ALIGN(512);
+       fbi->palette_cpu        = dma_alloc_coherent(&pdev->dev,
+                                                    fbi->palette_size,
+                                                    &fbi->palette_phys,
+                                                    GFP_KERNEL);
+       if (fbi->palette_cpu == NULL) {
+               dev_err(&pdev->dev, "Failed to allocate palette buffer\n");
+               ret = -ENOMEM;
+               goto failed_free_io;
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(&pdev->dev, "no IRQ defined\n");
+               ret = -ENODEV;
+               goto failed_free_palette;
+       }
+
+       ret = request_irq(irq, vt8500lcd_handle_irq, IRQF_DISABLED, "LCD", fbi);
+       if (ret) {
+               dev_err(&pdev->dev, "request_irq failed: %d\n", ret);
+               ret = -EBUSY;
+               goto failed_free_palette;
+       }
+
+       init_waitqueue_head(&fbi->wait);
+
+       if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
+               dev_err(&pdev->dev, "Failed to allocate color map\n");
+               ret = -ENOMEM;
+               goto failed_free_irq;
+       }
+
+       fb_videomode_to_var(&fbi->fb.var, &pdata->mode);
+       fbi->fb.var.bits_per_pixel      = pdata->bpp;
+       fbi->fb.var.xres_virtual        = pdata->xres_virtual;
+       fbi->fb.var.yres_virtual        = pdata->yres_virtual;
+
+       ret = vt8500lcd_set_par(&fbi->fb);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to set parameters\n");
+               goto failed_free_cmap;
+       }
+
+       writel(fbi->fb.fix.smem_start >> 22, fbi->regbase + 0x1c);
+       writel((fbi->palette_phys & 0xfffffe00) | 1, fbi->regbase + 0x18);
+
+       platform_set_drvdata(pdev, fbi);
+
+       ret = register_framebuffer(&fbi->fb);
+       if (ret < 0) {
+               dev_err(&pdev->dev,
+                       "Failed to register framebuffer device: %d\n", ret);
+               goto failed_free_cmap;
+       }
+
+       /*
+        * Ok, now enable the LCD controller
+        */
+       writel(readl(fbi->regbase) | 1, fbi->regbase);
+
+       return 0;
+
+failed_free_cmap:
+       if (fbi->fb.cmap.len)
+               fb_dealloc_cmap(&fbi->fb.cmap);
+failed_free_irq:
+       free_irq(irq, fbi);
+failed_free_palette:
+       dma_free_coherent(&pdev->dev, fbi->palette_size,
+                         fbi->palette_cpu, fbi->palette_phys);
+failed_free_io:
+       iounmap(fbi->regbase);
+failed_free_res:
+       release_mem_region(res->start, resource_size(res));
+failed_fbi:
+       platform_set_drvdata(pdev, NULL);
+       kfree(fbi);
+failed:
+       return ret;
+}
+
+static int __devexit vt8500lcd_remove(struct platform_device *pdev)
+{
+       struct vt8500lcd_info *fbi = platform_get_drvdata(pdev);
+       struct resource *res;
+       int irq;
+
+       unregister_framebuffer(&fbi->fb);
+
+       writel(0, fbi->regbase);
+
+       if (fbi->fb.cmap.len)
+               fb_dealloc_cmap(&fbi->fb.cmap);
+
+       irq = platform_get_irq(pdev, 0);
+       free_irq(irq, fbi);
+
+       dma_free_coherent(&pdev->dev, fbi->palette_size,
+                         fbi->palette_cpu, fbi->palette_phys);
+
+       iounmap(fbi->regbase);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(res->start, resource_size(res));
+
+       kfree(fbi);
+
+       return 0;
+}
+
+static struct platform_driver vt8500lcd_driver = {
+       .probe          = vt8500lcd_probe,
+       .remove         = __devexit_p(vt8500lcd_remove),
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = "vt8500-lcd",
+       },
+};
+
+static int __init vt8500lcd_init(void)
+{
+       return platform_driver_register(&vt8500lcd_driver);
+}
+
+static void __exit vt8500lcd_exit(void)
+{
+       platform_driver_unregister(&vt8500lcd_driver);
+}
+
+module_init(vt8500lcd_init);
+module_exit(vt8500lcd_exit);
+
+MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
+MODULE_DESCRIPTION("LCD controller driver for VIA VT8500");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/vt8500lcdfb.h b/drivers/video/vt8500lcdfb.h
new file mode 100644 (file)
index 0000000..36ca3ca
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *  linux/drivers/video/vt8500lcdfb.h
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+struct vt8500lcd_info {
+       struct fb_info          fb;
+       void __iomem            *regbase;
+       void __iomem            *palette_cpu;
+       dma_addr_t              palette_phys;
+       size_t                  palette_size;
+       wait_queue_head_t       wait;
+};
+
+static int bpp_values[] = {
+       1,
+       2,
+       4,
+       8,
+       12,
+       16,
+       18,
+       24,
+};
diff --git a/drivers/video/wm8505fb.c b/drivers/video/wm8505fb.c
new file mode 100644 (file)
index 0000000..96e34a5
--- /dev/null
@@ -0,0 +1,422 @@
+/*
+ *  WonderMedia WM8505 Frame Buffer device driver
+ *
+ *  Copyright (C) 2010 Ed Spiridonov <edo.rus@gmail.com>
+ *    Based on vt8500lcdfb.c
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/wait.h>
+
+#include <mach/vt8500fb.h>
+
+#include "wm8505fb_regs.h"
+#include "wmt_ge_rops.h"
+
+#define DRIVER_NAME "wm8505-fb"
+
+#define to_wm8505fb_info(__info) container_of(__info, \
+                                               struct wm8505fb_info, fb)
+struct wm8505fb_info {
+       struct fb_info          fb;
+       void __iomem            *regbase;
+       unsigned int            contrast;
+};
+
+
+static int wm8505fb_init_hw(struct fb_info *info)
+{
+       struct wm8505fb_info *fbi = to_wm8505fb_info(info);
+
+       int i;
+
+       /* I know the purpose only of few registers, so clear unknown */
+       for (i = 0; i < 0x200; i += 4)
+               writel(0, fbi->regbase + i);
+
+       /* Set frame buffer address */
+       writel(fbi->fb.fix.smem_start, fbi->regbase + WMT_GOVR_FBADDR);
+       writel(fbi->fb.fix.smem_start, fbi->regbase + WMT_GOVR_FBADDR1);
+
+       /* Set in-memory picture format to RGB 32bpp */
+       writel(0x1c,                   fbi->regbase + WMT_GOVR_COLORSPACE);
+       writel(1,                      fbi->regbase + WMT_GOVR_COLORSPACE1);
+
+       /* Virtual buffer size */
+       writel(info->var.xres,         fbi->regbase + WMT_GOVR_XRES);
+       writel(info->var.xres_virtual, fbi->regbase + WMT_GOVR_XRES_VIRTUAL);
+
+       /* black magic ;) */
+       writel(0xf,                    fbi->regbase + WMT_GOVR_FHI);
+       writel(4,                      fbi->regbase + WMT_GOVR_DVO_SET);
+       writel(1,                      fbi->regbase + WMT_GOVR_MIF_ENABLE);
+       writel(1,                      fbi->regbase + WMT_GOVR_REG_UPDATE);
+
+       return 0;
+}
+
+static int wm8505fb_set_timing(struct fb_info *info)
+{
+       struct wm8505fb_info *fbi = to_wm8505fb_info(info);
+
+       int h_start = info->var.left_margin;
+       int h_end = h_start + info->var.xres;
+       int h_all = h_end + info->var.right_margin;
+       int h_sync = info->var.hsync_len;
+
+       int v_start = info->var.upper_margin;
+       int v_end = v_start + info->var.yres;
+       int v_all = v_end + info->var.lower_margin;
+       int v_sync = info->var.vsync_len;
+
+       writel(0, fbi->regbase + WMT_GOVR_TG);
+
+       writel(h_start, fbi->regbase + WMT_GOVR_TIMING_H_START);
+       writel(h_end,   fbi->regbase + WMT_GOVR_TIMING_H_END);
+       writel(h_all,   fbi->regbase + WMT_GOVR_TIMING_H_ALL);
+       writel(h_sync,  fbi->regbase + WMT_GOVR_TIMING_H_SYNC);
+
+       writel(v_start, fbi->regbase + WMT_GOVR_TIMING_V_START);
+       writel(v_end,   fbi->regbase + WMT_GOVR_TIMING_V_END);
+       writel(v_all,   fbi->regbase + WMT_GOVR_TIMING_V_ALL);
+       writel(v_sync,  fbi->regbase + WMT_GOVR_TIMING_V_SYNC);
+
+       writel(1, fbi->regbase + WMT_GOVR_TG);
+
+       return 0;
+}
+
+
+static int wm8505fb_set_par(struct fb_info *info)
+{
+       struct wm8505fb_info *fbi = to_wm8505fb_info(info);
+
+       if (!fbi)
+               return -EINVAL;
+
+       if (info->var.bits_per_pixel == 32) {
+               info->var.red.offset = 16;
+               info->var.red.length = 8;
+               info->var.red.msb_right = 0;
+               info->var.green.offset = 8;
+               info->var.green.length = 8;
+               info->var.green.msb_right = 0;
+               info->var.blue.offset = 0;
+               info->var.blue.length = 8;
+               info->var.blue.msb_right = 0;
+               info->fix.visual = FB_VISUAL_TRUECOLOR;
+               info->fix.line_length = info->var.xres_virtual << 2;
+       }
+
+       wm8505fb_set_timing(info);
+
+       writel(fbi->contrast<<16 | fbi->contrast<<8 | fbi->contrast,
+               fbi->regbase + WMT_GOVR_CONTRAST);
+
+       return 0;
+}
+
+static ssize_t contrast_show(struct device *dev,
+                            struct device_attribute *attr, char *buf)
+{
+       struct fb_info *info = dev_get_drvdata(dev);
+       struct wm8505fb_info *fbi = to_wm8505fb_info(info);
+
+       return sprintf(buf, "%d\n", fbi->contrast);
+}
+
+static ssize_t contrast_store(struct device *dev,
+                             struct device_attribute *attr,
+                             const char *buf, size_t count)
+{
+       struct fb_info *info = dev_get_drvdata(dev);
+       struct wm8505fb_info *fbi = to_wm8505fb_info(info);
+       unsigned long tmp;
+
+       if (strict_strtoul(buf, 10, &tmp) || (tmp > 0xff))
+               return -EINVAL;
+       fbi->contrast = tmp;
+
+       wm8505fb_set_par(info);
+
+       return count;
+}
+
+static DEVICE_ATTR(contrast, 0644, contrast_show, contrast_store);
+
+static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+       chan &= 0xffff;
+       chan >>= 16 - bf->length;
+       return chan << bf->offset;
+}
+
+static int wm8505fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+                          unsigned blue, unsigned transp,
+                          struct fb_info *info) {
+       struct wm8505fb_info *fbi = to_wm8505fb_info(info);
+       int ret = 1;
+       unsigned int val;
+       if (regno >= 256)
+               return -EINVAL;
+
+       if (info->var.grayscale)
+               red = green = blue =
+                       (19595 * red + 38470 * green + 7471 * blue) >> 16;
+
+       switch (fbi->fb.fix.visual) {
+       case FB_VISUAL_TRUECOLOR:
+               if (regno < 16) {
+                       u32 *pal = info->pseudo_palette;
+
+                       val  = chan_to_field(red, &fbi->fb.var.red);
+                       val |= chan_to_field(green, &fbi->fb.var.green);
+                       val |= chan_to_field(blue, &fbi->fb.var.blue);
+
+                       pal[regno] = val;
+                       ret = 0;
+               }
+               break;
+       }
+
+       return ret;
+}
+
+static int wm8505fb_pan_display(struct fb_var_screeninfo *var,
+                               struct fb_info *info)
+{
+       struct wm8505fb_info *fbi = to_wm8505fb_info(info);
+
+       writel(var->xoffset, fbi->regbase + WMT_GOVR_XPAN);
+       writel(var->yoffset, fbi->regbase + WMT_GOVR_YPAN);
+       return 0;
+}
+
+static int wm8505fb_blank(int blank, struct fb_info *info)
+{
+       struct wm8505fb_info *fbi = to_wm8505fb_info(info);
+
+       switch (blank) {
+       case FB_BLANK_UNBLANK:
+               wm8505fb_set_timing(info);
+               break;
+       default:
+               writel(0,  fbi->regbase + WMT_GOVR_TIMING_V_SYNC);
+               break;
+       }
+
+       return 0;
+}
+
+static struct fb_ops wm8505fb_ops = {
+       .owner          = THIS_MODULE,
+       .fb_set_par     = wm8505fb_set_par,
+       .fb_setcolreg   = wm8505fb_setcolreg,
+       .fb_fillrect    = wmt_ge_fillrect,
+       .fb_copyarea    = wmt_ge_copyarea,
+       .fb_imageblit   = sys_imageblit,
+       .fb_sync        = wmt_ge_sync,
+       .fb_pan_display = wm8505fb_pan_display,
+       .fb_blank       = wm8505fb_blank,
+};
+
+static int __devinit wm8505fb_probe(struct platform_device *pdev)
+{
+       struct wm8505fb_info    *fbi;
+       struct resource         *res;
+       void                    *addr;
+       struct vt8500fb_platform_data *pdata;
+       int ret;
+
+       pdata = pdev->dev.platform_data;
+
+       ret = -ENOMEM;
+       fbi = NULL;
+
+       fbi = kzalloc(sizeof(struct wm8505fb_info) + sizeof(u32) * 16,
+                                                       GFP_KERNEL);
+       if (!fbi) {
+               dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
+               ret = -ENOMEM;
+               goto failed;
+       }
+
+       strcpy(fbi->fb.fix.id, DRIVER_NAME);
+
+       fbi->fb.fix.type        = FB_TYPE_PACKED_PIXELS;
+       fbi->fb.fix.xpanstep    = 1;
+       fbi->fb.fix.ypanstep    = 1;
+       fbi->fb.fix.ywrapstep   = 0;
+       fbi->fb.fix.accel       = FB_ACCEL_NONE;
+
+       fbi->fb.fbops           = &wm8505fb_ops;
+       fbi->fb.flags           = FBINFO_DEFAULT
+                               | FBINFO_HWACCEL_COPYAREA
+                               | FBINFO_HWACCEL_FILLRECT
+                               | FBINFO_HWACCEL_XPAN
+                               | FBINFO_HWACCEL_YPAN
+                               | FBINFO_VIRTFB
+                               | FBINFO_PARTIAL_PAN_OK;
+       fbi->fb.node            = -1;
+
+       addr = fbi;
+       addr = addr + sizeof(struct wm8505fb_info);
+       fbi->fb.pseudo_palette  = addr;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "no I/O memory resource defined\n");
+               ret = -ENODEV;
+               goto failed_fbi;
+       }
+
+       res = request_mem_region(res->start, resource_size(res), DRIVER_NAME);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "failed to request I/O memory\n");
+               ret = -EBUSY;
+               goto failed_fbi;
+       }
+
+       fbi->regbase = ioremap(res->start, resource_size(res));
+       if (fbi->regbase == NULL) {
+               dev_err(&pdev->dev, "failed to map I/O memory\n");
+               ret = -EBUSY;
+               goto failed_free_res;
+       }
+
+       fb_videomode_to_var(&fbi->fb.var, &pdata->mode);
+
+       fbi->fb.var.nonstd              = 0;
+       fbi->fb.var.activate            = FB_ACTIVATE_NOW;
+
+       fbi->fb.var.height              = -1;
+       fbi->fb.var.width               = -1;
+       fbi->fb.var.xres_virtual        = pdata->xres_virtual;
+       fbi->fb.var.yres_virtual        = pdata->yres_virtual;
+       fbi->fb.var.bits_per_pixel      = pdata->bpp;
+
+       fbi->fb.fix.smem_start  = pdata->video_mem_phys;
+       fbi->fb.fix.smem_len    = pdata->video_mem_len;
+       fbi->fb.screen_base     = pdata->video_mem_virt;
+       fbi->fb.screen_size     = pdata->video_mem_len;
+
+       if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
+               dev_err(&pdev->dev, "Failed to allocate color map\n");
+               ret = -ENOMEM;
+               goto failed_free_io;
+       }
+
+       wm8505fb_init_hw(&fbi->fb);
+
+       fbi->contrast = 0x80;
+       ret = wm8505fb_set_par(&fbi->fb);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to set parameters\n");
+               goto failed_free_cmap;
+       }
+
+       platform_set_drvdata(pdev, fbi);
+
+       ret = register_framebuffer(&fbi->fb);
+       if (ret < 0) {
+               dev_err(&pdev->dev,
+                       "Failed to register framebuffer device: %d\n", ret);
+               goto failed_free_cmap;
+       }
+
+       ret = device_create_file(&pdev->dev, &dev_attr_contrast);
+       if (ret < 0) {
+               printk(KERN_WARNING "fb%d: failed to register attributes (%d)\n",
+                       fbi->fb.node, ret);
+       }
+
+       printk(KERN_INFO "fb%d: %s frame buffer at 0x%lx-0x%lx\n",
+              fbi->fb.node, fbi->fb.fix.id, fbi->fb.fix.smem_start,
+              fbi->fb.fix.smem_start + fbi->fb.fix.smem_len - 1);
+
+       return 0;
+
+failed_free_cmap:
+       if (fbi->fb.cmap.len)
+               fb_dealloc_cmap(&fbi->fb.cmap);
+failed_free_io:
+       iounmap(fbi->regbase);
+failed_free_res:
+       release_mem_region(res->start, resource_size(res));
+failed_fbi:
+       platform_set_drvdata(pdev, NULL);
+       kfree(fbi);
+failed:
+       return ret;
+}
+
+static int __devexit wm8505fb_remove(struct platform_device *pdev)
+{
+       struct wm8505fb_info *fbi = platform_get_drvdata(pdev);
+       struct resource *res;
+
+       device_remove_file(&pdev->dev, &dev_attr_contrast);
+
+       unregister_framebuffer(&fbi->fb);
+
+       writel(0, fbi->regbase);
+
+       if (fbi->fb.cmap.len)
+               fb_dealloc_cmap(&fbi->fb.cmap);
+
+       iounmap(fbi->regbase);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(res->start, resource_size(res));
+
+       kfree(fbi);
+
+       return 0;
+}
+
+static struct platform_driver wm8505fb_driver = {
+       .probe          = wm8505fb_probe,
+       .remove         = __devexit_p(wm8505fb_remove),
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = DRIVER_NAME,
+       },
+};
+
+static int __init wm8505fb_init(void)
+{
+       return platform_driver_register(&wm8505fb_driver);
+}
+
+static void __exit wm8505fb_exit(void)
+{
+       platform_driver_unregister(&wm8505fb_driver);
+}
+
+module_init(wm8505fb_init);
+module_exit(wm8505fb_exit);
+
+MODULE_AUTHOR("Ed Spiridonov <edo.rus@gmail.com>");
+MODULE_DESCRIPTION("Framebuffer driver for WMT WM8505");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/wm8505fb_regs.h b/drivers/video/wm8505fb_regs.h
new file mode 100644 (file)
index 0000000..4dd4166
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ *  GOVR registers list for WM8505 chips
+ *
+ *  Copyright (C) 2010 Ed Spiridonov <edo.rus@gmail.com>
+ *   Based on VIA/WonderMedia wm8510-govrh-reg.h
+ *   http://github.com/projectgus/kernel_wm8505/blob/wm8505_2.6.29/
+ *         drivers/video/wmt/register/wm8510/wm8510-govrh-reg.h
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#ifndef _WM8505FB_REGS_H
+#define _WM8505FB_REGS_H
+
+/*
+ * Color space select register, default value 0x1c
+ *   BIT0 GOVRH_DVO_YUV2RGB_ENABLE
+ *   BIT1 GOVRH_VGA_YUV2RGB_ENABLE
+ *   BIT2 GOVRH_RGB_MODE
+ *   BIT3 GOVRH_DAC_CLKINV
+ *   BIT4 GOVRH_BLANK_ZERO
+ */
+#define WMT_GOVR_COLORSPACE    0x1e4
+/*
+ * Another colorspace select register, default value 1
+ *   BIT0 GOVRH_DVO_RGB
+ *   BIT1 GOVRH_DVO_YUV422
+ */
+#define WMT_GOVR_COLORSPACE1    0x30
+
+#define WMT_GOVR_CONTRAST      0x1b8
+#define WMT_GOVR_BRGHTNESS     0x1bc /* incompatible with RGB? */
+
+/* Framubeffer address */
+#define WMT_GOVR_FBADDR                 0x90
+#define WMT_GOVR_FBADDR1        0x94 /* UV offset in YUV mode */
+
+/* Offset of visible window */
+#define WMT_GOVR_XPAN           0xa4
+#define WMT_GOVR_YPAN           0xa0
+
+#define WMT_GOVR_XRES           0x98
+#define WMT_GOVR_XRES_VIRTUAL   0x9c
+
+#define WMT_GOVR_MIF_ENABLE     0x80
+#define WMT_GOVR_FHI            0xa8
+#define WMT_GOVR_REG_UPDATE     0xe4
+
+/*
+ *   BIT0 GOVRH_DVO_OUTWIDTH
+ *   BIT1 GOVRH_DVO_SYNC_POLAR
+ *   BIT2 GOVRH_DVO_ENABLE
+ */
+#define WMT_GOVR_DVO_SET       0x148
+
+/* Timing generator? */
+#define WMT_GOVR_TG            0x100
+
+/* Timings */
+#define WMT_GOVR_TIMING_H_ALL  0x108
+#define WMT_GOVR_TIMING_V_ALL  0x10c
+#define WMT_GOVR_TIMING_V_START        0x110
+#define WMT_GOVR_TIMING_V_END  0x114
+#define WMT_GOVR_TIMING_H_START        0x118
+#define WMT_GOVR_TIMING_H_END  0x11c
+#define WMT_GOVR_TIMING_V_SYNC 0x128
+#define WMT_GOVR_TIMING_H_SYNC 0x12c
+
+#endif /* _WM8505FB_REGS_H */
diff --git a/drivers/video/wmt_ge_rops.c b/drivers/video/wmt_ge_rops.c
new file mode 100644 (file)
index 0000000..45832b7
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ *  linux/drivers/video/wmt_ge_rops.c
+ *
+ *  Accelerators for raster operations using WonderMedia Graphics Engine
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/fb.h>
+#include <linux/platform_device.h>
+#include "fb_draw.h"
+
+#define GE_COMMAND_OFF         0x00
+#define GE_DEPTH_OFF           0x04
+#define GE_HIGHCOLOR_OFF       0x08
+#define GE_ROPCODE_OFF         0x14
+#define GE_FIRE_OFF            0x18
+#define GE_SRCBASE_OFF         0x20
+#define GE_SRCDISPW_OFF                0x24
+#define GE_SRCDISPH_OFF                0x28
+#define GE_SRCAREAX_OFF                0x2c
+#define GE_SRCAREAY_OFF                0x30
+#define GE_SRCAREAW_OFF                0x34
+#define GE_SRCAREAH_OFF                0x38
+#define GE_DESTBASE_OFF                0x3c
+#define GE_DESTDISPW_OFF       0x40
+#define GE_DESTDISPH_OFF       0x44
+#define GE_DESTAREAX_OFF       0x48
+#define GE_DESTAREAY_OFF       0x4c
+#define GE_DESTAREAW_OFF       0x50
+#define GE_DESTAREAH_OFF       0x54
+#define GE_PAT0C_OFF           0x88    /* Pattern 0 color */
+#define GE_ENABLE_OFF          0xec
+#define GE_INTEN_OFF           0xf0
+#define GE_STATUS_OFF          0xf8
+
+static void __iomem *regbase;
+
+void wmt_ge_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
+{
+       unsigned long fg, pat;
+
+       if (p->state != FBINFO_STATE_RUNNING)
+               return;
+
+       if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
+           p->fix.visual == FB_VISUAL_DIRECTCOLOR)
+               fg = ((u32 *) (p->pseudo_palette))[rect->color];
+       else
+               fg = rect->color;
+
+       pat = pixel_to_pat(p->var.bits_per_pixel, fg);
+
+       if (p->fbops->fb_sync)
+               p->fbops->fb_sync(p);
+
+       writel(p->var.bits_per_pixel == 32 ? 3 :
+             (p->var.bits_per_pixel == 8 ? 0 : 1), regbase + GE_DEPTH_OFF);
+       writel(p->var.bits_per_pixel == 15 ? 1 : 0, regbase + GE_HIGHCOLOR_OFF);
+       writel(p->fix.smem_start, regbase + GE_DESTBASE_OFF);
+       writel(p->var.xres_virtual - 1, regbase + GE_DESTDISPW_OFF);
+       writel(p->var.yres_virtual - 1, regbase + GE_DESTDISPH_OFF);
+       writel(rect->dx, regbase + GE_DESTAREAX_OFF);
+       writel(rect->dy, regbase + GE_DESTAREAY_OFF);
+       writel(rect->width - 1, regbase + GE_DESTAREAW_OFF);
+       writel(rect->height - 1, regbase + GE_DESTAREAH_OFF);
+
+       writel(pat, regbase + GE_PAT0C_OFF);
+       writel(1, regbase + GE_COMMAND_OFF);
+       writel(rect->rop == ROP_XOR ? 0x5a : 0xf0, regbase + GE_ROPCODE_OFF);
+       writel(1, regbase + GE_FIRE_OFF);
+}
+EXPORT_SYMBOL_GPL(wmt_ge_fillrect);
+
+void wmt_ge_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+{
+       if (p->state != FBINFO_STATE_RUNNING)
+               return;
+
+       if (p->fbops->fb_sync)
+               p->fbops->fb_sync(p);
+
+       writel(p->var.bits_per_pixel > 16 ? 3 :
+             (p->var.bits_per_pixel > 8 ? 1 : 0), regbase + GE_DEPTH_OFF);
+
+       writel(p->fix.smem_start, regbase + GE_SRCBASE_OFF);
+       writel(p->var.xres_virtual - 1, regbase + GE_SRCDISPW_OFF);
+       writel(p->var.yres_virtual - 1, regbase + GE_SRCDISPH_OFF);
+       writel(area->sx, regbase + GE_SRCAREAX_OFF);
+       writel(area->sy, regbase + GE_SRCAREAY_OFF);
+       writel(area->width - 1, regbase + GE_SRCAREAW_OFF);
+       writel(area->height - 1, regbase + GE_SRCAREAH_OFF);
+
+       writel(p->fix.smem_start, regbase + GE_DESTBASE_OFF);
+       writel(p->var.xres_virtual - 1, regbase + GE_DESTDISPW_OFF);
+       writel(p->var.yres_virtual - 1, regbase + GE_DESTDISPH_OFF);
+       writel(area->dx, regbase + GE_DESTAREAX_OFF);
+       writel(area->dy, regbase + GE_DESTAREAY_OFF);
+       writel(area->width - 1, regbase + GE_DESTAREAW_OFF);
+       writel(area->height - 1, regbase + GE_DESTAREAH_OFF);
+
+       writel(0xcc, regbase + GE_ROPCODE_OFF);
+       writel(1, regbase + GE_COMMAND_OFF);
+       writel(1, regbase + GE_FIRE_OFF);
+}
+EXPORT_SYMBOL_GPL(wmt_ge_copyarea);
+
+int wmt_ge_sync(struct fb_info *p)
+{
+       int loops = 5000000;
+       while ((readl(regbase + GE_STATUS_OFF) & 4) && --loops)
+               cpu_relax();
+       return loops > 0 ? 0 : -EBUSY;
+}
+EXPORT_SYMBOL_GPL(wmt_ge_sync);
+
+static int __devinit wmt_ge_rops_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "no I/O memory resource defined\n");
+               return -ENODEV;
+       }
+
+       /* Only one ROP engine is presently supported. */
+       if (unlikely(regbase)) {
+               WARN_ON(1);
+               return -EBUSY;
+       }
+
+       regbase = ioremap(res->start, resource_size(res));
+       if (regbase == NULL) {
+               dev_err(&pdev->dev, "failed to map I/O memory\n");
+               return -EBUSY;
+       }
+
+       writel(1, regbase + GE_ENABLE_OFF);
+       printk(KERN_INFO "Enabled support for WMT GE raster acceleration\n");
+
+       return 0;
+}
+
+static int __devexit wmt_ge_rops_remove(struct platform_device *pdev)
+{
+       iounmap(regbase);
+       return 0;
+}
+
+static struct platform_driver wmt_ge_rops_driver = {
+       .probe          = wmt_ge_rops_probe,
+       .remove         = __devexit_p(wmt_ge_rops_remove),
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = "wmt_ge_rops",
+       },
+};
+
+static int __init wmt_ge_rops_init(void)
+{
+       return platform_driver_register(&wmt_ge_rops_driver);
+}
+
+static void __exit wmt_ge_rops_exit(void)
+{
+       platform_driver_unregister(&wmt_ge_rops_driver);
+}
+
+module_init(wmt_ge_rops_init);
+module_exit(wmt_ge_rops_exit);
+
+MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com");
+MODULE_DESCRIPTION("Accelerators for raster operations using "
+                  "WonderMedia Graphics Engine");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/wmt_ge_rops.h b/drivers/video/wmt_ge_rops.h
new file mode 100644 (file)
index 0000000..8738075
--- /dev/null
@@ -0,0 +1,5 @@
+extern void wmt_ge_fillrect(struct fb_info *info,
+                           const struct fb_fillrect *rect);
+extern void wmt_ge_copyarea(struct fb_info *info,
+                           const struct fb_copyarea *area);
+extern int wmt_ge_sync(struct fb_info *info);
index 3a43ebf83a49d6b869339e8f94da1f097141cb07..efb35aa8309abe0397bc8f1c7fd8f88da6ded96d 100644 (file)
@@ -9,19 +9,19 @@ static ssize_t device_show(struct device *_d,
                           struct device_attribute *attr, char *buf)
 {
        struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
-       return sprintf(buf, "%hu", dev->id.device);
+       return sprintf(buf, "0x%04x\n", dev->id.device);
 }
 static ssize_t vendor_show(struct device *_d,
                           struct device_attribute *attr, char *buf)
 {
        struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
-       return sprintf(buf, "%hu", dev->id.vendor);
+       return sprintf(buf, "0x%04x\n", dev->id.vendor);
 }
 static ssize_t status_show(struct device *_d,
                           struct device_attribute *attr, char *buf)
 {
        struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
-       return sprintf(buf, "0x%08x", dev->config->get_status(dev));
+       return sprintf(buf, "0x%08x\n", dev->config->get_status(dev));
 }
 static ssize_t modalias_show(struct device *_d,
                             struct device_attribute *attr, char *buf)
index 1475ed6b575fd7a9984380b9e0841ac5f019a306..cc2f73e03475b620053765b373c8b1a39fc08762 100644 (file)
@@ -230,9 +230,6 @@ add_head:
        pr_debug("Added buffer head %i to %p\n", head, vq);
        END_USE(vq);
 
-       /* If we're indirect, we can fit many (assuming not OOM). */
-       if (vq->indirect)
-               return vq->num_free ? vq->vring.num : 0;
        return vq->num_free;
 }
 EXPORT_SYMBOL_GPL(virtqueue_add_buf_gfp);
index 4a291045ebac16696cda5539a824a1207def3d33..a5ad77ef4266f22b166d8d86a5484aec5094178f 100644 (file)
@@ -558,6 +558,9 @@ config IT8712F_WDT
          This is the driver for the built-in watchdog timer on the IT8712F
          Super I/0 chipset used on many motherboards.
 
+         If the driver does not work, then make sure that the game port in
+         the BIOS is enabled.
+
          To compile this driver as a module, choose M here: the
          module will be called it8712f_wdt.
 
index a1debc89356b0c0c0f4d01b839b5bc0dfbfefb36..3c5045a206ddbded9e82fbb9db41fa5fa50c178d 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/miscdevice.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/reboot.h>
 #include <linux/types.h>
 #include <linux/uaccess.h>
 #include <linux/watchdog.h>
@@ -220,14 +219,6 @@ static long bcm63xx_wdt_ioctl(struct file *file, unsigned int cmd,
        }
 }
 
-static int bcm63xx_wdt_notify_sys(struct notifier_block *this,
-                               unsigned long code, void *unused)
-{
-       if (code == SYS_DOWN || code == SYS_HALT)
-               bcm63xx_wdt_pause();
-       return NOTIFY_DONE;
-}
-
 static const struct file_operations bcm63xx_wdt_fops = {
        .owner          = THIS_MODULE,
        .llseek         = no_llseek,
@@ -243,12 +234,8 @@ static struct miscdevice bcm63xx_wdt_miscdev = {
        .fops   = &bcm63xx_wdt_fops,
 };
 
-static struct notifier_block bcm63xx_wdt_notifier = {
-       .notifier_call = bcm63xx_wdt_notify_sys,
-};
 
-
-static int bcm63xx_wdt_probe(struct platform_device *pdev)
+static int __devinit bcm63xx_wdt_probe(struct platform_device *pdev)
 {
        int ret;
        struct resource *r;
@@ -280,16 +267,10 @@ static int bcm63xx_wdt_probe(struct platform_device *pdev)
                        wdt_time);
        }
 
-       ret = register_reboot_notifier(&bcm63xx_wdt_notifier);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to register reboot_notifier\n");
-               goto unregister_timer;
-       }
-
        ret = misc_register(&bcm63xx_wdt_miscdev);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to register watchdog device\n");
-               goto unregister_reboot_notifier;
+               goto unregister_timer;
        }
 
        dev_info(&pdev->dev, " started, timer margin: %d sec\n",
@@ -297,8 +278,6 @@ static int bcm63xx_wdt_probe(struct platform_device *pdev)
 
        return 0;
 
-unregister_reboot_notifier:
-       unregister_reboot_notifier(&bcm63xx_wdt_notifier);
 unregister_timer:
        bcm63xx_timer_unregister(TIMER_WDT_ID);
 unmap:
@@ -306,25 +285,28 @@ unmap:
        return ret;
 }
 
-static int bcm63xx_wdt_remove(struct platform_device *pdev)
+static int __devexit bcm63xx_wdt_remove(struct platform_device *pdev)
 {
        if (!nowayout)
                bcm63xx_wdt_pause();
 
        misc_deregister(&bcm63xx_wdt_miscdev);
-
-       iounmap(bcm63xx_wdt_device.regs);
-
-       unregister_reboot_notifier(&bcm63xx_wdt_notifier);
        bcm63xx_timer_unregister(TIMER_WDT_ID);
-
+       iounmap(bcm63xx_wdt_device.regs);
        return 0;
 }
 
+static void bcm63xx_wdt_shutdown(struct platform_device *pdev)
+{
+       bcm63xx_wdt_pause();
+}
+
 static struct platform_driver bcm63xx_wdt = {
        .probe  = bcm63xx_wdt_probe,
-       .remove = bcm63xx_wdt_remove,
+       .remove = __devexit_p(bcm63xx_wdt_remove),
+       .shutdown = bcm63xx_wdt_shutdown,
        .driver = {
+               .owner = THIS_MODULE,
                .name = "bcm63xx-wdt",
        }
 };
index 9c21d19043a63980372d032ceee5d2933e3a591f..f6bd6f10fcece63c04aa106ca84b54f8684c7896 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/module.h>
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
+#include <linux/fs.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/io.h>
index f7e90fe47b71fb823620ed06496370cfcf6b3c30..b8838d2c67a63bae588a7a06edbe0fb4c796f822 100644 (file)
@@ -32,6 +32,7 @@
  *     document number 322169-001, 322170-003: 5 Series, 3400 Series (PCH)
  *     document number 320066-003, 320257-008: EP80597 (IICH)
  *     document number TBD                   : Cougar Point (CPT)
+ *     document number TBD                   : Patsburg (PBG)
  */
 
 /*
@@ -146,7 +147,8 @@ enum iTCO_chipsets {
        TCO_CPT29,      /* Cougar Point */
        TCO_CPT30,      /* Cougar Point */
        TCO_CPT31,      /* Cougar Point */
-       TCO_PBG,        /* Patsburg */
+       TCO_PBG1,       /* Patsburg */
+       TCO_PBG2,       /* Patsburg */
 };
 
 static struct {
@@ -235,6 +237,7 @@ static struct {
        {"Cougar Point", 2},
        {"Cougar Point", 2},
        {"Patsburg", 2},
+       {"Patsburg", 2},
        {NULL, 0}
 };
 
@@ -350,7 +353,8 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = {
        { ITCO_PCI_DEVICE(0x1c5d,                               TCO_CPT29)},
        { ITCO_PCI_DEVICE(0x1c5e,                               TCO_CPT30)},
        { ITCO_PCI_DEVICE(0x1c5f,                               TCO_CPT31)},
-       { ITCO_PCI_DEVICE(0x1d40,                               TCO_PBG)},
+       { ITCO_PCI_DEVICE(0x1d40,                               TCO_PBG1)},
+       { ITCO_PCI_DEVICE(0x1d41,                               TCO_PBG2)},
        { 0, },                 /* End of list */
 };
 MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl);
index eb8a78d77d9d2a7fb70f81ac54ae902e6b29204d..533a199e7a3f94911ef9665ab5e1789c63bef6d2 100644 (file)
@@ -8,9 +8,12 @@ obj-$(CONFIG_BLOCK)            += biomerge.o
 obj-$(CONFIG_HOTPLUG_CPU)      += cpu_hotplug.o
 obj-$(CONFIG_XEN_XENCOMM)      += xencomm.o
 obj-$(CONFIG_XEN_BALLOON)      += balloon.o
-obj-$(CONFIG_XEN_DEV_EVTCHN)   += evtchn.o
+obj-$(CONFIG_XEN_DEV_EVTCHN)   += xen-evtchn.o
 obj-$(CONFIG_XENFS)            += xenfs/
 obj-$(CONFIG_XEN_SYS_HYPERVISOR)       += sys-hypervisor.o
 obj-$(CONFIG_XEN_PLATFORM_PCI) += platform-pci.o
 obj-$(CONFIG_SWIOTLB_XEN)      += swiotlb-xen.o
 obj-$(CONFIG_XEN_DOM0)         += pci.o
+
+xen-evtchn-y                   := evtchn.o
+
index 500290b150bb526cf27b9f5e82d9a08b160a2d91..43f9f02c7db0671668343fc19bed043fbbe61fad 100644 (file)
@@ -50,6 +50,7 @@
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
 #include <asm/tlb.h>
+#include <asm/e820.h>
 
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
@@ -119,7 +120,7 @@ static void scrub_page(struct page *page)
 }
 
 /* balloon_append: add the given page to the balloon. */
-static void balloon_append(struct page *page)
+static void __balloon_append(struct page *page)
 {
        /* Lowmem is re-populated first, so highmem pages go at list tail. */
        if (PageHighMem(page)) {
@@ -130,7 +131,11 @@ static void balloon_append(struct page *page)
                list_add(&page->lru, &ballooned_pages);
                balloon_stats.balloon_low++;
        }
+}
 
+static void balloon_append(struct page *page)
+{
+       __balloon_append(page);
        totalram_pages--;
 }
 
@@ -191,7 +196,7 @@ static unsigned long current_target(void)
 
 static int increase_reservation(unsigned long nr_pages)
 {
-       unsigned long  pfn, i, flags;
+       unsigned long  pfn, i;
        struct page   *page;
        long           rc;
        struct xen_memory_reservation reservation = {
@@ -203,8 +208,6 @@ static int increase_reservation(unsigned long nr_pages)
        if (nr_pages > ARRAY_SIZE(frame_list))
                nr_pages = ARRAY_SIZE(frame_list);
 
-       spin_lock_irqsave(&xen_reservation_lock, flags);
-
        page = balloon_first_page();
        for (i = 0; i < nr_pages; i++) {
                BUG_ON(page == NULL);
@@ -247,14 +250,12 @@ static int increase_reservation(unsigned long nr_pages)
        balloon_stats.current_pages += rc;
 
  out:
-       spin_unlock_irqrestore(&xen_reservation_lock, flags);
-
        return rc < 0 ? rc : rc != nr_pages;
 }
 
 static int decrease_reservation(unsigned long nr_pages)
 {
-       unsigned long  pfn, i, flags;
+       unsigned long  pfn, i;
        struct page   *page;
        int            need_sleep = 0;
        int ret;
@@ -292,8 +293,6 @@ static int decrease_reservation(unsigned long nr_pages)
        kmap_flush_unused();
        flush_tlb_all();
 
-       spin_lock_irqsave(&xen_reservation_lock, flags);
-
        /* No more mappings: invalidate P2M and add to balloon. */
        for (i = 0; i < nr_pages; i++) {
                pfn = mfn_to_pfn(frame_list[i]);
@@ -308,8 +307,6 @@ static int decrease_reservation(unsigned long nr_pages)
 
        balloon_stats.current_pages -= nr_pages;
 
-       spin_unlock_irqrestore(&xen_reservation_lock, flags);
-
        return need_sleep;
 }
 
@@ -395,7 +392,7 @@ static struct notifier_block xenstore_notifier;
 
 static int __init balloon_init(void)
 {
-       unsigned long pfn;
+       unsigned long pfn, extra_pfn_end;
        struct page *page;
 
        if (!xen_pv_domain())
@@ -415,11 +412,24 @@ static int __init balloon_init(void)
 
        register_balloon(&balloon_sysdev);
 
-       /* Initialise the balloon with excess memory space. */
-       for (pfn = xen_start_info->nr_pages; pfn < max_pfn; pfn++) {
+       /*
+        * Initialise the balloon with excess memory space.  We need
+        * to make sure we don't add memory which doesn't exist or
+        * logically exist.  The E820 map can be trimmed to be smaller
+        * than the amount of physical memory due to the mem= command
+        * line parameter.  And if this is a 32-bit non-HIGHMEM kernel
+        * on a system with memory which requires highmem to access,
+        * don't try to use it.
+        */
+       extra_pfn_end = min(min(max_pfn, e820_end_of_ram_pfn()),
+                           (unsigned long)PFN_DOWN(xen_extra_mem_start + xen_extra_mem_size));
+       for (pfn = PFN_UP(xen_extra_mem_start);
+            pfn < extra_pfn_end;
+            pfn++) {
                page = pfn_to_page(pfn);
-               if (!PageReserved(page))
-                       balloon_append(page);
+               /* totalram_pages doesn't include the boot-time
+                  balloon extension, so don't subtract from it. */
+               __balloon_append(page);
        }
 
        target_watch.callback = watch_target;
index 321a0c8346e581bc3504ac0891b7b4883d98589c..31af0ac31a98bffc310cfb79bcaa2d7e03393e81 100644 (file)
@@ -105,7 +105,6 @@ struct irq_info
 
 static struct irq_info *irq_info;
 static int *pirq_to_irq;
-static int nr_pirqs;
 
 static int *evtchn_to_irq;
 struct cpu_evtchn_s {
@@ -278,17 +277,17 @@ static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
        cpumask_copy(irq_to_desc(irq)->affinity, cpumask_of(cpu));
 #endif
 
-       __clear_bit(chn, cpu_evtchn_mask(cpu_from_irq(irq)));
-       __set_bit(chn, cpu_evtchn_mask(cpu));
+       clear_bit(chn, cpu_evtchn_mask(cpu_from_irq(irq)));
+       set_bit(chn, cpu_evtchn_mask(cpu));
 
        irq_info[irq].cpu = cpu;
 }
 
 static void init_evtchn_cpu_bindings(void)
 {
+       int i;
 #ifdef CONFIG_SMP
        struct irq_desc *desc;
-       int i;
 
        /* By default all event channels notify CPU#0. */
        for_each_irq_desc(i, desc) {
@@ -296,7 +295,10 @@ static void init_evtchn_cpu_bindings(void)
        }
 #endif
 
-       memset(cpu_evtchn_mask(0), ~0, sizeof(struct cpu_evtchn_s));
+       for_each_possible_cpu(i)
+               memset(cpu_evtchn_mask(i),
+                      (i == 0) ? ~0 : 0, sizeof(struct cpu_evtchn_s));
+
 }
 
 static inline void clear_evtchn(int port)
@@ -382,12 +384,17 @@ static int get_nr_hw_irqs(void)
        return ret;
 }
 
-/* callers of this function should make sure that PHYSDEVOP_get_nr_pirqs
- * succeeded otherwise nr_pirqs won't hold the right value */
-static int find_unbound_pirq(void)
+static int find_unbound_pirq(int type)
 {
-       int i;
-       for (i = nr_pirqs-1; i >= 0; i--) {
+       int rc, i;
+       struct physdev_get_free_pirq op_get_free_pirq;
+       op_get_free_pirq.type = type;
+
+       rc = HYPERVISOR_physdev_op(PHYSDEVOP_get_free_pirq, &op_get_free_pirq);
+       if (!rc)
+               return op_get_free_pirq.pirq;
+
+       for (i = 0; i < nr_irqs; i++) {
                if (pirq_to_irq[i] < 0)
                        return i;
        }
@@ -420,7 +427,7 @@ static int find_unbound_irq(void)
        if (irq == start)
                goto no_irqs;
 
-       res = irq_alloc_desc_at(irq, 0);
+       res = irq_alloc_desc_at(irq, -1);
 
        if (WARN_ON(res != irq))
                return -1;
@@ -608,10 +615,10 @@ int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name)
 
        spin_lock(&irq_mapping_update_lock);
 
-       if ((pirq > nr_pirqs) || (gsi > nr_irqs)) {
+       if ((pirq > nr_irqs) || (gsi > nr_irqs)) {
                printk(KERN_WARNING "xen_map_pirq_gsi: %s %s is incorrect!\n",
-                       pirq > nr_pirqs ? "nr_pirqs" :"",
-                       gsi > nr_irqs ? "nr_irqs" : "");
+                       pirq > nr_irqs ? "pirq" :"",
+                       gsi > nr_irqs ? "gsi" : "");
                goto out;
        }
 
@@ -627,7 +634,7 @@ int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name)
        if (identity_mapped_irq(gsi) || (!xen_initial_domain() &&
                                xen_pv_domain())) {
                irq = gsi;
-               irq_alloc_desc_at(irq, 0);
+               irq_alloc_desc_at(irq, -1);
        } else
                irq = find_unbound_irq();
 
@@ -661,17 +668,21 @@ out:
 #include <linux/msi.h>
 #include "../pci/msi.h"
 
-void xen_allocate_pirq_msi(char *name, int *irq, int *pirq)
+void xen_allocate_pirq_msi(char *name, int *irq, int *pirq, int alloc)
 {
        spin_lock(&irq_mapping_update_lock);
 
-       *irq = find_unbound_irq();
-       if (*irq == -1)
-               goto out;
+       if (alloc & XEN_ALLOC_IRQ) {
+               *irq = find_unbound_irq();
+               if (*irq == -1)
+                       goto out;
+       }
 
-       *pirq = find_unbound_pirq();
-       if (*pirq == -1)
-               goto out;
+       if (alloc & XEN_ALLOC_PIRQ) {
+               *pirq = find_unbound_pirq(MAP_PIRQ_TYPE_MSI);
+               if (*pirq == -1)
+                       goto out;
+       }
 
        set_irq_chip_and_handler_name(*irq, &xen_pirq_chip,
                                      handle_level_irq, name);
@@ -752,13 +763,14 @@ int xen_destroy_irq(int irq)
                goto out;
 
        if (xen_initial_domain()) {
-               unmap_irq.pirq = info->u.pirq.gsi;
+               unmap_irq.pirq = info->u.pirq.pirq;
                unmap_irq.domid = DOMID_SELF;
                rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq);
                if (rc) {
                        printk(KERN_WARNING "unmap irq failed %d\n", rc);
                        goto out;
                }
+               pirq_to_irq[info->u.pirq.pirq] = -1;
        }
        irq_info[irq] = mk_unbound_info();
 
@@ -779,6 +791,11 @@ int xen_gsi_from_irq(unsigned irq)
        return gsi_from_irq(irq);
 }
 
+int xen_irq_from_pirq(unsigned pirq)
+{
+       return pirq_to_irq[pirq];
+}
+
 int bind_evtchn_to_irq(unsigned int evtchn)
 {
        int irq;
@@ -1276,6 +1293,42 @@ static int retrigger_dynirq(unsigned int irq)
        return ret;
 }
 
+static void restore_cpu_pirqs(void)
+{
+       int pirq, rc, irq, gsi;
+       struct physdev_map_pirq map_irq;
+
+       for (pirq = 0; pirq < nr_irqs; pirq++) {
+               irq = pirq_to_irq[pirq];
+               if (irq == -1)
+                       continue;
+
+               /* save/restore of PT devices doesn't work, so at this point the
+                * only devices present are GSI based emulated devices */
+               gsi = gsi_from_irq(irq);
+               if (!gsi)
+                       continue;
+
+               map_irq.domid = DOMID_SELF;
+               map_irq.type = MAP_PIRQ_TYPE_GSI;
+               map_irq.index = gsi;
+               map_irq.pirq = pirq;
+
+               rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
+               if (rc) {
+                       printk(KERN_WARNING "xen map irq failed gsi=%d irq=%d pirq=%d rc=%d\n",
+                                       gsi, irq, pirq, rc);
+                       irq_info[irq] = mk_unbound_info();
+                       pirq_to_irq[pirq] = -1;
+                       continue;
+               }
+
+               printk(KERN_DEBUG "xen: --> irq=%d, pirq=%d\n", irq, map_irq.pirq);
+
+               startup_pirq(irq);
+       }
+}
+
 static void restore_cpu_virqs(unsigned int cpu)
 {
        struct evtchn_bind_virq bind_virq;
@@ -1419,6 +1472,8 @@ void xen_irq_resume(void)
 
                unmask_evtchn(evtchn);
        }
+
+       restore_cpu_pirqs();
 }
 
 static struct irq_chip xen_dynamic_chip __read_mostly = {
@@ -1503,26 +1558,17 @@ void xen_callback_vector(void) {}
 
 void __init xen_init_IRQ(void)
 {
-       int i, rc;
-       struct physdev_nr_pirqs op_nr_pirqs;
+       int i;
 
        cpu_evtchn_mask_p = kcalloc(nr_cpu_ids, sizeof(struct cpu_evtchn_s),
                                    GFP_KERNEL);
        irq_info = kcalloc(nr_irqs, sizeof(*irq_info), GFP_KERNEL);
 
-       rc = HYPERVISOR_physdev_op(PHYSDEVOP_get_nr_pirqs, &op_nr_pirqs);
-       if (rc < 0) {
-               nr_pirqs = nr_irqs;
-               if (rc != -ENOSYS)
-                       printk(KERN_WARNING "PHYSDEVOP_get_nr_pirqs returned rc=%d\n", rc);
-       } else {
-               if (xen_pv_domain() && !xen_initial_domain())
-                       nr_pirqs = max((int)op_nr_pirqs.nr_pirqs, nr_irqs);
-               else
-                       nr_pirqs = op_nr_pirqs.nr_pirqs;
-       }
-       pirq_to_irq = kcalloc(nr_pirqs, sizeof(*pirq_to_irq), GFP_KERNEL);
-       for (i = 0; i < nr_pirqs; i++)
+       /* We are using nr_irqs as the maximum number of pirq available but
+        * that number is actually chosen by Xen and we don't know exactly
+        * what it is. Be careful choosing high pirq numbers. */
+       pirq_to_irq = kcalloc(nr_irqs, sizeof(*pirq_to_irq), GFP_KERNEL);
+       for (i = 0; i < nr_irqs; i++)
                pirq_to_irq[i] = -1;
 
        evtchn_to_irq = kcalloc(NR_EVENT_CHANNELS, sizeof(*evtchn_to_irq),
index fec6ba3c08a8e885d663ce3ac9c8b031ff971273..ef11daf0cafe9f086f3944b42fd32ff48811f4b2 100644 (file)
@@ -69,20 +69,51 @@ struct per_user_data {
        const char *name;
 };
 
-/* Who's bound to each port? */
-static struct per_user_data *port_user[NR_EVENT_CHANNELS];
+/*
+ * Who's bound to each port?  This is logically an array of struct
+ * per_user_data *, but we encode the current enabled-state in bit 0.
+ */
+static unsigned long *port_user;
 static DEFINE_SPINLOCK(port_user_lock); /* protects port_user[] and ring_prod */
 
-irqreturn_t evtchn_interrupt(int irq, void *data)
+static inline struct per_user_data *get_port_user(unsigned port)
+{
+       return (struct per_user_data *)(port_user[port] & ~1);
+}
+
+static inline void set_port_user(unsigned port, struct per_user_data *u)
+{
+       port_user[port] = (unsigned long)u;
+}
+
+static inline bool get_port_enabled(unsigned port)
+{
+       return port_user[port] & 1;
+}
+
+static inline void set_port_enabled(unsigned port, bool enabled)
+{
+       if (enabled)
+               port_user[port] |= 1;
+       else
+               port_user[port] &= ~1;
+}
+
+static irqreturn_t evtchn_interrupt(int irq, void *data)
 {
        unsigned int port = (unsigned long)data;
        struct per_user_data *u;
 
        spin_lock(&port_user_lock);
 
-       u = port_user[port];
+       u = get_port_user(port);
+
+       WARN(!get_port_enabled(port),
+            "Interrupt for port %d, but apparently not enabled; per-user %p\n",
+            port, u);
 
        disable_irq_nosync(irq);
+       set_port_enabled(port, false);
 
        if ((u->ring_prod - u->ring_cons) < EVTCHN_RING_SIZE) {
                u->ring[EVTCHN_RING_MASK(u->ring_prod)] = port;
@@ -92,9 +123,8 @@ irqreturn_t evtchn_interrupt(int irq, void *data)
                        kill_fasync(&u->evtchn_async_queue,
                                    SIGIO, POLL_IN);
                }
-       } else {
+       } else
                u->ring_overflow = 1;
-       }
 
        spin_unlock(&port_user_lock);
 
@@ -198,9 +228,18 @@ static ssize_t evtchn_write(struct file *file, const char __user *buf,
                goto out;
 
        spin_lock_irq(&port_user_lock);
-       for (i = 0; i < (count/sizeof(evtchn_port_t)); i++)
-               if ((kbuf[i] < NR_EVENT_CHANNELS) && (port_user[kbuf[i]] == u))
-                       enable_irq(irq_from_evtchn(kbuf[i]));
+
+       for (i = 0; i < (count/sizeof(evtchn_port_t)); i++) {
+               unsigned port = kbuf[i];
+
+               if (port < NR_EVENT_CHANNELS &&
+                   get_port_user(port) == u &&
+                   !get_port_enabled(port)) {
+                       set_port_enabled(port, true);
+                       enable_irq(irq_from_evtchn(port));
+               }
+       }
+
        spin_unlock_irq(&port_user_lock);
 
        rc = count;
@@ -222,8 +261,9 @@ static int evtchn_bind_to_user(struct per_user_data *u, int port)
         * interrupt handler yet, and our caller has already
         * serialized bind operations.)
         */
-       BUG_ON(port_user[port] != NULL);
-       port_user[port] = u;
+       BUG_ON(get_port_user(port) != NULL);
+       set_port_user(port, u);
+       set_port_enabled(port, true); /* start enabled */
 
        rc = bind_evtchn_to_irqhandler(port, evtchn_interrupt, IRQF_DISABLED,
                                       u->name, (void *)(unsigned long)port);
@@ -239,10 +279,7 @@ static void evtchn_unbind_from_user(struct per_user_data *u, int port)
 
        unbind_from_irqhandler(irq, (void *)(unsigned long)port);
 
-       /* make sure we unbind the irq handler before clearing the port */
-       barrier();
-
-       port_user[port] = NULL;
+       set_port_user(port, NULL);
 }
 
 static long evtchn_ioctl(struct file *file,
@@ -333,15 +370,17 @@ static long evtchn_ioctl(struct file *file,
                spin_lock_irq(&port_user_lock);
 
                rc = -ENOTCONN;
-               if (port_user[unbind.port] != u) {
+               if (get_port_user(unbind.port) != u) {
                        spin_unlock_irq(&port_user_lock);
                        break;
                }
 
-               evtchn_unbind_from_user(u, unbind.port);
+               disable_irq(irq_from_evtchn(unbind.port));
 
                spin_unlock_irq(&port_user_lock);
 
+               evtchn_unbind_from_user(u, unbind.port);
+
                rc = 0;
                break;
        }
@@ -355,7 +394,7 @@ static long evtchn_ioctl(struct file *file,
 
                if (notify.port >= NR_EVENT_CHANNELS) {
                        rc = -EINVAL;
-               } else if (port_user[notify.port] != u) {
+               } else if (get_port_user(notify.port) != u) {
                        rc = -ENOTCONN;
                } else {
                        notify_remote_via_evtchn(notify.port);
@@ -431,7 +470,7 @@ static int evtchn_open(struct inode *inode, struct file *filp)
 
        filp->private_data = u;
 
-       return 0;
+       return nonseekable_open(inode, filp);;
 }
 
 static int evtchn_release(struct inode *inode, struct file *filp)
@@ -444,14 +483,21 @@ static int evtchn_release(struct inode *inode, struct file *filp)
        free_page((unsigned long)u->ring);
 
        for (i = 0; i < NR_EVENT_CHANNELS; i++) {
-               if (port_user[i] != u)
+               if (get_port_user(i) != u)
                        continue;
 
-               evtchn_unbind_from_user(port_user[i], i);
+               disable_irq(irq_from_evtchn(i));
        }
 
        spin_unlock_irq(&port_user_lock);
 
+       for (i = 0; i < NR_EVENT_CHANNELS; i++) {
+               if (get_port_user(i) != u)
+                       continue;
+
+               evtchn_unbind_from_user(get_port_user(i), i);
+       }
+
        kfree(u->name);
        kfree(u);
 
@@ -467,12 +513,12 @@ static const struct file_operations evtchn_fops = {
        .fasync  = evtchn_fasync,
        .open    = evtchn_open,
        .release = evtchn_release,
-       .llseek = noop_llseek,
+       .llseek  = no_llseek,
 };
 
 static struct miscdevice evtchn_miscdev = {
        .minor        = MISC_DYNAMIC_MINOR,
-       .name         = "evtchn",
+       .name         = "xen/evtchn",
        .fops         = &evtchn_fops,
 };
 static int __init evtchn_init(void)
@@ -482,8 +528,11 @@ static int __init evtchn_init(void)
        if (!xen_domain())
                return -ENODEV;
 
+       port_user = kcalloc(NR_EVENT_CHANNELS, sizeof(*port_user), GFP_KERNEL);
+       if (port_user == NULL)
+               return -ENOMEM;
+
        spin_lock_init(&port_user_lock);
-       memset(port_user, 0, sizeof(port_user));
 
        /* Create '/dev/misc/evtchn'. */
        err = misc_register(&evtchn_miscdev);
@@ -499,6 +548,9 @@ static int __init evtchn_init(void)
 
 static void __exit evtchn_cleanup(void)
 {
+       kfree(port_user);
+       port_user = NULL;
+
        misc_deregister(&evtchn_miscdev);
 }
 
index ef9c7db52077c6d58c0d5f036be0a03bd771dffa..db8c4c4ac88086bf7c2e9d1dfa946da399e91b27 100644 (file)
@@ -49,6 +49,7 @@ static int xen_hvm_suspend(void *data)
 
        if (!*cancelled) {
                xen_irq_resume();
+               xen_console_resume();
                xen_timer_resume();
        }
 
index 0f5d4162b22d50b66ce84eca9add1f6fdaa5c3d2..dbd3b16fd1317adc9f1fa8afedfd0e6d3fc53400 100644 (file)
@@ -265,9 +265,7 @@ static int mmap_return_errors(void *data, void *state)
        xen_pfn_t *mfnp = data;
        struct mmap_batch_state *st = state;
 
-       put_user(*mfnp, st->user++);
-
-       return 0;
+       return put_user(*mfnp, st->user++);
 }
 
 static struct vm_operations_struct privcmd_vm_ops;
@@ -322,10 +320,8 @@ static long privcmd_ioctl_mmap_batch(void __user *udata)
        up_write(&mm->mmap_sem);
 
        if (state.err > 0) {
-               ret = 0;
-
                state.user = m.arr;
-               traverse_pages(m.num, sizeof(xen_pfn_t),
+               ret = traverse_pages(m.num, sizeof(xen_pfn_t),
                               &pagelist,
                               mmap_return_errors, &state);
        }
@@ -383,8 +379,9 @@ static int privcmd_mmap(struct file *file, struct vm_area_struct *vma)
        if (xen_feature(XENFEAT_auto_translated_physmap))
                return -ENOSYS;
 
-       /* DONTCOPY is essential for Xen as copy_page_range is broken. */
-       vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY;
+       /* DONTCOPY is essential for Xen because copy_page_range doesn't know
+        * how to recreate these mappings */
+       vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY | VM_PFNMAP;
        vma->vm_ops = &privcmd_vm_ops;
        vma->vm_private_data = NULL;
 
index f6339d11d59cbdebc8d558f552cc199175003e05..1aa3897198462112a3bc1db479986653cf0a716f 100644 (file)
@@ -12,8 +12,6 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/magic.h>
-#include <linux/mm.h>
-#include <linux/backing-dev.h>
 
 #include <xen/xen.h>
 
 MODULE_DESCRIPTION("Xen filesystem");
 MODULE_LICENSE("GPL");
 
-static int xenfs_set_page_dirty(struct page *page)
-{
-       return !TestSetPageDirty(page);
-}
-
-static const struct address_space_operations xenfs_aops = {
-       .set_page_dirty = xenfs_set_page_dirty,
-};
-
-static struct backing_dev_info xenfs_backing_dev_info = {
-       .ra_pages       = 0,    /* No readahead */
-       .capabilities   = BDI_CAP_NO_ACCT_AND_WRITEBACK,
-};
-
 static struct inode *xenfs_make_inode(struct super_block *sb, int mode)
 {
        struct inode *ret = new_inode(sb);
 
        if (ret) {
                ret->i_mode = mode;
-               ret->i_mapping->a_ops = &xenfs_aops;
-               ret->i_mapping->backing_dev_info = &xenfs_backing_dev_info;
                ret->i_uid = ret->i_gid = 0;
                ret->i_blocks = 0;
                ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
@@ -121,9 +103,9 @@ static int xenfs_fill_super(struct super_block *sb, void *data, int silent)
        return rc;
 }
 
-static int xenfs_mount(struct file_system_type *fs_type,
-                       int flags, const char *dev_name,
-                       void *data)
+static struct dentry *xenfs_mount(struct file_system_type *fs_type,
+                                 int flags, const char *dev_name,
+                                 void *data)
 {
        return mount_single(fs_type, flags, data, xenfs_fill_super);
 }
@@ -137,25 +119,11 @@ static struct file_system_type xenfs_type = {
 
 static int __init xenfs_init(void)
 {
-       int err;
-       if (!xen_domain()) {
-               printk(KERN_INFO "xenfs: not registering filesystem on non-xen platform\n");
-               return 0;
-       }
-
-       err = register_filesystem(&xenfs_type);
-       if (err) {
-               printk(KERN_ERR "xenfs: Unable to register filesystem!\n");
-               goto out;
-       }
-
-       err = bdi_init(&xenfs_backing_dev_info);
-       if (err)
-               unregister_filesystem(&xenfs_type);
-
- out:
+       if (xen_domain())
+               return register_filesystem(&xenfs_type);
 
-       return err;
+       printk(KERN_INFO "XENFS: not registering filesystem on non-xen platform\n");
+       return 0;
 }
 
 static void __exit xenfs_exit(void)
index d5c1401f00310979b117f9eaaecc0e026fd11c93..d34896cfb19f1512855d907b9d4c8c6b4cac2e09 100644 (file)
@@ -980,19 +980,11 @@ static int autofs4_root_ioctl_unlocked(struct inode *inode, struct file *filp,
        }
 }
 
-static DEFINE_MUTEX(autofs4_ioctl_mutex);
-
 static long autofs4_root_ioctl(struct file *filp,
                               unsigned int cmd, unsigned long arg)
 {
-       long ret;
        struct inode *inode = filp->f_dentry->d_inode;
-
-       mutex_lock(&autofs4_ioctl_mutex);
-       ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg);
-       mutex_unlock(&autofs4_ioctl_mutex);
-
-       return ret;
+       return autofs4_root_ioctl_unlocked(inode, filp, cmd, arg);
 }
 
 #ifdef CONFIG_COMPAT
@@ -1002,13 +994,11 @@ static long autofs4_root_compat_ioctl(struct file *filp,
        struct inode *inode = filp->f_path.dentry->d_inode;
        int ret;
 
-       mutex_lock(&autofs4_ioctl_mutex);
        if (cmd == AUTOFS_IOC_READY || cmd == AUTOFS_IOC_FAIL)
                ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg);
        else
                ret = autofs4_root_ioctl_unlocked(inode, filp, cmd,
                        (unsigned long)compat_ptr(arg));
-       mutex_unlock(&autofs4_ioctl_mutex);
 
        return ret;
 }
index 7845d1f7d1d927f79ac45c09af730963a426b8e5..b50bc4bd5c5677e1f77926d30449e4bc32794e21 100644 (file)
@@ -91,23 +91,10 @@ static inline int compressed_bio_size(struct btrfs_root *root,
 static struct bio *compressed_bio_alloc(struct block_device *bdev,
                                        u64 first_byte, gfp_t gfp_flags)
 {
-       struct bio *bio;
        int nr_vecs;
 
        nr_vecs = bio_get_nr_vecs(bdev);
-       bio = bio_alloc(gfp_flags, nr_vecs);
-
-       if (bio == NULL && (current->flags & PF_MEMALLOC)) {
-               while (!bio && (nr_vecs /= 2))
-                       bio = bio_alloc(gfp_flags, nr_vecs);
-       }
-
-       if (bio) {
-               bio->bi_size = 0;
-               bio->bi_bdev = bdev;
-               bio->bi_sector = first_byte >> 9;
-       }
-       return bio;
+       return btrfs_bio_alloc(bdev, first_byte >> 9, nr_vecs, gfp_flags);
 }
 
 static int check_compressed_csum(struct inode *inode,
index 8db9234f6b418db0cc1f99afa6876f369116a1b8..af52f6d7a4d8ed8269f0cf835ab09c14d9a5c8a1 100644 (file)
@@ -808,9 +808,9 @@ struct btrfs_block_group_cache {
        int extents_thresh;
        int free_extents;
        int total_bitmaps;
-       int ro:1;
-       int dirty:1;
-       int iref:1;
+       unsigned int ro:1;
+       unsigned int dirty:1;
+       unsigned int iref:1;
 
        int disk_cache_state;
 
index fb827d0d71811baff7aec0f49a2584f7eedbaf84..51d2e4de34ebe58d4eb5d2c99d1fc1bb83f692f9 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/freezer.h>
 #include <linux/crc32c.h>
 #include <linux/slab.h>
+#include <linux/migrate.h>
 #include "compat.h"
 #include "ctree.h"
 #include "disk-io.h"
@@ -355,6 +356,8 @@ static int csum_dirty_buffer(struct btrfs_root *root, struct page *page)
        ret = btree_read_extent_buffer_pages(root, eb, start + PAGE_CACHE_SIZE,
                                             btrfs_header_generation(eb));
        BUG_ON(ret);
+       WARN_ON(!btrfs_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN));
+
        found_start = btrfs_header_bytenr(eb);
        if (found_start != start) {
                WARN_ON(1);
@@ -693,6 +696,27 @@ static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio,
                                   __btree_submit_bio_done);
 }
 
+#ifdef CONFIG_MIGRATION
+static int btree_migratepage(struct address_space *mapping,
+                       struct page *newpage, struct page *page)
+{
+       /*
+        * we can't safely write a btree page from here,
+        * we haven't done the locking hook
+        */
+       if (PageDirty(page))
+               return -EAGAIN;
+       /*
+        * Buffers may be managed in a filesystem specific way.
+        * We must have no buffers or drop them.
+        */
+       if (page_has_private(page) &&
+           !try_to_release_page(page, GFP_KERNEL))
+               return -EAGAIN;
+       return migrate_page(mapping, newpage, page);
+}
+#endif
+
 static int btree_writepage(struct page *page, struct writeback_control *wbc)
 {
        struct extent_io_tree *tree;
@@ -707,8 +731,7 @@ static int btree_writepage(struct page *page, struct writeback_control *wbc)
        }
 
        redirty_page_for_writepage(wbc, page);
-       eb = btrfs_find_tree_block(root, page_offset(page),
-                                     PAGE_CACHE_SIZE);
+       eb = btrfs_find_tree_block(root, page_offset(page), PAGE_CACHE_SIZE);
        WARN_ON(!eb);
 
        was_dirty = test_and_set_bit(EXTENT_BUFFER_DIRTY, &eb->bflags);
@@ -799,6 +822,9 @@ static const struct address_space_operations btree_aops = {
        .releasepage    = btree_releasepage,
        .invalidatepage = btree_invalidatepage,
        .sync_page      = block_sync_page,
+#ifdef CONFIG_MIGRATION
+       .migratepage    = btree_migratepage,
+#endif
 };
 
 int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize,
@@ -981,7 +1007,10 @@ static int find_and_setup_root(struct btrfs_root *tree_root,
        blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item));
        root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
                                     blocksize, generation);
-       BUG_ON(!root->node);
+       if (!root->node || !btrfs_buffer_uptodate(root->node, generation)) {
+               free_extent_buffer(root->node);
+               return -EIO;
+       }
        root->commit_root = btrfs_root_node(root);
        return 0;
 }
@@ -1538,10 +1567,8 @@ struct btrfs_root *open_ctree(struct super_block *sb,
                                                 GFP_NOFS);
        struct btrfs_root *csum_root = kzalloc(sizeof(struct btrfs_root),
                                                 GFP_NOFS);
-       struct btrfs_root *tree_root = kzalloc(sizeof(struct btrfs_root),
-                                              GFP_NOFS);
-       struct btrfs_fs_info *fs_info = kzalloc(sizeof(*fs_info),
-                                               GFP_NOFS);
+       struct btrfs_root *tree_root = btrfs_sb(sb);
+       struct btrfs_fs_info *fs_info = tree_root->fs_info;
        struct btrfs_root *chunk_root = kzalloc(sizeof(struct btrfs_root),
                                                GFP_NOFS);
        struct btrfs_root *dev_root = kzalloc(sizeof(struct btrfs_root),
index 951ef09b82f4abb02d220f259d78c16af180a210..659f532d26a01f6b3b1da403a3834ba116d20bdd 100644 (file)
@@ -166,7 +166,7 @@ static struct dentry *btrfs_fh_to_dentry(struct super_block *sb, struct fid *fh,
 static struct dentry *btrfs_get_parent(struct dentry *child)
 {
        struct inode *dir = child->d_inode;
-       static struct dentry *dentry;
+       struct dentry *dentry;
        struct btrfs_root *root = BTRFS_I(dir)->root;
        struct btrfs_path *path;
        struct extent_buffer *leaf;
@@ -232,9 +232,85 @@ fail:
        return ERR_PTR(ret);
 }
 
+static int btrfs_get_name(struct dentry *parent, char *name,
+                         struct dentry *child)
+{
+       struct inode *inode = child->d_inode;
+       struct inode *dir = parent->d_inode;
+       struct btrfs_path *path;
+       struct btrfs_root *root = BTRFS_I(dir)->root;
+       struct btrfs_inode_ref *iref;
+       struct btrfs_root_ref *rref;
+       struct extent_buffer *leaf;
+       unsigned long name_ptr;
+       struct btrfs_key key;
+       int name_len;
+       int ret;
+
+       if (!dir || !inode)
+               return -EINVAL;
+
+       if (!S_ISDIR(dir->i_mode))
+               return -EINVAL;
+
+       path = btrfs_alloc_path();
+       if (!path)
+               return -ENOMEM;
+       path->leave_spinning = 1;
+
+       if (inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) {
+               key.objectid = BTRFS_I(inode)->root->root_key.objectid;
+               key.type = BTRFS_ROOT_BACKREF_KEY;
+               key.offset = (u64)-1;
+               root = root->fs_info->tree_root;
+       } else {
+               key.objectid = inode->i_ino;
+               key.offset = dir->i_ino;
+               key.type = BTRFS_INODE_REF_KEY;
+       }
+
+       ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+       if (ret < 0) {
+               btrfs_free_path(path);
+               return ret;
+       } else if (ret > 0) {
+               if (inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) {
+                       path->slots[0]--;
+               } else {
+                       btrfs_free_path(path);
+                       return -ENOENT;
+               }
+       }
+       leaf = path->nodes[0];
+
+       if (inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) {
+              rref = btrfs_item_ptr(leaf, path->slots[0],
+                                    struct btrfs_root_ref);
+              name_ptr = (unsigned long)(rref + 1);
+              name_len = btrfs_root_ref_name_len(leaf, rref);
+       } else {
+               iref = btrfs_item_ptr(leaf, path->slots[0],
+                                     struct btrfs_inode_ref);
+               name_ptr = (unsigned long)(iref + 1);
+               name_len = btrfs_inode_ref_name_len(leaf, iref);
+       }
+
+       read_extent_buffer(leaf, name, name_ptr, name_len);
+       btrfs_free_path(path);
+
+       /*
+        * have to add the null termination to make sure that reconnect_path
+        * gets the right len for strlen
+        */
+       name[name_len] = '\0';
+
+       return 0;
+}
+
 const struct export_operations btrfs_export_ops = {
        .encode_fh      = btrfs_encode_fh,
        .fh_to_dentry   = btrfs_fh_to_dentry,
        .fh_to_parent   = btrfs_fh_to_parent,
        .get_parent     = btrfs_get_parent,
+       .get_name       = btrfs_get_name,
 };
index 0c097f3aec418564e25df5b7e0af8d9a81a79d1d..227e5815d8382393d4adc4d0a340ee636bca9d3e 100644 (file)
@@ -429,6 +429,7 @@ err:
 
 static int cache_block_group(struct btrfs_block_group_cache *cache,
                             struct btrfs_trans_handle *trans,
+                            struct btrfs_root *root,
                             int load_cache_only)
 {
        struct btrfs_fs_info *fs_info = cache->fs_info;
@@ -442,9 +443,12 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
 
        /*
         * We can't do the read from on-disk cache during a commit since we need
-        * to have the normal tree locking.
+        * to have the normal tree locking.  Also if we are currently trying to
+        * allocate blocks for the tree root we can't do the fast caching since
+        * we likely hold important locks.
         */
-       if (!trans->transaction->in_commit) {
+       if (!trans->transaction->in_commit &&
+           (root && root != root->fs_info->tree_root)) {
                spin_lock(&cache->lock);
                if (cache->cached != BTRFS_CACHE_NO) {
                        spin_unlock(&cache->lock);
@@ -2741,6 +2745,7 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group,
        struct btrfs_root *root = block_group->fs_info->tree_root;
        struct inode *inode = NULL;
        u64 alloc_hint = 0;
+       int dcs = BTRFS_DC_ERROR;
        int num_pages = 0;
        int retries = 0;
        int ret = 0;
@@ -2795,6 +2800,8 @@ again:
 
        spin_lock(&block_group->lock);
        if (block_group->cached != BTRFS_CACHE_FINISHED) {
+               /* We're not cached, don't bother trying to write stuff out */
+               dcs = BTRFS_DC_WRITTEN;
                spin_unlock(&block_group->lock);
                goto out_put;
        }
@@ -2821,6 +2828,8 @@ again:
        ret = btrfs_prealloc_file_range_trans(inode, trans, 0, 0, num_pages,
                                              num_pages, num_pages,
                                              &alloc_hint);
+       if (!ret)
+               dcs = BTRFS_DC_SETUP;
        btrfs_free_reserved_data_space(inode, num_pages);
 out_put:
        iput(inode);
@@ -2828,10 +2837,7 @@ out_free:
        btrfs_release_path(root, path);
 out:
        spin_lock(&block_group->lock);
-       if (ret)
-               block_group->disk_cache_state = BTRFS_DC_ERROR;
-       else
-               block_group->disk_cache_state = BTRFS_DC_SETUP;
+       block_group->disk_cache_state = dcs;
        spin_unlock(&block_group->lock);
 
        return ret;
@@ -3037,7 +3043,13 @@ static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
 
 u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags)
 {
-       u64 num_devices = root->fs_info->fs_devices->rw_devices;
+       /*
+        * we add in the count of missing devices because we want
+        * to make sure that any RAID levels on a degraded FS
+        * continue to be honored.
+        */
+       u64 num_devices = root->fs_info->fs_devices->rw_devices +
+               root->fs_info->fs_devices->missing_devices;
 
        if (num_devices == 1)
                flags &= ~(BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID0);
@@ -3412,7 +3424,7 @@ again:
         * our reservation.
         */
        if (unused <= space_info->total_bytes) {
-               unused -= space_info->total_bytes;
+               unused = space_info->total_bytes - unused;
                if (unused >= num_bytes) {
                        if (!reserved)
                                space_info->bytes_reserved += orig_bytes;
@@ -4080,7 +4092,7 @@ static int update_block_group(struct btrfs_trans_handle *trans,
                 * space back to the block group, otherwise we will leak space.
                 */
                if (!alloc && cache->cached == BTRFS_CACHE_NO)
-                       cache_block_group(cache, trans, 1);
+                       cache_block_group(cache, trans, NULL, 1);
 
                byte_in_group = bytenr - cache->key.objectid;
                WARN_ON(byte_in_group > cache->key.offset);
@@ -4930,11 +4942,31 @@ search:
                btrfs_get_block_group(block_group);
                search_start = block_group->key.objectid;
 
+               /*
+                * this can happen if we end up cycling through all the
+                * raid types, but we want to make sure we only allocate
+                * for the proper type.
+                */
+               if (!block_group_bits(block_group, data)) {
+                   u64 extra = BTRFS_BLOCK_GROUP_DUP |
+                               BTRFS_BLOCK_GROUP_RAID1 |
+                               BTRFS_BLOCK_GROUP_RAID10;
+
+                       /*
+                        * if they asked for extra copies and this block group
+                        * doesn't provide them, bail.  This does allow us to
+                        * fill raid0 from raid1.
+                        */
+                       if ((data & extra) && !(block_group->flags & extra))
+                               goto loop;
+               }
+
 have_block_group:
                if (unlikely(block_group->cached == BTRFS_CACHE_NO)) {
                        u64 free_percent;
 
-                       ret = cache_block_group(block_group, trans, 1);
+                       ret = cache_block_group(block_group, trans,
+                                               orig_root, 1);
                        if (block_group->cached == BTRFS_CACHE_FINISHED)
                                goto have_block_group;
 
@@ -4958,7 +4990,8 @@ have_block_group:
                        if (loop > LOOP_CACHING_NOWAIT ||
                            (loop > LOOP_FIND_IDEAL &&
                             atomic_read(&space_info->caching_threads) < 2)) {
-                               ret = cache_block_group(block_group, trans, 0);
+                               ret = cache_block_group(block_group, trans,
+                                                       orig_root, 0);
                                BUG_ON(ret);
                        }
                        found_uncached_bg = true;
@@ -5515,7 +5548,7 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans,
        u64 num_bytes = ins->offset;
 
        block_group = btrfs_lookup_block_group(root->fs_info, ins->objectid);
-       cache_block_group(block_group, trans, 0);
+       cache_block_group(block_group, trans, NULL, 0);
        caching_ctl = get_caching_control(block_group);
 
        if (!caching_ctl) {
@@ -6300,9 +6333,13 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
                                           NULL, NULL);
                BUG_ON(ret < 0);
                if (ret > 0) {
-                       ret = btrfs_del_orphan_item(trans, tree_root,
-                                                   root->root_key.objectid);
-                       BUG_ON(ret);
+                       /* if we fail to delete the orphan item this time
+                        * around, it'll get picked up the next time.
+                        *
+                        * The most common failure here is just -ENOENT.
+                        */
+                       btrfs_del_orphan_item(trans, tree_root,
+                                             root->root_key.objectid);
                }
        }
 
@@ -7878,7 +7915,14 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags)
        u64 stripped = BTRFS_BLOCK_GROUP_RAID0 |
                BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10;
 
-       num_devices = root->fs_info->fs_devices->rw_devices;
+       /*
+        * we add in the count of missing devices because we want
+        * to make sure that any RAID levels on a degraded FS
+        * continue to be honored.
+        */
+       num_devices = root->fs_info->fs_devices->rw_devices +
+               root->fs_info->fs_devices->missing_devices;
+
        if (num_devices == 1) {
                stripped |= BTRFS_BLOCK_GROUP_DUP;
                stripped = flags & ~stripped;
@@ -8247,7 +8291,6 @@ int btrfs_read_block_groups(struct btrfs_root *root)
                        break;
                if (ret != 0)
                        goto error;
-
                leaf = path->nodes[0];
                btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
                cache = kzalloc(sizeof(*cache), GFP_NOFS);
index eac10e3260a982e24149957981c3f2a7be792d09..3e86b9f3650736a6e77e5468197815ac5646fb83 100644 (file)
@@ -1828,9 +1828,9 @@ static void end_bio_extent_preparewrite(struct bio *bio, int err)
        bio_put(bio);
 }
 
-static struct bio *
-extent_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs,
-                gfp_t gfp_flags)
+struct bio *
+btrfs_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs,
+               gfp_t gfp_flags)
 {
        struct bio *bio;
 
@@ -1919,7 +1919,7 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree,
        else
                nr = bio_get_nr_vecs(bdev);
 
-       bio = extent_bio_alloc(bdev, sector, nr, GFP_NOFS | __GFP_HIGH);
+       bio = btrfs_bio_alloc(bdev, sector, nr, GFP_NOFS | __GFP_HIGH);
 
        bio_add_page(bio, page, page_size, offset);
        bio->bi_end_io = end_io_func;
@@ -2901,21 +2901,53 @@ out:
 int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                __u64 start, __u64 len, get_extent_t *get_extent)
 {
-       int ret;
+       int ret = 0;
        u64 off = start;
        u64 max = start + len;
        u32 flags = 0;
+       u32 found_type;
+       u64 last;
        u64 disko = 0;
+       struct btrfs_key found_key;
        struct extent_map *em = NULL;
        struct extent_state *cached_state = NULL;
+       struct btrfs_path *path;
+       struct btrfs_file_extent_item *item;
        int end = 0;
        u64 em_start = 0, em_len = 0;
        unsigned long emflags;
-       ret = 0;
+       int hole = 0;
 
        if (len == 0)
                return -EINVAL;
 
+       path = btrfs_alloc_path();
+       if (!path)
+               return -ENOMEM;
+       path->leave_spinning = 1;
+
+       ret = btrfs_lookup_file_extent(NULL, BTRFS_I(inode)->root,
+                                      path, inode->i_ino, -1, 0);
+       if (ret < 0) {
+               btrfs_free_path(path);
+               return ret;
+       }
+       WARN_ON(!ret);
+       path->slots[0]--;
+       item = btrfs_item_ptr(path->nodes[0], path->slots[0],
+                             struct btrfs_file_extent_item);
+       btrfs_item_key_to_cpu(path->nodes[0], &found_key, path->slots[0]);
+       found_type = btrfs_key_type(&found_key);
+
+       /* No extents, just return */
+       if (found_key.objectid != inode->i_ino ||
+           found_type != BTRFS_EXTENT_DATA_KEY) {
+               btrfs_free_path(path);
+               return 0;
+       }
+       last = found_key.offset;
+       btrfs_free_path(path);
+
        lock_extent_bits(&BTRFS_I(inode)->io_tree, start, start + len, 0,
                         &cached_state, GFP_NOFS);
        em = get_extent(inode, NULL, 0, off, max - off, 0);
@@ -2925,11 +2957,18 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                ret = PTR_ERR(em);
                goto out;
        }
+
        while (!end) {
+               hole = 0;
                off = em->start + em->len;
                if (off >= max)
                        end = 1;
 
+               if (em->block_start == EXTENT_MAP_HOLE) {
+                       hole = 1;
+                       goto next;
+               }
+
                em_start = em->start;
                em_len = em->len;
 
@@ -2939,8 +2978,6 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                if (em->block_start == EXTENT_MAP_LAST_BYTE) {
                        end = 1;
                        flags |= FIEMAP_EXTENT_LAST;
-               } else if (em->block_start == EXTENT_MAP_HOLE) {
-                       flags |= FIEMAP_EXTENT_UNWRITTEN;
                } else if (em->block_start == EXTENT_MAP_INLINE) {
                        flags |= (FIEMAP_EXTENT_DATA_INLINE |
                                  FIEMAP_EXTENT_NOT_ALIGNED);
@@ -2953,10 +2990,10 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags))
                        flags |= FIEMAP_EXTENT_ENCODED;
 
+next:
                emflags = em->flags;
                free_extent_map(em);
                em = NULL;
-
                if (!end) {
                        em = get_extent(inode, NULL, 0, off, max - off, 0);
                        if (!em)
@@ -2967,15 +3004,23 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                        }
                        emflags = em->flags;
                }
+
                if (test_bit(EXTENT_FLAG_VACANCY, &emflags)) {
                        flags |= FIEMAP_EXTENT_LAST;
                        end = 1;
                }
 
-               ret = fiemap_fill_next_extent(fieinfo, em_start, disko,
-                                       em_len, flags);
-               if (ret)
-                       goto out_free;
+               if (em_start == last) {
+                       flags |= FIEMAP_EXTENT_LAST;
+                       end = 1;
+               }
+
+               if (!hole) {
+                       ret = fiemap_fill_next_extent(fieinfo, em_start, disko,
+                                               em_len, flags);
+                       if (ret)
+                               goto out_free;
+               }
        }
 out_free:
        free_extent_map(em);
@@ -3836,8 +3881,10 @@ int try_release_extent_buffer(struct extent_io_tree *tree, struct page *page)
 
        spin_lock(&tree->buffer_lock);
        eb = radix_tree_lookup(&tree->buffer, start >> PAGE_CACHE_SHIFT);
-       if (!eb)
-               goto out;
+       if (!eb) {
+               spin_unlock(&tree->buffer_lock);
+               return ret;
+       }
 
        if (test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags)) {
                ret = 0;
index 1c6d4f342ef7e8089ac6f17e3e6ed40e83722e45..4183c8178f01a846f7da0f016f74db5402de12c7 100644 (file)
@@ -310,4 +310,7 @@ int extent_clear_unlock_delalloc(struct inode *inode,
                                struct extent_io_tree *tree,
                                u64 start, u64 end, struct page *locked_page,
                                unsigned long op);
+struct bio *
+btrfs_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs,
+               gfp_t gfp_flags);
 #endif
index e354c33df0824592bb9356be4987fd0ddfbbdc71..66836d85763bbfd2dafe3821a1be30f173784fdc 100644 (file)
@@ -48,30 +48,34 @@ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages,
                                         struct page **prepared_pages,
                                         struct iov_iter *i)
 {
-       size_t copied;
+       size_t copied = 0;
        int pg = 0;
        int offset = pos & (PAGE_CACHE_SIZE - 1);
+       int total_copied = 0;
 
        while (write_bytes > 0) {
                size_t count = min_t(size_t,
                                     PAGE_CACHE_SIZE - offset, write_bytes);
                struct page *page = prepared_pages[pg];
-again:
-               if (unlikely(iov_iter_fault_in_readable(i, count)))
-                       return -EFAULT;
-
-               /* Copy data from userspace to the current page */
-               copied = iov_iter_copy_from_user(page, i, offset, count);
+               /*
+                * Copy data from userspace to the current page
+                *
+                * Disable pagefault to avoid recursive lock since
+                * the pages are already locked
+                */
+               pagefault_disable();
+               copied = iov_iter_copy_from_user_atomic(page, i, offset, count);
+               pagefault_enable();
 
                /* Flush processor's dcache for this page */
                flush_dcache_page(page);
                iov_iter_advance(i, copied);
                write_bytes -= copied;
+               total_copied += copied;
 
+               /* Return to btrfs_file_aio_write to fault page */
                if (unlikely(copied == 0)) {
-                       count = min_t(size_t, PAGE_CACHE_SIZE - offset,
-                                     iov_iter_single_seg_count(i));
-                       goto again;
+                       break;
                }
 
                if (unlikely(copied < PAGE_CACHE_SIZE - offset)) {
@@ -81,7 +85,7 @@ again:
                        offset = 0;
                }
        }
-       return 0;
+       return total_copied;
 }
 
 /*
@@ -854,6 +858,8 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
        unsigned long last_index;
        int will_write;
        int buffered = 0;
+       int copied = 0;
+       int dirty_pages = 0;
 
        will_write = ((file->f_flags & O_DSYNC) || IS_SYNC(inode) ||
                      (file->f_flags & O_DIRECT));
@@ -970,7 +976,17 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
                WARN_ON(num_pages > nrptrs);
                memset(pages, 0, sizeof(struct page *) * nrptrs);
 
-               ret = btrfs_delalloc_reserve_space(inode, write_bytes);
+               /*
+                * Fault pages before locking them in prepare_pages
+                * to avoid recursive lock
+                */
+               if (unlikely(iov_iter_fault_in_readable(&i, write_bytes))) {
+                       ret = -EFAULT;
+                       goto out;
+               }
+
+               ret = btrfs_delalloc_reserve_space(inode,
+                                       num_pages << PAGE_CACHE_SHIFT);
                if (ret)
                        goto out;
 
@@ -978,37 +994,49 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
                                    pos, first_index, last_index,
                                    write_bytes);
                if (ret) {
-                       btrfs_delalloc_release_space(inode, write_bytes);
+                       btrfs_delalloc_release_space(inode,
+                                       num_pages << PAGE_CACHE_SHIFT);
                        goto out;
                }
 
-               ret = btrfs_copy_from_user(pos, num_pages,
+               copied = btrfs_copy_from_user(pos, num_pages,
                                           write_bytes, pages, &i);
-               if (ret == 0) {
+               dirty_pages = (copied + PAGE_CACHE_SIZE - 1) >>
+                                       PAGE_CACHE_SHIFT;
+
+               if (num_pages > dirty_pages) {
+                       if (copied > 0)
+                               atomic_inc(
+                                       &BTRFS_I(inode)->outstanding_extents);
+                       btrfs_delalloc_release_space(inode,
+                                       (num_pages - dirty_pages) <<
+                                       PAGE_CACHE_SHIFT);
+               }
+
+               if (copied > 0) {
                        dirty_and_release_pages(NULL, root, file, pages,
-                                               num_pages, pos, write_bytes);
+                                               dirty_pages, pos, copied);
                }
 
                btrfs_drop_pages(pages, num_pages);
-               if (ret) {
-                       btrfs_delalloc_release_space(inode, write_bytes);
-                       goto out;
-               }
 
-               if (will_write) {
-                       filemap_fdatawrite_range(inode->i_mapping, pos,
-                                                pos + write_bytes - 1);
-               } else {
-                       balance_dirty_pages_ratelimited_nr(inode->i_mapping,
-                                                          num_pages);
-                       if (num_pages <
-                           (root->leafsize >> PAGE_CACHE_SHIFT) + 1)
-                               btrfs_btree_balance_dirty(root, 1);
-                       btrfs_throttle(root);
+               if (copied > 0) {
+                       if (will_write) {
+                               filemap_fdatawrite_range(inode->i_mapping, pos,
+                                                        pos + copied - 1);
+                       } else {
+                               balance_dirty_pages_ratelimited_nr(
+                                                       inode->i_mapping,
+                                                       dirty_pages);
+                               if (dirty_pages <
+                               (root->leafsize >> PAGE_CACHE_SHIFT) + 1)
+                                       btrfs_btree_balance_dirty(root, 1);
+                               btrfs_throttle(root);
+                       }
                }
 
-               pos += write_bytes;
-               num_written += write_bytes;
+               pos += copied;
+               num_written += copied;
 
                cond_resched();
        }
@@ -1047,8 +1075,14 @@ out:
 
                if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) {
                        trans = btrfs_start_transaction(root, 0);
+                       if (IS_ERR(trans)) {
+                               num_written = PTR_ERR(trans);
+                               goto done;
+                       }
+                       mutex_lock(&inode->i_mutex);
                        ret = btrfs_log_dentry_safe(trans, root,
                                                    file->f_dentry);
+                       mutex_unlock(&inode->i_mutex);
                        if (ret == 0) {
                                ret = btrfs_sync_log(trans, root);
                                if (ret == 0)
@@ -1067,6 +1101,7 @@ out:
                             (start_pos + num_written - 1) >> PAGE_CACHE_SHIFT);
                }
        }
+done:
        current->backing_dev_info = NULL;
        return num_written ? num_written : err;
 }
index 22ee0dc2e6b8a712900c68a8c44df4a453fb86f0..60d684266959bbf8f96c14873e9a1f57e069a29e 100644 (file)
@@ -290,7 +290,7 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info,
                       (unsigned long long)BTRFS_I(inode)->generation,
                       (unsigned long long)generation,
                       (unsigned long long)block_group->key.objectid);
-               goto out;
+               goto free_cache;
        }
 
        if (!num_entries)
@@ -524,6 +524,12 @@ int btrfs_write_out_cache(struct btrfs_root *root,
                return 0;
        }
 
+       node = rb_first(&block_group->free_space_offset);
+       if (!node) {
+               iput(inode);
+               return 0;
+       }
+
        last_index = (i_size_read(inode) - 1) >> PAGE_CACHE_SHIFT;
        filemap_write_and_wait(inode->i_mapping);
        btrfs_wait_ordered_range(inode, inode->i_size &
@@ -543,10 +549,6 @@ int btrfs_write_out_cache(struct btrfs_root *root,
         */
        first_page_offset = (sizeof(u32) * num_checksums) + sizeof(u64);
 
-       node = rb_first(&block_group->free_space_offset);
-       if (!node)
-               goto out_free;
-
        /*
         * Lock all pages first so we can lock the extent safely.
         *
index 558cac2dfa547032637bd0a746153eba46d73f8d..72f31ecb5c90085a2d6adfdc9b690ee038bf508f 100644 (file)
@@ -495,7 +495,7 @@ again:
                add_async_extent(async_cow, start, num_bytes,
                                 total_compressed, pages, nr_pages_ret);
 
-               if (start + num_bytes < end && start + num_bytes < actual_end) {
+               if (start + num_bytes < end) {
                        start += num_bytes;
                        pages = NULL;
                        cond_resched();
@@ -4501,6 +4501,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
        BTRFS_I(inode)->index_cnt = 2;
        BTRFS_I(inode)->root = root;
        BTRFS_I(inode)->generation = trans->transid;
+       inode->i_generation = BTRFS_I(inode)->generation;
        btrfs_set_inode_space_info(root, inode);
 
        if (mode & S_IFDIR)
@@ -4622,12 +4623,12 @@ int btrfs_add_link(struct btrfs_trans_handle *trans,
 }
 
 static int btrfs_add_nondir(struct btrfs_trans_handle *trans,
-                           struct dentry *dentry, struct inode *inode,
-                           int backref, u64 index)
+                           struct inode *dir, struct dentry *dentry,
+                           struct inode *inode, int backref, u64 index)
 {
-       int err = btrfs_add_link(trans, dentry->d_parent->d_inode,
-                                inode, dentry->d_name.name,
-                                dentry->d_name.len, backref, index);
+       int err = btrfs_add_link(trans, dir, inode,
+                                dentry->d_name.name, dentry->d_name.len,
+                                backref, index);
        if (!err) {
                d_instantiate(dentry, inode);
                return 0;
@@ -4668,8 +4669,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
        btrfs_set_trans_block_group(trans, dir);
 
        inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
-                               dentry->d_name.len,
-                               dentry->d_parent->d_inode->i_ino, objectid,
+                               dentry->d_name.len, dir->i_ino, objectid,
                                BTRFS_I(dir)->block_group, mode, &index);
        err = PTR_ERR(inode);
        if (IS_ERR(inode))
@@ -4682,7 +4682,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
        }
 
        btrfs_set_trans_block_group(trans, inode);
-       err = btrfs_add_nondir(trans, dentry, inode, 0, index);
+       err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index);
        if (err)
                drop_inode = 1;
        else {
@@ -4730,10 +4730,8 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
        btrfs_set_trans_block_group(trans, dir);
 
        inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
-                               dentry->d_name.len,
-                               dentry->d_parent->d_inode->i_ino,
-                               objectid, BTRFS_I(dir)->block_group, mode,
-                               &index);
+                               dentry->d_name.len, dir->i_ino, objectid,
+                               BTRFS_I(dir)->block_group, mode, &index);
        err = PTR_ERR(inode);
        if (IS_ERR(inode))
                goto out_unlock;
@@ -4745,7 +4743,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
        }
 
        btrfs_set_trans_block_group(trans, inode);
-       err = btrfs_add_nondir(trans, dentry, inode, 0, index);
+       err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index);
        if (err)
                drop_inode = 1;
        else {
@@ -4787,6 +4785,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
                return -EPERM;
 
        btrfs_inc_nlink(inode);
+       inode->i_ctime = CURRENT_TIME;
 
        err = btrfs_set_inode_index(dir, &index);
        if (err)
@@ -4805,15 +4804,17 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
        btrfs_set_trans_block_group(trans, dir);
        ihold(inode);
 
-       err = btrfs_add_nondir(trans, dentry, inode, 1, index);
+       err = btrfs_add_nondir(trans, dir, dentry, inode, 1, index);
 
        if (err) {
                drop_inode = 1;
        } else {
+               struct dentry *parent = dget_parent(dentry);
                btrfs_update_inode_block_group(trans, dir);
                err = btrfs_update_inode(trans, root, inode);
                BUG_ON(err);
-               btrfs_log_new_name(trans, inode, NULL, dentry->d_parent);
+               btrfs_log_new_name(trans, inode, NULL, parent);
+               dput(parent);
        }
 
        nr = trans->blocks_used;
@@ -4853,8 +4854,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        btrfs_set_trans_block_group(trans, dir);
 
        inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
-                               dentry->d_name.len,
-                               dentry->d_parent->d_inode->i_ino, objectid,
+                               dentry->d_name.len, dir->i_ino, objectid,
                                BTRFS_I(dir)->block_group, S_IFDIR | mode,
                                &index);
        if (IS_ERR(inode)) {
@@ -4877,9 +4877,8 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        if (err)
                goto out_fail;
 
-       err = btrfs_add_link(trans, dentry->d_parent->d_inode,
-                                inode, dentry->d_name.name,
-                                dentry->d_name.len, 0, index);
+       err = btrfs_add_link(trans, dir, inode, dentry->d_name.name,
+                            dentry->d_name.len, 0, index);
        if (err)
                goto out_fail;
 
@@ -5535,13 +5534,21 @@ struct btrfs_dio_private {
        u64 bytes;
        u32 *csums;
        void *private;
+
+       /* number of bios pending for this dio */
+       atomic_t pending_bios;
+
+       /* IO errors */
+       int errors;
+
+       struct bio *orig_bio;
 };
 
 static void btrfs_endio_direct_read(struct bio *bio, int err)
 {
+       struct btrfs_dio_private *dip = bio->bi_private;
        struct bio_vec *bvec_end = bio->bi_io_vec + bio->bi_vcnt - 1;
        struct bio_vec *bvec = bio->bi_io_vec;
-       struct btrfs_dio_private *dip = bio->bi_private;
        struct inode *inode = dip->inode;
        struct btrfs_root *root = BTRFS_I(inode)->root;
        u64 start;
@@ -5595,15 +5602,18 @@ static void btrfs_endio_direct_write(struct bio *bio, int err)
        struct btrfs_trans_handle *trans;
        struct btrfs_ordered_extent *ordered = NULL;
        struct extent_state *cached_state = NULL;
+       u64 ordered_offset = dip->logical_offset;
+       u64 ordered_bytes = dip->bytes;
        int ret;
 
        if (err)
                goto out_done;
-
-       ret = btrfs_dec_test_ordered_pending(inode, &ordered,
-                                            dip->logical_offset, dip->bytes);
+again:
+       ret = btrfs_dec_test_first_ordered_pending(inode, &ordered,
+                                                  &ordered_offset,
+                                                  ordered_bytes);
        if (!ret)
-               goto out_done;
+               goto out_test;
 
        BUG_ON(!ordered);
 
@@ -5663,8 +5673,20 @@ out_unlock:
 out:
        btrfs_delalloc_release_metadata(inode, ordered->len);
        btrfs_end_transaction(trans, root);
+       ordered_offset = ordered->file_offset + ordered->len;
        btrfs_put_ordered_extent(ordered);
        btrfs_put_ordered_extent(ordered);
+
+out_test:
+       /*
+        * our bio might span multiple ordered extents.  If we haven't
+        * completed the accounting for the whole dio, go back and try again
+        */
+       if (ordered_offset < dip->logical_offset + dip->bytes) {
+               ordered_bytes = dip->logical_offset + dip->bytes -
+                       ordered_offset;
+               goto again;
+       }
 out_done:
        bio->bi_private = dip->private;
 
@@ -5684,6 +5706,176 @@ static int __btrfs_submit_bio_start_direct_io(struct inode *inode, int rw,
        return 0;
 }
 
+static void btrfs_end_dio_bio(struct bio *bio, int err)
+{
+       struct btrfs_dio_private *dip = bio->bi_private;
+
+       if (err) {
+               printk(KERN_ERR "btrfs direct IO failed ino %lu rw %lu "
+                     "sector %#Lx len %u err no %d\n",
+                     dip->inode->i_ino, bio->bi_rw,
+                     (unsigned long long)bio->bi_sector, bio->bi_size, err);
+               dip->errors = 1;
+
+               /*
+                * before atomic variable goto zero, we must make sure
+                * dip->errors is perceived to be set.
+                */
+               smp_mb__before_atomic_dec();
+       }
+
+       /* if there are more bios still pending for this dio, just exit */
+       if (!atomic_dec_and_test(&dip->pending_bios))
+               goto out;
+
+       if (dip->errors)
+               bio_io_error(dip->orig_bio);
+       else {
+               set_bit(BIO_UPTODATE, &dip->orig_bio->bi_flags);
+               bio_endio(dip->orig_bio, 0);
+       }
+out:
+       bio_put(bio);
+}
+
+static struct bio *btrfs_dio_bio_alloc(struct block_device *bdev,
+                                      u64 first_sector, gfp_t gfp_flags)
+{
+       int nr_vecs = bio_get_nr_vecs(bdev);
+       return btrfs_bio_alloc(bdev, first_sector, nr_vecs, gfp_flags);
+}
+
+static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode,
+                                        int rw, u64 file_offset, int skip_sum,
+                                        u32 *csums)
+{
+       int write = rw & REQ_WRITE;
+       struct btrfs_root *root = BTRFS_I(inode)->root;
+       int ret;
+
+       bio_get(bio);
+       ret = btrfs_bio_wq_end_io(root->fs_info, bio, 0);
+       if (ret)
+               goto err;
+
+       if (write && !skip_sum) {
+               ret = btrfs_wq_submit_bio(root->fs_info,
+                                  inode, rw, bio, 0, 0,
+                                  file_offset,
+                                  __btrfs_submit_bio_start_direct_io,
+                                  __btrfs_submit_bio_done);
+               goto err;
+       } else if (!skip_sum)
+               btrfs_lookup_bio_sums_dio(root, inode, bio,
+                                         file_offset, csums);
+
+       ret = btrfs_map_bio(root, rw, bio, 0, 1);
+err:
+       bio_put(bio);
+       return ret;
+}
+
+static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
+                                   int skip_sum)
+{
+       struct inode *inode = dip->inode;
+       struct btrfs_root *root = BTRFS_I(inode)->root;
+       struct btrfs_mapping_tree *map_tree = &root->fs_info->mapping_tree;
+       struct bio *bio;
+       struct bio *orig_bio = dip->orig_bio;
+       struct bio_vec *bvec = orig_bio->bi_io_vec;
+       u64 start_sector = orig_bio->bi_sector;
+       u64 file_offset = dip->logical_offset;
+       u64 submit_len = 0;
+       u64 map_length;
+       int nr_pages = 0;
+       u32 *csums = dip->csums;
+       int ret = 0;
+
+       bio = btrfs_dio_bio_alloc(orig_bio->bi_bdev, start_sector, GFP_NOFS);
+       if (!bio)
+               return -ENOMEM;
+       bio->bi_private = dip;
+       bio->bi_end_io = btrfs_end_dio_bio;
+       atomic_inc(&dip->pending_bios);
+
+       map_length = orig_bio->bi_size;
+       ret = btrfs_map_block(map_tree, READ, start_sector << 9,
+                             &map_length, NULL, 0);
+       if (ret) {
+               bio_put(bio);
+               return -EIO;
+       }
+
+       while (bvec <= (orig_bio->bi_io_vec + orig_bio->bi_vcnt - 1)) {
+               if (unlikely(map_length < submit_len + bvec->bv_len ||
+                   bio_add_page(bio, bvec->bv_page, bvec->bv_len,
+                                bvec->bv_offset) < bvec->bv_len)) {
+                       /*
+                        * inc the count before we submit the bio so
+                        * we know the end IO handler won't happen before
+                        * we inc the count. Otherwise, the dip might get freed
+                        * before we're done setting it up
+                        */
+                       atomic_inc(&dip->pending_bios);
+                       ret = __btrfs_submit_dio_bio(bio, inode, rw,
+                                                    file_offset, skip_sum,
+                                                    csums);
+                       if (ret) {
+                               bio_put(bio);
+                               atomic_dec(&dip->pending_bios);
+                               goto out_err;
+                       }
+
+                       if (!skip_sum)
+                               csums = csums + nr_pages;
+                       start_sector += submit_len >> 9;
+                       file_offset += submit_len;
+
+                       submit_len = 0;
+                       nr_pages = 0;
+
+                       bio = btrfs_dio_bio_alloc(orig_bio->bi_bdev,
+                                                 start_sector, GFP_NOFS);
+                       if (!bio)
+                               goto out_err;
+                       bio->bi_private = dip;
+                       bio->bi_end_io = btrfs_end_dio_bio;
+
+                       map_length = orig_bio->bi_size;
+                       ret = btrfs_map_block(map_tree, READ, start_sector << 9,
+                                             &map_length, NULL, 0);
+                       if (ret) {
+                               bio_put(bio);
+                               goto out_err;
+                       }
+               } else {
+                       submit_len += bvec->bv_len;
+                       nr_pages ++;
+                       bvec++;
+               }
+       }
+
+       ret = __btrfs_submit_dio_bio(bio, inode, rw, file_offset, skip_sum,
+                                    csums);
+       if (!ret)
+               return 0;
+
+       bio_put(bio);
+out_err:
+       dip->errors = 1;
+       /*
+        * before atomic variable goto zero, we must
+        * make sure dip->errors is perceived to be set.
+        */
+       smp_mb__before_atomic_dec();
+       if (atomic_dec_and_test(&dip->pending_bios))
+               bio_io_error(dip->orig_bio);
+
+       /* bio_end_io() will handle error, so we needn't return it */
+       return 0;
+}
+
 static void btrfs_submit_direct(int rw, struct bio *bio, struct inode *inode,
                                loff_t file_offset)
 {
@@ -5723,36 +5915,18 @@ static void btrfs_submit_direct(int rw, struct bio *bio, struct inode *inode,
 
        dip->disk_bytenr = (u64)bio->bi_sector << 9;
        bio->bi_private = dip;
+       dip->errors = 0;
+       dip->orig_bio = bio;
+       atomic_set(&dip->pending_bios, 0);
 
        if (write)
                bio->bi_end_io = btrfs_endio_direct_write;
        else
                bio->bi_end_io = btrfs_endio_direct_read;
 
-       ret = btrfs_bio_wq_end_io(root->fs_info, bio, 0);
-       if (ret)
-               goto out_err;
-
-       if (write && !skip_sum) {
-               ret = btrfs_wq_submit_bio(BTRFS_I(inode)->root->fs_info,
-                                  inode, rw, bio, 0, 0,
-                                  dip->logical_offset,
-                                  __btrfs_submit_bio_start_direct_io,
-                                  __btrfs_submit_bio_done);
-               if (ret)
-                       goto out_err;
+       ret = btrfs_submit_direct_hook(rw, dip, skip_sum);
+       if (!ret)
                return;
-       } else if (!skip_sum)
-               btrfs_lookup_bio_sums_dio(root, inode, bio,
-                                         dip->logical_offset, dip->csums);
-
-       ret = btrfs_map_bio(root, rw, bio, 0, 1);
-       if (ret)
-               goto out_err;
-       return;
-out_err:
-       kfree(dip->csums);
-       kfree(dip);
 free_ordered:
        /*
         * If this is a write, we need to clean up the reserved space and kill
@@ -5760,8 +5934,7 @@ free_ordered:
         */
        if (write) {
                struct btrfs_ordered_extent *ordered;
-               ordered = btrfs_lookup_ordered_extent(inode,
-                                                     dip->logical_offset);
+               ordered = btrfs_lookup_ordered_extent(inode, file_offset);
                if (!test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags) &&
                    !test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags))
                        btrfs_free_reserved_extent(root, ordered->start,
@@ -6607,8 +6780,9 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        BUG_ON(ret);
 
        if (old_inode->i_ino != BTRFS_FIRST_FREE_OBJECTID) {
-               btrfs_log_new_name(trans, old_inode, old_dir,
-                                  new_dentry->d_parent);
+               struct dentry *parent = dget_parent(new_dentry);
+               btrfs_log_new_name(trans, old_inode, old_dir, parent);
+               dput(parent);
                btrfs_end_log_trans(root);
        }
 out_fail:
@@ -6758,8 +6932,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
        btrfs_set_trans_block_group(trans, dir);
 
        inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
-                               dentry->d_name.len,
-                               dentry->d_parent->d_inode->i_ino, objectid,
+                               dentry->d_name.len, dir->i_ino, objectid,
                                BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO,
                                &index);
        err = PTR_ERR(inode);
@@ -6773,7 +6946,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
        }
 
        btrfs_set_trans_block_group(trans, inode);
-       err = btrfs_add_nondir(trans, dentry, inode, 0, index);
+       err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index);
        if (err)
                drop_inode = 1;
        else {
@@ -6844,6 +7017,7 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_key ins;
        u64 cur_offset = start;
+       u64 i_size;
        int ret = 0;
        bool own_trans = true;
 
@@ -6885,11 +7059,11 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
                    (actual_len > inode->i_size) &&
                    (cur_offset > inode->i_size)) {
                        if (cur_offset > actual_len)
-                               i_size_write(inode, actual_len);
+                               i_size = actual_len;
                        else
-                               i_size_write(inode, cur_offset);
-                       i_size_write(inode, cur_offset);
-                       btrfs_ordered_update_i_size(inode, cur_offset, NULL);
+                               i_size = cur_offset;
+                       i_size_write(inode, i_size);
+                       btrfs_ordered_update_i_size(inode, i_size, NULL);
                }
 
                ret = btrfs_update_inode(trans, root, inode);
@@ -6943,6 +7117,10 @@ static long btrfs_fallocate(struct inode *inode, int mode,
        btrfs_wait_ordered_range(inode, alloc_start, alloc_end - alloc_start);
 
        mutex_lock(&inode->i_mutex);
+       ret = inode_newsize_ok(inode, alloc_end);
+       if (ret)
+               goto out;
+
        if (alloc_start > inode->i_size) {
                ret = btrfs_cont_expand(inode, alloc_start);
                if (ret)
@@ -7139,6 +7317,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = {
        .readlink       = generic_readlink,
        .follow_link    = page_follow_link_light,
        .put_link       = page_put_link,
+       .getattr        = btrfs_getattr,
        .permission     = btrfs_permission,
        .setxattr       = btrfs_setxattr,
        .getxattr       = btrfs_getxattr,
index 463d91b4dd3a720ece2afb592b2edefca855aaba..f87552a1d7ea0beeb540aa59ddac3754242304cc 100644 (file)
@@ -233,7 +233,8 @@ static noinline int create_subvol(struct btrfs_root *root,
        struct btrfs_inode_item *inode_item;
        struct extent_buffer *leaf;
        struct btrfs_root *new_root;
-       struct inode *dir = dentry->d_parent->d_inode;
+       struct dentry *parent = dget_parent(dentry);
+       struct inode *dir;
        int ret;
        int err;
        u64 objectid;
@@ -242,8 +243,13 @@ static noinline int create_subvol(struct btrfs_root *root,
 
        ret = btrfs_find_free_objectid(NULL, root->fs_info->tree_root,
                                       0, &objectid);
-       if (ret)
+       if (ret) {
+               dput(parent);
                return ret;
+       }
+
+       dir = parent->d_inode;
+
        /*
         * 1 - inode item
         * 2 - refs
@@ -251,8 +257,10 @@ static noinline int create_subvol(struct btrfs_root *root,
         * 2 - dir items
         */
        trans = btrfs_start_transaction(root, 6);
-       if (IS_ERR(trans))
+       if (IS_ERR(trans)) {
+               dput(parent);
                return PTR_ERR(trans);
+       }
 
        leaf = btrfs_alloc_free_block(trans, root, root->leafsize,
                                      0, objectid, NULL, 0, 0, 0);
@@ -339,6 +347,7 @@ static noinline int create_subvol(struct btrfs_root *root,
 
        d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry));
 fail:
+       dput(parent);
        if (async_transid) {
                *async_transid = trans->transid;
                err = btrfs_commit_transaction_async(trans, root, 1);
@@ -354,6 +363,7 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
                           char *name, int namelen, u64 *async_transid)
 {
        struct inode *inode;
+       struct dentry *parent;
        struct btrfs_pending_snapshot *pending_snapshot;
        struct btrfs_trans_handle *trans;
        int ret;
@@ -396,7 +406,9 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
 
        btrfs_orphan_cleanup(pending_snapshot->snap);
 
-       inode = btrfs_lookup_dentry(dentry->d_parent->d_inode, dentry);
+       parent = dget_parent(dentry);
+       inode = btrfs_lookup_dentry(parent->d_inode, dentry);
+       dput(parent);
        if (IS_ERR(inode)) {
                ret = PTR_ERR(inode);
                goto fail;
@@ -935,23 +947,42 @@ out:
 
 static noinline int btrfs_ioctl_snap_create(struct file *file,
                                            void __user *arg, int subvol,
-                                           int async)
+                                           int v2)
 {
        struct btrfs_ioctl_vol_args *vol_args = NULL;
-       struct btrfs_ioctl_async_vol_args *async_vol_args = NULL;
+       struct btrfs_ioctl_vol_args_v2 *vol_args_v2 = NULL;
        char *name;
        u64 fd;
-       u64 transid = 0;
        int ret;
 
-       if (async) {
-               async_vol_args = memdup_user(arg, sizeof(*async_vol_args));
-               if (IS_ERR(async_vol_args))
-                       return PTR_ERR(async_vol_args);
+       if (v2) {
+               u64 transid = 0;
+               u64 *ptr = NULL;
+
+               vol_args_v2 = memdup_user(arg, sizeof(*vol_args_v2));
+               if (IS_ERR(vol_args_v2))
+                       return PTR_ERR(vol_args_v2);
+
+               if (vol_args_v2->flags & ~BTRFS_SUBVOL_CREATE_ASYNC) {
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               name = vol_args_v2->name;
+               fd = vol_args_v2->fd;
+               vol_args_v2->name[BTRFS_SUBVOL_NAME_MAX] = '\0';
+
+               if (vol_args_v2->flags & BTRFS_SUBVOL_CREATE_ASYNC)
+                       ptr = &transid;
+
+               ret = btrfs_ioctl_snap_create_transid(file, name, fd,
+                                                     subvol, ptr);
 
-               name = async_vol_args->name;
-               fd = async_vol_args->fd;
-               async_vol_args->name[BTRFS_SNAPSHOT_NAME_MAX] = '\0';
+               if (ret == 0 && ptr &&
+                   copy_to_user(arg +
+                                offsetof(struct btrfs_ioctl_vol_args_v2,
+                                         transid), ptr, sizeof(*ptr)))
+                       ret = -EFAULT;
        } else {
                vol_args = memdup_user(arg, sizeof(*vol_args));
                if (IS_ERR(vol_args))
@@ -959,20 +990,13 @@ static noinline int btrfs_ioctl_snap_create(struct file *file,
                name = vol_args->name;
                fd = vol_args->fd;
                vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
-       }
-
-       ret = btrfs_ioctl_snap_create_transid(file, name, fd,
-                                             subvol, &transid);
 
-       if (!ret && async) {
-               if (copy_to_user(arg +
-                               offsetof(struct btrfs_ioctl_async_vol_args,
-                               transid), &transid, sizeof(transid)))
-                       return -EFAULT;
+               ret = btrfs_ioctl_snap_create_transid(file, name, fd,
+                                                     subvol, NULL);
        }
-
+out:
        kfree(vol_args);
-       kfree(async_vol_args);
+       kfree(vol_args_v2);
 
        return ret;
 }
@@ -1669,12 +1693,11 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
                olen = len = src->i_size - off;
        /* if we extend to eof, continue to block boundary */
        if (off + len == src->i_size)
-               len = ((src->i_size + bs-1) & ~(bs-1))
-                       - off;
+               len = ALIGN(src->i_size, bs) - off;
 
        /* verify the end result is block aligned */
-       if ((off & (bs-1)) ||
-           ((off + len) & (bs-1)))
+       if (!IS_ALIGNED(off, bs) || !IS_ALIGNED(off + len, bs) ||
+           !IS_ALIGNED(destoff, bs))
                goto out_unlock;
 
        /* do any pending delalloc/csum calc on src, one way or
@@ -1874,8 +1897,8 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
                         * but shouldn't round up the file size
                         */
                        endoff = new_key.offset + datal;
-                       if (endoff > off+olen)
-                               endoff = off+olen;
+                       if (endoff > destoff+olen)
+                               endoff = destoff+olen;
                        if (endoff > inode->i_size)
                                btrfs_i_size_write(inode, endoff);
 
@@ -2235,7 +2258,7 @@ long btrfs_ioctl(struct file *file, unsigned int
                return btrfs_ioctl_getversion(file, argp);
        case BTRFS_IOC_SNAP_CREATE:
                return btrfs_ioctl_snap_create(file, argp, 0, 0);
-       case BTRFS_IOC_SNAP_CREATE_ASYNC:
+       case BTRFS_IOC_SNAP_CREATE_V2:
                return btrfs_ioctl_snap_create(file, argp, 0, 1);
        case BTRFS_IOC_SUBVOL_CREATE:
                return btrfs_ioctl_snap_create(file, argp, 1, 0);
index 17c99ebdf96049a8ad028cd6e138355df86f0c9e..c344d12c646bf7d1cbb953f8c4aba6257b6db8b9 100644 (file)
@@ -30,11 +30,15 @@ struct btrfs_ioctl_vol_args {
        char name[BTRFS_PATH_NAME_MAX + 1];
 };
 
-#define BTRFS_SNAPSHOT_NAME_MAX 4079
-struct btrfs_ioctl_async_vol_args {
+#define BTRFS_SUBVOL_CREATE_ASYNC      (1ULL << 0)
+
+#define BTRFS_SUBVOL_NAME_MAX 4039
+struct btrfs_ioctl_vol_args_v2 {
        __s64 fd;
        __u64 transid;
-       char name[BTRFS_SNAPSHOT_NAME_MAX + 1];
+       __u64 flags;
+       __u64 unused[4];
+       char name[BTRFS_SUBVOL_NAME_MAX + 1];
 };
 
 #define BTRFS_INO_LOOKUP_PATH_MAX 4080
@@ -187,6 +191,6 @@ struct btrfs_ioctl_space_args {
                                    struct btrfs_ioctl_space_args)
 #define BTRFS_IOC_START_SYNC _IOR(BTRFS_IOCTL_MAGIC, 24, __u64)
 #define BTRFS_IOC_WAIT_SYNC  _IOW(BTRFS_IOCTL_MAGIC, 22, __u64)
-#define BTRFS_IOC_SNAP_CREATE_ASYNC _IOW(BTRFS_IOCTL_MAGIC, 23, \
-                                  struct btrfs_ioctl_async_vol_args)
+#define BTRFS_IOC_SNAP_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 23, \
+                                  struct btrfs_ioctl_vol_args_v2)
 #endif
index f4621f6deca1d51f91db57ea406c4c7351a7fd5d..ae7737e352c90f7ede523c357f72a92d78c80676 100644 (file)
@@ -248,6 +248,73 @@ int btrfs_add_ordered_sum(struct inode *inode,
        return 0;
 }
 
+/*
+ * this is used to account for finished IO across a given range
+ * of the file.  The IO may span ordered extents.  If
+ * a given ordered_extent is completely done, 1 is returned, otherwise
+ * 0.
+ *
+ * test_and_set_bit on a flag in the struct btrfs_ordered_extent is used
+ * to make sure this function only returns 1 once for a given ordered extent.
+ *
+ * file_offset is updated to one byte past the range that is recorded as
+ * complete.  This allows you to walk forward in the file.
+ */
+int btrfs_dec_test_first_ordered_pending(struct inode *inode,
+                                  struct btrfs_ordered_extent **cached,
+                                  u64 *file_offset, u64 io_size)
+{
+       struct btrfs_ordered_inode_tree *tree;
+       struct rb_node *node;
+       struct btrfs_ordered_extent *entry = NULL;
+       int ret;
+       u64 dec_end;
+       u64 dec_start;
+       u64 to_dec;
+
+       tree = &BTRFS_I(inode)->ordered_tree;
+       spin_lock(&tree->lock);
+       node = tree_search(tree, *file_offset);
+       if (!node) {
+               ret = 1;
+               goto out;
+       }
+
+       entry = rb_entry(node, struct btrfs_ordered_extent, rb_node);
+       if (!offset_in_entry(entry, *file_offset)) {
+               ret = 1;
+               goto out;
+       }
+
+       dec_start = max(*file_offset, entry->file_offset);
+       dec_end = min(*file_offset + io_size, entry->file_offset +
+                     entry->len);
+       *file_offset = dec_end;
+       if (dec_start > dec_end) {
+               printk(KERN_CRIT "bad ordering dec_start %llu end %llu\n",
+                      (unsigned long long)dec_start,
+                      (unsigned long long)dec_end);
+       }
+       to_dec = dec_end - dec_start;
+       if (to_dec > entry->bytes_left) {
+               printk(KERN_CRIT "bad ordered accounting left %llu size %llu\n",
+                      (unsigned long long)entry->bytes_left,
+                      (unsigned long long)to_dec);
+       }
+       entry->bytes_left -= to_dec;
+       if (entry->bytes_left == 0)
+               ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags);
+       else
+               ret = 1;
+out:
+       if (!ret && cached && entry) {
+               *cached = entry;
+               atomic_inc(&entry->refs);
+       }
+       spin_unlock(&tree->lock);
+       return ret == 0;
+}
+
 /*
  * this is used to account for finished IO across a given range
  * of the file.  The IO should not span ordered extents.  If
index 8ac365492a3f4f01ba13aac1bb6f1041a97f3608..61dca83119ddf9a4994fbb107edccb93d3163487 100644 (file)
@@ -141,6 +141,9 @@ int btrfs_remove_ordered_extent(struct inode *inode,
 int btrfs_dec_test_ordered_pending(struct inode *inode,
                                   struct btrfs_ordered_extent **cached,
                                   u64 file_offset, u64 io_size);
+int btrfs_dec_test_first_ordered_pending(struct inode *inode,
+                                  struct btrfs_ordered_extent **cached,
+                                  u64 *file_offset, u64 io_size);
 int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset,
                             u64 start, u64 len, u64 disk_len, int type);
 int btrfs_add_ordered_extent_dio(struct inode *inode, u64 file_offset,
index 79cba5fbc28ef8061e2d599110a3a525216a7bfd..f8be250963a09a283b8ec4ab04bcb1c3a962427e 100644 (file)
@@ -56,8 +56,12 @@ int btrfs_del_orphan_item(struct btrfs_trans_handle *trans,
                return -ENOMEM;
 
        ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
-       if (ret)
+       if (ret < 0)
                goto out;
+       if (ret) {
+               ret = -ENOENT;
+               goto out;
+       }
 
        ret = btrfs_del_item(trans, root, path);
 
index 8299a25ffc8f8313064cbd3e54278e9f5ebbc662..883c6fa1367eb866002d7f67d3ae2ce6497f4367 100644 (file)
@@ -244,6 +244,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                case Opt_space_cache:
                        printk(KERN_INFO "btrfs: enabling disk space caching\n");
                        btrfs_set_opt(info->mount_opt, SPACE_CACHE);
+                       break;
                case Opt_clear_cache:
                        printk(KERN_INFO "btrfs: force clearing of disk cache\n");
                        btrfs_set_opt(info->mount_opt, CLEAR_CACHE);
@@ -562,12 +563,26 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
 
 static int btrfs_test_super(struct super_block *s, void *data)
 {
-       struct btrfs_fs_devices *test_fs_devices = data;
+       struct btrfs_root *test_root = data;
        struct btrfs_root *root = btrfs_sb(s);
 
-       return root->fs_info->fs_devices == test_fs_devices;
+       /*
+        * If this super block is going away, return false as it
+        * can't match as an existing super block.
+        */
+       if (!atomic_read(&s->s_active))
+               return 0;
+       return root->fs_info->fs_devices == test_root->fs_info->fs_devices;
+}
+
+static int btrfs_set_super(struct super_block *s, void *data)
+{
+       s->s_fs_info = data;
+
+       return set_anon_super(s, data);
 }
 
+
 /*
  * Find a superblock for the given device / mount point.
  *
@@ -581,6 +596,8 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
        struct super_block *s;
        struct dentry *root;
        struct btrfs_fs_devices *fs_devices = NULL;
+       struct btrfs_root *tree_root = NULL;
+       struct btrfs_fs_info *fs_info = NULL;
        fmode_t mode = FMODE_READ;
        char *subvol_name = NULL;
        u64 subvol_objectid = 0;
@@ -608,8 +625,24 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
                goto error_close_devices;
        }
 
+       /*
+        * Setup a dummy root and fs_info for test/set super.  This is because
+        * we don't actually fill this stuff out until open_ctree, but we need
+        * it for searching for existing supers, so this lets us do that and
+        * then open_ctree will properly initialize everything later.
+        */
+       fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_NOFS);
+       tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS);
+       if (!fs_info || !tree_root) {
+               error = -ENOMEM;
+               goto error_close_devices;
+       }
+       fs_info->tree_root = tree_root;
+       fs_info->fs_devices = fs_devices;
+       tree_root->fs_info = fs_info;
+
        bdev = fs_devices->latest_bdev;
-       s = sget(fs_type, btrfs_test_super, set_anon_super, fs_devices);
+       s = sget(fs_type, btrfs_test_super, btrfs_set_super, tree_root);
        if (IS_ERR(s))
                goto error_s;
 
@@ -652,9 +685,9 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
                mutex_unlock(&root->d_inode->i_mutex);
 
                if (IS_ERR(new_root)) {
+                       dput(root);
                        deactivate_locked_super(s);
                        error = PTR_ERR(new_root);
-                       dput(root);
                        goto error_free_subvol_name;
                }
                if (!new_root->d_inode) {
@@ -675,6 +708,8 @@ error_s:
        error = PTR_ERR(s);
 error_close_devices:
        btrfs_close_devices(fs_devices);
+       kfree(fs_info);
+       kfree(tree_root);
 error_free_subvol_name:
        kfree(subvol_name);
        return ERR_PTR(error);
index 1fffbc017bdfe0451cc2e67ccf5fd85623a12aee..f50e931fc217b978b0bcf1fb54f0d661d3b53562 100644 (file)
@@ -902,6 +902,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        struct btrfs_root *root = pending->root;
        struct btrfs_root *parent_root;
        struct inode *parent_inode;
+       struct dentry *parent;
        struct dentry *dentry;
        struct extent_buffer *tmp;
        struct extent_buffer *old;
@@ -941,7 +942,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        trans->block_rsv = &pending->block_rsv;
 
        dentry = pending->dentry;
-       parent_inode = dentry->d_parent->d_inode;
+       parent = dget_parent(dentry);
+       parent_inode = parent->d_inode;
        parent_root = BTRFS_I(parent_inode)->root;
        record_root_in_trans(trans, parent_root);
 
@@ -989,6 +991,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
                                 parent_inode->i_ino, index,
                                 dentry->d_name.name, dentry->d_name.len);
        BUG_ON(ret);
+       dput(parent);
 
        key.offset = (u64)-1;
        pending->snap = btrfs_read_fs_root_no_name(root->fs_info, &key);
index a29f19384a27bc91526d46fb3cbefdbe2bd8a5ce..054744ac571907e4c76a5e35f35b8baba24152e2 100644 (file)
@@ -2869,6 +2869,7 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans,
 {
        int ret = 0;
        struct btrfs_root *root;
+       struct dentry *old_parent = NULL;
 
        /*
         * for regular files, if its inode is already on disk, we don't
@@ -2910,10 +2911,13 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans,
                if (IS_ROOT(parent))
                        break;
 
-               parent = parent->d_parent;
+               parent = dget_parent(parent);
+               dput(old_parent);
+               old_parent = parent;
                inode = parent->d_inode;
 
        }
+       dput(old_parent);
 out:
        return ret;
 }
@@ -2945,6 +2949,7 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
 {
        int inode_only = exists_only ? LOG_INODE_EXISTS : LOG_INODE_ALL;
        struct super_block *sb;
+       struct dentry *old_parent = NULL;
        int ret = 0;
        u64 last_committed = root->fs_info->last_trans_committed;
 
@@ -3016,10 +3021,13 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
                if (IS_ROOT(parent))
                        break;
 
-               parent = parent->d_parent;
+               parent = dget_parent(parent);
+               dput(old_parent);
+               old_parent = parent;
        }
        ret = 0;
 end_trans:
+       dput(old_parent);
        if (ret < 0) {
                BUG_ON(ret != -ENOSPC);
                root->fs_info->last_trans_log_full_commit = trans->transid;
@@ -3039,8 +3047,13 @@ end_no_trans:
 int btrfs_log_dentry_safe(struct btrfs_trans_handle *trans,
                          struct btrfs_root *root, struct dentry *dentry)
 {
-       return btrfs_log_inode_parent(trans, root, dentry->d_inode,
-                                     dentry->d_parent, 0);
+       struct dentry *parent = dget_parent(dentry);
+       int ret;
+
+       ret = btrfs_log_inode_parent(trans, root, dentry->d_inode, parent, 0);
+       dput(parent);
+
+       return ret;
 }
 
 /*
index cc04dc1445d64da8694401c2cbc2fde27105b8f9..6b9884507837581ba6231bc6c4cfb85a036b82f6 100644 (file)
@@ -412,12 +412,16 @@ static noinline int device_list_add(const char *path,
 
                device->fs_devices = fs_devices;
                fs_devices->num_devices++;
-       } else if (strcmp(device->name, path)) {
+       } else if (!device->name || strcmp(device->name, path)) {
                name = kstrdup(path, GFP_NOFS);
                if (!name)
                        return -ENOMEM;
                kfree(device->name);
                device->name = name;
+               if (device->missing) {
+                       fs_devices->missing_devices--;
+                       device->missing = 0;
+               }
        }
 
        if (found_transid > fs_devices->latest_trans) {
@@ -1236,6 +1240,9 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
 
        device->fs_devices->num_devices--;
 
+       if (device->missing)
+               root->fs_info->fs_devices->missing_devices--;
+
        next_device = list_entry(root->fs_info->fs_devices->devices.next,
                                 struct btrfs_device, dev_list);
        if (device->bdev == root->fs_info->sb->s_bdev)
@@ -3080,7 +3087,9 @@ static struct btrfs_device *add_missing_dev(struct btrfs_root *root,
        device->devid = devid;
        device->work.func = pending_bios_fn;
        device->fs_devices = fs_devices;
+       device->missing = 1;
        fs_devices->num_devices++;
+       fs_devices->missing_devices++;
        spin_lock_init(&device->io_lock);
        INIT_LIST_HEAD(&device->dev_alloc_list);
        memcpy(device->uuid, dev_uuid, BTRFS_UUID_SIZE);
@@ -3278,6 +3287,15 @@ static int read_one_dev(struct btrfs_root *root,
                        device = add_missing_dev(root, devid, dev_uuid);
                        if (!device)
                                return -ENOMEM;
+               } else if (!device->missing) {
+                       /*
+                        * this happens when a device that was properly setup
+                        * in the device info lists suddenly goes bad.
+                        * device->bdev is NULL, and so we have to set
+                        * device->missing to one here
+                        */
+                       root->fs_info->fs_devices->missing_devices++;
+                       device->missing = 1;
                }
        }
 
index 2b638b6e4eeae7cb9428490a897c1e10a9aaad1f..2740db49eb04d7a8de03d18e5935a97ff43ef9db 100644 (file)
@@ -44,6 +44,7 @@ struct btrfs_device {
 
        int writeable;
        int in_fs_metadata;
+       int missing;
 
        spinlock_t io_lock;
 
@@ -93,6 +94,7 @@ struct btrfs_fs_devices {
        u64 num_devices;
        u64 open_devices;
        u64 rw_devices;
+       u64 missing_devices;
        u64 total_rw_bytes;
        struct block_device *latest_bdev;
 
index e9c874abc9e1f4a7ec00b68595fdd674a4f1da2e..561438b6a50cd3789b90d54e473562431d528ec8 100644 (file)
@@ -204,7 +204,7 @@ static int readpage_nounlock(struct file *filp, struct page *page)
        err = ceph_osdc_readpages(osdc, ceph_vino(inode), &ci->i_layout,
                                  page->index << PAGE_CACHE_SHIFT, &len,
                                  ci->i_truncate_seq, ci->i_truncate_size,
-                                 &page, 1);
+                                 &page, 1, 0);
        if (err == -ENOENT)
                err = 0;
        if (err < 0) {
@@ -287,7 +287,7 @@ static int ceph_readpages(struct file *file, struct address_space *mapping,
        rc = ceph_osdc_readpages(osdc, ceph_vino(inode), &ci->i_layout,
                                 offset, &len,
                                 ci->i_truncate_seq, ci->i_truncate_size,
-                                pages, nr_pages);
+                                pages, nr_pages, 0);
        if (rc == -ENOENT)
                rc = 0;
        if (rc < 0)
@@ -774,7 +774,7 @@ get_more_pages:
                                            snapc, do_sync,
                                            ci->i_truncate_seq,
                                            ci->i_truncate_size,
-                                           &inode->i_mtime, true, 1);
+                                           &inode->i_mtime, true, 1, 0);
                                max_pages = req->r_num_pages;
 
                                alloc_page_vec(fsc, req);
index 98ab13e2b71d9d8ebcbf1715da112d78cb0bac17..60d27bc9eb83d82f61e448031495625e42c752d3 100644 (file)
@@ -1430,8 +1430,8 @@ static int try_nonblocking_invalidate(struct inode *inode)
            invalidating_gen == ci->i_rdcache_gen) {
                /* success. */
                dout("try_nonblocking_invalidate %p success\n", inode);
-               ci->i_rdcache_gen = 0;
-               ci->i_rdcache_revoking = 0;
+               /* save any racing async invalidate some trouble */
+               ci->i_rdcache_revoking = ci->i_rdcache_gen - 1;
                return 0;
        }
        dout("try_nonblocking_invalidate %p failed\n", inode);
@@ -2273,8 +2273,7 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
 {
        struct ceph_inode_info *ci = ceph_inode(inode);
        int mds = session->s_mds;
-       unsigned seq = le32_to_cpu(grant->seq);
-       unsigned issue_seq = le32_to_cpu(grant->issue_seq);
+       int seq = le32_to_cpu(grant->seq);
        int newcaps = le32_to_cpu(grant->caps);
        int issued, implemented, used, wanted, dirty;
        u64 size = le64_to_cpu(grant->size);
@@ -2286,8 +2285,8 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
        int revoked_rdcache = 0;
        int queue_invalidate = 0;
 
-       dout("handle_cap_grant inode %p cap %p mds%d seq %u/%u %s\n",
-            inode, cap, mds, seq, issue_seq, ceph_cap_string(newcaps));
+       dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n",
+            inode, cap, mds, seq, ceph_cap_string(newcaps));
        dout(" size %llu max_size %llu, i_size %llu\n", size, max_size,
                inode->i_size);
 
@@ -2383,7 +2382,6 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
        }
 
        cap->seq = seq;
-       cap->issue_seq = issue_seq;
 
        /* file layout may have changed */
        ci->i_layout = grant->layout;
@@ -2691,6 +2689,11 @@ static void handle_cap_import(struct ceph_mds_client *mdsc,
                     NULL /* no caps context */);
        try_flush_caps(inode, session, NULL);
        up_read(&mdsc->snap_rwsem);
+
+       /* make sure we re-request max_size, if necessary */
+       spin_lock(&inode->i_lock);
+       ci->i_requested_max_size = 0;
+       spin_unlock(&inode->i_lock);
 }
 
 /*
index e0a2dc6fcafcb62266909c5ec71329e58083d1d7..d902948a90d88622e9af8bbfc505a779fe735d99 100644 (file)
@@ -40,7 +40,8 @@ int ceph_init_dentry(struct dentry *dentry)
        if (dentry->d_fsdata)
                return 0;
 
-       if (ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP)
+       if (dentry->d_parent == NULL ||   /* nfs fh_to_dentry */
+           ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP)
                dentry->d_op = &ceph_dentry_ops;
        else if (ceph_snap(dentry->d_parent->d_inode) == CEPH_SNAPDIR)
                dentry->d_op = &ceph_snapdir_dentry_ops;
@@ -114,8 +115,8 @@ static int __dcache_readdir(struct file *filp,
        spin_lock(&dcache_lock);
 
        /* start at beginning? */
-       if (filp->f_pos == 2 || (last &&
-                                filp->f_pos < ceph_dentry(last)->offset)) {
+       if (filp->f_pos == 2 || last == NULL ||
+           filp->f_pos < ceph_dentry(last)->offset) {
                if (list_empty(&parent->d_subdirs))
                        goto out_unlock;
                p = parent->d_subdirs.prev;
@@ -336,7 +337,10 @@ more:
                if (req->r_reply_info.dir_end) {
                        kfree(fi->last_name);
                        fi->last_name = NULL;
-                       fi->next_offset = 2;
+                       if (ceph_frag_is_rightmost(frag))
+                               fi->next_offset = 2;
+                       else
+                               fi->next_offset = 0;
                } else {
                        rinfo = &req->r_reply_info;
                        err = note_last_dentry(fi,
@@ -355,18 +359,22 @@ more:
                u64 pos = ceph_make_fpos(frag, off);
                struct ceph_mds_reply_inode *in =
                        rinfo->dir_in[off - fi->offset].in;
+               struct ceph_vino vino;
+               ino_t ino;
+
                dout("readdir off %d (%d/%d) -> %lld '%.*s' %p\n",
                     off, off - fi->offset, rinfo->dir_nr, pos,
                     rinfo->dir_dname_len[off - fi->offset],
                     rinfo->dir_dname[off - fi->offset], in);
                BUG_ON(!in);
                ftype = le32_to_cpu(in->mode) >> 12;
+               vino.ino = le64_to_cpu(in->ino);
+               vino.snap = le64_to_cpu(in->snapid);
+               ino = ceph_vino_to_ino(vino);
                if (filldir(dirent,
                            rinfo->dir_dname[off - fi->offset],
                            rinfo->dir_dname_len[off - fi->offset],
-                           pos,
-                           le64_to_cpu(in->ino),
-                           ftype) < 0) {
+                           pos, ino, ftype) < 0) {
                        dout("filldir stopping us...\n");
                        return 0;
                }
@@ -414,6 +422,7 @@ static void reset_readdir(struct ceph_file_info *fi)
                fi->last_readdir = NULL;
        }
        kfree(fi->last_name);
+       fi->last_name = NULL;
        fi->next_offset = 2;  /* compensate for . and .. */
        if (fi->dentry) {
                dput(fi->dentry);
index e77c28cf369059112dd06ee3b7c78c5146f0ffdc..7d0e4a82d898a83f2695eead6ffc767689ffe140 100644 (file)
@@ -154,11 +154,13 @@ int ceph_open(struct inode *inode, struct file *file)
        }
 
        /*
-        * No need to block if we have any caps.  Update wanted set
+        * No need to block if we have caps on the auth MDS (for
+        * write) or any MDS (for read).  Update wanted set
         * asynchronously.
         */
        spin_lock(&inode->i_lock);
-       if (__ceph_is_any_real_caps(ci)) {
+       if (__ceph_is_any_real_caps(ci) &&
+           (((fmode & CEPH_FILE_MODE_WR) == 0) || ci->i_auth_cap)) {
                int mds_wanted = __ceph_caps_mds_wanted(ci);
                int issued = __ceph_caps_issued(ci, NULL);
 
@@ -280,11 +282,13 @@ int ceph_release(struct inode *inode, struct file *file)
 static int striped_read(struct inode *inode,
                        u64 off, u64 len,
                        struct page **pages, int num_pages,
-                       int *checkeof)
+                       int *checkeof, bool align_to_pages,
+                       unsigned long buf_align)
 {
        struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
        struct ceph_inode_info *ci = ceph_inode(inode);
        u64 pos, this_len;
+       int io_align, page_align;
        int page_off = off & ~PAGE_CACHE_MASK; /* first byte's offset in page */
        int left, pages_left;
        int read;
@@ -300,14 +304,19 @@ static int striped_read(struct inode *inode,
        page_pos = pages;
        pages_left = num_pages;
        read = 0;
+       io_align = off & ~PAGE_MASK;
 
 more:
+       if (align_to_pages)
+               page_align = (pos - io_align + buf_align) & ~PAGE_MASK;
+       else
+               page_align = pos & ~PAGE_MASK;
        this_len = left;
        ret = ceph_osdc_readpages(&fsc->client->osdc, ceph_vino(inode),
                                  &ci->i_layout, pos, &this_len,
                                  ci->i_truncate_seq,
                                  ci->i_truncate_size,
-                                 page_pos, pages_left);
+                                 page_pos, pages_left, page_align);
        hit_stripe = this_len < left;
        was_short = ret >= 0 && ret < this_len;
        if (ret == -ENOENT)
@@ -368,32 +377,34 @@ static ssize_t ceph_sync_read(struct file *file, char __user *data,
        struct inode *inode = file->f_dentry->d_inode;
        struct page **pages;
        u64 off = *poff;
-       int num_pages = calc_pages_for(off, len);
-       int ret;
+       int num_pages, ret;
 
        dout("sync_read on file %p %llu~%u %s\n", file, off, len,
             (file->f_flags & O_DIRECT) ? "O_DIRECT" : "");
 
        if (file->f_flags & O_DIRECT) {
-               pages = ceph_get_direct_page_vector(data, num_pages, off, len);
-
-               /*
-                * flush any page cache pages in this range.  this
-                * will make concurrent normal and O_DIRECT io slow,
-                * but it will at least behave sensibly when they are
-                * in sequence.
-                */
+               num_pages = calc_pages_for((unsigned long)data, len);
+               pages = ceph_get_direct_page_vector(data, num_pages, true);
        } else {
+               num_pages = calc_pages_for(off, len);
                pages = ceph_alloc_page_vector(num_pages, GFP_NOFS);
        }
        if (IS_ERR(pages))
                return PTR_ERR(pages);
 
+       /*
+        * flush any page cache pages in this range.  this
+        * will make concurrent normal and sync io slow,
+        * but it will at least behave sensibly when they are
+        * in sequence.
+        */
        ret = filemap_write_and_wait(inode->i_mapping);
        if (ret < 0)
                goto done;
 
-       ret = striped_read(inode, off, len, pages, num_pages, checkeof);
+       ret = striped_read(inode, off, len, pages, num_pages, checkeof,
+                          file->f_flags & O_DIRECT,
+                          (unsigned long)data & ~PAGE_MASK);
 
        if (ret >= 0 && (file->f_flags & O_DIRECT) == 0)
                ret = ceph_copy_page_vector_to_user(pages, data, off, ret);
@@ -402,7 +413,7 @@ static ssize_t ceph_sync_read(struct file *file, char __user *data,
 
 done:
        if (file->f_flags & O_DIRECT)
-               ceph_put_page_vector(pages, num_pages);
+               ceph_put_page_vector(pages, num_pages, true);
        else
                ceph_release_page_vector(pages, num_pages);
        dout("sync_read result %d\n", ret);
@@ -448,6 +459,8 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data,
        int flags;
        int do_sync = 0;
        int check_caps = 0;
+       int page_align, io_align;
+       unsigned long buf_align;
        int ret;
        struct timespec mtime = CURRENT_TIME;
 
@@ -462,6 +475,9 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data,
        else
                pos = *offset;
 
+       io_align = pos & ~PAGE_MASK;
+       buf_align = (unsigned long)data & ~PAGE_MASK;
+
        ret = filemap_write_and_wait_range(inode->i_mapping, pos, pos + left);
        if (ret < 0)
                return ret;
@@ -486,20 +502,27 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data,
         */
 more:
        len = left;
+       if (file->f_flags & O_DIRECT) {
+               /* write from beginning of first page, regardless of
+                  io alignment */
+               page_align = (pos - io_align + buf_align) & ~PAGE_MASK;
+               num_pages = calc_pages_for((unsigned long)data, len);
+       } else {
+               page_align = pos & ~PAGE_MASK;
+               num_pages = calc_pages_for(pos, len);
+       }
        req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout,
                                    ceph_vino(inode), pos, &len,
                                    CEPH_OSD_OP_WRITE, flags,
                                    ci->i_snap_realm->cached_context,
                                    do_sync,
                                    ci->i_truncate_seq, ci->i_truncate_size,
-                                   &mtime, false, 2);
+                                   &mtime, false, 2, page_align);
        if (!req)
                return -ENOMEM;
 
-       num_pages = calc_pages_for(pos, len);
-
        if (file->f_flags & O_DIRECT) {
-               pages = ceph_get_direct_page_vector(data, num_pages, pos, len);
+               pages = ceph_get_direct_page_vector(data, num_pages, false);
                if (IS_ERR(pages)) {
                        ret = PTR_ERR(pages);
                        goto out;
@@ -549,7 +572,7 @@ more:
        }
 
        if (file->f_flags & O_DIRECT)
-               ceph_put_page_vector(pages, num_pages);
+               ceph_put_page_vector(pages, num_pages, false);
        else if (file->f_flags & O_SYNC)
                ceph_release_page_vector(pages, num_pages);
 
index 524b80be4482d0a824a8adddcdfa39656b9eb44b..bf1286588f26b3afb039e4036ddb2a469fcad638 100644 (file)
@@ -470,7 +470,9 @@ void ceph_fill_file_time(struct inode *inode, int issued,
 
        if (issued & (CEPH_CAP_FILE_EXCL|
                      CEPH_CAP_FILE_WR|
-                     CEPH_CAP_FILE_BUFFER)) {
+                     CEPH_CAP_FILE_BUFFER|
+                     CEPH_CAP_AUTH_EXCL|
+                     CEPH_CAP_XATTR_EXCL)) {
                if (timespec_compare(ctime, &inode->i_ctime) > 0) {
                        dout("ctime %ld.%09ld -> %ld.%09ld inc w/ cap\n",
                             inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
@@ -510,7 +512,7 @@ void ceph_fill_file_time(struct inode *inode, int issued,
                        warn = 1;
                }
        } else {
-               /* we have no write caps; whatever the MDS says is true */
+               /* we have no write|excl caps; whatever the MDS says is true */
                if (ceph_seq_cmp(time_warp_seq, ci->i_time_warp_seq) >= 0) {
                        inode->i_ctime = *ctime;
                        inode->i_mtime = *mtime;
@@ -566,12 +568,17 @@ static int fill_inode(struct inode *inode,
 
        /*
         * provided version will be odd if inode value is projected,
-        * even if stable.  skip the update if we have a newer info
-        * (e.g., due to inode info racing form multiple MDSs), or if
-        * we are getting projected (unstable) inode info.
+        * even if stable.  skip the update if we have newer stable
+        * info (ours>=theirs, e.g. due to racing mds replies), unless
+        * we are getting projected (unstable) info (in which case the
+        * version is odd, and we want ours>theirs).
+        *   us   them
+        *   2    2     skip
+        *   3    2     skip
+        *   3    3     update
         */
        if (le64_to_cpu(info->version) > 0 &&
-           (ci->i_version & ~1) > le64_to_cpu(info->version))
+           (ci->i_version & ~1) >= le64_to_cpu(info->version))
                goto no_change;
 
        issued = __ceph_caps_issued(ci, &implemented);
@@ -605,7 +612,14 @@ static int fill_inode(struct inode *inode,
                            le32_to_cpu(info->time_warp_seq),
                            &ctime, &mtime, &atime);
 
-       ci->i_max_size = le64_to_cpu(info->max_size);
+       /* only update max_size on auth cap */
+       if ((info->cap.flags & CEPH_CAP_FLAG_AUTH) &&
+           ci->i_max_size != le64_to_cpu(info->max_size)) {
+               dout("max_size %lld -> %llu\n", ci->i_max_size,
+                    le64_to_cpu(info->max_size));
+               ci->i_max_size = le64_to_cpu(info->max_size);
+       }
+
        ci->i_layout = info->layout;
        inode->i_blkbits = fls(le32_to_cpu(info->layout.fl_stripe_unit)) - 1;
 
@@ -1054,7 +1068,8 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
                ininfo = rinfo->targeti.in;
                vino.ino = le64_to_cpu(ininfo->ino);
                vino.snap = le64_to_cpu(ininfo->snapid);
-               if (!dn->d_inode) {
+               in = dn->d_inode;
+               if (!in) {
                        in = ceph_get_inode(sb, vino);
                        if (IS_ERR(in)) {
                                pr_err("fill_trace bad get_inode "
@@ -1385,11 +1400,8 @@ static void ceph_invalidate_work(struct work_struct *work)
        spin_lock(&inode->i_lock);
        dout("invalidate_pages %p gen %d revoking %d\n", inode,
             ci->i_rdcache_gen, ci->i_rdcache_revoking);
-       if (ci->i_rdcache_gen == 0 ||
-           ci->i_rdcache_revoking != ci->i_rdcache_gen) {
-               BUG_ON(ci->i_rdcache_revoking > ci->i_rdcache_gen);
+       if (ci->i_rdcache_revoking != ci->i_rdcache_gen) {
                /* nevermind! */
-               ci->i_rdcache_revoking = 0;
                spin_unlock(&inode->i_lock);
                goto out;
        }
@@ -1399,15 +1411,16 @@ static void ceph_invalidate_work(struct work_struct *work)
        ceph_invalidate_nondirty_pages(inode->i_mapping);
 
        spin_lock(&inode->i_lock);
-       if (orig_gen == ci->i_rdcache_gen) {
+       if (orig_gen == ci->i_rdcache_gen &&
+           orig_gen == ci->i_rdcache_revoking) {
                dout("invalidate_pages %p gen %d successful\n", inode,
                     ci->i_rdcache_gen);
-               ci->i_rdcache_gen = 0;
-               ci->i_rdcache_revoking = 0;
+               ci->i_rdcache_revoking--;
                check = 1;
        } else {
-               dout("invalidate_pages %p gen %d raced, gen now %d\n",
-                    inode, orig_gen, ci->i_rdcache_gen);
+               dout("invalidate_pages %p gen %d raced, now %d revoking %d\n",
+                    inode, orig_gen, ci->i_rdcache_gen,
+                    ci->i_rdcache_revoking);
        }
        spin_unlock(&inode->i_lock);
 
@@ -1738,7 +1751,7 @@ int ceph_do_getattr(struct inode *inode, int mask)
                return 0;
        }
 
-       dout("do_getattr inode %p mask %s\n", inode, ceph_cap_string(mask));
+       dout("do_getattr inode %p mask %s mode 0%o\n", inode, ceph_cap_string(mask), inode->i_mode);
        if (ceph_caps_issued_mask(ceph_inode(inode), mask, 1))
                return 0;
 
index a6ce54e94eb5ab435670093cd6ad789e72cc627b..52e8fd74d450b9e2895eb7c29d80e38b77eb0807 100644 (file)
@@ -4,7 +4,7 @@
 #include <linux/ioctl.h>
 #include <linux/types.h>
 
-#define CEPH_IOCTL_MAGIC 0x98
+#define CEPH_IOCTL_MAGIC 0x97
 
 /* just use u64 to align sanely on all archs */
 struct ceph_ioctl_layout {
index 40abde93c345d054279fd51cbca998525c4931c7..476b329867d41cf2cec7b3e2ad51e5f3885d9d7a 100644 (file)
  * Implement fcntl and flock locking functions.
  */
 static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file,
-                            u64 pid, u64 pid_ns,
-                            int cmd, u64 start, u64 length, u8 wait)
+                            int cmd, u8 wait, struct file_lock *fl)
 {
        struct inode *inode = file->f_dentry->d_inode;
        struct ceph_mds_client *mdsc =
                ceph_sb_to_client(inode->i_sb)->mdsc;
        struct ceph_mds_request *req;
        int err;
+       u64 length = 0;
 
        req = ceph_mdsc_create_request(mdsc, operation, USE_AUTH_MDS);
        if (IS_ERR(req))
                return PTR_ERR(req);
        req->r_inode = igrab(inode);
 
+       /* mds requires start and length rather than start and end */
+       if (LLONG_MAX == fl->fl_end)
+               length = 0;
+       else
+               length = fl->fl_end - fl->fl_start + 1;
+
        dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, "
             "length: %llu, wait: %d, type`: %d", (int)lock_type,
-            (int)operation, pid, start, length, wait, cmd);
+            (int)operation, (u64)fl->fl_pid, fl->fl_start,
+            length, wait, fl->fl_type);
+
 
        req->r_args.filelock_change.rule = lock_type;
        req->r_args.filelock_change.type = cmd;
-       req->r_args.filelock_change.pid = cpu_to_le64(pid);
+       req->r_args.filelock_change.pid = cpu_to_le64((u64)fl->fl_pid);
        /* This should be adjusted, but I'm not sure if
           namespaces actually get id numbers*/
        req->r_args.filelock_change.pid_namespace =
-               cpu_to_le64((u64)pid_ns);
-       req->r_args.filelock_change.start = cpu_to_le64(start);
+               cpu_to_le64((u64)(unsigned long)fl->fl_nspid);
+       req->r_args.filelock_change.start = cpu_to_le64(fl->fl_start);
        req->r_args.filelock_change.length = cpu_to_le64(length);
        req->r_args.filelock_change.wait = wait;
 
        err = ceph_mdsc_do_request(mdsc, inode, req);
+
+       if ( operation == CEPH_MDS_OP_GETFILELOCK){
+               fl->fl_pid = le64_to_cpu(req->r_reply_info.filelock_reply->pid);
+               if (CEPH_LOCK_SHARED == req->r_reply_info.filelock_reply->type)
+                       fl->fl_type = F_RDLCK;
+               else if (CEPH_LOCK_EXCL == req->r_reply_info.filelock_reply->type)
+                       fl->fl_type = F_WRLCK;
+               else
+                       fl->fl_type = F_UNLCK;
+
+               fl->fl_start = le64_to_cpu(req->r_reply_info.filelock_reply->start);
+               length = le64_to_cpu(req->r_reply_info.filelock_reply->start) +
+                                                le64_to_cpu(req->r_reply_info.filelock_reply->length);
+               if (length >= 1)
+                       fl->fl_end = length -1;
+               else
+                       fl->fl_end = 0;
+
+       }
        ceph_mdsc_put_request(req);
        dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, "
-            "length: %llu, wait: %d, type`: %d err code %d", (int)lock_type,
-            (int)operation, pid, start, length, wait, cmd, err);
+            "length: %llu, wait: %d, type`: %d, err code %d", (int)lock_type,
+            (int)operation, (u64)fl->fl_pid, fl->fl_start,
+            length, wait, fl->fl_type, err);
        return err;
 }
 
@@ -54,7 +82,6 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file,
  */
 int ceph_lock(struct file *file, int cmd, struct file_lock *fl)
 {
-       u64 length;
        u8 lock_cmd;
        int err;
        u8 wait = 0;
@@ -76,29 +103,20 @@ int ceph_lock(struct file *file, int cmd, struct file_lock *fl)
        else
                lock_cmd = CEPH_LOCK_UNLOCK;
 
-       if (LLONG_MAX == fl->fl_end)
-               length = 0;
-       else
-               length = fl->fl_end - fl->fl_start + 1;
-
-       err = ceph_lock_message(CEPH_LOCK_FCNTL, op, file,
-                               (u64)fl->fl_pid,
-                               (u64)(unsigned long)fl->fl_nspid,
-                               lock_cmd, fl->fl_start,
-                               length, wait);
+       err = ceph_lock_message(CEPH_LOCK_FCNTL, op, file, lock_cmd, wait, fl);
        if (!err) {
-               dout("mds locked, locking locally");
-               err = posix_lock_file(file, fl, NULL);
-               if (err && (CEPH_MDS_OP_SETFILELOCK == op)) {
-                       /* undo! This should only happen if the kernel detects
-                        * local deadlock. */
-                       ceph_lock_message(CEPH_LOCK_FCNTL, op, file,
-                                         (u64)fl->fl_pid,
-                                         (u64)(unsigned long)fl->fl_nspid,
-                                         CEPH_LOCK_UNLOCK, fl->fl_start,
-                                         length, 0);
-                       dout("got %d on posix_lock_file, undid lock", err);
+               if ( op != CEPH_MDS_OP_GETFILELOCK ){
+                       dout("mds locked, locking locally");
+                       err = posix_lock_file(file, fl, NULL);
+                       if (err && (CEPH_MDS_OP_SETFILELOCK == op)) {
+                               /* undo! This should only happen if the kernel detects
+                                * local deadlock. */
+                               ceph_lock_message(CEPH_LOCK_FCNTL, op, file,
+                                                 CEPH_LOCK_UNLOCK, 0, fl);
+                               dout("got %d on posix_lock_file, undid lock", err);
+                       }
                }
+
        } else {
                dout("mds returned error code %d", err);
        }
@@ -107,7 +125,6 @@ int ceph_lock(struct file *file, int cmd, struct file_lock *fl)
 
 int ceph_flock(struct file *file, int cmd, struct file_lock *fl)
 {
-       u64 length;
        u8 lock_cmd;
        int err;
        u8 wait = 1;
@@ -127,26 +144,15 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl)
                lock_cmd = CEPH_LOCK_EXCL;
        else
                lock_cmd = CEPH_LOCK_UNLOCK;
-       /* mds requires start and length rather than start and end */
-       if (LLONG_MAX == fl->fl_end)
-               length = 0;
-       else
-               length = fl->fl_end - fl->fl_start + 1;
 
        err = ceph_lock_message(CEPH_LOCK_FLOCK, CEPH_MDS_OP_SETFILELOCK,
-                               file, (u64)fl->fl_pid,
-                               (u64)(unsigned long)fl->fl_nspid,
-                               lock_cmd, fl->fl_start,
-                               length, wait);
+                               file, lock_cmd, wait, fl);
        if (!err) {
                err = flock_lock_file_wait(file, fl);
                if (err) {
                        ceph_lock_message(CEPH_LOCK_FLOCK,
                                          CEPH_MDS_OP_SETFILELOCK,
-                                         file, (u64)fl->fl_pid,
-                                         (u64)(unsigned long)fl->fl_nspid,
-                                         CEPH_LOCK_UNLOCK, fl->fl_start,
-                                         length, 0);
+                                         file, CEPH_LOCK_UNLOCK, 0, fl);
                        dout("got %d on flock_lock_file_wait, undid lock", err);
                }
        } else {
index 7799cac2b629de0f5b7ef47a911d65801261cab9..38800eaa81d066bd8f06a401d082ecd3bb3f6fea 100644 (file)
@@ -201,6 +201,38 @@ out_bad:
        return err;
 }
 
+/*
+ * parse fcntl F_GETLK results
+ */
+static int parse_reply_info_filelock(void **p, void *end,
+                struct ceph_mds_reply_info_parsed *info)
+{
+       if (*p + sizeof(*info->filelock_reply) > end)
+               goto bad;
+
+       info->filelock_reply = *p;
+       *p += sizeof(*info->filelock_reply);
+
+       if (unlikely(*p != end))
+               goto bad;
+       return 0;
+
+bad:
+       return -EIO;
+}
+
+/*
+ * parse extra results
+ */
+static int parse_reply_info_extra(void **p, void *end,
+                struct ceph_mds_reply_info_parsed *info)
+{
+       if (info->head->op == CEPH_MDS_OP_GETFILELOCK)
+               return parse_reply_info_filelock(p, end, info);
+       else
+               return parse_reply_info_dir(p, end, info);
+}
+
 /*
  * parse entire mds reply
  */
@@ -223,10 +255,10 @@ static int parse_reply_info(struct ceph_msg *msg,
                        goto out_bad;
        }
 
-       /* dir content */
+       /* extra */
        ceph_decode_32_safe(&p, end, len, bad);
        if (len > 0) {
-               err = parse_reply_info_dir(&p, p+len, info);
+               err = parse_reply_info_extra(&p, p+len, info);
                if (err < 0)
                        goto out_bad;
        }
@@ -528,6 +560,9 @@ static void __register_request(struct ceph_mds_client *mdsc,
        ceph_mdsc_get_request(req);
        __insert_request(mdsc, req);
 
+       req->r_uid = current_fsuid();
+       req->r_gid = current_fsgid();
+
        if (dir) {
                struct ceph_inode_info *ci = ceph_inode(dir);
 
@@ -1587,8 +1622,8 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc,
 
        head->mdsmap_epoch = cpu_to_le32(mdsc->mdsmap->m_epoch);
        head->op = cpu_to_le32(req->r_op);
-       head->caller_uid = cpu_to_le32(current_fsuid());
-       head->caller_gid = cpu_to_le32(current_fsgid());
+       head->caller_uid = cpu_to_le32(req->r_uid);
+       head->caller_gid = cpu_to_le32(req->r_gid);
        head->args = req->r_args;
 
        ceph_encode_filepath(&p, end, ino1, path1);
@@ -2071,7 +2106,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
 
        mutex_lock(&session->s_mutex);
        if (err < 0) {
-               pr_err("mdsc_handle_reply got corrupt reply mds%d\n", mds);
+               pr_err("mdsc_handle_reply got corrupt reply mds%d(tid:%lld)\n", mds, tid);
                ceph_msg_dump(msg);
                goto out_err;
        }
@@ -2091,7 +2126,8 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
        mutex_lock(&req->r_fill_mutex);
        err = ceph_fill_trace(mdsc->fsc->sb, req, req->r_session);
        if (err == 0) {
-               if (result == 0 && rinfo->dir_nr)
+               if (result == 0 && req->r_op != CEPH_MDS_OP_GETFILELOCK &&
+                   rinfo->dir_nr)
                        ceph_readdir_prepopulate(req, req->r_session);
                ceph_unreserve_caps(mdsc, &req->r_caps_reservation);
        }
index d66d63c7235526ef63d16ff0ea1e9ba3899df586..aabe563b54db308af80ee9fff18dd81610a9cf94 100644 (file)
@@ -42,26 +42,37 @@ struct ceph_mds_reply_info_in {
 };
 
 /*
- * parsed info about an mds reply, including information about the
- * target inode and/or its parent directory and dentry, and directory
- * contents (for readdir results).
+ * parsed info about an mds reply, including information about
+ * either: 1) the target inode and/or its parent directory and dentry,
+ * and directory contents (for readdir results), or
+ * 2) the file range lock info (for fcntl F_GETLK results).
  */
 struct ceph_mds_reply_info_parsed {
        struct ceph_mds_reply_head    *head;
 
+       /* trace */
        struct ceph_mds_reply_info_in diri, targeti;
        struct ceph_mds_reply_dirfrag *dirfrag;
        char                          *dname;
        u32                           dname_len;
        struct ceph_mds_reply_lease   *dlease;
 
-       struct ceph_mds_reply_dirfrag *dir_dir;
-       int                           dir_nr;
-       char                          **dir_dname;
-       u32                           *dir_dname_len;
-       struct ceph_mds_reply_lease   **dir_dlease;
-       struct ceph_mds_reply_info_in *dir_in;
-       u8                            dir_complete, dir_end;
+       /* extra */
+       union {
+               /* for fcntl F_GETLK results */
+               struct ceph_filelock *filelock_reply;
+
+               /* for readdir results */
+               struct {
+                       struct ceph_mds_reply_dirfrag *dir_dir;
+                       int                           dir_nr;
+                       char                          **dir_dname;
+                       u32                           *dir_dname_len;
+                       struct ceph_mds_reply_lease   **dir_dlease;
+                       struct ceph_mds_reply_info_in *dir_in;
+                       u8                            dir_complete, dir_end;
+               };
+       };
 
        /* encoded blob describing snapshot contexts for certain
           operations (e.g., open) */
@@ -170,6 +181,8 @@ struct ceph_mds_request {
 
        union ceph_mds_request_args r_args;
        int r_fmode;        /* file mode, if expecting cap */
+       uid_t r_uid;
+       gid_t r_gid;
 
        /* for choosing which mds to send this request to */
        int r_direct_mode;
index 1886294e12f7a3106c00f3376d92e43330514081..7f01728a46571f2fa22a47fbd062f6eadf4cba83 100644 (file)
@@ -293,9 +293,7 @@ struct ceph_inode_info {
        int i_rd_ref, i_rdcache_ref, i_wr_ref;
        int i_wrbuffer_ref, i_wrbuffer_ref_head;
        u32 i_shared_gen;       /* increment each time we get FILE_SHARED */
-       u32 i_rdcache_gen;      /* we increment this each time we get
-                                  FILE_CACHE.  If it's non-zero, we
-                                  _may_ have cached pages. */
+       u32 i_rdcache_gen;      /* incremented each time we get FILE_CACHE. */
        u32 i_rdcache_revoking; /* RDCACHE gen to async invalidate, if any */
 
        struct list_head i_unsafe_writes; /* uncommitted sync writes */
index 0ed213970cede228e097a04eec99c94ce97a6146..ee45648b0d1a9fead5722811171c6f5bcc3d8043 100644 (file)
@@ -4,6 +4,7 @@ config CIFS
        select NLS
        select CRYPTO
        select CRYPTO_MD5
+       select CRYPTO_HMAC
        select CRYPTO_ARC4
        help
          This is the client VFS module for the Common Internet File System
@@ -143,6 +144,13 @@ config CIFS_FSCACHE
            to be cached locally on disk through the general filesystem cache
            manager. If unsure, say N.
 
+config CIFS_ACL
+         bool "Provide CIFS ACL support (EXPERIMENTAL)"
+         depends on EXPERIMENTAL && CIFS_XATTR
+         help
+           Allows to fetch CIFS/NTFS ACL from the server.  The DACL blob
+           is handed over to the application/caller.
+
 config CIFS_EXPERIMENTAL
          bool "CIFS Experimental Features (EXPERIMENTAL)"
          depends on CIFS && EXPERIMENTAL
index adefa60a9bdc10108ec9c802e4cbe1ea26f3f6e0..43b19dd391912476c395ffbabaaabbacc28d0146 100644 (file)
@@ -6,7 +6,9 @@ obj-$(CONFIG_CIFS) += cifs.o
 cifs-y := 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 \
-         readdir.o ioctl.o sess.o export.o cifsacl.o
+         readdir.o ioctl.o sess.o export.o
+
+cifs-$(CONFIG_CIFS_ACL) += cifsacl.o
 
 cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o
 
index ee68d1036544d591930af8119d5e7450634adfff..46af99ab3614d545675e41e788686b39fd51204b 100644 (file)
@@ -337,6 +337,15 @@ A partial list of the supported mount options follows:
   wsize                default write size (default 57344)
                maximum wsize currently allowed by CIFS is 57344 (fourteen
                4096 byte pages)
+  actimeo=n    attribute cache timeout in seconds (default 1 second).
+               After this timeout, the cifs client requests fresh attribute
+               information from the server. This option allows to tune the
+               attribute cache timeout to suit the workload needs. Shorter
+               timeouts mean better the cache coherency, but increased number
+               of calls to the server. Longer timeouts mean reduced number
+               of calls to the server at the expense of less stricter cache
+               coherency checks (i.e. incorrect attribute cache for a short
+               period of time).
   rw           mount the network share read-write (note that the
                server may still consider the share read-only)
   ro           mount network share read-only
index e9a393c9c2ca4ddb8ec3d75cfcf0766234ec1789..7852cd6770517a8a5da7877fb788a834a0534c86 100644 (file)
@@ -48,6 +48,7 @@ struct cifs_sb_info {
        struct nls_table *local_nls;
        unsigned int rsize;
        unsigned int wsize;
+       unsigned long actimeo; /* attribute cache timeout (jiffies) */
        atomic_t active;
        uid_t   mnt_uid;
        gid_t   mnt_gid;
index c9b4792ae82538761b056ffba55173e77a2f2c8c..a437ec391a015fb7c05725543d6c118eadefc466 100644 (file)
@@ -30,8 +30,6 @@
 #include "cifs_debug.h"
 
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
-
 static struct cifs_wksid wksidarr[NUM_WK_SIDS] = {
        {{1, 0, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, "null user"},
        {{1, 1, {0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0} }, "nobody"},
@@ -560,7 +558,7 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
        struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
 
        if (IS_ERR(tlink))
-               return NULL;
+               return ERR_CAST(tlink);
 
        xid = GetXid();
        rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
@@ -568,7 +566,9 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
 
        cifs_put_tlink(tlink);
 
-       cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen);
+       cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
+       if (rc)
+               return ERR_PTR(rc);
        return pntsd;
 }
 
@@ -583,7 +583,7 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
        struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
 
        if (IS_ERR(tlink))
-               return NULL;
+               return ERR_CAST(tlink);
 
        tcon = tlink_tcon(tlink);
        xid = GetXid();
@@ -591,23 +591,22 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
        rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, 0,
                         &fid, &oplock, NULL, cifs_sb->local_nls,
                         cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
-       if (rc) {
-               cERROR(1, "Unable to open file to get ACL");
-               goto out;
+       if (!rc) {
+               rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
+               CIFSSMBClose(xid, tcon, fid);
        }
 
-       rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
-       cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen);
-
-       CIFSSMBClose(xid, tcon, fid);
- out:
        cifs_put_tlink(tlink);
        FreeXid(xid);
+
+       cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
+       if (rc)
+               return ERR_PTR(rc);
        return pntsd;
 }
 
 /* Retrieve an ACL from the server */
-static struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
+struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
                                      struct inode *inode, const char *path,
                                      u32 *pacllen)
 {
@@ -695,7 +694,7 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
 }
 
 /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
-void
+int
 cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
                  struct inode *inode, const char *path, const __u16 *pfid)
 {
@@ -711,17 +710,21 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
                pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
 
        /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
-       if (pntsd)
+       if (IS_ERR(pntsd)) {
+               rc = PTR_ERR(pntsd);
+               cERROR(1, "%s: error %d getting sec desc", __func__, rc);
+       } else {
                rc = parse_sec_desc(pntsd, acllen, fattr);
-       if (rc)
-               cFYI(1, "parse sec desc failed rc = %d", rc);
+               kfree(pntsd);
+               if (rc)
+                       cERROR(1, "parse sec desc failed rc = %d", rc);
+       }
 
-       kfree(pntsd);
-       return;
+       return rc;
 }
 
 /* Convert mode bits to an ACL so we can update the ACL on the server */
-int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
+int mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode)
 {
        int rc = 0;
        __u32 secdesclen = 0;
@@ -736,7 +739,10 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
        /* Add three ACEs for owner, group, everyone getting rid of
           other ACEs as chmod disables ACEs and set the security descriptor */
 
-       if (pntsd) {
+       if (IS_ERR(pntsd)) {
+               rc = PTR_ERR(pntsd);
+               cERROR(1, "%s: error %d getting sec desc", __func__, rc);
+       } else {
                /* allocate memory for the smb header,
                   set security descriptor request security descriptor
                   parameters, and secuirty descriptor itself */
@@ -766,4 +772,3 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
 
        return rc;
 }
-#endif /* CONFIG_CIFS_EXPERIMENTAL */
index 6c8096cf51557764aa10af6c28d108d3e93ce6e7..c4ae7d0365631f5d01db610ef3153502f2531c9d 100644 (file)
@@ -74,11 +74,7 @@ struct cifs_wksid {
        char sidname[SIDNAMELENGTH];
 } __attribute__((packed));
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
-
 extern int match_sid(struct cifs_sid *);
 extern int compare_sids(const struct cifs_sid *, const struct cifs_sid *);
 
-#endif /*  CONFIG_CIFS_EXPERIMENTAL */
-
 #endif /* _CIFSACL_H */
index 9c3789762ab7c4c92a7d67859c34b32cb196f1ab..3936aa7f2c2285cfb59857f8fe1925528920543a 100644 (file)
@@ -458,9 +458,13 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
                seq_printf(s, ",acl");
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
                seq_printf(s, ",mfsymlinks");
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE)
+               seq_printf(s, ",fsc");
 
        seq_printf(s, ",rsize=%d", cifs_sb->rsize);
        seq_printf(s, ",wsize=%d", cifs_sb->wsize);
+       /* convert actimeo and display it in seconds */
+               seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ);
 
        return 0;
 }
@@ -933,7 +937,6 @@ init_cifs(void)
        GlobalCurrentXid = 0;
        GlobalTotalActiveXid = 0;
        GlobalMaxActiveXid = 0;
-       memset(Local_System_Name, 0, 15);
        spin_lock_init(&cifs_tcp_ses_lock);
        spin_lock_init(&cifs_file_list_lock);
        spin_lock_init(&GlobalMid_Lock);
index b577bf0a1bb3622491ed0a885ca30b9e7684d24e..7136c0c3e2f961ec2c57d882163a1ffbc0e50ef1 100644 (file)
 
 #define CIFS_MIN_RCV_POOL 4
 
+/*
+ * default attribute cache timeout (jiffies)
+ */
+#define CIFS_DEF_ACTIMEO (1 * HZ)
+
+/*
+ * max attribute cache timeout (jiffies) - 2^30
+ */
+#define CIFS_MAX_ACTIMEO (1 << 30)
+
 /*
  * MAX_REQ is the maximum number of requests that WE will send
  * on one socket concurrently. It also matches the most common
@@ -746,8 +756,6 @@ GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */
 GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */
 GLOBAL_EXTERN spinlock_t GlobalMid_Lock;  /* protects above & list operations */
                                          /* on midQ entries */
-GLOBAL_EXTERN char Local_System_Name[15];
-
 /*
  *  Global counters, updated atomically
  */
index 7ed69b6b5fe6719f66ed5af0a0b38d2cda1aa352..e6d1481b16c1403cbe1c7fcae04e11abcc3f91f9 100644 (file)
@@ -54,7 +54,8 @@ do {                                                          \
             __func__, curr_xid, (int)rc);                      \
 } while (0)
 extern char *build_path_from_dentry(struct dentry *);
-extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb);
+extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb,
+                                       struct cifsTconInfo *tcon);
 extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
 extern char *cifs_compose_mount_options(const char *sb_mountdata,
                const char *fullpath, const struct dfs_info3_param *ref,
@@ -79,9 +80,7 @@ extern bool is_valid_oplock_break(struct smb_hdr *smb,
                                  struct TCP_Server_Info *);
 extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
 extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool);
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool);
-#endif
 extern unsigned int smbCalcSize(struct smb_hdr *ptr);
 extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
 extern int decode_negTokenInit(unsigned char *security_blob, int length,
@@ -130,10 +129,12 @@ extern int cifs_get_file_info_unix(struct file *filp);
 extern int cifs_get_inode_info_unix(struct inode **pinode,
                        const unsigned char *search_path,
                        struct super_block *sb, int xid);
-extern void cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
+extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
                              struct cifs_fattr *fattr, struct inode *inode,
                              const char *path, const __u16 *pfid);
-extern int mode_to_acl(struct inode *inode, const char *path, __u64);
+extern int mode_to_cifs_acl(struct inode *inode, const char *path, __u64);
+extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *,
+                                       const char *, u32 *);
 
 extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
                        const char *);
index 2f2632b6df5a1efd960bf44502d280e0e9499908..67acfb3acad271a51be1a1446d4f9828119e6b39 100644 (file)
@@ -2478,95 +2478,6 @@ querySymLinkRetry:
 }
 
 #ifdef CONFIG_CIFS_EXPERIMENTAL
-/* Initialize NT TRANSACT SMB into small smb request buffer.
-   This assumes that all NT TRANSACTS that we init here have
-   total parm and data under about 400 bytes (to fit in small cifs
-   buffer size), which is the case so far, it easily fits. NB:
-       Setup words themselves and ByteCount
-       MaxSetupCount (size of returned setup area) and
-       MaxParameterCount (returned parms size) must be set by caller */
-static int
-smb_init_nttransact(const __u16 sub_command, const int setup_count,
-                  const int parm_len, struct cifsTconInfo *tcon,
-                  void **ret_buf)
-{
-       int rc;
-       __u32 temp_offset;
-       struct smb_com_ntransact_req *pSMB;
-
-       rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
-                               (void **)&pSMB);
-       if (rc)
-               return rc;
-       *ret_buf = (void *)pSMB;
-       pSMB->Reserved = 0;
-       pSMB->TotalParameterCount = cpu_to_le32(parm_len);
-       pSMB->TotalDataCount  = 0;
-       pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
-                                         MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
-       pSMB->ParameterCount = pSMB->TotalParameterCount;
-       pSMB->DataCount  = pSMB->TotalDataCount;
-       temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
-                       (setup_count * 2) - 4 /* for rfc1001 length itself */;
-       pSMB->ParameterOffset = cpu_to_le32(temp_offset);
-       pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
-       pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
-       pSMB->SubCommand = cpu_to_le16(sub_command);
-       return 0;
-}
-
-static int
-validate_ntransact(char *buf, char **ppparm, char **ppdata,
-                  __u32 *pparmlen, __u32 *pdatalen)
-{
-       char *end_of_smb;
-       __u32 data_count, data_offset, parm_count, parm_offset;
-       struct smb_com_ntransact_rsp *pSMBr;
-
-       *pdatalen = 0;
-       *pparmlen = 0;
-
-       if (buf == NULL)
-               return -EINVAL;
-
-       pSMBr = (struct smb_com_ntransact_rsp *)buf;
-
-       /* ByteCount was converted from little endian in SendReceive */
-       end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
-                       (char *)&pSMBr->ByteCount;
-
-       data_offset = le32_to_cpu(pSMBr->DataOffset);
-       data_count = le32_to_cpu(pSMBr->DataCount);
-       parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
-       parm_count = le32_to_cpu(pSMBr->ParameterCount);
-
-       *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
-       *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
-
-       /* should we also check that parm and data areas do not overlap? */
-       if (*ppparm > end_of_smb) {
-               cFYI(1, "parms start after end of smb");
-               return -EINVAL;
-       } else if (parm_count + *ppparm > end_of_smb) {
-               cFYI(1, "parm end after end of smb");
-               return -EINVAL;
-       } else if (*ppdata > end_of_smb) {
-               cFYI(1, "data starts after end of smb");
-               return -EINVAL;
-       } else if (data_count + *ppdata > end_of_smb) {
-               cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
-                       *ppdata, data_count, (data_count + *ppdata),
-                       end_of_smb, pSMBr);
-               return -EINVAL;
-       } else if (parm_count + data_count > pSMBr->ByteCount) {
-               cFYI(1, "parm count and data count larger than SMB");
-               return -EINVAL;
-       }
-       *pdatalen = data_count;
-       *pparmlen = parm_count;
-       return 0;
-}
-
 int
 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
                        const unsigned char *searchName,
@@ -3056,7 +2967,97 @@ GetExtAttrOut:
 
 #endif /* CONFIG_POSIX */
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
+#ifdef CONFIG_CIFS_ACL
+/*
+ * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
+ * all NT TRANSACTS that we init here have total parm and data under about 400
+ * bytes (to fit in small cifs buffer size), which is the case so far, it
+ * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
+ * returned setup area) and MaxParameterCount (returned parms size) must be set
+ * by caller
+ */
+static int
+smb_init_nttransact(const __u16 sub_command, const int setup_count,
+                  const int parm_len, struct cifsTconInfo *tcon,
+                  void **ret_buf)
+{
+       int rc;
+       __u32 temp_offset;
+       struct smb_com_ntransact_req *pSMB;
+
+       rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
+                               (void **)&pSMB);
+       if (rc)
+               return rc;
+       *ret_buf = (void *)pSMB;
+       pSMB->Reserved = 0;
+       pSMB->TotalParameterCount = cpu_to_le32(parm_len);
+       pSMB->TotalDataCount  = 0;
+       pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
+                                         MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
+       pSMB->ParameterCount = pSMB->TotalParameterCount;
+       pSMB->DataCount  = pSMB->TotalDataCount;
+       temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
+                       (setup_count * 2) - 4 /* for rfc1001 length itself */;
+       pSMB->ParameterOffset = cpu_to_le32(temp_offset);
+       pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
+       pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
+       pSMB->SubCommand = cpu_to_le16(sub_command);
+       return 0;
+}
+
+static int
+validate_ntransact(char *buf, char **ppparm, char **ppdata,
+                  __u32 *pparmlen, __u32 *pdatalen)
+{
+       char *end_of_smb;
+       __u32 data_count, data_offset, parm_count, parm_offset;
+       struct smb_com_ntransact_rsp *pSMBr;
+
+       *pdatalen = 0;
+       *pparmlen = 0;
+
+       if (buf == NULL)
+               return -EINVAL;
+
+       pSMBr = (struct smb_com_ntransact_rsp *)buf;
+
+       /* ByteCount was converted from little endian in SendReceive */
+       end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
+                       (char *)&pSMBr->ByteCount;
+
+       data_offset = le32_to_cpu(pSMBr->DataOffset);
+       data_count = le32_to_cpu(pSMBr->DataCount);
+       parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
+       parm_count = le32_to_cpu(pSMBr->ParameterCount);
+
+       *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
+       *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
+
+       /* should we also check that parm and data areas do not overlap? */
+       if (*ppparm > end_of_smb) {
+               cFYI(1, "parms start after end of smb");
+               return -EINVAL;
+       } else if (parm_count + *ppparm > end_of_smb) {
+               cFYI(1, "parm end after end of smb");
+               return -EINVAL;
+       } else if (*ppdata > end_of_smb) {
+               cFYI(1, "data starts after end of smb");
+               return -EINVAL;
+       } else if (data_count + *ppdata > end_of_smb) {
+               cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
+                       *ppdata, data_count, (data_count + *ppdata),
+                       end_of_smb, pSMBr);
+               return -EINVAL;
+       } else if (parm_count + data_count > pSMBr->ByteCount) {
+               cFYI(1, "parm count and data count larger than SMB");
+               return -EINVAL;
+       }
+       *pdatalen = data_count;
+       *pparmlen = parm_count;
+       return 0;
+}
+
 /* Get Security Descriptor (by handle) from remote server for a file or dir */
 int
 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
@@ -3214,7 +3215,7 @@ setCifsAclRetry:
        return (rc);
 }
 
-#endif /* CONFIG_CIFS_EXPERIMENTAL */
+#endif /* CONFIG_CIFS_ACL */
 
 /* Legacy Query Path Information call for lookup to old servers such
    as Win9x/WinME */
index 251a17c03545dfc35e8ab37e1ea5a612e94f7536..cc1a8604a790b46767e066a59ef897f314144163 100644 (file)
@@ -105,6 +105,7 @@ struct smb_vol {
        unsigned int wsize;
        bool sockopt_tcp_nodelay:1;
        unsigned short int port;
+       unsigned long actimeo; /* attribute cache timeout (jiffies) */
        char *prepath;
        struct sockaddr_storage srcaddr; /* allow binding to a local IP */
        struct nls_table *local_nls;
@@ -806,23 +807,20 @@ cifs_parse_mount_options(char *options, const char *devname,
        short int override_gid = -1;
        bool uid_specified = false;
        bool gid_specified = false;
+       char *nodename = utsname()->nodename;
 
        separator[0] = ',';
        separator[1] = 0;
 
-       if (Local_System_Name[0] != 0)
-               memcpy(vol->source_rfc1001_name, Local_System_Name, 15);
-       else {
-               char *nodename = utsname()->nodename;
-               int n = strnlen(nodename, 15);
-               memset(vol->source_rfc1001_name, 0x20, 15);
-               for (i = 0; i < n; i++) {
-                       /* does not have to be perfect mapping since field is
-                       informational, only used for servers that do not support
-                       port 445 and it can be overridden at mount time */
-                       vol->source_rfc1001_name[i] = toupper(nodename[i]);
-               }
-       }
+       /*
+        * does not have to be perfect mapping since field is
+        * informational, only used for servers that do not support
+        * port 445 and it can be overridden at mount time
+        */
+       memset(vol->source_rfc1001_name, 0x20, 15);
+       for (i = 0; i < strnlen(nodename, 15); i++)
+               vol->source_rfc1001_name[i] = toupper(nodename[i]);
+
        vol->source_rfc1001_name[15] = 0;
        /* null target name indicates to use *SMBSERVR default called name
           if we end up sending RFC1001 session initialize */
@@ -840,6 +838,8 @@ cifs_parse_mount_options(char *options, const char *devname,
        /* default to using server inode numbers where available */
        vol->server_ino = 1;
 
+       vol->actimeo = CIFS_DEF_ACTIMEO;
+
        if (!options)
                return 1;
 
@@ -1214,6 +1214,16 @@ cifs_parse_mount_options(char *options, const char *devname,
                                        printk(KERN_WARNING "CIFS: server net"
                                        "biosname longer than 15 truncated.\n");
                        }
+               } else if (strnicmp(data, "actimeo", 7) == 0) {
+                       if (value && *value) {
+                               vol->actimeo = HZ * simple_strtoul(value,
+                                                                  &value, 0);
+                               if (vol->actimeo > CIFS_MAX_ACTIMEO) {
+                                       cERROR(1, "CIFS: attribute cache"
+                                                       "timeout too large");
+                                       return 1;
+                               }
+                       }
                } else if (strnicmp(data, "credentials", 4) == 0) {
                        /* ignore */
                } else if (strnicmp(data, "version", 3) == 0) {
@@ -1352,6 +1362,11 @@ cifs_parse_mount_options(char *options, const char *devname,
                                "supported. Instead set "
                                "/proc/fs/cifs/LookupCacheEnabled to 0\n");
                } else if (strnicmp(data, "fsc", 3) == 0) {
+#ifndef CONFIG_CIFS_FSCACHE
+                       cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE"
+                                 "kernel config option set");
+                       return 1;
+#endif
                        vol->fsc = true;
                } else if (strnicmp(data, "mfsymlinks", 10) == 0) {
                        vol->mfsymlinks = true;
@@ -2566,6 +2581,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
        cFYI(1, "file mode: 0x%x  dir mode: 0x%x",
                cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
 
+       cifs_sb->actimeo = pvolume_info->actimeo;
+
        if (pvolume_info->noperm)
                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
        if (pvolume_info->setuids)
@@ -2816,13 +2833,13 @@ remote_path_check:
        /* check if a whole path (including prepath) is not remote */
        if (!rc && cifs_sb->prepathlen && tcon) {
                /* build_path_to_root works only when we have a valid tcon */
-               full_path = cifs_build_path_to_root(cifs_sb);
+               full_path = cifs_build_path_to_root(cifs_sb, tcon);
                if (full_path == NULL) {
                        rc = -ENOMEM;
                        goto mount_fail_check;
                }
                rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
-               if (rc != -EREMOTE) {
+               if (rc != 0 && rc != -EREMOTE) {
                        kfree(full_path);
                        goto mount_fail_check;
                }
index 0eb87026cad3a4bf1050af0d2409ca0bfd7c928a..548f06230a6df50063b5c747b77330c4815fdd2e 100644 (file)
@@ -66,7 +66,7 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
        /* Search for server name delimiter */
        sep = memchr(hostname, '\\', len);
        if (sep)
-               len = sep - unc;
+               len = sep - hostname;
        else
                cFYI(1, "%s: probably server name is whole unc: %s",
                     __func__, unc);
index 06c3e83fa387fecf63b93e33a0455dac6da45f6d..5a28660ca2b5e619955c05d74d9d84b95a994a4b 100644 (file)
@@ -1108,7 +1108,6 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file,
        return total_written;
 }
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
                                        bool fsuid_only)
 {
@@ -1142,7 +1141,6 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
        spin_unlock(&cifs_file_list_lock);
        return NULL;
 }
-#endif
 
 struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
                                        bool fsuid_only)
@@ -2271,8 +2269,10 @@ void cifs_oplock_break_get(struct cifsFileInfo *cfile)
 
 void cifs_oplock_break_put(struct cifsFileInfo *cfile)
 {
+       struct super_block *sb = cfile->dentry->d_sb;
+
        cifsFileInfo_put(cfile);
-       cifs_sb_deactive(cfile->dentry->d_sb);
+       cifs_sb_deactive(sb);
 }
 
 const struct address_space_operations cifs_addr_ops = {
index a2ad94efcfe65a6eb1fb93c614b59cc3fdfae609..297a43d0ff7f5a4716d13eccd595286b44b3af65 100644 (file)
@@ -2,7 +2,7 @@
  *   fs/cifs/fscache.c - CIFS filesystem cache interface
  *
  *   Copyright (c) 2010 Novell, Inc.
- *   Author(s): Suresh Jayaraman (sjayaraman@suse.de>
+ *   Author(s): Suresh Jayaraman <sjayaraman@suse.de>
  *
  *   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
@@ -67,10 +67,12 @@ static void cifs_fscache_enable_inode_cookie(struct inode *inode)
        if (cifsi->fscache)
                return;
 
-       cifsi->fscache = fscache_acquire_cookie(tcon->fscache,
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) {
+               cifsi->fscache = fscache_acquire_cookie(tcon->fscache,
                                &cifs_fscache_inode_object_def, cifsi);
-       cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)", tcon->fscache,
+               cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)", tcon->fscache,
                                cifsi->fscache);
+       }
 }
 
 void cifs_fscache_release_inode_cookie(struct inode *inode)
@@ -101,10 +103,8 @@ void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
 {
        if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
                cifs_fscache_disable_inode_cookie(inode);
-       else {
+       else
                cifs_fscache_enable_inode_cookie(inode);
-               cFYI(1, "CIFS: fscache inode cookie set");
-       }
 }
 
 void cifs_fscache_reset_inode_cookie(struct inode *inode)
index ef3a55bf86b6d3700c521e074954548c6f53223f..589f3e3f6e0023b1f8b09f1e030119896117c94f 100644 (file)
@@ -686,13 +686,18 @@ int cifs_get_inode_info(struct inode **pinode,
                        cFYI(1, "cifs_sfu_type failed: %d", tmprc);
        }
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
+#ifdef CONFIG_CIFS_ACL
        /* fill in 0777 bits from ACL */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
-               cFYI(1, "Getting mode bits from ACL");
-               cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, pfid);
+               rc = cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path,
+                                               pfid);
+               if (rc) {
+                       cFYI(1, "%s: Getting ACL failed with error: %d",
+                               __func__, rc);
+                       goto cgii_exit;
+               }
        }
-#endif
+#endif /* CONFIG_CIFS_ACL */
 
        /* fill in remaining high mode bits e.g. SUID, VTX */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
@@ -723,12 +728,12 @@ static const struct inode_operations cifs_ipc_inode_ops = {
        .lookup = cifs_lookup,
 };
 
-char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
+char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb,
+                               struct cifsTconInfo *tcon)
 {
        int pplen = cifs_sb->prepathlen;
        int dfsplen;
        char *full_path = NULL;
-       struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
 
        /* if no prefix path, simply set path to the root of share to "" */
        if (pplen == 0) {
@@ -870,7 +875,7 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
        char *full_path;
        struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
 
-       full_path = cifs_build_path_to_root(cifs_sb);
+       full_path = cifs_build_path_to_root(cifs_sb, tcon);
        if (full_path == NULL)
                return ERR_PTR(-ENOMEM);
 
@@ -881,8 +886,10 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
                rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
                                                xid, NULL);
 
-       if (!inode)
-               return ERR_PTR(rc);
+       if (!inode) {
+               inode = ERR_PTR(rc);
+               goto out;
+       }
 
 #ifdef CONFIG_CIFS_FSCACHE
        /* populate tcon->resource_id */
@@ -898,13 +905,11 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
                inode->i_uid = cifs_sb->mnt_uid;
                inode->i_gid = cifs_sb->mnt_gid;
        } else if (rc) {
-               kfree(full_path);
-               _FreeXid(xid);
                iget_failed(inode);
-               return ERR_PTR(rc);
+               inode = ERR_PTR(rc);
        }
 
-
+out:
        kfree(full_path);
        /* can not call macro FreeXid here since in a void func
         * TODO: This is no longer true
@@ -1648,6 +1653,7 @@ static bool
 cifs_inode_needs_reval(struct inode *inode)
 {
        struct cifsInodeInfo *cifs_i = CIFS_I(inode);
+       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
 
        if (cifs_i->clientCanCacheRead)
                return false;
@@ -1658,19 +1664,21 @@ cifs_inode_needs_reval(struct inode *inode)
        if (cifs_i->time == 0)
                return true;
 
-       /* FIXME: the actimeo should be tunable */
-       if (time_after_eq(jiffies, cifs_i->time + HZ))
+       if (!time_in_range(jiffies, cifs_i->time,
+                               cifs_i->time + cifs_sb->actimeo))
                return true;
 
        /* hardlinked files w/ noserverino get "special" treatment */
-       if (!(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
+       if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
            S_ISREG(inode->i_mode) && inode->i_nlink != 1)
                return true;
 
        return false;
 }
 
-/* check invalid_mapping flag and zap the cache if it's set */
+/*
+ * Zap the cache. Called when invalid_mapping flag is set.
+ */
 static void
 cifs_invalidate_mapping(struct inode *inode)
 {
@@ -2114,11 +2122,16 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
 
        if (attrs->ia_valid & ATTR_MODE) {
                rc = 0;
-#ifdef CONFIG_CIFS_EXPERIMENTAL
-               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
-                       rc = mode_to_acl(inode, full_path, mode);
-               else
-#endif
+#ifdef CONFIG_CIFS_ACL
+               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
+                       rc = mode_to_cifs_acl(inode, full_path, mode);
+                       if (rc) {
+                               cFYI(1, "%s: Setting ACL failed with error: %d",
+                                       __func__, rc);
+                               goto cifs_setattr_exit;
+                       }
+               } else
+#endif /* CONFIG_CIFS_ACL */
                if (((mode & S_IWUGO) == 0) &&
                    (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
 
index ef7bb7b50f58e679ffabb8b8dad65420efb81271..a73eb9f4bdaf3608c2bf6f5dc124b5fabdd4445b 100644 (file)
@@ -226,26 +226,29 @@ static int initiate_cifs_search(const int xid, struct file *file)
        char *full_path = NULL;
        struct cifsFileInfo *cifsFile;
        struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
-       struct tcon_link *tlink;
+       struct tcon_link *tlink = NULL;
        struct cifsTconInfo *pTcon;
 
-       tlink = cifs_sb_tlink(cifs_sb);
-       if (IS_ERR(tlink))
-               return PTR_ERR(tlink);
-       pTcon = tlink_tcon(tlink);
-
-       if (file->private_data == NULL)
-               file->private_data =
-                       kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
        if (file->private_data == NULL) {
-               rc = -ENOMEM;
-               goto error_exit;
+               tlink = cifs_sb_tlink(cifs_sb);
+               if (IS_ERR(tlink))
+                       return PTR_ERR(tlink);
+
+               cifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
+               if (cifsFile == NULL) {
+                       rc = -ENOMEM;
+                       goto error_exit;
+               }
+               file->private_data = cifsFile;
+               cifsFile->tlink = cifs_get_tlink(tlink);
+               pTcon = tlink_tcon(tlink);
+       } else {
+               cifsFile = file->private_data;
+               pTcon = tlink_tcon(cifsFile->tlink);
        }
 
-       cifsFile = file->private_data;
        cifsFile->invalidHandle = true;
        cifsFile->srch_inf.endOfSearch = false;
-       cifsFile->tlink = cifs_get_tlink(tlink);
 
        full_path = build_path_from_dentry(file->f_path.dentry);
        if (full_path == NULL) {
@@ -756,18 +759,6 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
        rc = filldir(direntry, qstring.name, qstring.len, file->f_pos,
                     ino, fattr.cf_dtype);
 
-       /*
-        * we can not return filldir errors to the caller since they are
-        * "normal" when the stat blocksize is too small - we return remapped
-        * error instead
-        *
-        * FIXME: This looks bogus. filldir returns -EOVERFLOW in the above
-        * case already. Why should we be clobbering other errors from it?
-        */
-       if (rc) {
-               cFYI(1, "filldir rc = %d", rc);
-               rc = -EOVERFLOW;
-       }
        dput(tmp_dentry);
        return rc;
 }
index a264b744bb41f4e62d9375b496758d5450520460..eae2a14916080160c4723868dd69d9c3496c99fa 100644 (file)
 
 #define MAX_EA_VALUE_SIZE 65535
 #define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib"
+#define CIFS_XATTR_CIFS_ACL "system.cifs_acl"
 #define CIFS_XATTR_USER_PREFIX "user."
 #define CIFS_XATTR_SYSTEM_PREFIX "system."
 #define CIFS_XATTR_OS2_PREFIX "os2."
-#define CIFS_XATTR_SECURITY_PREFIX ".security"
+#define CIFS_XATTR_SECURITY_PREFIX "security."
 #define CIFS_XATTR_TRUSTED_PREFIX "trusted."
 #define XATTR_TRUSTED_PREFIX_LEN  8
 #define XATTR_SECURITY_PREFIX_LEN 9
@@ -277,29 +278,8 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
                                cifs_sb->local_nls,
                                cifs_sb->mnt_cifs_flags &
                                        CIFS_MOUNT_MAP_SPECIAL_CHR);
-#ifdef CONFIG_CIFS_EXPERIMENTAL
-               else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
-                       __u16 fid;
-                       int oplock = 0;
-                       struct cifs_ntsd *pacl = NULL;
-                       __u32 buflen = 0;
-                       if (experimEnabled)
-                               rc = CIFSSMBOpen(xid, pTcon, full_path,
-                                       FILE_OPEN, GENERIC_READ, 0, &fid,
-                                       &oplock, NULL, cifs_sb->local_nls,
-                                       cifs_sb->mnt_cifs_flags &
-                                       CIFS_MOUNT_MAP_SPECIAL_CHR);
-                       /* else rc is EOPNOTSUPP from above */
-
-                       if (rc == 0) {
-                               rc = CIFSSMBGetCIFSACL(xid, pTcon, fid, &pacl,
-                                                     &buflen);
-                               CIFSSMBClose(xid, pTcon, fid);
-                       }
-               }
-#endif /* EXPERIMENTAL */
 #else
-               cFYI(1, "query POSIX ACL not supported yet");
+               cFYI(1, "Query POSIX ACL not supported yet");
 #endif /* CONFIG_CIFS_POSIX */
        } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT,
                          strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
@@ -311,8 +291,33 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
                                cifs_sb->mnt_cifs_flags &
                                        CIFS_MOUNT_MAP_SPECIAL_CHR);
 #else
-               cFYI(1, "query POSIX default ACL not supported yet");
-#endif
+               cFYI(1, "Query POSIX default ACL not supported yet");
+#endif /* CONFIG_CIFS_POSIX */
+       } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL,
+                               strlen(CIFS_XATTR_CIFS_ACL)) == 0) {
+#ifdef CONFIG_CIFS_ACL
+                       u32 acllen;
+                       struct cifs_ntsd *pacl;
+
+                       pacl = get_cifs_acl(cifs_sb, direntry->d_inode,
+                                               full_path, &acllen);
+                       if (IS_ERR(pacl)) {
+                               rc = PTR_ERR(pacl);
+                               cERROR(1, "%s: error %zd getting sec desc",
+                                               __func__, rc);
+                       } else {
+                               if (ea_value) {
+                                       if (acllen > buf_size)
+                                               acllen = -ERANGE;
+                                       else
+                                               memcpy(ea_value, pacl, acllen);
+                               }
+                               rc = acllen;
+                               kfree(pacl);
+                       }
+#else
+               cFYI(1, "Query CIFS ACL not supported yet");
+#endif /* CONFIG_CIFS_ACL */
        } else if (strncmp(ea_name,
                  CIFS_XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) {
                cFYI(1, "Trusted xattr namespace not supported yet");
index c580c322fa6b1bab00a8b949cd3284f691bc366a..eb1740ac8c0a1e9e167b5e53e0f49d425774ff3d 100644 (file)
@@ -1350,6 +1350,10 @@ static int compat_count(compat_uptr_t __user *argv, int max)
                        argv++;
                        if (i++ >= max)
                                return -E2BIG;
+
+                       if (fatal_signal_pending(current))
+                               return -ERESTARTNOHAND;
+                       cond_resched();
                }
        }
        return i;
@@ -1391,6 +1395,12 @@ static int compat_copy_strings(int argc, compat_uptr_t __user *argv,
                while (len > 0) {
                        int offset, bytes_to_copy;
 
+                       if (fatal_signal_pending(current)) {
+                               ret = -ERESTARTNOHAND;
+                               goto out;
+                       }
+                       cond_resched();
+
                        offset = pos % PAGE_SIZE;
                        if (offset == 0)
                                offset = PAGE_SIZE;
@@ -1407,18 +1417,8 @@ static int compat_copy_strings(int argc, compat_uptr_t __user *argv,
                        if (!kmapped_page || kpos != (pos & PAGE_MASK)) {
                                struct page *page;
 
-#ifdef CONFIG_STACK_GROWSUP
-                               ret = expand_stack_downwards(bprm->vma, pos);
-                               if (ret < 0) {
-                                       /* We've exceed the stack rlimit. */
-                                       ret = -E2BIG;
-                                       goto out;
-                               }
-#endif
-                               ret = get_user_pages(current, bprm->mm, pos,
-                                                    1, 1, 1, &page, NULL);
-                               if (ret <= 0) {
-                                       /* We've exceed the stack rlimit. */
+                               page = get_arg_page(bprm, pos, 1);
+                               if (!page) {
                                        ret = -E2BIG;
                                        goto out;
                                }
@@ -1539,8 +1539,10 @@ int compat_do_execve(char * filename,
        return retval;
 
 out:
-       if (bprm->mm)
+       if (bprm->mm) {
+               acct_arg_size(bprm, 0);
                mmput(bprm->mm);
+       }
 
 out_file:
        if (bprm->file) {
index 99d33a1371e9aeaf7298c4548ed18a634b9f2427..c62efcb959c73fc458367d811c576e634fb49634 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -164,7 +164,26 @@ out:
 
 #ifdef CONFIG_MMU
 
-static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
+void acct_arg_size(struct linux_binprm *bprm, unsigned long pages)
+{
+       struct mm_struct *mm = current->mm;
+       long diff = (long)(pages - bprm->vma_pages);
+
+       if (!mm || !diff)
+               return;
+
+       bprm->vma_pages = pages;
+
+#ifdef SPLIT_RSS_COUNTING
+       add_mm_counter(mm, MM_ANONPAGES, diff);
+#else
+       spin_lock(&mm->page_table_lock);
+       add_mm_counter(mm, MM_ANONPAGES, diff);
+       spin_unlock(&mm->page_table_lock);
+#endif
+}
+
+struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
                int write)
 {
        struct page *page;
@@ -186,6 +205,8 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
                unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start;
                struct rlimit *rlim;
 
+               acct_arg_size(bprm, size / PAGE_SIZE);
+
                /*
                 * We've historically supported up to 32 pages (ARG_MAX)
                 * of argument strings even with small stacks
@@ -254,6 +275,11 @@ static int __bprm_mm_init(struct linux_binprm *bprm)
        vma->vm_flags = VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP;
        vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
        INIT_LIST_HEAD(&vma->anon_vma_chain);
+
+       err = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1);
+       if (err)
+               goto err;
+
        err = insert_vm_struct(mm, vma);
        if (err)
                goto err;
@@ -276,7 +302,11 @@ static bool valid_arg_len(struct linux_binprm *bprm, long len)
 
 #else
 
-static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
+void acct_arg_size(struct linux_binprm *bprm, unsigned long pages)
+{
+}
+
+struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
                int write)
 {
        struct page *page;
@@ -1003,6 +1033,7 @@ int flush_old_exec(struct linux_binprm * bprm)
        /*
         * Release all of the old mmap stuff
         */
+       acct_arg_size(bprm, 0);
        retval = exec_mmap(bprm->mm);
        if (retval)
                goto out;
@@ -1426,8 +1457,10 @@ int do_execve(const char * filename,
        return retval;
 
 out:
-       if (bprm->mm)
-               mmput (bprm->mm);
+       if (bprm->mm) {
+               acct_arg_size(bprm, 0);
+               mmput(bprm->mm);
+       }
 
 out_file:
        if (bprm->file) {
index 6a5edea2d70b3ac7c56e8b272686b5a799eabbcf..94ce3d7a1c4b9fe83b42954d309c8ac93b284ff5 100644 (file)
@@ -910,6 +910,7 @@ struct ext4_inode_info {
 #define EXT4_MOUNT_JOURNAL_CHECKSUM    0x800000 /* Journal checksums */
 #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT        0x1000000 /* Journal Async Commit */
 #define EXT4_MOUNT_I_VERSION            0x2000000 /* i_version support */
+#define EXT4_MOUNT_MBLK_IO_SUBMIT      0x4000000 /* multi-block io submits */
 #define EXT4_MOUNT_DELALLOC            0x8000000 /* Delalloc support */
 #define EXT4_MOUNT_DATA_ERR_ABORT      0x10000000 /* Abort on file data write */
 #define EXT4_MOUNT_BLOCK_VALIDITY      0x20000000 /* Block validity checking */
index bdbe69902207c151df025d98690c4c016cf0b0e9..e659597b690b508e1325182de702031a73843f4d 100644 (file)
@@ -2125,9 +2125,12 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd,
                         */
                        if (unlikely(journal_data && PageChecked(page)))
                                err = __ext4_journalled_writepage(page, len);
-                       else
+                       else if (test_opt(inode->i_sb, MBLK_IO_SUBMIT))
                                err = ext4_bio_write_page(&io_submit, page,
                                                          len, mpd->wbc);
+                       else
+                               err = block_write_full_page(page,
+                                       noalloc_get_block_write, mpd->wbc);
 
                        if (!err)
                                mpd->pages_written++;
index bf5ae883b1bdc30ff55cbc616bab7c24f9d57dbb..eb3bc2fe647e710de889f04da3afaf5821e00556 100644 (file)
@@ -331,6 +331,30 @@ mext_out:
                return err;
        }
 
+       case FITRIM:
+       {
+               struct super_block *sb = inode->i_sb;
+               struct fstrim_range range;
+               int ret = 0;
+
+               if (!capable(CAP_SYS_ADMIN))
+                       return -EPERM;
+
+               if (copy_from_user(&range, (struct fstrim_range *)arg,
+                   sizeof(range)))
+                       return -EFAULT;
+
+               ret = ext4_trim_fs(sb, &range);
+               if (ret < 0)
+                       return ret;
+
+               if (copy_to_user((struct fstrim_range *)arg, &range,
+                   sizeof(range)))
+                       return -EFAULT;
+
+               return 0;
+       }
+
        default:
                return -ENOTTY;
        }
index 92203b8a099f076ebbc0d794b3356289096c663f..dc40e75cba8857e6068739646b4932bb315688fd 100644 (file)
@@ -872,7 +872,7 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
        if (namelen > EXT4_NAME_LEN)
                return NULL;
        if ((namelen <= 2) && (name[0] == '.') &&
-           (name[1] == '.' || name[1] == '0')) {
+           (name[1] == '.' || name[1] == '\0')) {
                /*
                 * "." or ".." will only be in the first block
                 * NFS may look up ".."; "." should be handled by the VFS
index 7f5451cd1d38bff2399471750618fc7429ce5c5e..beacce11ac506ff3dd9958d1a3f82db095a36468 100644 (file)
@@ -237,8 +237,6 @@ static void ext4_end_bio(struct bio *bio, int error)
                        } while (bh != head);
                }
 
-               put_io_page(io_end->pages[i]);
-
                /*
                 * If this is a partial write which happened to make
                 * all buffers uptodate then we can optimize away a
@@ -248,6 +246,8 @@ static void ext4_end_bio(struct bio *bio, int error)
                 */
                if (!partial_write)
                        SetPageUptodate(page);
+
+               put_io_page(io_end->pages[i]);
        }
        io_end->num_io_pages = 0;
        inode = io_end->inode;
index 61182fe6254e94ad606a6c67fed1b30ef289ad38..fb15c9c0be74d5c06ba421f04449d981a69337ed 100644 (file)
@@ -1026,6 +1026,8 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
            !(def_mount_opts & EXT4_DEFM_NODELALLOC))
                seq_puts(seq, ",nodelalloc");
 
+       if (test_opt(sb, MBLK_IO_SUBMIT))
+               seq_puts(seq, ",mblk_io_submit");
        if (sbi->s_stripe)
                seq_printf(seq, ",stripe=%lu", sbi->s_stripe);
        /*
@@ -1197,7 +1199,6 @@ static const struct super_operations ext4_sops = {
        .quota_write    = ext4_quota_write,
 #endif
        .bdev_try_to_free_page = bdev_try_to_free_page,
-       .trim_fs        = ext4_trim_fs
 };
 
 static const struct super_operations ext4_nojournal_sops = {
@@ -1240,8 +1241,8 @@ enum {
        Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota,
        Opt_noquota, Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err,
        Opt_resize, Opt_usrquota, Opt_grpquota, Opt_i_version,
-       Opt_stripe, Opt_delalloc, Opt_nodelalloc,
-       Opt_block_validity, Opt_noblock_validity,
+       Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_mblk_io_submit,
+       Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity,
        Opt_inode_readahead_blks, Opt_journal_ioprio,
        Opt_dioread_nolock, Opt_dioread_lock,
        Opt_discard, Opt_nodiscard,
@@ -1305,6 +1306,8 @@ static const match_table_t tokens = {
        {Opt_resize, "resize"},
        {Opt_delalloc, "delalloc"},
        {Opt_nodelalloc, "nodelalloc"},
+       {Opt_mblk_io_submit, "mblk_io_submit"},
+       {Opt_nomblk_io_submit, "nomblk_io_submit"},
        {Opt_block_validity, "block_validity"},
        {Opt_noblock_validity, "noblock_validity"},
        {Opt_inode_readahead_blks, "inode_readahead_blks=%u"},
@@ -1726,6 +1729,12 @@ set_qf_format:
                case Opt_nodelalloc:
                        clear_opt(sbi->s_mount_opt, DELALLOC);
                        break;
+               case Opt_mblk_io_submit:
+                       set_opt(sbi->s_mount_opt, MBLK_IO_SUBMIT);
+                       break;
+               case Opt_nomblk_io_submit:
+                       clear_opt(sbi->s_mount_opt, MBLK_IO_SUBMIT);
+                       break;
                case Opt_stripe:
                        if (match_int(&args[0], &option))
                                return 0;
@@ -2799,9 +2808,6 @@ static void ext4_clear_request_list(void)
        struct ext4_li_request *elr;
 
        mutex_lock(&ext4_li_info->li_list_mtx);
-       if (list_empty(&ext4_li_info->li_request_list))
-               return;
-
        list_for_each_safe(pos, n, &ext4_li_info->li_request_list) {
                elr = list_entry(pos, struct ext4_li_request,
                                 lr_request);
@@ -3268,13 +3274,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
         * Test whether we have more sectors than will fit in sector_t,
         * and whether the max offset is addressable by the page cache.
         */
-       ret = generic_check_addressable(sb->s_blocksize_bits,
+       err = generic_check_addressable(sb->s_blocksize_bits,
                                        ext4_blocks_count(es));
-       if (ret) {
+       if (err) {
                ext4_msg(sb, KERN_ERR, "filesystem"
                         " too large to mount safely on this system");
                if (sizeof(sector_t) < 8)
                        ext4_msg(sb, KERN_WARNING, "CONFIG_LBDAF not enabled");
+               ret = err;
                goto failed_mount;
        }
 
index c8224587123f6e2ff84c8933f8d56a50ffd06c80..8b984a2cebbda185af01a6d4d5f8c31c89fc6fbe 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/module.h>
+#include <linux/compat.h>
 
 static const struct file_operations fuse_direct_io_file_operations;
 
@@ -134,6 +135,7 @@ EXPORT_SYMBOL_GPL(fuse_do_open);
 void fuse_finish_open(struct inode *inode, struct file *file)
 {
        struct fuse_file *ff = file->private_data;
+       struct fuse_conn *fc = get_fuse_conn(inode);
 
        if (ff->open_flags & FOPEN_DIRECT_IO)
                file->f_op = &fuse_direct_io_file_operations;
@@ -141,6 +143,15 @@ void fuse_finish_open(struct inode *inode, struct file *file)
                invalidate_inode_pages2(inode->i_mapping);
        if (ff->open_flags & FOPEN_NONSEEKABLE)
                nonseekable_open(inode, file);
+       if (fc->atomic_o_trunc && (file->f_flags & O_TRUNC)) {
+               struct fuse_inode *fi = get_fuse_inode(inode);
+
+               spin_lock(&fc->lock);
+               fi->attr_version = ++fc->attr_version;
+               i_size_write(inode, 0);
+               spin_unlock(&fc->lock);
+               fuse_invalidate_attr(inode);
+       }
 }
 
 int fuse_open_common(struct inode *inode, struct file *file, bool isdir)
@@ -1617,6 +1628,58 @@ static int fuse_ioctl_copy_user(struct page **pages, struct iovec *iov,
        return 0;
 }
 
+/*
+ * CUSE servers compiled on 32bit broke on 64bit kernels because the
+ * ABI was defined to be 'struct iovec' which is different on 32bit
+ * and 64bit.  Fortunately we can determine which structure the server
+ * used from the size of the reply.
+ */
+static int fuse_copy_ioctl_iovec(struct iovec *dst, void *src,
+                                size_t transferred, unsigned count,
+                                bool is_compat)
+{
+#ifdef CONFIG_COMPAT
+       if (count * sizeof(struct compat_iovec) == transferred) {
+               struct compat_iovec *ciov = src;
+               unsigned i;
+
+               /*
+                * With this interface a 32bit server cannot support
+                * non-compat (i.e. ones coming from 64bit apps) ioctl
+                * requests
+                */
+               if (!is_compat)
+                       return -EINVAL;
+
+               for (i = 0; i < count; i++) {
+                       dst[i].iov_base = compat_ptr(ciov[i].iov_base);
+                       dst[i].iov_len = ciov[i].iov_len;
+               }
+               return 0;
+       }
+#endif
+
+       if (count * sizeof(struct iovec) != transferred)
+               return -EIO;
+
+       memcpy(dst, src, transferred);
+       return 0;
+}
+
+/* Make sure iov_length() won't overflow */
+static int fuse_verify_ioctl_iov(struct iovec *iov, size_t count)
+{
+       size_t n;
+       u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT;
+
+       for (n = 0; n < count; n++) {
+               if (iov->iov_len > (size_t) max)
+                       return -ENOMEM;
+               max -= iov->iov_len;
+       }
+       return 0;
+}
+
 /*
  * For ioctls, there is no generic way to determine how much memory
  * needs to be read and/or written.  Furthermore, ioctls are allowed
@@ -1798,18 +1861,25 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
                    in_iovs + out_iovs > FUSE_IOCTL_MAX_IOV)
                        goto out;
 
-               err = -EIO;
-               if ((in_iovs + out_iovs) * sizeof(struct iovec) != transferred)
-                       goto out;
-
-               /* okay, copy in iovs and retry */
                vaddr = kmap_atomic(pages[0], KM_USER0);
-               memcpy(page_address(iov_page), vaddr, transferred);
+               err = fuse_copy_ioctl_iovec(page_address(iov_page), vaddr,
+                                           transferred, in_iovs + out_iovs,
+                                           (flags & FUSE_IOCTL_COMPAT) != 0);
                kunmap_atomic(vaddr, KM_USER0);
+               if (err)
+                       goto out;
 
                in_iov = page_address(iov_page);
                out_iov = in_iov + in_iovs;
 
+               err = fuse_verify_ioctl_iov(in_iov, in_iovs);
+               if (err)
+                       goto out;
+
+               err = fuse_verify_ioctl_iov(out_iov, out_iovs);
+               if (err)
+                       goto out;
+
                goto retry;
        }
 
index 58a9b9998b42d0d9603c7a49ffc746ab4a22ef87..f606baf9ba7247e9a5fd9ccfb2cc9426019e589e 100644 (file)
@@ -631,6 +631,7 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
                             struct fs_disk_quota *fdq)
 {
        struct inode *inode = &ip->i_inode;
+       struct gfs2_sbd *sdp = GFS2_SB(inode);
        struct address_space *mapping = inode->i_mapping;
        unsigned long index = loc >> PAGE_CACHE_SHIFT;
        unsigned offset = loc & (PAGE_CACHE_SIZE - 1);
@@ -658,11 +659,11 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
        qd->qd_qb.qb_value = qp->qu_value;
        if (fdq) {
                if (fdq->d_fieldmask & FS_DQ_BSOFT) {
-                       qp->qu_warn = cpu_to_be64(fdq->d_blk_softlimit);
+                       qp->qu_warn = cpu_to_be64(fdq->d_blk_softlimit >> sdp->sd_fsb2bb_shift);
                        qd->qd_qb.qb_warn = qp->qu_warn;
                }
                if (fdq->d_fieldmask & FS_DQ_BHARD) {
-                       qp->qu_limit = cpu_to_be64(fdq->d_blk_hardlimit);
+                       qp->qu_limit = cpu_to_be64(fdq->d_blk_hardlimit >> sdp->sd_fsb2bb_shift);
                        qd->qd_qb.qb_limit = qp->qu_limit;
                }
        }
@@ -1497,9 +1498,9 @@ static int gfs2_get_dqblk(struct super_block *sb, int type, qid_t id,
        fdq->d_version = FS_DQUOT_VERSION;
        fdq->d_flags = (type == QUOTA_USER) ? FS_USER_QUOTA : FS_GROUP_QUOTA;
        fdq->d_id = id;
-       fdq->d_blk_hardlimit = be64_to_cpu(qlvb->qb_limit);
-       fdq->d_blk_softlimit = be64_to_cpu(qlvb->qb_warn);
-       fdq->d_bcount = be64_to_cpu(qlvb->qb_value);
+       fdq->d_blk_hardlimit = be64_to_cpu(qlvb->qb_limit) << sdp->sd_fsb2bb_shift;
+       fdq->d_blk_softlimit = be64_to_cpu(qlvb->qb_warn) << sdp->sd_fsb2bb_shift;
+       fdq->d_bcount = be64_to_cpu(qlvb->qb_value) << sdp->sd_fsb2bb_shift;
 
        gfs2_glock_dq_uninit(&q_gh);
 out:
@@ -1566,10 +1567,10 @@ static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id,
 
        /* If nothing has changed, this is a no-op */
        if ((fdq->d_fieldmask & FS_DQ_BSOFT) &&
-           (fdq->d_blk_softlimit == be64_to_cpu(qd->qd_qb.qb_warn)))
+           ((fdq->d_blk_softlimit >> sdp->sd_fsb2bb_shift) == be64_to_cpu(qd->qd_qb.qb_warn)))
                fdq->d_fieldmask ^= FS_DQ_BSOFT;
        if ((fdq->d_fieldmask & FS_DQ_BHARD) &&
-           (fdq->d_blk_hardlimit == be64_to_cpu(qd->qd_qb.qb_limit)))
+           ((fdq->d_blk_hardlimit >> sdp->sd_fsb2bb_shift) == be64_to_cpu(qd->qd_qb.qb_limit)))
                fdq->d_fieldmask ^= FS_DQ_BHARD;
        if (fdq->d_fieldmask == 0)
                goto out_i;
index 4f46752ce4f9f7d02ce9afd7520117ba2ac01a23..d6cc16476620760b6f01233f87fe5842335ba760 100644 (file)
@@ -529,41 +529,6 @@ static int ioctl_fsthaw(struct file *filp)
        return thaw_super(sb);
 }
 
-static int ioctl_fstrim(struct file *filp, void __user *argp)
-{
-       struct super_block *sb = filp->f_path.dentry->d_inode->i_sb;
-       struct fstrim_range range;
-       int ret = 0;
-
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-
-       /* If filesystem doesn't support trim feature, return. */
-       if (sb->s_op->trim_fs == NULL)
-               return -EOPNOTSUPP;
-
-       /* If a blockdevice-backed filesystem isn't specified, return EINVAL. */
-       if (sb->s_bdev == NULL)
-               return -EINVAL;
-
-       if (argp == NULL) {
-               range.start = 0;
-               range.len = ULLONG_MAX;
-               range.minlen = 0;
-       } else if (copy_from_user(&range, argp, sizeof(range)))
-               return -EFAULT;
-
-       ret = sb->s_op->trim_fs(sb, &range);
-       if (ret < 0)
-               return ret;
-
-       if ((argp != NULL) &&
-           (copy_to_user(argp, &range, sizeof(range))))
-               return -EFAULT;
-
-       return 0;
-}
-
 /*
  * When you add any new common ioctls to the switches above and below
  * please update compat_sys_ioctl() too.
@@ -614,10 +579,6 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
                error = ioctl_fsthaw(filp);
                break;
 
-       case FITRIM:
-               error = ioctl_fstrim(filp, argp);
-               break;
-
        case FS_IOC_FIEMAP:
                return ioctl_fiemap(filp, arg);
 
index 2f7d05c899220e06d99ac9ecc9f8047903faa3a0..7da2a06508e5448c59aebcee03518d78f2b0599b 100644 (file)
@@ -103,22 +103,15 @@ SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio)
        }
 
        ret = -ESRCH;
-       /*
-        * We want IOPRIO_WHO_PGRP/IOPRIO_WHO_USER to be "atomic",
-        * so we can't use rcu_read_lock(). See re-copy of ->ioprio
-        * in copy_process().
-        */
-       read_lock(&tasklist_lock);
+       rcu_read_lock();
        switch (which) {
                case IOPRIO_WHO_PROCESS:
-                       rcu_read_lock();
                        if (!who)
                                p = current;
                        else
                                p = find_task_by_vpid(who);
                        if (p)
                                ret = set_task_ioprio(p, ioprio);
-                       rcu_read_unlock();
                        break;
                case IOPRIO_WHO_PGRP:
                        if (!who)
@@ -141,12 +134,7 @@ SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio)
                                break;
 
                        do_each_thread(g, p) {
-                               int match;
-
-                               rcu_read_lock();
-                               match = __task_cred(p)->uid == who;
-                               rcu_read_unlock();
-                               if (!match)
+                               if (__task_cred(p)->uid != who)
                                        continue;
                                ret = set_task_ioprio(p, ioprio);
                                if (ret)
@@ -160,7 +148,7 @@ free_uid:
                        ret = -EINVAL;
        }
 
-       read_unlock(&tasklist_lock);
+       rcu_read_unlock();
        return ret;
 }
 
@@ -204,17 +192,15 @@ SYSCALL_DEFINE2(ioprio_get, int, which, int, who)
        int ret = -ESRCH;
        int tmpio;
 
-       read_lock(&tasklist_lock);
+       rcu_read_lock();
        switch (which) {
                case IOPRIO_WHO_PROCESS:
-                       rcu_read_lock();
                        if (!who)
                                p = current;
                        else
                                p = find_task_by_vpid(who);
                        if (p)
                                ret = get_task_ioprio(p);
-                       rcu_read_unlock();
                        break;
                case IOPRIO_WHO_PGRP:
                        if (!who)
@@ -241,12 +227,7 @@ SYSCALL_DEFINE2(ioprio_get, int, which, int, who)
                                break;
 
                        do_each_thread(g, p) {
-                               int match;
-
-                               rcu_read_lock();
-                               match = __task_cred(p)->uid == user->uid;
-                               rcu_read_unlock();
-                               if (!match)
+                               if (__task_cred(p)->uid != user->uid)
                                        continue;
                                tmpio = get_task_ioprio(p);
                                if (tmpio < 0)
@@ -264,6 +245,6 @@ SYSCALL_DEFINE2(ioprio_get, int, which, int, who)
                        ret = -EINVAL;
        }
 
-       read_unlock(&tasklist_lock);
+       rcu_read_unlock();
        return ret;
 }
index c590d155c0959bfbe1f8ce2f6be9702afd2904f4..f837ba953529690e9de45c1e1731470897edeeb4 100644 (file)
@@ -899,6 +899,14 @@ journal_t * jbd2_journal_init_dev(struct block_device *bdev,
 
        /* journal descriptor can store up to n blocks -bzzz */
        journal->j_blocksize = blocksize;
+       journal->j_dev = bdev;
+       journal->j_fs_dev = fs_dev;
+       journal->j_blk_offset = start;
+       journal->j_maxlen = len;
+       bdevname(journal->j_dev, journal->j_devname);
+       p = journal->j_devname;
+       while ((p = strchr(p, '/')))
+               *p = '!';
        jbd2_stats_proc_init(journal);
        n = journal->j_blocksize / sizeof(journal_block_tag_t);
        journal->j_wbufsize = n;
@@ -908,14 +916,6 @@ journal_t * jbd2_journal_init_dev(struct block_device *bdev,
                        __func__);
                goto out_err;
        }
-       journal->j_dev = bdev;
-       journal->j_fs_dev = fs_dev;
-       journal->j_blk_offset = start;
-       journal->j_maxlen = len;
-       bdevname(journal->j_dev, journal->j_devname);
-       p = journal->j_devname;
-       while ((p = strchr(p, '/')))
-               *p = '!';
 
        bh = __getblk(journal->j_dev, start, journal->j_blocksize);
        if (!bh) {
index 5362af9b73729905817a76b5c24a5b33c48d5ce7..4ff7ca530533b121763dbe3b415ad79b162a85fb 100644 (file)
@@ -1748,6 +1748,9 @@ struct file *do_filp_open(int dfd, const char *pathname,
        if (!(open_flag & O_CREAT))
                mode = 0;
 
+       /* Must never be set by userspace */
+       open_flag &= ~FMODE_NONOTIFY;
+
        /*
         * O_SYNC is implemented as __O_SYNC|O_DSYNC.  As many places only
         * check for O_DSYNC if the need any syncing at all we enforce it's
index 662df2a5fad5d06fac235314220e7270fe9eef02..996dd8989a9135203cab110f57e7c1f8df49e200 100644 (file)
@@ -57,7 +57,7 @@ static int nfs_rename(struct inode *, struct dentry *,
                      struct inode *, struct dentry *);
 static int nfs_fsync_dir(struct file *, int);
 static loff_t nfs_llseek_dir(struct file *, loff_t, int);
-static int nfs_readdir_clear_array(struct page*, gfp_t);
+static void nfs_readdir_clear_array(struct page*);
 
 const struct file_operations nfs_dir_operations = {
        .llseek         = nfs_llseek_dir,
@@ -83,8 +83,8 @@ const struct inode_operations nfs_dir_inode_operations = {
        .setattr        = nfs_setattr,
 };
 
-const struct address_space_operations nfs_dir_addr_space_ops = {
-       .releasepage = nfs_readdir_clear_array,
+const struct address_space_operations nfs_dir_aops = {
+       .freepage = nfs_readdir_clear_array,
 };
 
 #ifdef CONFIG_NFS_V3
@@ -162,6 +162,7 @@ struct nfs_cache_array_entry {
        u64 cookie;
        u64 ino;
        struct qstr string;
+       unsigned char d_type;
 };
 
 struct nfs_cache_array {
@@ -171,14 +172,13 @@ struct nfs_cache_array {
        struct nfs_cache_array_entry array[0];
 };
 
-#define MAX_READDIR_ARRAY ((PAGE_SIZE - sizeof(struct nfs_cache_array)) / sizeof(struct nfs_cache_array_entry))
-
 typedef __be32 * (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int);
 typedef struct {
        struct file     *file;
        struct page     *page;
        unsigned long   page_index;
        u64             *dir_cookie;
+       u64             last_cookie;
        loff_t          current_index;
        decode_dirent_t decode;
 
@@ -214,17 +214,15 @@ void nfs_readdir_release_array(struct page *page)
  * we are freeing strings created by nfs_add_to_readdir_array()
  */
 static
-int nfs_readdir_clear_array(struct page *page, gfp_t mask)
+void nfs_readdir_clear_array(struct page *page)
 {
-       struct nfs_cache_array *array = nfs_readdir_get_array(page);
+       struct nfs_cache_array *array;
        int i;
 
-       if (IS_ERR(array))
-               return PTR_ERR(array);
+       array = kmap_atomic(page, KM_USER0);
        for (i = 0; i < array->size; i++)
                kfree(array->array[i].string.name);
-       nfs_readdir_release_array(page);
-       return 0;
+       kunmap_atomic(array, KM_USER0);
 }
 
 /*
@@ -257,19 +255,23 @@ int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page)
 
        if (IS_ERR(array))
                return PTR_ERR(array);
+
+       cache_entry = &array->array[array->size];
+
+       /* Check that this entry lies within the page bounds */
        ret = -ENOSPC;
-       if (array->size >= MAX_READDIR_ARRAY)
+       if ((char *)&cache_entry[1] - (char *)page_address(page) > PAGE_SIZE)
                goto out;
 
-       cache_entry = &array->array[array->size];
        cache_entry->cookie = entry->prev_cookie;
        cache_entry->ino = entry->ino;
+       cache_entry->d_type = entry->d_type;
        ret = nfs_readdir_make_qstr(&cache_entry->string, entry->name, entry->len);
        if (ret)
                goto out;
        array->last_cookie = entry->cookie;
        array->size++;
-       if (entry->eof == 1)
+       if (entry->eof != 0)
                array->eof_index = array->size;
 out:
        nfs_readdir_release_array(page);
@@ -309,15 +311,14 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des
        for (i = 0; i < array->size; i++) {
                if (array->array[i].cookie == *desc->dir_cookie) {
                        desc->cache_entry_index = i;
-                       status = 0;
-                       goto out;
+                       return 0;
                }
        }
-       if (i == array->eof_index) {
-               desc->eof = 1;
+       if (array->eof_index >= 0) {
                status = -EBADCOOKIE;
+               if (*desc->dir_cookie == array->last_cookie)
+                       desc->eof = 1;
        }
-out:
        return status;
 }
 
@@ -325,10 +326,7 @@ static
 int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc)
 {
        struct nfs_cache_array *array;
-       int status = -EBADCOOKIE;
-
-       if (desc->dir_cookie == NULL)
-               goto out;
+       int status;
 
        array = nfs_readdir_get_array(desc->page);
        if (IS_ERR(array)) {
@@ -341,6 +339,10 @@ int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc)
        else
                status = nfs_readdir_search_for_cookie(array, desc);
 
+       if (status == -EAGAIN) {
+               desc->last_cookie = array->last_cookie;
+               desc->page_index++;
+       }
        nfs_readdir_release_array(desc->page);
 out:
        return status;
@@ -392,13 +394,9 @@ int xdr_decode(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, struct x
 static
 int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry)
 {
-       struct nfs_inode *node;
        if (dentry->d_inode == NULL)
                goto different;
-       node = NFS_I(dentry->d_inode);
-       if (node->fh.size != entry->fh->size)
-               goto different;
-       if (strncmp(node->fh.data, entry->fh->data, node->fh.size) != 0)
+       if (nfs_compare_fh(entry->fh, NFS_FH(dentry->d_inode)) != 0)
                goto different;
        return 1;
 different:
@@ -466,8 +464,9 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
        struct xdr_stream stream;
        struct xdr_buf buf;
        __be32 *ptr = xdr_page;
-       int status;
        struct nfs_cache_array *array;
+       unsigned int count = 0;
+       int status;
 
        buf.head->iov_base = xdr_page;
        buf.head->iov_len = buflen;
@@ -488,7 +487,9 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
                        break;
                }
 
-               if (desc->plus == 1)
+               count++;
+
+               if (desc->plus != 0)
                        nfs_prime_dcache(desc->file->f_path.dentry, entry);
 
                status = nfs_readdir_add_to_array(entry, page);
@@ -496,13 +497,14 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
                        break;
        } while (!entry->eof);
 
-       if (status == -EBADCOOKIE && entry->eof) {
+       if (count == 0 || (status == -EBADCOOKIE && entry->eof != 0)) {
                array = nfs_readdir_get_array(page);
                if (!IS_ERR(array)) {
                        array->eof_index = array->size;
                        status = 0;
                        nfs_readdir_release_array(page);
-               }
+               } else
+                       status = PTR_ERR(array);
        }
        return status;
 }
@@ -560,7 +562,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
        unsigned int array_size = ARRAY_SIZE(pages);
 
        entry.prev_cookie = 0;
-       entry.cookie = *desc->dir_cookie;
+       entry.cookie = desc->last_cookie;
        entry.eof = 0;
        entry.fh = nfs_alloc_fhandle();
        entry.fattr = nfs_alloc_fattr();
@@ -633,6 +635,8 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page)
 static
 void cache_page_release(nfs_readdir_descriptor_t *desc)
 {
+       if (!desc->page->mapping)
+               nfs_readdir_clear_array(desc->page);
        page_cache_release(desc->page);
        desc->page = NULL;
 }
@@ -657,9 +661,8 @@ int find_cache_page(nfs_readdir_descriptor_t *desc)
                return PTR_ERR(desc->page);
 
        res = nfs_readdir_search_array(desc);
-       if (res == 0)
-               return 0;
-       cache_page_release(desc);
+       if (res != 0)
+               cache_page_release(desc);
        return res;
 }
 
@@ -669,22 +672,16 @@ int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
 {
        int res;
 
-       if (desc->page_index == 0)
+       if (desc->page_index == 0) {
                desc->current_index = 0;
-       while (1) {
-               res = find_cache_page(desc);
-               if (res != -EAGAIN)
-                       break;
-               desc->page_index++;
+               desc->last_cookie = 0;
        }
+       do {
+               res = find_cache_page(desc);
+       } while (res == -EAGAIN);
        return res;
 }
 
-static inline unsigned int dt_type(struct inode *inode)
-{
-       return (inode->i_mode >> 12) & 15;
-}
-
 /*
  * Once we've found the start of the dirent within a page: fill 'er up...
  */
@@ -696,35 +693,35 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
        int i = 0;
        int res = 0;
        struct nfs_cache_array *array = NULL;
-       unsigned int d_type = DT_UNKNOWN;
-       struct dentry *dentry = NULL;
 
        array = nfs_readdir_get_array(desc->page);
-       if (IS_ERR(array))
-               return PTR_ERR(array);
+       if (IS_ERR(array)) {
+               res = PTR_ERR(array);
+               goto out;
+       }
 
        for (i = desc->cache_entry_index; i < array->size; i++) {
-               d_type = DT_UNKNOWN;
+               struct nfs_cache_array_entry *ent;
 
-               res = filldir(dirent, array->array[i].string.name,
-                       array->array[i].string.len, file->f_pos,
-                       nfs_compat_user_ino64(array->array[i].ino), d_type);
-               if (res < 0)
+               ent = &array->array[i];
+               if (filldir(dirent, ent->string.name, ent->string.len,
+                   file->f_pos, nfs_compat_user_ino64(ent->ino),
+                   ent->d_type) < 0) {
+                       desc->eof = 1;
                        break;
+               }
                file->f_pos++;
-               desc->cache_entry_index = i;
                if (i < (array->size-1))
                        *desc->dir_cookie = array->array[i+1].cookie;
                else
                        *desc->dir_cookie = array->last_cookie;
        }
-       if (i == array->eof_index)
+       if (array->eof_index >= 0)
                desc->eof = 1;
 
        nfs_readdir_release_array(desc->page);
+out:
        cache_page_release(desc);
-       if (dentry != NULL)
-               dput(dentry);
        dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n",
                        (unsigned long long)*desc->dir_cookie, res);
        return res;
@@ -759,13 +756,14 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
                goto out;
        }
 
-       if (nfs_readdir_xdr_to_array(desc, page, inode) == -1) {
-               status = -EIO;
-               goto out_release;
-       }
-
        desc->page_index = 0;
+       desc->last_cookie = *desc->dir_cookie;
        desc->page = page;
+
+       status = nfs_readdir_xdr_to_array(desc, page, inode);
+       if (status < 0)
+               goto out_release;
+
        status = nfs_do_filldir(desc, dirent, filldir);
 
  out:
@@ -787,7 +785,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
        struct inode    *inode = dentry->d_inode;
        nfs_readdir_descriptor_t my_desc,
                        *desc = &my_desc;
-       int res = -ENOMEM;
+       int res;
 
        dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n",
                        dentry->d_parent->d_name.name, dentry->d_name.name,
@@ -812,18 +810,18 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
        if (res < 0)
                goto out;
 
-       while (desc->eof != 1) {
+       do {
                res = readdir_search_pagecache(desc);
 
                if (res == -EBADCOOKIE) {
+                       res = 0;
                        /* This means either end of directory */
                        if (*desc->dir_cookie && desc->eof == 0) {
                                /* Or that the server has 'lost' a cookie */
                                res = uncached_readdir(desc, dirent, filldir);
-                               if (res >= 0)
+                               if (res == 0)
                                        continue;
                        }
-                       res = 0;
                        break;
                }
                if (res == -ETOOSMALL && desc->plus) {
@@ -838,11 +836,9 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                        break;
 
                res = nfs_do_filldir(desc, dirent, filldir);
-               if (res < 0) {
-                       res = 0;
+               if (res < 0)
                        break;
-               }
-       }
+       } while (!desc->eof);
 out:
        nfs_unblock_sillyrename(dentry);
        if (res > 0)
index 84d3c8b902068a057805e33c9533ffda7f6c0100..e6ace0d93c71485870be33434830740941aa43ac 100644 (file)
@@ -867,7 +867,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov,
                goto out;
        nfs_alloc_commit_data(dreq);
 
-       if (dreq->commit_data == NULL || count < wsize)
+       if (dreq->commit_data == NULL || count <= wsize)
                sync = NFS_FILE_SYNC;
 
        dreq->inode = inode;
index 60677f9f13110d1a98774595de819fddf2c0ccdf..7bf029ef4084c6e7f02e05e355382168e85e2cb8 100644 (file)
@@ -693,6 +693,7 @@ do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
 {
        struct inode *inode = filp->f_mapping->host;
        int status = 0;
+       unsigned int saved_type = fl->fl_type;
 
        /* Try local locking first */
        posix_test_lock(filp, fl);
@@ -700,6 +701,7 @@ do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
                /* found a conflict */
                goto out;
        }
+       fl->fl_type = saved_type;
 
        if (nfs_have_delegation(inode, FMODE_READ))
                goto out_noconflict;
index 314f57164602eda0762c0a226db44aa19be461f5..e67e31c734163c6fe6c0eef0d338a2b87ae55763 100644 (file)
@@ -289,6 +289,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
                } else if (S_ISDIR(inode->i_mode)) {
                        inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->dir_inode_ops;
                        inode->i_fop = &nfs_dir_operations;
+                       inode->i_data.a_ops = &nfs_dir_aops;
                        if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS))
                                set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags);
                        /* Deal with crossing mountpoints */
index db08ff3ff454d840baf84ea8b7ce8e5583c6cdf9..e6356b750b777ae6224b8821fc253b1b4da30de6 100644 (file)
@@ -361,6 +361,15 @@ unsigned int nfs_page_length(struct page *page)
        return 0;
 }
 
+/*
+ * Convert a umode to a dirent->d_type
+ */
+static inline
+unsigned char nfs_umode_to_dtype(umode_t mode)
+{
+       return (mode >> 12) & 15;
+}
+
 /*
  * Determine the number of pages in an array of length 'len' and
  * with a base offset of 'base'
index eceafe74f4737ea5fbcea90b8ac19749737667b9..4f981f1f668925cba6bebe6ed4cf485da6a56dbb 100644 (file)
@@ -505,13 +505,13 @@ static struct rpc_procinfo mnt3_procedures[] = {
 
 static struct rpc_version mnt_version1 = {
        .number         = 1,
-       .nrprocs        = 2,
+       .nrprocs        = ARRAY_SIZE(mnt_procedures),
        .procs          = mnt_procedures,
 };
 
 static struct rpc_version mnt_version3 = {
        .number         = 3,
-       .nrprocs        = 2,
+       .nrprocs        = ARRAY_SIZE(mnt3_procedures),
        .procs          = mnt3_procedures,
 };
 
index 2563f765c9b4ba49b37615657f4c3f5f76e7576d..5914a1911c951dda6839e5c0490164e2e6d13bbc 100644 (file)
@@ -485,6 +485,8 @@ nfs_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_se
        entry->prev_cookie        = entry->cookie;
        entry->cookie     = ntohl(*p++);
 
+       entry->d_type = DT_UNKNOWN;
+
        p = xdr_inline_peek(xdr, 8);
        if (p != NULL)
                entry->eof = !p[0] && p[1];
@@ -495,7 +497,7 @@ nfs_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_se
 
 out_overflow:
        print_overflow_msg(__func__, xdr);
-       return ERR_PTR(-EIO);
+       return ERR_PTR(-EAGAIN);
 }
 
 /*
index 748dc91a4a147466529d9b1b49a20cc0ab2aad93..f6cc60f06dac4e517f7743bb3c0c148106807120 100644 (file)
@@ -622,11 +622,13 @@ nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_s
        entry->prev_cookie = entry->cookie;
        p = xdr_decode_hyper(p, &entry->cookie);
 
+       entry->d_type = DT_UNKNOWN;
        if (plus) {
                entry->fattr->valid = 0;
                p = xdr_decode_post_op_attr_stream(xdr, entry->fattr);
                if (IS_ERR(p))
                        goto out_overflow_exit;
+               entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
                /* In fact, a post_op_fh3: */
                p = xdr_inline_decode(xdr, 4);
                if (unlikely(!p))
@@ -656,7 +658,7 @@ nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_s
 out_overflow:
        print_overflow_msg(__func__, xdr);
 out_overflow_exit:
-       return ERR_PTR(-EIO);
+       return ERR_PTR(-EAGAIN);
 }
 
 /*
index 6a653ffd8e4e121e37c29d88ff2f5b0b4dbe264f..4435e5e1f904e3e5ba26f4eb578fc30c5f6d997b 100644 (file)
@@ -3361,6 +3361,8 @@ static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
        ret = nfs_revalidate_inode(server, inode);
        if (ret < 0)
                return ret;
+       if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_ACL)
+               nfs_zap_acl_cache(inode);
        ret = nfs4_read_cached_acl(inode, buf, buflen);
        if (ret != -ENOENT)
                return ret;
@@ -3389,6 +3391,13 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
        nfs_inode_return_delegation(inode);
        buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
        ret = nfs4_call_sync(server, &msg, &arg, &res, 1);
+       /*
+        * Acl update can result in inode attribute update.
+        * so mark the attribute cache invalid.
+        */
+       spin_lock(&inode->i_lock);
+       NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR;
+       spin_unlock(&inode->i_lock);
        nfs_access_zap_cache(inode);
        nfs_zap_acl_cache(inode);
        return ret;
index b7a204ff6fe1504efe287b7620532407cc692f89..9f1826b012e63bb2bf11486e1a2a8ba0dd58ff9b 100644 (file)
@@ -6208,6 +6208,10 @@ __be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
        if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID)
                entry->ino = entry->fattr->fileid;
 
+       entry->d_type = DT_UNKNOWN;
+       if (entry->fattr->valid & NFS_ATTR_FATTR_TYPE)
+               entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
+
        if (verify_attr_len(xdr, p, len) < 0)
                goto out_overflow;
 
@@ -6221,7 +6225,7 @@ __be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
 
 out_overflow:
        print_overflow_msg(__func__, xdr);
-       return ERR_PTR(-EIO);
+       return ERR_PTR(-EAGAIN);
 }
 
 /*
index 137b549e63dbcfa3971aac43091eb91a29a7b69f..b68536cc9046ec937b9b4ccddb98b2acf468f1db 100644 (file)
@@ -115,7 +115,7 @@ int nfs_set_page_tag_locked(struct nfs_page *req)
 {
        if (!nfs_lock_request_dontget(req))
                return 0;
-       if (req->wb_page != NULL)
+       if (test_bit(PG_MAPPED, &req->wb_flags))
                radix_tree_tag_set(&NFS_I(req->wb_context->path.dentry->d_inode)->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
        return 1;
 }
@@ -125,7 +125,7 @@ int nfs_set_page_tag_locked(struct nfs_page *req)
  */
 void nfs_clear_page_tag_locked(struct nfs_page *req)
 {
-       if (req->wb_page != NULL) {
+       if (test_bit(PG_MAPPED, &req->wb_flags)) {
                struct inode *inode = req->wb_context->path.dentry->d_inode;
                struct nfs_inode *nfsi = NFS_I(inode);
 
index e4b62c6f5a6e9eb721eda53d836c41055ab2e1b7..aedcaa7f291fbe4405f2b68c13f407c7de6be9ba 100644 (file)
@@ -152,7 +152,6 @@ static void nfs_readpage_release(struct nfs_page *req)
                        (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
                        req->wb_bytes,
                        (long long)req_offset(req));
-       nfs_clear_request(req);
        nfs_release_request(req);
 }
 
index 3c045044fca25183147704f3689c744549ebd77b..4100630c9a5b65f47bb5379ee2bc62f78e60284e 100644 (file)
@@ -1069,12 +1069,10 @@ static int nfs_parse_mount_options(char *raw,
                        mnt->flags |= NFS_MOUNT_VER3;
                        mnt->version = 3;
                        break;
-#ifdef CONFIG_NFS_V4
                case Opt_v4:
                        mnt->flags &= ~NFS_MOUNT_VER3;
                        mnt->version = 4;
                        break;
-#endif
                case Opt_udp:
                        mnt->flags &= ~NFS_MOUNT_TCP;
                        mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP;
@@ -1286,12 +1284,10 @@ static int nfs_parse_mount_options(char *raw,
                                mnt->flags |= NFS_MOUNT_VER3;
                                mnt->version = 3;
                                break;
-#ifdef CONFIG_NFS_V4
                        case NFS4_VERSION:
                                mnt->flags &= ~NFS_MOUNT_VER3;
                                mnt->version = 4;
                                break;
-#endif
                        default:
                                goto out_invalid_value;
                        }
index 4c14c17a5276a410bb383e3650f106ab56cf47d6..10d648ea128bf6345df70da0e15ee8ce443ab8e6 100644 (file)
@@ -390,6 +390,7 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
                if (nfs_have_delegation(inode, FMODE_WRITE))
                        nfsi->change_attr++;
        }
+       set_bit(PG_MAPPED, &req->wb_flags);
        SetPagePrivate(req->wb_page);
        set_page_private(req->wb_page, (unsigned long)req);
        nfsi->npages++;
@@ -415,6 +416,7 @@ static void nfs_inode_remove_request(struct nfs_page *req)
        spin_lock(&inode->i_lock);
        set_page_private(req->wb_page, 0);
        ClearPagePrivate(req->wb_page);
+       clear_bit(PG_MAPPED, &req->wb_flags);
        radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index);
        nfsi->npages--;
        if (!nfsi->npages) {
@@ -422,7 +424,6 @@ static void nfs_inode_remove_request(struct nfs_page *req)
                iput(inode);
        } else
                spin_unlock(&inode->i_lock);
-       nfs_clear_request(req);
        nfs_release_request(req);
 }
 
index 2a533a0af2a98ed91afb84e71669d328cb67a866..7e84a852cdae8117334fec6ee00d085fc29c0c66 100644 (file)
@@ -260,9 +260,11 @@ void fill_post_wcc(struct svc_fh *fhp)
        err = vfs_getattr(fhp->fh_export->ex_path.mnt, fhp->fh_dentry,
                        &fhp->fh_post_attr);
        fhp->fh_post_change = fhp->fh_dentry->d_inode->i_version;
-       if (err)
+       if (err) {
                fhp->fh_post_saved = 0;
-       else
+               /* Grab the ctime anyway - set_change_info might use it */
+               fhp->fh_post_attr.ctime = fhp->fh_dentry->d_inode->i_ctime;
+       } else
                fhp->fh_post_saved = 1;
 }
 
index 4d476ff08ae6add1ec3a1b597909f1375af78b7b..60fce3dc5cb5d9f90d22b9f9c91ddc7ddeb9ff1d 100644 (file)
@@ -484,18 +484,17 @@ static inline bool nfsd4_not_cached(struct nfsd4_compoundres *resp)
 static inline void
 set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)
 {
-       BUG_ON(!fhp->fh_pre_saved || !fhp->fh_post_saved);
-       cinfo->atomic = 1;
+       BUG_ON(!fhp->fh_pre_saved);
+       cinfo->atomic = fhp->fh_post_saved;
        cinfo->change_supported = IS_I_VERSION(fhp->fh_dentry->d_inode);
-       if (cinfo->change_supported) {
-               cinfo->before_change = fhp->fh_pre_change;
-               cinfo->after_change = fhp->fh_post_change;
-       } else {
-               cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec;
-               cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec;
-               cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec;
-               cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec;
-       }
+
+       cinfo->before_change = fhp->fh_pre_change;
+       cinfo->after_change = fhp->fh_post_change;
+       cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec;
+       cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec;
+       cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec;
+       cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec;
+
 }
 
 int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *);
index 49c844dab33ac63d829d63ff151ab8b5403631fd..59e5fe742f7bd7bcc6d6aa88dbdcf595e4c64019 100644 (file)
@@ -335,7 +335,7 @@ int nilfs_dat_move(struct inode *dat, __u64 vblocknr, sector_t blocknr)
         * the device at this point.
         *
         * To prevent nilfs_dat_translate() from returning the
-        * uncommited block number, this makes a copy of the entry
+        * uncommitted block number, this makes a copy of the entry
         * buffer and redirects nilfs_dat_translate() to the copy.
         */
        if (!buffer_nilfs_redirected(entry_bh)) {
index 33ad25ddd5c442a7875e8eca9b078b363e10d9ce..caf9a6a3fb54f0e0dd4cd63ccf103fd6aef20a70 100644 (file)
@@ -176,7 +176,6 @@ int nilfs_gccache_wait_and_mark_dirty(struct buffer_head *bh)
 int nilfs_init_gcinode(struct inode *inode)
 {
        struct nilfs_inode_info *ii = NILFS_I(inode);
-       struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
 
        inode->i_mode = S_IFREG;
        mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
@@ -186,14 +185,6 @@ int nilfs_init_gcinode(struct inode *inode)
        ii->i_flags = 0;
        nilfs_bmap_init_gc(ii->i_bmap);
 
-       /*
-        * Add the inode to GC inode list. Garbage Collection
-        * is serialized and no two processes manipulate the
-        * list simultaneously.
-        */
-       igrab(inode);
-       list_add(&NILFS_I(inode)->i_dirty, &nilfs->ns_gc_inodes);
-
        return 0;
 }
 
index 3e90f86d5bfeeaae741f3475a32ebe7666e46aa7..b185e937a335471ec224314909a959684f56d174 100644 (file)
@@ -337,6 +337,7 @@ static int nilfs_ioctl_move_blocks(struct super_block *sb,
                                   struct nilfs_argv *argv, void *buf)
 {
        size_t nmembs = argv->v_nmembs;
+       struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs;
        struct inode *inode;
        struct nilfs_vdesc *vdesc;
        struct buffer_head *bh, *n;
@@ -349,10 +350,21 @@ static int nilfs_ioctl_move_blocks(struct super_block *sb,
                ino = vdesc->vd_ino;
                cno = vdesc->vd_cno;
                inode = nilfs_iget_for_gc(sb, ino, cno);
-               if (unlikely(inode == NULL)) {
-                       ret = -ENOMEM;
+               if (IS_ERR(inode)) {
+                       ret = PTR_ERR(inode);
                        goto failed;
                }
+               if (list_empty(&NILFS_I(inode)->i_dirty)) {
+                       /*
+                        * Add the inode to GC inode list. Garbage Collection
+                        * is serialized and no two processes manipulate the
+                        * list simultaneously.
+                        */
+                       igrab(inode);
+                       list_add(&NILFS_I(inode)->i_dirty,
+                                &nilfs->ns_gc_inodes);
+               }
+
                do {
                        ret = nilfs_ioctl_move_inode_block(inode, vdesc,
                                                           &buffers);
index b04f88eed09e98b6134f275cb7ba530a06e7f998..f35794b97e8e5cb5cc396af28206d69ca1202935 100644 (file)
@@ -92,7 +92,11 @@ static int fanotify_get_response_from_access(struct fsnotify_group *group,
 
        pr_debug("%s: group=%p event=%p\n", __func__, group, event);
 
-       wait_event(group->fanotify_data.access_waitq, event->response);
+       wait_event(group->fanotify_data.access_waitq, event->response ||
+                               atomic_read(&group->fanotify_data.bypass_perm));
+
+       if (!event->response) /* bypass_perm set */
+               return 0;
 
        /* userspace responded, convert to something usable */
        spin_lock(&event->lock);
index 063224812b7e607879bffeedd5b90f9c4967346f..8b61220cffc597873bc0292bbf2fcd86300f3d5c 100644 (file)
@@ -106,20 +106,29 @@ static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event)
        return client_fd;
 }
 
-static ssize_t fill_event_metadata(struct fsnotify_group *group,
+static int fill_event_metadata(struct fsnotify_group *group,
                                   struct fanotify_event_metadata *metadata,
                                   struct fsnotify_event *event)
 {
+       int ret = 0;
+
        pr_debug("%s: group=%p metadata=%p event=%p\n", __func__,
                 group, metadata, event);
 
        metadata->event_len = FAN_EVENT_METADATA_LEN;
+       metadata->metadata_len = FAN_EVENT_METADATA_LEN;
        metadata->vers = FANOTIFY_METADATA_VERSION;
        metadata->mask = event->mask & FAN_ALL_OUTGOING_EVENTS;
        metadata->pid = pid_vnr(event->tgid);
-       metadata->fd = create_fd(group, event);
+       if (unlikely(event->mask & FAN_Q_OVERFLOW))
+               metadata->fd = FAN_NOFD;
+       else {
+               metadata->fd = create_fd(group, event);
+               if (metadata->fd < 0)
+                       ret = metadata->fd;
+       }
 
-       return metadata->fd;
+       return ret;
 }
 
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
@@ -200,7 +209,7 @@ static int prepare_for_access_response(struct fsnotify_group *group,
 
        mutex_lock(&group->fanotify_data.access_mutex);
 
-       if (group->fanotify_data.bypass_perm) {
+       if (atomic_read(&group->fanotify_data.bypass_perm)) {
                mutex_unlock(&group->fanotify_data.access_mutex);
                kmem_cache_free(fanotify_response_event_cache, re);
                event->response = FAN_ALLOW;
@@ -257,24 +266,34 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
 
        pr_debug("%s: group=%p event=%p\n", __func__, group, event);
 
-       fd = fill_event_metadata(group, &fanotify_event_metadata, event);
-       if (fd < 0)
-               return fd;
+       ret = fill_event_metadata(group, &fanotify_event_metadata, event);
+       if (ret < 0)
+               goto out;
 
+       fd = fanotify_event_metadata.fd;
        ret = prepare_for_access_response(group, event, fd);
        if (ret)
                goto out_close_fd;
 
        ret = -EFAULT;
-       if (copy_to_user(buf, &fanotify_event_metadata, FAN_EVENT_METADATA_LEN))
+       if (copy_to_user(buf, &fanotify_event_metadata,
+                        fanotify_event_metadata.event_len))
                goto out_kill_access_response;
 
-       return FAN_EVENT_METADATA_LEN;
+       return fanotify_event_metadata.event_len;
 
 out_kill_access_response:
        remove_access_response(group, event, fd);
 out_close_fd:
-       sys_close(fd);
+       if (fd != FAN_NOFD)
+               sys_close(fd);
+out:
+#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
+       if (event->mask & FAN_ALL_PERM_EVENTS) {
+               event->response = FAN_DENY;
+               wake_up(&group->fanotify_data.access_waitq);
+       }
+#endif
        return ret;
 }
 
@@ -382,7 +401,7 @@ static int fanotify_release(struct inode *ignored, struct file *file)
 
        mutex_lock(&group->fanotify_data.access_mutex);
 
-       group->fanotify_data.bypass_perm = true;
+       atomic_inc(&group->fanotify_data.bypass_perm);
 
        list_for_each_entry_safe(re, lre, &group->fanotify_data.access_list, list) {
                pr_debug("%s: found group=%p re=%p event=%p\n", __func__, group,
@@ -586,11 +605,10 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
 {
        struct fsnotify_mark *fsn_mark;
        __u32 added;
+       int ret = 0;
 
        fsn_mark = fsnotify_find_vfsmount_mark(group, mnt);
        if (!fsn_mark) {
-               int ret;
-
                if (atomic_read(&group->num_marks) > group->fanotify_data.max_marks)
                        return -ENOSPC;
 
@@ -600,17 +618,16 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
 
                fsnotify_init_mark(fsn_mark, fanotify_free_mark);
                ret = fsnotify_add_mark(fsn_mark, group, NULL, mnt, 0);
-               if (ret) {
-                       fanotify_free_mark(fsn_mark);
-                       return ret;
-               }
+               if (ret)
+                       goto err;
        }
        added = fanotify_mark_add_to_mask(fsn_mark, mask, flags);
-       fsnotify_put_mark(fsn_mark);
+
        if (added & ~mnt->mnt_fsnotify_mask)
                fsnotify_recalc_vfsmount_mask(mnt);
-
-       return 0;
+err:
+       fsnotify_put_mark(fsn_mark);
+       return ret;
 }
 
 static int fanotify_add_inode_mark(struct fsnotify_group *group,
@@ -619,6 +636,7 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,
 {
        struct fsnotify_mark *fsn_mark;
        __u32 added;
+       int ret = 0;
 
        pr_debug("%s: group=%p inode=%p\n", __func__, group, inode);
 
@@ -634,8 +652,6 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,
 
        fsn_mark = fsnotify_find_inode_mark(group, inode);
        if (!fsn_mark) {
-               int ret;
-
                if (atomic_read(&group->num_marks) > group->fanotify_data.max_marks)
                        return -ENOSPC;
 
@@ -645,16 +661,16 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,
 
                fsnotify_init_mark(fsn_mark, fanotify_free_mark);
                ret = fsnotify_add_mark(fsn_mark, group, inode, NULL, 0);
-               if (ret) {
-                       fanotify_free_mark(fsn_mark);
-                       return ret;
-               }
+               if (ret)
+                       goto err;
        }
        added = fanotify_mark_add_to_mask(fsn_mark, mask, flags);
-       fsnotify_put_mark(fsn_mark);
+
        if (added & ~inode->i_fsnotify_mask)
                fsnotify_recalc_inode_mask(inode);
-       return 0;
+err:
+       fsnotify_put_mark(fsn_mark);
+       return ret;
 }
 
 /* fanotify syscalls */
@@ -687,8 +703,10 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 
        /* fsnotify_alloc_group takes a ref.  Dropped in fanotify_release */
        group = fsnotify_alloc_group(&fanotify_fsnotify_ops);
-       if (IS_ERR(group))
+       if (IS_ERR(group)) {
+               free_uid(user);
                return PTR_ERR(group);
+       }
 
        group->fanotify_data.user = user;
        atomic_inc(&user->fanotify_listeners);
@@ -698,6 +716,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
        mutex_init(&group->fanotify_data.access_mutex);
        init_waitqueue_head(&group->fanotify_data.access_waitq);
        INIT_LIST_HEAD(&group->fanotify_data.access_list);
+       atomic_set(&group->fanotify_data.bypass_perm, 0);
 #endif
        switch (flags & FAN_ALL_CLASS_BITS) {
        case FAN_CLASS_NOTIF:
@@ -764,8 +783,10 @@ SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags,
        if (flags & ~FAN_ALL_MARK_FLAGS)
                return -EINVAL;
        switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_FLUSH)) {
-       case FAN_MARK_ADD:
+       case FAN_MARK_ADD:              /* fallthrough */
        case FAN_MARK_REMOVE:
+               if (!mask)
+                       return -EINVAL;
        case FAN_MARK_FLUSH:
                break;
        default:
index 444c305a468c531b7e9e8dda803a2d650a257c58..4cd5d5d78f9fa2b85f38bd9422efc3d387780295 100644 (file)
@@ -752,6 +752,7 @@ SYSCALL_DEFINE1(inotify_init1, int, flags)
        if (ret >= 0)
                return ret;
 
+       fsnotify_put_group(group);
        atomic_dec(&user->inotify_devs);
 out_free_uid:
        free_uid(user);
index 52c7557f3e25ad4cce288883ed070eb48f970a4e..9f26ac9be2a45d38e340bed6d51164492fab0ca6 100644 (file)
@@ -1964,8 +1964,10 @@ static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *g
        if (reg == NULL)
                return ERR_PTR(-ENOMEM);
 
-       if (strlen(name) > O2HB_MAX_REGION_NAME_LEN)
-               return ERR_PTR(-ENAMETOOLONG);
+       if (strlen(name) > O2HB_MAX_REGION_NAME_LEN) {
+               ret = -ENAMETOOLONG;
+               goto free;
+       }
 
        spin_lock(&o2hb_live_lock);
        reg->hr_region_num = 0;
@@ -1974,7 +1976,8 @@ static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *g
                                                         O2NM_MAX_REGIONS);
                if (reg->hr_region_num >= O2NM_MAX_REGIONS) {
                        spin_unlock(&o2hb_live_lock);
-                       return ERR_PTR(-EFBIG);
+                       ret = -EFBIG;
+                       goto free;
                }
                set_bit(reg->hr_region_num, o2hb_region_bitmap);
        }
@@ -1986,10 +1989,13 @@ static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *g
        ret = o2hb_debug_region_init(reg, o2hb_debug_dir);
        if (ret) {
                config_item_put(&reg->hr_item);
-               return ERR_PTR(ret);
+               goto free;
        }
 
        return &reg->hr_item;
+free:
+       kfree(reg);
+       return ERR_PTR(ret);
 }
 
 static void o2hb_heartbeat_group_drop_item(struct config_group *group,
index edaded48e7e9f083ac7c67e72a9f031123f7844a..895532ac4d983376ed122f016ef13ad36e3c95b3 100644 (file)
@@ -476,7 +476,6 @@ static void ocfs2_dentry_iput(struct dentry *dentry, struct inode *inode)
 
 out:
        iput(inode);
-       ocfs2_dentry_attach_gen(dentry);
 }
 
 /*
index 58a93b953735ebcaeda134794195449da4e98a53..cc2aaa96cfe5c58540c23f863701102a0c8096a8 100644 (file)
@@ -959,7 +959,7 @@ static int dlm_match_regions(struct dlm_ctxt *dlm,
                r += O2HB_MAX_REGION_NAME_LEN;
        }
 
-       local = kmalloc(sizeof(qr->qr_regions), GFP_KERNEL);
+       local = kmalloc(sizeof(qr->qr_regions), GFP_ATOMIC);
        if (!local) {
                status = -ENOMEM;
                goto bail;
index 1efea3615589ae1d5c30509d73cd03c09ccc973e..70dd3b1798f136130f4ef5ab5198012c2e3bc82d 100644 (file)
@@ -159,9 +159,9 @@ struct ocfs2_lock_res {
        char                     l_name[OCFS2_LOCK_ID_MAX_LEN];
        unsigned int             l_ro_holders;
        unsigned int             l_ex_holders;
-       char                     l_level;
-       char                     l_requested;
-       char                     l_blocking;
+       signed char              l_level;
+       signed char              l_requested;
+       signed char              l_blocking;
 
        /* Data packed - type enum ocfs2_lock_type */
        unsigned char            l_type;
index 252e7c82f929c203aca6a294d24b49dd17612cee..a5ebe421195fea3df8d66f2dc3573534a3bc298a 100644 (file)
@@ -190,7 +190,7 @@ static struct ocfs2_live_connection *ocfs2_connection_find(const char *name)
                        return c;
        }
 
-       return c;
+       return NULL;
 }
 
 /*
index a8012a955720418eb059b237ac68bd98760891bb..04629f36e3978dc44ec1611994664f157cc9d4f8 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -1199,12 +1199,24 @@ int pipe_proc_fn(struct ctl_table *table, int write, void __user *buf,
        return ret;
 }
 
+/*
+ * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same
+ * location, so checking ->i_pipe is not enough to verify that this is a
+ * pipe.
+ */
+struct pipe_inode_info *get_pipe_info(struct file *file)
+{
+       struct inode *i = file->f_path.dentry->d_inode;
+
+       return S_ISFIFO(i->i_mode) ? i->i_pipe : NULL;
+}
+
 long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        struct pipe_inode_info *pipe;
        long ret;
 
-       pipe = file->f_path.dentry->d_inode->i_pipe;
+       pipe = get_pipe_info(file);
        if (!pipe)
                return -EBADF;
 
index f3d02ca461ecfcc341eb783fd15da8df486fde11..182845147fe45bde8f5607a799f23cc1e2818117 100644 (file)
@@ -1574,7 +1574,7 @@ static int do_proc_readlink(struct path *path, char __user *buffer, int buflen)
        if (!tmp)
                return -ENOMEM;
 
-       pathname = d_path_with_unreachable(path, tmp, PAGE_SIZE);
+       pathname = d_path(path, tmp, PAGE_SIZE);
        len = PTR_ERR(pathname);
        if (IS_ERR(pathname))
                goto out;
index da6b01d70f019506face0dae73f0b78c3200d299..c126c83b9a45bc838125d1ac12b44e13f89d8b26 100644 (file)
@@ -706,6 +706,7 @@ static int pagemap_hugetlb_range(pte_t *pte, unsigned long hmask,
  * skip over unmapped regions.
  */
 #define PAGEMAP_WALK_SIZE      (PMD_SIZE)
+#define PAGEMAP_WALK_MASK      (PMD_MASK)
 static ssize_t pagemap_read(struct file *file, char __user *buf,
                            size_t count, loff_t *ppos)
 {
@@ -776,7 +777,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
                unsigned long end;
 
                pm.pos = 0;
-               end = start_vaddr + PAGEMAP_WALK_SIZE;
+               end = (start_vaddr + PAGEMAP_WALK_SIZE) & PAGEMAP_WALK_MASK;
                /* overflow ? */
                if (end < start_vaddr || end > end_vaddr)
                        end = end_vaddr;
index bd9763e76bae42844a6cf792d1da86a3454dbe38..79265fdc317a09889c6ce3c2343bb17594bce40e 100644 (file)
@@ -183,12 +183,11 @@ int reiserfs_unpack(struct inode *inode, struct file *filp)
                return 0;
        }
 
-       /* we need to make sure nobody is changing the file size beneath
-        ** us
-        */
-       reiserfs_mutex_lock_safe(&inode->i_mutex, inode->i_sb);
        depth = reiserfs_write_lock_once(inode->i_sb);
 
+       /* we need to make sure nobody is changing the file size beneath us */
+       reiserfs_mutex_lock_safe(&inode->i_mutex, inode->i_sb);
+
        write_from = inode->i_size & (blocksize - 1);
        /* if we are on a block boundary, we are already unpacked.  */
        if (write_from == 0) {
index 536d697a8a283102f57053fcbb3338bd784bf559..90d2fcb67a314633a4f3855dc08e057a43390a40 100644 (file)
@@ -472,7 +472,9 @@ int reiserfs_acl_chmod(struct inode *inode)
                struct reiserfs_transaction_handle th;
                size_t size = reiserfs_xattr_nblocks(inode,
                                             reiserfs_acl_size(clone->a_count));
-               reiserfs_write_lock(inode->i_sb);
+               int depth;
+
+               depth = reiserfs_write_lock_once(inode->i_sb);
                error = journal_begin(&th, inode->i_sb, size * 2);
                if (!error) {
                        int error2;
@@ -482,7 +484,7 @@ int reiserfs_acl_chmod(struct inode *inode)
                        if (error2)
                                error = error2;
                }
-               reiserfs_write_unlock(inode->i_sb);
+               reiserfs_write_unlock_once(inode->i_sb, depth);
        }
        posix_acl_release(clone);
        return error;
index 8f1dfaecc8f06125429d3bc66b052d779f61f446..ce2f02579e3539ff504f564564077b0641691e6d 100644 (file)
@@ -1311,18 +1311,6 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
 static int splice_pipe_to_pipe(struct pipe_inode_info *ipipe,
                               struct pipe_inode_info *opipe,
                               size_t len, unsigned int flags);
-/*
- * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same
- * location, so checking ->i_pipe is not enough to verify that this is a
- * pipe.
- */
-static inline struct pipe_inode_info *pipe_info(struct inode *inode)
-{
-       if (S_ISFIFO(inode->i_mode))
-               return inode->i_pipe;
-
-       return NULL;
-}
 
 /*
  * Determine where to splice to/from.
@@ -1336,8 +1324,8 @@ static long do_splice(struct file *in, loff_t __user *off_in,
        loff_t offset, *off;
        long ret;
 
-       ipipe = pipe_info(in->f_path.dentry->d_inode);
-       opipe = pipe_info(out->f_path.dentry->d_inode);
+       ipipe = get_pipe_info(in);
+       opipe = get_pipe_info(out);
 
        if (ipipe && opipe) {
                if (off_in || off_out)
@@ -1555,7 +1543,7 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *iov,
        int error;
        long ret;
 
-       pipe = pipe_info(file->f_path.dentry->d_inode);
+       pipe = get_pipe_info(file);
        if (!pipe)
                return -EBADF;
 
@@ -1642,7 +1630,7 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *iov,
        };
        long ret;
 
-       pipe = pipe_info(file->f_path.dentry->d_inode);
+       pipe = get_pipe_info(file);
        if (!pipe)
                return -EBADF;
 
@@ -2022,8 +2010,8 @@ static int link_pipe(struct pipe_inode_info *ipipe,
 static long do_tee(struct file *in, struct file *out, size_t len,
                   unsigned int flags)
 {
-       struct pipe_inode_info *ipipe = pipe_info(in->f_path.dentry->d_inode);
-       struct pipe_inode_info *opipe = pipe_info(out->f_path.dentry->d_inode);
+       struct pipe_inode_info *ipipe = get_pipe_info(in);
+       struct pipe_inode_info *opipe = get_pipe_info(out);
        int ret = -EINVAL;
 
        /*
index 7d287afccde58ac16c854ee5dc2eb31f2f7b1637..691f61223ed628137bfeb2ed2856a3ccbcf71894 100644 (file)
@@ -934,7 +934,6 @@ xfs_aops_discard_page(
        struct xfs_inode        *ip = XFS_I(inode);
        struct buffer_head      *bh, *head;
        loff_t                  offset = page_offset(page);
-       ssize_t                 len = 1 << inode->i_blkbits;
 
        if (!xfs_is_delayed_page(page, IO_DELAY))
                goto out_invalidate;
@@ -949,58 +948,14 @@ xfs_aops_discard_page(
        xfs_ilock(ip, XFS_ILOCK_EXCL);
        bh = head = page_buffers(page);
        do {
-               int             done;
-               xfs_fileoff_t   offset_fsb;
-               xfs_bmbt_irec_t imap;
-               int             nimaps = 1;
                int             error;
-               xfs_fsblock_t   firstblock;
-               xfs_bmap_free_t flist;
+               xfs_fileoff_t   start_fsb;
 
                if (!buffer_delay(bh))
                        goto next_buffer;
 
-               offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset);
-
-               /*
-                * Map the range first and check that it is a delalloc extent
-                * before trying to unmap the range. Otherwise we will be
-                * trying to remove a real extent (which requires a
-                * transaction) or a hole, which is probably a bad idea...
-                */
-               error = xfs_bmapi(NULL, ip, offset_fsb, 1,
-                               XFS_BMAPI_ENTIRE,  NULL, 0, &imap,
-                               &nimaps, NULL);
-
-               if (error) {
-                       /* something screwed, just bail */
-                       if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
-                               xfs_fs_cmn_err(CE_ALERT, ip->i_mount,
-                               "page discard failed delalloc mapping lookup.");
-                       }
-                       break;
-               }
-               if (!nimaps) {
-                       /* nothing there */
-                       goto next_buffer;
-               }
-               if (imap.br_startblock != DELAYSTARTBLOCK) {
-                       /* been converted, ignore */
-                       goto next_buffer;
-               }
-               WARN_ON(imap.br_blockcount == 0);
-
-               /*
-                * Note: while we initialise the firstblock/flist pair, they
-                * should never be used because blocks should never be
-                * allocated or freed for a delalloc extent and hence we need
-                * don't cancel or finish them after the xfs_bunmapi() call.
-                */
-               xfs_bmap_init(&flist, &firstblock);
-               error = xfs_bunmapi(NULL, ip, offset_fsb, 1, 0, 1, &firstblock,
-                                       &flist, &done);
-
-               ASSERT(!flist.xbf_count && !flist.xbf_first);
+               start_fsb = XFS_B_TO_FSBT(ip->i_mount, offset);
+               error = xfs_bmap_punch_delalloc_range(ip, start_fsb, 1);
                if (error) {
                        /* something screwed, just bail */
                        if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
@@ -1010,7 +965,7 @@ xfs_aops_discard_page(
                        break;
                }
 next_buffer:
-               offset += len;
+               offset += 1 << inode->i_blkbits;
 
        } while ((bh = bh->b_this_page) != head);
 
@@ -1505,11 +1460,42 @@ xfs_vm_write_failed(
        struct inode            *inode = mapping->host;
 
        if (to > inode->i_size) {
-               struct iattr    ia = {
-                       .ia_valid       = ATTR_SIZE | ATTR_FORCE,
-                       .ia_size        = inode->i_size,
-               };
-               xfs_setattr(XFS_I(inode), &ia, XFS_ATTR_NOLOCK);
+               /*
+                * punch out the delalloc blocks we have already allocated. We
+                * don't call xfs_setattr() to do this as we may be in the
+                * middle of a multi-iovec write and so the vfs inode->i_size
+                * will not match the xfs ip->i_size and so it will zero too
+                * much. Hence we jus truncate the page cache to zero what is
+                * necessary and punch the delalloc blocks directly.
+                */
+               struct xfs_inode        *ip = XFS_I(inode);
+               xfs_fileoff_t           start_fsb;
+               xfs_fileoff_t           end_fsb;
+               int                     error;
+
+               truncate_pagecache(inode, to, inode->i_size);
+
+               /*
+                * Check if there are any blocks that are outside of i_size
+                * that need to be trimmed back.
+                */
+               start_fsb = XFS_B_TO_FSB(ip->i_mount, inode->i_size) + 1;
+               end_fsb = XFS_B_TO_FSB(ip->i_mount, to);
+               if (end_fsb <= start_fsb)
+                       return;
+
+               xfs_ilock(ip, XFS_ILOCK_EXCL);
+               error = xfs_bmap_punch_delalloc_range(ip, start_fsb,
+                                                       end_fsb - start_fsb);
+               if (error) {
+                       /* something screwed, just bail */
+                       if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
+                               xfs_fs_cmn_err(CE_ALERT, ip->i_mount,
+                       "xfs_vm_write_failed: unable to clean up ino %lld",
+                                               ip->i_ino);
+                       }
+               }
+               xfs_iunlock(ip, XFS_ILOCK_EXCL);
        }
 }
 
index aa1d353def29c64903cf02db9af159d612259b87..4c5deb6e9e3192f1bd279ca9e7b02e824fe9e7cc 100644 (file)
@@ -488,29 +488,16 @@ found:
        spin_unlock(&pag->pag_buf_lock);
        xfs_perag_put(pag);
 
-       /* Attempt to get the semaphore without sleeping,
-        * if this does not work then we need to drop the
-        * spinlock and do a hard attempt on the semaphore.
-        */
-       if (down_trylock(&bp->b_sema)) {
+       if (xfs_buf_cond_lock(bp)) {
+               /* failed, so wait for the lock if requested. */
                if (!(flags & XBF_TRYLOCK)) {
-                       /* wait for buffer ownership */
                        xfs_buf_lock(bp);
                        XFS_STATS_INC(xb_get_locked_waited);
                } else {
-                       /* We asked for a trylock and failed, no need
-                        * to look at file offset and length here, we
-                        * know that this buffer at least overlaps our
-                        * buffer and is locked, therefore our buffer
-                        * either does not exist, or is this buffer.
-                        */
                        xfs_buf_rele(bp);
                        XFS_STATS_INC(xb_busy_locked);
                        return NULL;
                }
-       } else {
-               /* trylock worked */
-               XB_SET_OWNER(bp);
        }
 
        if (bp->b_flags & XBF_STALE) {
@@ -876,10 +863,18 @@ xfs_buf_rele(
  */
 
 /*
- *     Locks a buffer object, if it is not already locked.
- *     Note that this in no way locks the underlying pages, so it is only
- *     useful for synchronizing concurrent use of buffer objects, not for
- *     synchronizing independent access to the underlying pages.
+ *     Locks a buffer object, if it is not already locked.  Note that this in
+ *     no way locks the underlying pages, so it is only useful for
+ *     synchronizing concurrent use of buffer objects, not for synchronizing
+ *     independent access to the underlying pages.
+ *
+ *     If we come across a stale, pinned, locked buffer, we know that we are
+ *     being asked to lock a buffer that has been reallocated. Because it is
+ *     pinned, we know that the log has not been pushed to disk and hence it
+ *     will still be locked.  Rather than continuing to have trylock attempts
+ *     fail until someone else pushes the log, push it ourselves before
+ *     returning.  This means that the xfsaild will not get stuck trying
+ *     to push on stale inode buffers.
  */
 int
 xfs_buf_cond_lock(
@@ -890,6 +885,8 @@ xfs_buf_cond_lock(
        locked = down_trylock(&bp->b_sema) == 0;
        if (locked)
                XB_SET_OWNER(bp);
+       else if (atomic_read(&bp->b_pin_count) && (bp->b_flags & XBF_STALE))
+               xfs_log_force(bp->b_target->bt_mount, 0);
 
        trace_xfs_buf_cond_lock(bp, _RET_IP_);
        return locked ? 0 : -EBUSY;
index 8abd12e32e133578441ac9eab1a4ab46cdb55035..4111cd3966c764b3c41300d1e7a51a7579ead435 100644 (file)
@@ -5471,8 +5471,13 @@ xfs_getbmap(
                        if (error)
                                goto out_unlock_iolock;
                }
-
-               ASSERT(ip->i_delayed_blks == 0);
+               /*
+                * even after flushing the inode, there can still be delalloc
+                * blocks on the inode beyond EOF due to speculative
+                * preallocation. These are not removed until the release
+                * function is called or the inode is inactivated. Hence we
+                * cannot assert here that ip->i_delayed_blks == 0.
+                */
        }
 
        lock = xfs_ilock_map_shared(ip);
@@ -6070,3 +6075,79 @@ xfs_bmap_disk_count_leaves(
                *count += xfs_bmbt_disk_get_blockcount(frp);
        }
 }
+
+/*
+ * dead simple method of punching delalyed allocation blocks from a range in
+ * the inode. Walks a block at a time so will be slow, but is only executed in
+ * rare error cases so the overhead is not critical. This will alays punch out
+ * both the start and end blocks, even if the ranges only partially overlap
+ * them, so it is up to the caller to ensure that partial blocks are not
+ * passed in.
+ */
+int
+xfs_bmap_punch_delalloc_range(
+       struct xfs_inode        *ip,
+       xfs_fileoff_t           start_fsb,
+       xfs_fileoff_t           length)
+{
+       xfs_fileoff_t           remaining = length;
+       int                     error = 0;
+
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+
+       do {
+               int             done;
+               xfs_bmbt_irec_t imap;
+               int             nimaps = 1;
+               xfs_fsblock_t   firstblock;
+               xfs_bmap_free_t flist;
+
+               /*
+                * Map the range first and check that it is a delalloc extent
+                * before trying to unmap the range. Otherwise we will be
+                * trying to remove a real extent (which requires a
+                * transaction) or a hole, which is probably a bad idea...
+                */
+               error = xfs_bmapi(NULL, ip, start_fsb, 1,
+                               XFS_BMAPI_ENTIRE,  NULL, 0, &imap,
+                               &nimaps, NULL);
+
+               if (error) {
+                       /* something screwed, just bail */
+                       if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
+                               xfs_fs_cmn_err(CE_ALERT, ip->i_mount,
+                       "Failed delalloc mapping lookup ino %lld fsb %lld.",
+                                               ip->i_ino, start_fsb);
+                       }
+                       break;
+               }
+               if (!nimaps) {
+                       /* nothing there */
+                       goto next_block;
+               }
+               if (imap.br_startblock != DELAYSTARTBLOCK) {
+                       /* been converted, ignore */
+                       goto next_block;
+               }
+               WARN_ON(imap.br_blockcount == 0);
+
+               /*
+                * Note: while we initialise the firstblock/flist pair, they
+                * should never be used because blocks should never be
+                * allocated or freed for a delalloc extent and hence we need
+                * don't cancel or finish them after the xfs_bunmapi() call.
+                */
+               xfs_bmap_init(&flist, &firstblock);
+               error = xfs_bunmapi(NULL, ip, start_fsb, 1, 0, 1, &firstblock,
+                                       &flist, &done);
+               if (error)
+                       break;
+
+               ASSERT(!flist.xbf_count && !flist.xbf_first);
+next_block:
+               start_fsb++;
+               remaining--;
+       } while(remaining > 0);
+
+       return error;
+}
index 71ec9b6ecdfcbb15e65d7857681cd3f9126cc9b1..3651191daea10cd99bae79443a2b1b9305940250 100644 (file)
@@ -394,6 +394,11 @@ xfs_bmap_count_blocks(
        int                     whichfork,
        int                     *count);
 
+int
+xfs_bmap_punch_delalloc_range(
+       struct xfs_inode        *ip,
+       xfs_fileoff_t           start_fsb,
+       xfs_fileoff_t           length);
 #endif /* __KERNEL__ */
 
 #endif /* __XFS_BMAP_H__ */
index 3b9582c60a225117f7b6d4180e4287b0118375ed..e60490bc00a61b6c8bc1bfbe04df4e56e536596c 100644 (file)
@@ -377,6 +377,19 @@ xfs_swap_extents(
        ip->i_d.di_format = tip->i_d.di_format;
        tip->i_d.di_format = tmp;
 
+       /*
+        * The extents in the source inode could still contain speculative
+        * preallocation beyond EOF (e.g. the file is open but not modified
+        * while defrag is in progress). In that case, we need to copy over the
+        * number of delalloc blocks the data fork in the source inode is
+        * tracking beyond EOF so that when the fork is truncated away when the
+        * temporary inode is unlinked we don't underrun the i_delayed_blks
+        * counter on that inode.
+        */
+       ASSERT(tip->i_delayed_blks == 0);
+       tip->i_delayed_blks = ip->i_delayed_blks;
+       ip->i_delayed_blks = 0;
+
        ilf_fields = XFS_ILOG_CORE;
 
        switch(ip->i_d.di_format) {
index ed99902676615e166a8e08371bf79c3a33d98021..c78cc6a3d87c0bb061092564c9f27c52d48519fa 100644 (file)
@@ -58,6 +58,7 @@ xfs_error_trap(int e)
 int    xfs_etest[XFS_NUM_INJECT_ERROR];
 int64_t        xfs_etest_fsid[XFS_NUM_INJECT_ERROR];
 char * xfs_etest_fsname[XFS_NUM_INJECT_ERROR];
+int    xfs_error_test_active;
 
 int
 xfs_error_test(int error_tag, int *fsidp, char *expression,
@@ -108,6 +109,7 @@ xfs_errortag_add(int error_tag, xfs_mount_t *mp)
                        len = strlen(mp->m_fsname);
                        xfs_etest_fsname[i] = kmem_alloc(len + 1, KM_SLEEP);
                        strcpy(xfs_etest_fsname[i], mp->m_fsname);
+                       xfs_error_test_active++;
                        return 0;
                }
        }
@@ -137,6 +139,7 @@ xfs_errortag_clearall(xfs_mount_t *mp, int loud)
                        xfs_etest_fsid[i] = 0LL;
                        kmem_free(xfs_etest_fsname[i]);
                        xfs_etest_fsname[i] = NULL;
+                       xfs_error_test_active--;
                }
        }
 
index c2c1a072bb82493bc210c50c9f6980633f8c9732..f338847f80b8d36c5c017214ec9538dab795459b 100644 (file)
@@ -127,13 +127,14 @@ extern void xfs_corruption_error(const char *tag, int level,
 #define        XFS_RANDOM_BMAPIFORMAT                          XFS_RANDOM_DEFAULT
 
 #ifdef DEBUG
+extern int xfs_error_test_active;
 extern int xfs_error_test(int, int *, char *, int, char *, unsigned long);
 
 #define        XFS_NUM_INJECT_ERROR                            10
 #define XFS_TEST_ERROR(expr, mp, tag, rf)              \
-       ((expr) || \
+       ((expr) || (xfs_error_test_active && \
         xfs_error_test((tag), (mp)->m_fixedfsid, "expr", __LINE__, __FILE__, \
-                       (rf)))
+                       (rf))))
 
 extern int xfs_errortag_add(int error_tag, xfs_mount_t *mp);
 extern int xfs_errortag_clearall(xfs_mount_t *mp, int loud);
index c7ac020705df1fbad86550c58784ba34cf2ee3ba..7c8d30c453c340de5afbab276505487ddbbf3373 100644 (file)
@@ -657,18 +657,37 @@ xfs_inode_item_unlock(
 }
 
 /*
- * This is called to find out where the oldest active copy of the
- * inode log item in the on disk log resides now that the last log
- * write of it completed at the given lsn.  Since we always re-log
- * all dirty data in an inode, the latest copy in the on disk log
- * is the only one that matters.  Therefore, simply return the
- * given lsn.
+ * This is called to find out where the oldest active copy of the inode log
+ * item in the on disk log resides now that the last log write of it completed
+ * at the given lsn.  Since we always re-log all dirty data in an inode, the
+ * latest copy in the on disk log is the only one that matters.  Therefore,
+ * simply return the given lsn.
+ *
+ * If the inode has been marked stale because the cluster is being freed, we
+ * don't want to (re-)insert this inode into the AIL. There is a race condition
+ * where the cluster buffer may be unpinned before the inode is inserted into
+ * the AIL during transaction committed processing. If the buffer is unpinned
+ * before the inode item has been committed and inserted, then it is possible
+ * for the buffer to be written and IO completions before the inode is inserted
+ * into the AIL. In that case, we'd be inserting a clean, stale inode into the
+ * AIL which will never get removed. It will, however, get reclaimed which
+ * triggers an assert in xfs_inode_free() complaining about freein an inode
+ * still in the AIL.
+ *
+ * To avoid this, return a lower LSN than the one passed in so that the
+ * transaction committed code will not move the inode forward in the AIL but
+ * will still unpin it properly.
  */
 STATIC xfs_lsn_t
 xfs_inode_item_committed(
        struct xfs_log_item     *lip,
        xfs_lsn_t               lsn)
 {
+       struct xfs_inode_log_item *iip = INODE_ITEM(lip);
+       struct xfs_inode        *ip = iip->ili_inode;
+
+       if (xfs_iflags_test(ip, XFS_ISTALE))
+               return lsn - 1;
        return lsn;
 }
 
index d2af0a8381a63975e9668d1aa7babb942bd4f4e2..77a59891734e925318f4a91723f96eb55f7b5ae8 100644 (file)
@@ -297,6 +297,7 @@ xfs_rename(
         * it and some incremental backup programs won't work without it.
         */
        xfs_trans_ichgtime(tp, src_ip, XFS_ICHGTIME_CHG);
+       xfs_trans_log_inode(tp, src_ip, XFS_ILOG_CORE);
 
        /*
         * Adjust the link count on src_dp.  This is necessary when
index 551793c9b6e8c25b2b1d3e36a4fe8ffcb4a0f24a..0e98e679d3a749cfda3898c2fe59f82d18ca87c3 100644 (file)
@@ -1,6 +1,10 @@
 #ifndef __ACPI_VIDEO_H
 #define __ACPI_VIDEO_H
 
+#include <linux/errno.h> /* for ENODEV */
+
+struct acpi_device;
+
 #define ACPI_VIDEO_DISPLAY_CRT  1
 #define ACPI_VIDEO_DISPLAY_TV   2
 #define ACPI_VIDEO_DISPLAY_DVI  3
@@ -26,4 +30,3 @@ static inline int acpi_video_get_edid(struct acpi_device *device, int type,
 #endif
 
 #endif
-
index 8c641bed9bbd36526870b6741fdd16f780e3b0ec..a2776e2807a4ce39051df02b7384da32d58c1545 100644 (file)
@@ -287,6 +287,8 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_EXECBUF2          9
 #define I915_PARAM_HAS_BSD              10
 #define I915_PARAM_HAS_BLT              11
+#define I915_PARAM_HAS_RELAXED_FENCING  12
+#define I915_PARAM_HAS_COHERENT_RINGS   13
 
 typedef struct drm_i915_getparam {
        int param;
index 01a7141195068c8e0fd384c0dde661adfb9601b6..bc5590b1a1acbe852314995f11b479e221ba6281 100644 (file)
@@ -80,6 +80,7 @@ struct drm_nouveau_gpuobj_free {
 #define NOUVEAU_GETPARAM_VM_VRAM_BASE    12
 #define NOUVEAU_GETPARAM_GRAPH_UNITS     13
 #define NOUVEAU_GETPARAM_PTIMER_TIME     14
+#define NOUVEAU_GETPARAM_HAS_BO_USAGE    15
 struct drm_nouveau_getparam {
        uint64_t param;
        uint64_t value;
@@ -95,6 +96,12 @@ struct drm_nouveau_setparam {
 #define NOUVEAU_GEM_DOMAIN_GART      (1 << 2)
 #define NOUVEAU_GEM_DOMAIN_MAPPABLE  (1 << 3)
 
+#define NOUVEAU_GEM_TILE_LAYOUT_MASK 0x0000ff00
+#define NOUVEAU_GEM_TILE_16BPP       0x00000001
+#define NOUVEAU_GEM_TILE_32BPP       0x00000002
+#define NOUVEAU_GEM_TILE_ZETA        0x00000004
+#define NOUVEAU_GEM_TILE_NONCONTIG   0x00000008
+
 struct drm_nouveau_gem_info {
        uint32_t handle;
        uint32_t domain;
index 050a7bccb8365ef117f365ebe3d3a8d337efc390..67c91b4418b06e59ea9de82e0c67dfb4cc5a7554 100644 (file)
@@ -219,7 +219,7 @@ static inline int acpi_video_display_switch_support(void)
 
 extern int acpi_blacklisted(void);
 extern void acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d);
-extern int acpi_osi_setup(char *str);
+extern void acpi_osi_setup(char *str);
 
 #ifdef CONFIG_ACPI_NUMA
 int acpi_get_pxm(acpi_handle handle);
index a8e4e832cdbb094d8a99ad9d831db3d14cbdbe23..475f8c42c0e928b57fbaf370bb89471642391b77 100644 (file)
@@ -427,8 +427,10 @@ extern rwlock_t vcc_sklist_lock;
 
 #define ATM_SKB(skb) (((struct atm_skb_data *) (skb)->cb))
 
-struct atm_dev *atm_dev_register(const char *type,const struct atmdev_ops *ops,
-    int number,unsigned long *flags); /* number == -1: pick first available */
+struct atm_dev *atm_dev_register(const char *type, struct device *parent,
+                                const struct atmdev_ops *ops,
+                                int number, /* -1 == pick first available */
+                                unsigned long *flags);
 struct atm_dev *atm_dev_lookup(int number);
 void atm_dev_deregister(struct atm_dev *dev);
 
index a065612fc928768268cf0352c91c34dc3f7c448a..64a7114a939427b5a7e74c761c27c0bdd9ee6d05 100644 (file)
@@ -29,6 +29,7 @@ struct linux_binprm{
        char buf[BINPRM_BUF_SIZE];
 #ifdef CONFIG_MMU
        struct vm_area_struct *vma;
+       unsigned long vma_pages;
 #else
 # define MAX_ARG_PAGES 32
        struct page *page[MAX_ARG_PAGES];
@@ -59,6 +60,10 @@ struct linux_binprm{
        unsigned long loader, exec;
 };
 
+extern void acct_arg_size(struct linux_binprm *bprm, unsigned long pages);
+extern struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
+                                       int write);
+
 #define BINPRM_FLAGS_ENFORCE_NONDUMP_BIT 0
 #define BINPRM_FLAGS_ENFORCE_NONDUMP (1 << BINPRM_FLAGS_ENFORCE_NONDUMP_BIT)
 
index aae86fd10c4f5dcea0eaf43cf6c39667a805dae4..36ab42c9bb991566dc5004fad9ca3c0c958bfeb0 100644 (file)
@@ -250,7 +250,7 @@ struct queue_limits {
 
        unsigned char           misaligned;
        unsigned char           discard_misaligned;
-       unsigned char           no_cluster;
+       unsigned char           cluster;
        signed char             discard_zeroes_data;
 };
 
@@ -380,7 +380,6 @@ struct request_queue
 #endif
 };
 
-#define QUEUE_FLAG_CLUSTER     0       /* cluster several segments into 1 */
 #define QUEUE_FLAG_QUEUED      1       /* uses generic tag queueing */
 #define QUEUE_FLAG_STOPPED     2       /* queue is stopped */
 #define        QUEUE_FLAG_SYNCFULL     3       /* read queue has been filled */
@@ -403,7 +402,6 @@ struct request_queue
 #define QUEUE_FLAG_SECDISCARD  19      /* supports SECDISCARD */
 
 #define QUEUE_FLAG_DEFAULT     ((1 << QUEUE_FLAG_IO_STAT) |            \
-                                (1 << QUEUE_FLAG_CLUSTER) |            \
                                 (1 << QUEUE_FLAG_STACKABLE)    |       \
                                 (1 << QUEUE_FLAG_SAME_COMP)    |       \
                                 (1 << QUEUE_FLAG_ADD_RANDOM))
@@ -510,6 +508,11 @@ static inline void queue_flag_clear(unsigned int flag, struct request_queue *q)
 
 #define rq_data_dir(rq)                ((rq)->cmd_flags & 1)
 
+static inline unsigned int blk_queue_cluster(struct request_queue *q)
+{
+       return q->limits.cluster;
+}
+
 /*
  * We regard a request as sync, if either a read or a sync write
  */
@@ -805,6 +808,7 @@ extern struct request_queue *blk_init_allocated_queue(struct request_queue *,
 extern void blk_cleanup_queue(struct request_queue *);
 extern void blk_queue_make_request(struct request_queue *, make_request_fn *);
 extern void blk_queue_bounce_limit(struct request_queue *, u64);
+extern void blk_limits_max_hw_sectors(struct queue_limits *, unsigned int);
 extern void blk_queue_max_hw_sectors(struct request_queue *, unsigned int);
 extern void blk_queue_max_segments(struct request_queue *, unsigned short);
 extern void blk_queue_max_segment_size(struct request_queue *, unsigned int);
index 266ab92912327bb7bfe9bf1d87ff008260cc424f..499dfe982a0e8a21066e815daa400ac8b57ec5b4 100644 (file)
@@ -105,6 +105,8 @@ extern void *__alloc_bootmem_low_node(pg_data_t *pgdat,
 
 #define alloc_bootmem(x) \
        __alloc_bootmem(x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
+#define alloc_bootmem_align(x, align) \
+       __alloc_bootmem(x, align, __pa(MAX_DMA_ADDRESS))
 #define alloc_bootmem_nopanic(x) \
        __alloc_bootmem_nopanic(x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
 #define alloc_bootmem_pages(x) \
index f22b2e941686fc370f85b942526ee392f1f9ead6..72c72bfccb88181b8b7c480e445849bfc0c8ab28 100644 (file)
@@ -227,9 +227,10 @@ extern int ceph_open_session(struct ceph_client *client);
 extern void ceph_release_page_vector(struct page **pages, int num_pages);
 
 extern struct page **ceph_get_direct_page_vector(const char __user *data,
-                                           int num_pages,
-                                           loff_t off, size_t len);
-extern void ceph_put_page_vector(struct page **pages, int num_pages);
+                                                int num_pages,
+                                                bool write_page);
+extern void ceph_put_page_vector(struct page **pages, int num_pages,
+                                bool dirty);
 extern void ceph_release_page_vector(struct page **pages, int num_pages);
 extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags);
 extern int ceph_copy_user_to_page_vector(struct page **pages,
index 5956d62c3057139ac6634df8e13556659d07725e..a108b425fee25aff2cbf4dd1924c047b925f7ab0 100644 (file)
@@ -82,6 +82,7 @@ struct ceph_msg {
        struct ceph_buffer *middle;
        struct page **pages;            /* data payload.  NOT OWNER. */
        unsigned nr_pages;              /* size of page array */
+       unsigned page_alignment;        /* io offset in first page */
        struct ceph_pagelist *pagelist; /* instead of pages */
        struct list_head list_head;
        struct kref kref;
index 6c91fb032c39cd907a3ac509db75a3a860e564c1..a1af29648fb54be5c0b5ac1cfc62879314145d56 100644 (file)
@@ -79,6 +79,7 @@ struct ceph_osd_request {
        struct ceph_file_layout r_file_layout;
        struct ceph_snap_context *r_snapc;    /* snap context for writes */
        unsigned          r_num_pages;        /* size of page array (follows) */
+       unsigned          r_page_alignment;   /* io offset in first page */
        struct page     **r_pages;            /* pages for data payload */
        int               r_pages_from_pool;
        int               r_own_pages;        /* if true, i own page list */
@@ -194,7 +195,8 @@ extern struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *,
                                      int do_sync, u32 truncate_seq,
                                      u64 truncate_size,
                                      struct timespec *mtime,
-                                     bool use_mempool, int num_reply);
+                                     bool use_mempool, int num_reply,
+                                     int page_align);
 
 static inline void ceph_osdc_get_request(struct ceph_osd_request *req)
 {
@@ -218,7 +220,8 @@ extern int ceph_osdc_readpages(struct ceph_osd_client *osdc,
                               struct ceph_file_layout *layout,
                               u64 off, u64 *plen,
                               u32 truncate_seq, u64 truncate_size,
-                              struct page **pages, int nr_pages);
+                              struct page **pages, int nr_pages,
+                              int page_align);
 
 extern int ceph_osdc_writepages(struct ceph_osd_client *osdc,
                                struct ceph_vino vino,
index 7605fdd1eb65de1fffd5f1bf5b47428e16475133..e3d8bf26e5eb229a9ca2959fc5ea2b1638238988 100644 (file)
@@ -61,13 +61,31 @@ union cnt32_to_63 {
  *
  * 2) this code must not be preempted for a duration longer than the
  *    32-bit counter half period minus the longest period between two
- *    calls to this code.
+ *    calls to this code;
  *
  * Those requirements ensure proper update to the state bit in memory.
  * This is usually not a problem in practice, but if it is then a kernel
  * timer should be scheduled to manage for this code to be executed often
  * enough.
  *
+ * And finally:
+ *
+ * 3) the cnt_lo argument must be seen as a globally incrementing value,
+ *    meaning that it should be a direct reference to the counter data which
+ *    can be evaluated according to a specific ordering within the macro,
+ *    and not the result of a previous evaluation stored in a variable.
+ *
+ * For example, this is wrong:
+ *
+ *     u32 partial = get_hw_count();
+ *     u64 full = cnt32_to_63(partial);
+ *     return full;
+ *
+ * This is fine:
+ *
+ *     u64 full = cnt32_to_63(get_hw_count());
+ *     return full;
+ *
  * Note that the top bit (bit 63) in the returned value should be considered
  * as garbage.  It is not cleared here because callers are likely to use a
  * multiplier on the returned value which can get rid of the top bit
index 4823af64e9db2148c23e1ae4d0ad3fe21de4368a..5f09323ee8808abaa39ea0ab44e6f438591282c4 100644 (file)
  *
  * CPUs are exported via sysfs in the class/cpu/devices/
  * directory. 
- *
- * Per-cpu interfaces can be implemented using a struct device_interface. 
- * See the following for how to do this: 
- * - drivers/base/intf.c 
- * - Documentation/driver-model/interface.txt
  */
 #ifndef _LINUX_CPU_H_
 #define _LINUX_CPU_H_
index a7d9dc21391d276e94c7a008107d31a0c56d8dc6..7b776d71d36d0e465dfb4b6384899026253540cc 100644 (file)
@@ -175,10 +175,21 @@ static inline int set_msi_sid(struct irte *irte, struct pci_dev *dev)
        return 0;
 }
 
-#define enable_intr_remapping(mode)    (-1)
-#define disable_intr_remapping()       (0)
-#define reenable_intr_remapping(mode)  (0)
 #define intr_remapping_enabled         (0)
+
+static inline int enable_intr_remapping(int eim)
+{
+       return -1;
+}
+
+static inline void disable_intr_remapping(void)
+{
+}
+
+static inline int reenable_intr_remapping(int eim)
+{
+       return 0;
+}
 #endif
 
 /* Can't use the common MSI interrupt functions
index 0f0121467fc4b8cf261cbb06a9ff6347b3596474..6c6133f76e163c88041c4a13a4b091ef6ccf13ac 100644 (file)
                                 FAN_ALL_PERM_EVENTS |\
                                 FAN_Q_OVERFLOW)
 
-#define FANOTIFY_METADATA_VERSION      2
+#define FANOTIFY_METADATA_VERSION      3
 
 struct fanotify_event_metadata {
        __u32 event_len;
-       __u32 vers;
+       __u8 vers;
+       __u8 reserved;
+       __u16 metadata_len;
        __aligned_u64 mask;
        __s32 fd;
        __s32 pid;
@@ -96,11 +98,13 @@ struct fanotify_event_metadata {
 struct fanotify_response {
        __s32 fd;
        __u32 response;
-} __attribute__ ((packed));
+};
 
 /* Legit userspace responses to a _PERM event */
 #define FAN_ALLOW      0x01
 #define FAN_DENY       0x02
+/* No fd set in event */
+#define FAN_NOFD       -1
 
 /* Helper functions to deal with fanotify_event_metadata buffers */
 #define FAN_EVENT_METADATA_LEN (sizeof(struct fanotify_event_metadata))
index 7fca3dc4e47581ef77afc0096b36a7613a1acdb9..68ba85a00c063563c6142becb0e619be9c06007b 100644 (file)
@@ -1092,6 +1092,8 @@ extern int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var);
 extern const unsigned char *fb_firmware_edid(struct device *device);
 extern void fb_edid_to_monspecs(unsigned char *edid,
                                struct fb_monspecs *specs);
+extern void fb_edid_add_monspecs(unsigned char *edid,
+                                struct fb_monspecs *specs);
 extern void fb_destroy_modedb(struct fb_videomode *modedb);
 extern int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb);
 extern unsigned char *fb_ddc_read(struct i2c_adapter *adapter);
@@ -1122,6 +1124,7 @@ extern const struct fb_videomode *fb_find_best_display(const struct fb_monspecs
 
 /* drivers/video/fbcmap.c */
 extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);
+extern int fb_alloc_cmap_gfp(struct fb_cmap *cmap, int len, int transp, gfp_t flags);
 extern void fb_dealloc_cmap(struct fb_cmap *cmap);
 extern int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to);
 extern int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to);
@@ -1149,6 +1152,7 @@ struct fb_videomode {
 
 extern const char *fb_mode_option;
 extern const struct fb_videomode vesa_modes[];
+extern const struct fb_videomode cea_modes[64];
 
 struct fb_modelist {
        struct list_head list;
index 334d68a171081472a25f98baa510bc7eb4cfeb8e..090f0eacde296ec52a06fe5eb1b13c07808b7ada 100644 (file)
@@ -34,9 +34,9 @@
 #define SEEK_MAX       SEEK_END
 
 struct fstrim_range {
-       uint64_t start;
-       uint64_t len;
-       uint64_t minlen;
+       __u64 start;
+       __u64 len;
+       __u64 minlen;
 };
 
 /* And dynamically-tunable limits and defaults: */
@@ -602,6 +602,7 @@ struct address_space_operations {
        sector_t (*bmap)(struct address_space *, sector_t);
        void (*invalidatepage) (struct page *, unsigned long);
        int (*releasepage) (struct page *, gfp_t);
+       void (*freepage)(struct page *);
        ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
                        loff_t offset, unsigned long nr_segs);
        int (*get_xip_mem)(struct address_space *, pgoff_t, int,
@@ -1612,7 +1613,6 @@ struct super_operations {
        ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
 #endif
        int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
-       int (*trim_fs) (struct super_block *, struct fstrim_range *);
 };
 
 /*
index 5c185fa27089f03b4e9194445ee7bfd842f125c6..b10bcdeaef768b2b0b123c4a6c862b3f5f6c0694 100644 (file)
@@ -235,9 +235,6 @@ static inline void fsnotify_open(struct file *file)
        if (S_ISDIR(inode->i_mode))
                mask |= FS_ISDIR;
 
-       /* FMODE_NONOTIFY must never be set from user */
-       file->f_mode &= ~FMODE_NONOTIFY;
-
        fsnotify_parent(path, NULL, mask);
        fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
 }
index 0a68f924f06fcf3f6f75727f382971bc16e5608f..7380763595d30accb255728f45682550cc540d63 100644 (file)
@@ -166,7 +166,7 @@ struct fsnotify_group {
                        struct mutex access_mutex;
                        struct list_head access_list;
                        wait_queue_head_t access_waitq;
-                       bool bypass_perm; /* protected by access_mutex */
+                       atomic_t bypass_perm;
 #endif /* CONFIG_FANOTIFY_ACCESS_PERMISSIONS */
                        int f_flags;
                        unsigned int max_marks;
index e8713d55360ab90d85af0daca3b36bdfbcd430d1..f54adfcbec9c9ea1e8a44003bcf880f4ce8fe9cd 100644 (file)
@@ -360,7 +360,7 @@ void drain_local_pages(void *dummy);
 
 extern gfp_t gfp_allowed_mask;
 
-extern void set_gfp_allowed_mask(gfp_t mask);
-extern gfp_t clear_gfp_allowed_mask(gfp_t mask);
+extern void pm_restrict_gfp_mask(void);
+extern void pm_restore_gfp_mask(void);
 
 #endif /* __LINUX_GFP_H */
index ce73a30113b4d0181ef7a2131c060ca18f1de027..dd1a56fbe9241235f4baa059394d5d36bd050de7 100644 (file)
@@ -16,6 +16,8 @@ struct gpio_keys_button {
 struct gpio_keys_platform_data {
        struct gpio_keys_button *buttons;
        int nbuttons;
+       unsigned int poll_interval;     /* polling interval in msecs -
+                                          for polling driver only */
        unsigned int rep:1;             /* enable input subsystem auto repeat */
        int (*enable)(struct device *dev);
        void (*disable)(struct device *dev);
index 714da7e5d10c3aadccf1a3a8b0038d9594139b22..32f9fd6619b4160c997bba07e2661382f3afaacf 100644 (file)
@@ -94,6 +94,7 @@
 #define in_nmi()       (preempt_count() & NMI_MASK)
 
 #if defined(CONFIG_PREEMPT) && defined(CONFIG_BKL)
+# include <linux/sched.h>
 # define PREEMPT_INATOMIC_BASE (current->lock_depth >= 0)
 #else
 # define PREEMPT_INATOMIC_BASE 0
index a2d6ea49ec564e825ebffc3ebb059f57079fc73d..d1e55fed2c7dc0281cd0cf653bb5a56a399265cb 100644 (file)
@@ -33,6 +33,8 @@ enum bp_type_idx {
 
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
 
+extern int __init init_hw_breakpoint(void);
+
 static inline void hw_breakpoint_init(struct perf_event_attr *attr)
 {
        memset(attr, 0, sizeof(*attr));
@@ -108,6 +110,8 @@ static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp)
 
 #else /* !CONFIG_HAVE_HW_BREAKPOINT */
 
+static inline int __init init_hw_breakpoint(void) { return 0; }
+
 static inline struct perf_event *
 register_user_hw_breakpoint(struct perf_event_attr *attr,
                            perf_overflow_handler_t triggered,
index 6ef44465db8ddc31c41be1de00eeef38c53b5fa5..9777668883be6aa18a309b6388616fe08ee900ea 100644 (file)
@@ -47,6 +47,25 @@ struct input_id {
        __u16 version;
 };
 
+/**
+ * struct input_absinfo - used by EVIOCGABS/EVIOCSABS ioctls
+ * @value: latest reported value for the axis.
+ * @minimum: specifies minimum value for the axis.
+ * @maximum: specifies maximum value for the axis.
+ * @fuzz: specifies fuzz value that is used to filter noise from
+ *     the event stream.
+ * @flat: values that are within this value will be discarded by
+ *     joydev interface and reported as 0 instead.
+ * @resolution: specifies resolution for the values reported for
+ *     the axis.
+ *
+ * Note that input core does not clamp reported values to the
+ * [minimum, maximum] limits, such task is left to userspace.
+ *
+ * Resolution for main axes (ABS_X, ABS_Y, ABS_Z) is reported in
+ * units per millimeter (units/mm), resolution for rotational axes
+ * (ABS_RX, ABS_RY, ABS_RZ) is reported in units per radian.
+ */
 struct input_absinfo {
        __s32 value;
        __s32 minimum;
@@ -85,8 +104,10 @@ struct input_keymap_entry {
 #define EVIOCGREP              _IOR('E', 0x03, unsigned int[2])        /* get repeat settings */
 #define EVIOCSREP              _IOW('E', 0x03, unsigned int[2])        /* set repeat settings */
 
-#define EVIOCGKEYCODE          _IOR('E', 0x04, struct input_keymap_entry)      /* get keycode */
-#define EVIOCSKEYCODE          _IOW('E', 0x04, struct input_keymap_entry)      /* set keycode */
+#define EVIOCGKEYCODE          _IOR('E', 0x04, unsigned int[2])        /* get keycode */
+#define EVIOCGKEYCODE_V2       _IOR('E', 0x04, struct input_keymap_entry)
+#define EVIOCSKEYCODE          _IOW('E', 0x04, unsigned int[2])        /* set keycode */
+#define EVIOCSKEYCODE_V2       _IOW('E', 0x04, struct input_keymap_entry)
 
 #define EVIOCGNAME(len)                _IOC(_IOC_READ, 'E', 0x06, len)         /* get device name */
 #define EVIOCGPHYS(len)                _IOC(_IOC_READ, 'E', 0x07, len)         /* get physical location */
@@ -624,6 +645,10 @@ struct input_keymap_entry {
 #define KEY_CAMERA_FOCUS       0x210
 #define KEY_WPS_BUTTON         0x211   /* WiFi Protected Setup key */
 
+#define KEY_TOUCHPAD_TOGGLE    0x212   /* Request switch touchpad on or off */
+#define KEY_TOUCHPAD_ON                0x213
+#define KEY_TOUCHPAD_OFF       0x214
+
 #define BTN_TRIGGER_HAPPY              0x2c0
 #define BTN_TRIGGER_HAPPY1             0x2c0
 #define BTN_TRIGGER_HAPPY2             0x2c1
@@ -1130,7 +1155,7 @@ struct input_mt_slot {
  *     of tracked contacts
  * @mtsize: number of MT slots the device uses
  * @slot: MT slot currently being transmitted
- * @absinfo: array of &struct absinfo elements holding information
+ * @absinfo: array of &struct input_absinfo elements holding information
  *     about absolute axes (current value, min, max, flat, fuzz,
  *     resolution)
  * @key: reflects current state of device's keys/buttons
index d377ea815d453b9ec232f22efc5503f5d456b0cf..e9bb22cba764139cc69f3faa1e16f11cc0e05eb2 100644 (file)
@@ -112,7 +112,6 @@ struct resource_list {
 /* PC/ISA/whatever - the normal PC address spaces: IO and memory */
 extern struct resource ioport_resource;
 extern struct resource iomem_resource;
-extern int resource_alloc_from_bottom;
 
 extern struct resource *request_resource_conflict(struct resource *root, struct resource *new);
 extern int request_resource(struct resource *root, struct resource *new);
@@ -124,6 +123,7 @@ extern void reserve_region_with_split(struct resource *root,
 extern struct resource *insert_resource_conflict(struct resource *parent, struct resource *new);
 extern int insert_resource(struct resource *parent, struct resource *new);
 extern void insert_resource_expand_to_fit(struct resource *root, struct resource *new);
+extern void arch_remove_reservations(struct resource *avail);
 extern int allocate_resource(struct resource *root, struct resource *new,
                             resource_size_t size, resource_size_t min,
                             resource_size_t max, resource_size_t align,
index 1ff81b51b656a13f32c4d8b5253f803593cd033b..dd3c34ebca9a67e05c2e59649da81486210e802c 100644 (file)
@@ -11,6 +11,7 @@
 #define MARVELL_PHY_ID_88E1118         0x01410e10
 #define MARVELL_PHY_ID_88E1121R                0x01410cb0
 #define MARVELL_PHY_ID_88E1145         0x01410cd0
+#define MARVELL_PHY_ID_88E1149R                0x01410e50
 #define MARVELL_PHY_ID_88E1240         0x01410e30
 #define MARVELL_PHY_ID_88E1318S                0x01410e90
 
index 4307231bd22fb23ad9732295f472bc4b8564e200..31c237a00c48e472b7c8e6c435fe66de9b0e232a 100644 (file)
@@ -161,6 +161,9 @@ extern void register_page_bootmem_info_node(struct pglist_data *pgdat);
 extern void put_page_bootmem(struct page *page);
 #endif
 
+void lock_memory_hotplug(void);
+void unlock_memory_hotplug(void);
+
 #else /* ! CONFIG_MEMORY_HOTPLUG */
 /*
  * Stub functions for when hotplug is off
@@ -192,6 +195,9 @@ static inline void register_page_bootmem_info_node(struct pglist_data *pgdat)
 {
 }
 
+static inline void lock_memory_hotplug(void) {}
+static inline void unlock_memory_hotplug(void) {}
+
 #endif /* ! CONFIG_MEMORY_HOTPLUG */
 
 #ifdef CONFIG_MEMORY_HOTREMOVE
index a95141eafce390d7586c17c4eb3f3777c20669db..bd581c6fa0855bf9014a5cb061d5dc78df204e21 100644 (file)
 #define WM8350_MCLK_SEL_PLL_32K                        3
 #define WM8350_MCLK_SEL_MCLK                   5
 
-#define WM8350_MCLK_DIR_OUT                    0
-#define WM8350_MCLK_DIR_IN                     1
-
 /* clock divider id's */
 #define WM8350_ADC_CLKDIV                      0
 #define WM8350_DAC_CLKDIV                      1
index 5c51f367c0610166bbf6ec12d6fedc7587d7420e..add8a1b8bcf0057c3f328c51dc96a4d82ae331a5 100644 (file)
@@ -29,7 +29,7 @@ struct wm8994_ldo_pdata {
 #define WM8994_CONFIGURE_GPIO 0x8000
 
 #define WM8994_DRC_REGS 5
-#define WM8994_EQ_REGS  19
+#define WM8994_EQ_REGS  20
 
 /**
  * DRC configurations are specified with a label and a set of register
index 6d87f68ce4b6b70b8ff573f3e73e2550e9ca4acb..30f6fad99a58bb7f3a42e51606269a019826fbaa 100644 (file)
@@ -168,6 +168,7 @@ struct mmc_host {
                                                /* DDR mode at 1.8V */
 #define MMC_CAP_1_2V_DDR       (1 << 12)       /* can support */
                                                /* DDR mode at 1.2V */
+#define MMC_CAP_POWER_OFF_CARD (1 << 13)       /* Can power off after boot */
 
        mmc_pm_flag_t           pm_caps;        /* supported pm features */
 
index b29e7458b96642b2f36162aa755b10ff76b15abe..7575bbbdf2a2b8e6a716fb6252c3d8e958756f52 100644 (file)
@@ -517,7 +517,7 @@ static inline void __module_get(struct module *module)
 #define symbol_put_addr(p) do { } while(0)
 
 #endif /* CONFIG_MODULE_UNLOAD */
-int use_module(struct module *a, struct module *b);
+int ref_module(struct module *a, struct module *b);
 
 /* This is a #define so the string doesn't get put in every .o file */
 #define module_name(mod)                       \
index c66fdb7d6998129701f6eaa653f1d28dd641e332..29d504d5d1c31f5698433657dd534c1500f317b2 100644 (file)
@@ -401,6 +401,7 @@ extern const struct inode_operations nfs3_file_inode_operations;
 #endif /* CONFIG_NFS_V3 */
 extern const struct file_operations nfs_file_operations;
 extern const struct address_space_operations nfs_file_aops;
+extern const struct address_space_operations nfs_dir_aops;
 
 static inline struct nfs_open_context *nfs_file_open_context(struct file *filp)
 {
index f8b60e7f4c44d9b652a94bca2ab8945130bdb061..d55cee73f63477a326b73cf7eb15e3e277567b14 100644 (file)
@@ -29,6 +29,7 @@
  */
 enum {
        PG_BUSY = 0,
+       PG_MAPPED,
        PG_CLEAN,
        PG_NEED_COMMIT,
        PG_NEED_RESCHED,
index ba6cc8f223c94190a13a2e1ef2316f993c205010..80f07198a31a682814684d7946915cedd1df5d56 100644 (file)
@@ -483,6 +483,7 @@ struct nfs_entry {
        int                     eof;
        struct nfs_fh *         fh;
        struct nfs_fattr *      fattr;
+       unsigned char           d_type;
 };
 
 /*
index 06292dac3eab15ea6f4b82ddc868e7f955889e7e..1466945cc9ef46c252fe7cd7834758fb3ddf9e19 100644 (file)
  *
  * Nodes are exported via driverfs in the class/node/devices/
  * directory. 
- *
- * Per-node interfaces can be implemented using a struct device_interface. 
- * See the following for how to do this: 
- * - drivers/base/intf.c 
- * - Documentation/driver-model/interface.txt
  */
 #ifndef _LINUX_NODE_H_
 #define _LINUX_NODE_H_
index 5bb13b3db84d46ee155784a26acfd850e94c91ff..b02195dfc1b0d3eb3044972db401b50acb0ad27d 100644 (file)
@@ -59,8 +59,6 @@ static inline void ClearPageCgroup##uname(struct page_cgroup *pc)     \
 static inline int TestClearPageCgroup##uname(struct page_cgroup *pc)   \
        { return test_and_clear_bit(PCG_##lname, &pc->flags);  }
 
-TESTPCGFLAG(Locked, LOCK)
-
 /* Cache flag is set only once (at allocation) */
 TESTPCGFLAG(Cache, CACHE)
 CLEARPCGFLAG(Cache, CACHE)
@@ -104,6 +102,11 @@ static inline void unlock_page_cgroup(struct page_cgroup *pc)
        bit_spin_unlock(PCG_LOCK, &pc->flags);
 }
 
+static inline int page_is_cgroup_locked(struct page_cgroup *pc)
+{
+       return bit_spin_is_locked(PCG_LOCK, &pc->flags);
+}
+
 #else /* CONFIG_CGROUP_MEM_RES_CTLR */
 struct page_cgroup;
 
index c6bcfe93b9cab9deeab76844ce8b76e2a2adf5bb..cb845c16ad7d22fe2bd7f22eb9320085ff09c1ca 100644 (file)
 #define PCI_DEVICE_ID_AFAVLAB_P030     0x2182
 #define PCI_SUBDEVICE_ID_AFAVLAB_P061          0x2150
 
+#define PCI_VENDOR_ID_BCM_GVC          0x14a4
 #define PCI_VENDOR_ID_BROADCOM         0x14e4
 #define PCI_DEVICE_ID_TIGON3_5752      0x1600
 #define PCI_DEVICE_ID_TIGON3_5752M     0x1601
 #define PCI_DEVICE_ID_INTEL_MFD_SDIO2  0x0822
 #define PCI_DEVICE_ID_INTEL_MFD_EMMC0  0x0823
 #define PCI_DEVICE_ID_INTEL_MFD_EMMC1  0x0824
+#define PCI_DEVICE_ID_INTEL_MRST_SD2   0x084F
 #define PCI_DEVICE_ID_INTEL_I960       0x0960
 #define PCI_DEVICE_ID_INTEL_I960RM     0x0962
 #define PCI_DEVICE_ID_INTEL_8257X_SOL  0x1062
index 40150f345982cd4fd40e8b80470505e569f05b03..4f1279e105ee143e4317219b3cb093bc8bbdd954 100644 (file)
@@ -850,6 +850,7 @@ struct perf_event_context {
        int                             nr_active;
        int                             is_active;
        int                             nr_stat;
+       int                             rotate_disable;
        atomic_t                        refcount;
        struct task_struct              *task;
 
@@ -886,6 +887,7 @@ struct perf_cpu_context {
        int                             exclusive;
        struct list_head                rotation_list;
        int                             jiffies_interval;
+       struct pmu                      *active_pmu;
 };
 
 struct perf_output_handle {
@@ -908,20 +910,6 @@ extern int perf_num_counters(void);
 extern const char *perf_pmu_name(void);
 extern void __perf_event_task_sched_in(struct task_struct *task);
 extern void __perf_event_task_sched_out(struct task_struct *task, struct task_struct *next);
-
-extern atomic_t perf_task_events;
-
-static inline void perf_event_task_sched_in(struct task_struct *task)
-{
-       COND_STMT(&perf_task_events, __perf_event_task_sched_in(task));
-}
-
-static inline
-void perf_event_task_sched_out(struct task_struct *task, struct task_struct *next)
-{
-       COND_STMT(&perf_task_events, __perf_event_task_sched_out(task, next));
-}
-
 extern int perf_event_init_task(struct task_struct *child);
 extern void perf_event_exit_task(struct task_struct *child);
 extern void perf_event_free_task(struct task_struct *task);
@@ -1030,6 +1018,21 @@ have_event:
        __perf_sw_event(event_id, nr, nmi, regs, addr);
 }
 
+extern atomic_t perf_task_events;
+
+static inline void perf_event_task_sched_in(struct task_struct *task)
+{
+       COND_STMT(&perf_task_events, __perf_event_task_sched_in(task));
+}
+
+static inline
+void perf_event_task_sched_out(struct task_struct *task, struct task_struct *next)
+{
+       perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 1, NULL, 0);
+
+       COND_STMT(&perf_task_events, __perf_event_task_sched_out(task, next));
+}
+
 extern void perf_event_mmap(struct vm_area_struct *vma);
 extern struct perf_guest_info_callbacks *perf_guest_cbs;
 extern int perf_register_guest_info_callbacks(struct perf_guest_info_callbacks *callbacks);
index 445796945ac9d1c491c1d740f0f2ca7bfa1ae22b..bb27d7ec2fb95cac4599351532f482d1df129fab 100644 (file)
@@ -160,5 +160,6 @@ void generic_pipe_buf_release(struct pipe_inode_info *, struct pipe_buffer *);
 
 /* for F_SETPIPE_SZ and F_GETPIPE_SZ */
 long pipe_fcntl(struct file *, unsigned int, unsigned long arg);
+struct pipe_inode_info *get_pipe_info(struct file *file);
 
 #endif
index 3ec2358f8692d11027e6af927402fcbc0f039da2..d19f1cca7f740a9150f516c98e5c9deecfd271ae 100644 (file)
@@ -77,7 +77,8 @@ static inline void device_set_run_wake(struct device *dev, bool enable)
 
 static inline bool pm_runtime_suspended(struct device *dev)
 {
-       return dev->power.runtime_status == RPM_SUSPENDED;
+       return dev->power.runtime_status == RPM_SUSPENDED
+               && !dev->power.disable_depth;
 }
 
 static inline void pm_runtime_mark_last_busy(struct device *dev)
index d42f274418b884ea72f8de09cda464af817fd774..bbad657a37259c0f35e99341761a789731435e25 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/if_link.h>
 #include <linux/if_addr.h>
 #include <linux/neighbour.h>
-#include <linux/netdevice.h>
 
 /* rtnetlink families. Values up to 127 are reserved for real address
  * families, values above 128 may be used arbitrarily.
@@ -606,6 +605,7 @@ struct tcamsg {
 #ifdef __KERNEL__
 
 #include <linux/mutex.h>
+#include <linux/netdevice.h>
 
 static __inline__ int rtattr_strcmp(const struct rtattr *rta, const char *str)
 {
index 2c79e921a68baeb9d5afa9b0deaa731232685ed5..223874538b33208e3c5ff11710f3161d58b4aef2 100644 (file)
@@ -143,7 +143,7 @@ extern unsigned long nr_iowait_cpu(int cpu);
 extern unsigned long this_cpu_load(void);
 
 
-extern void calc_global_load(void);
+extern void calc_global_load(unsigned long ticks);
 
 extern unsigned long get_parent_ip(unsigned long addr);
 
index cea0c38e7a63dfad2544043c49fca25aea9a7563..9a52f72527dc5a38831686cb824bf043258c8a19 100644 (file)
@@ -19,11 +19,13 @@ struct clk_mapping {
 };
 
 struct clk_ops {
+#ifdef CONFIG_SH_CLK_CPG_LEGACY
        void (*init)(struct clk *clk);
+#endif
        int (*enable)(struct clk *clk);
        void (*disable)(struct clk *clk);
        unsigned long (*recalc)(struct clk *clk);
-       int (*set_rate)(struct clk *clk, unsigned long rate, int algo_id);
+       int (*set_rate)(struct clk *clk, unsigned long rate);
        int (*set_parent)(struct clk *clk, struct clk *parent);
        long (*round_rate)(struct clk *clk, unsigned long rate);
 };
@@ -67,36 +69,6 @@ int clk_register(struct clk *);
 void clk_unregister(struct clk *);
 void clk_enable_init_clocks(void);
 
-/**
- * clk_set_rate_ex - set the clock rate for a clock source, with additional parameter
- * @clk: clock source
- * @rate: desired clock rate in Hz
- * @algo_id: algorithm id to be passed down to ops->set_rate
- *
- * Returns success (0) or negative errno.
- */
-int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id);
-
-enum clk_sh_algo_id {
-       NO_CHANGE = 0,
-
-       IUS_N1_N1,
-       IUS_322,
-       IUS_522,
-       IUS_N11,
-
-       SB_N1,
-
-       SB3_N1,
-       SB3_32,
-       SB3_43,
-       SB3_54,
-
-       BP_N1,
-
-       IP_N1,
-};
-
 struct clk_div_mult_table {
        unsigned int *divisors;
        unsigned int nr_divisors;
index ebb0c80ffd6ebb53b02fb2263e0a6ff6a634eb6a..12b2b18e50c1c321f208a83d4bbda61ce985450c 100644 (file)
@@ -230,6 +230,7 @@ enum
        LINUX_MIB_TCPMINTTLDROP, /* RFC 5082 */
        LINUX_MIB_TCPDEFERACCEPTDROP,
        LINUX_MIB_IPRPFILTER, /* IP Reverse Path Filter (rp_filter) */
+       LINUX_MIB_TCPTIMEWAITOVERFLOW,          /* TCPTimeWaitOverflow */
        __LINUX_MIB_MAX
 };
 
index 942e3873690190addb45bdde24a069a812f3b8b8..eba52a100533349461c1965f996074c187eaab08 100644 (file)
@@ -96,16 +96,21 @@ static inline bool ssb_gige_must_flush_posted_writes(struct pci_dev *pdev)
        return 0;
 }
 
-extern char * nvram_get(const char *name);
+#ifdef CONFIG_BCM47XX
+#include <asm/mach-bcm47xx/nvram.h>
 /* Get the device MAC address */
 static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
 {
-#ifdef CONFIG_BCM47XX
-       char *res = nvram_get("et0macaddr");
-       if (res)
-               memcpy(macaddr, res, 6);
-#endif
+       char buf[20];
+       if (nvram_getenv("et0macaddr", buf, sizeof(buf)) < 0)
+               return;
+       nvram_parse_macaddr(buf, macaddr);
 }
+#else
+static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
+{
+}
+#endif
 
 extern int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,
                                          struct pci_dev *pdev);
index 032d79ff1d9d4ec7fcfb313261b27548f1d5f3dd..54e4eaaa05610d8b101a97f1c3faa11d11399861 100644 (file)
@@ -366,6 +366,7 @@ struct tty_file_private {
 #define TTY_HUPPED             18      /* Post driver->hangup() */
 #define TTY_FLUSHING           19      /* Flushing to ldisc in progress */
 #define TTY_FLUSHPENDING       20      /* Queued buffer flush pending */
+#define TTY_HUPPING            21      /* ->hangup() in progress */
 
 #define TTY_WRITE_FLUSH(tty) tty_write_flush((tty))
 
index d6188e5a52df900e9829461538b9c4976356d6b0..665517c05eaf2470f57b546a801b8e8bcac03e52 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright(C) 2005, Benedikt Spranger <b.spranger@linutronix.de>
  * Copyright(C) 2005, Thomas Gleixner <tglx@linutronix.de>
- * Copyright(C) 2006, Hans J. Koch <hjk@linutronix.de>
+ * Copyright(C) 2006, Hans J. Koch <hjk@hansjkoch.de>
  * Copyright(C) 2006, Greg Kroah-Hartman <greg@kroah.com>
  *
  * Userspace IO driver.
index 24300d8a1bc16eaf18c647056842102b47283980..a28eb25925778b3b156d9ccf8da5d3a593b97a3f 100644 (file)
@@ -313,6 +313,10 @@ struct usb_bus {
        int busnum;                     /* Bus number (in order of reg) */
        const char *bus_name;           /* stable id (PCI slot_name etc) */
        u8 uses_dma;                    /* Does the host controller use DMA? */
+       u8 uses_pio_for_control;        /*
+                                        * Does the host controller use PIO
+                                        * for control transfers?
+                                        */
        u8 otg_port;                    /* 0, or number of OTG/HNP port */
        unsigned is_b_host:1;           /* true during some HNP roleswitches */
        unsigned b_hnp_enable:1;        /* OTG: did A-Host enable HNP? */
index 38bffd8ccca58963f29ab33a77beb52b454f87eb..9c21cdf3e3b386e3090d1d4d57fe7860c6bb7be5 100644 (file)
@@ -59,6 +59,21 @@ struct via_port_cfg {
        u8                      ioport_index;
 };
 
+/*
+ * Allow subdevs to register suspend/resume hooks.
+ */
+#ifdef CONFIG_PM
+struct viafb_pm_hooks {
+       struct list_head list;
+       int (*suspend)(void *private);
+       int (*resume)(void *private);
+       void *private;
+};
+
+void viafb_pm_register(struct viafb_pm_hooks *hooks);
+void viafb_pm_unregister(struct viafb_pm_hooks *hooks);
+#endif /* CONFIG_PM */
+
 /*
  * This is the global viafb "device" containing stuff needed by
  * all subdevs.
index 2fb46bc9340d9b40617042ba8bb253754e4b6f67..ed5cdeb3604dbe6ea1fe807b33a69bf140d1622a 100644 (file)
@@ -23,6 +23,7 @@
 #ifndef _LINUX_VIDEO_OUTPUT_H
 #define _LINUX_VIDEO_OUTPUT_H
 #include <linux/device.h>
+#include <linux/err.h>
 struct output_device;
 struct output_properties {
        int (*set_state)(struct output_device *);
@@ -34,9 +35,23 @@ struct output_device {
        struct device dev;
 };
 #define to_output_device(obj) container_of(obj, struct output_device, dev)
+#if    defined(CONFIG_VIDEO_OUTPUT_CONTROL) || defined(CONFIG_VIDEO_OUTPUT_CONTROL_MODULE)
 struct output_device *video_output_register(const char *name,
        struct device *dev,
        void *devdata,
        struct output_properties *op);
 void video_output_unregister(struct output_device *dev);
+#else
+static struct output_device *video_output_register(const char *name,
+        struct device *dev,
+        void *devdata,
+        struct output_properties *op)
+{
+       return ERR_PTR(-ENODEV);
+}
+static void video_output_unregister(struct output_device *dev)
+{
+       return;
+}
+#endif
 #endif
index a03dcf62ca9d591d00290ced4394f7873b81329e..44b54f619ac6b29ef26b6bae7f7b10c05a536bc1 100644 (file)
@@ -7,8 +7,6 @@
 
 struct vm_area_struct;         /* vma defining user mapping in mm_types.h */
 
-extern bool vmap_lazy_unmap;
-
 /* bits in flags of vmalloc's vm_struct below */
 #define VM_IOREMAP     0x00000001      /* ioremap() and friends */
 #define VM_ALLOC       0x00000002      /* vmalloc() */
index 7a9f76ecbbbd8298339c5f88a92238af144e0a68..ac7ce00f39cff70a1fdd70e9b32dfb4c4a62c46f 100644 (file)
@@ -161,7 +161,7 @@ extern struct list_head saa7146_devices;
 extern struct mutex saa7146_devices_lock;
 int saa7146_register_extension(struct saa7146_extension*);
 int saa7146_unregister_extension(struct saa7146_extension*);
-struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc);
+struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fourcc);
 int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt);
 void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt);
 int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt, struct scatterlist *list, int length );
index 41dd480e45f105e78eecd7ba47bffc909d550186..239125af3ea3ae08ca0a09cf0d19c7aee2fe825e 100644 (file)
@@ -137,31 +137,27 @@ struct v4l2_subdev_ops;
 
 
 /* Load an i2c module and return an initialized v4l2_subdev struct.
-   Only call request_module if module_name != NULL.
    The client_type argument is the name of the chip that's on the adapter. */
 struct v4l2_subdev *v4l2_i2c_new_subdev_cfg(struct v4l2_device *v4l2_dev,
-               struct i2c_adapter *adapter,
-               const char *module_name, const char *client_type,
+               struct i2c_adapter *adapter, const char *client_type,
                int irq, void *platform_data,
                u8 addr, const unsigned short *probe_addrs);
 
 /* Load an i2c module and return an initialized v4l2_subdev struct.
-   Only call request_module if module_name != NULL.
    The client_type argument is the name of the chip that's on the adapter. */
 static inline struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev,
-               struct i2c_adapter *adapter,
-               const char *module_name, const char *client_type,
+               struct i2c_adapter *adapter, const char *client_type,
                u8 addr, const unsigned short *probe_addrs)
 {
-       return v4l2_i2c_new_subdev_cfg(v4l2_dev, adapter, module_name,
-                               client_type, 0, NULL, addr, probe_addrs);
+       return v4l2_i2c_new_subdev_cfg(v4l2_dev, adapter, client_type, 0, NULL,
+                                      addr, probe_addrs);
 }
 
 struct i2c_board_info;
 
 struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev,
-               struct i2c_adapter *adapter, const char *module_name,
-               struct i2c_board_info *info, const unsigned short *probe_addrs);
+               struct i2c_adapter *adapter, struct i2c_board_info *info,
+               const unsigned short *probe_addrs);
 
 /* Initialize an v4l2_subdev with data from an i2c_client struct */
 void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client,
index 6648036b728d7e32beb09fb91757931265780823..b16f307d471a2df59fd622cba1b338e42503ec16 100644 (file)
@@ -51,6 +51,8 @@ struct v4l2_device {
                        unsigned int notification, void *arg);
        /* The control handler. May be NULL. */
        struct v4l2_ctrl_handler *ctrl_handler;
+       /* BKL replacement mutex. Temporary solution only. */
+       struct mutex ioctl_lock;
 };
 
 /* Initialize v4l2_dev and make dev->driver_data point to v4l2_dev.
index 90c9e2872f27214b4727ecf4f440e4975be1f1df..18e5c3f675804eb6fbc84bb4aa0781944807c260 100644 (file)
@@ -10,6 +10,7 @@ extern void unix_inflight(struct file *fp);
 extern void unix_notinflight(struct file *fp);
 extern void unix_gc(void);
 extern void wait_for_unix_gc(void);
+extern struct sock *unix_get_socket(struct file *filp);
 
 #define UNIX_HASH_SIZE 256
 
@@ -56,6 +57,7 @@ struct unix_sock {
        spinlock_t              lock;
        unsigned int            gc_candidate : 1;
        unsigned int            gc_maybe_cycle : 1;
+       unsigned char           recursion_level;
        struct socket_wq        peer_wq;
 };
 #define unix_sk(__sk) ((struct unix_sock *)__sk)
index 2a7936d7851d55de60251fc708672a87d5beb81b..97b8b7c9b63cf9854e3b8c2e83154c8ecb0bea06 100644 (file)
@@ -1355,7 +1355,7 @@ enum wiphy_flags {
        WIPHY_FLAG_4ADDR_AP                     = BIT(5),
        WIPHY_FLAG_4ADDR_STATION                = BIT(6),
        WIPHY_FLAG_CONTROL_PORT_PROTOCOL        = BIT(7),
-       WIPHY_FLAG_IBSS_RSN                     = BIT(7),
+       WIPHY_FLAG_IBSS_RSN                     = BIT(8),
 };
 
 struct mac_address {
index 55590ab16b3ed5192413b4b6415a8785c1d1a5bb..6beb1ffc2b7fcfe9d360717ccde3f70bd8ac0e3d 100644 (file)
@@ -303,7 +303,7 @@ static inline void neigh_confirm(struct neighbour *neigh)
 
 static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
 {
-       unsigned long now = ACCESS_ONCE(jiffies);
+       unsigned long now = jiffies;
        
        if (neigh->used != now)
                neigh->used = now;
index a6338d039857bf6b00bcff087f974ebf46ae0875..659d968d95c54afe6df51c3289a0d2d6fb5b34ed 100644 (file)
@@ -1155,6 +1155,8 @@ extern void sk_common_release(struct sock *sk);
 /* Initialise core socket variables */
 extern void sock_init_data(struct socket *sock, struct sock *sk);
 
+extern void sk_filter_release_rcu(struct rcu_head *rcu);
+
 /**
  *     sk_filter_release - release a socket filter
  *     @fp: filter to remove
@@ -1165,7 +1167,7 @@ extern void sock_init_data(struct socket *sock, struct sock *sk);
 static inline void sk_filter_release(struct sk_filter *fp)
 {
        if (atomic_dec_and_test(&fp->refcnt))
-               kfree(fp);
+               call_rcu_bh(&fp->rcu, sk_filter_release_rcu);
 }
 
 static inline void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp)
index fa60cbda90a4553f69b9b1ce94e51fd7df9fa880..d79894192ae3e10cb5f072c51f2ed640c7ba76fd 100644 (file)
@@ -85,7 +85,9 @@
  *     ACK_MD (FSI2)
  *     CKG1   (FSI)
  *
- * err:  return value < 0
+ * err         : return value <  0
+ * no change   : return value == 0
+ * change xMD  : return value >  0
  *
  * 0x-00000AB
  *
 struct sh_fsi_platform_info {
        unsigned long porta_flags;
        unsigned long portb_flags;
-       int (*set_rate)(int is_porta, int rate); /* for master mode */
+       int (*set_rate)(struct device *dev, int is_porta, int rate, int enable);
 };
 
 #endif /* __SOUND_FSI_H */
index 6316cdabf73f5756a300ef501fe5a1aa11acef53..89d43b3d4cb9e3fe713fe5b8eaeb2de0616eb9fa 100644 (file)
@@ -99,7 +99,6 @@ struct lcd_sync_arg {
 #define FBIPUT_COLOR           _IOW('F', 6, int)
 #define FBIPUT_HSYNC           _IOW('F', 9, int)
 #define FBIPUT_VSYNC           _IOW('F', 10, int)
-#define FBIO_WAITFORVSYNC      _IOW('F', 0x20, u_int32_t)
 
 #endif  /* ifndef DA8XX_FB_H */
 
index f0736cff2ca3f15f2762634726f55a6f27af22e7..55f534491a3d1daac6f6c2ec9bc83ccc33082c38 100644 (file)
 #define S1DREG_DELAYOFF                        0xFFFE
 #define S1DREG_DELAYON                 0xFFFF
 
-#define BBLT_FIFO_EMPTY                        0x00
-#define BBLT_FIFO_NOT_EMPTY            0x40
-#define BBLT_FIFO_NOT_FULL             0x30
-#define BBLT_FIFO_HALF_FULL            0x20
-#define BBLT_FIFO_FULL                 0x10
-
 #define BBLT_SOLID_FILL                        0x0c
 
 
index 1e1aa54ab2e45bad0c1d6841572ba84ff0e912a3..b56932927d0a5e9ae92f7d43f8dd67c00c5991de 100644 (file)
@@ -13,6 +13,7 @@
 
 struct sh_mobile_lcdc_chan_cfg;
 struct device;
+struct clk;
 
 /*
  * flags format
@@ -33,6 +34,8 @@ struct sh_mobile_hdmi_info {
        struct sh_mobile_lcdc_chan_cfg  *lcd_chan;
        struct device                   *lcd_dev;
        unsigned int                     flags;
+       long (*clk_optimize_parent)(unsigned long target, unsigned long *best_freq,
+                                   unsigned long *parent_freq);
 };
 
 #endif
index 646dd17d3aa4263c1eb0a530a9057b2fa35383a2..00f53ddcc06284658d33ff80d66908e2b394d4ca 100644 (file)
@@ -76,7 +76,9 @@ int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name);
 
 #ifdef CONFIG_PCI_MSI
 /* Allocate an irq and a pirq to be used with MSIs. */
-void xen_allocate_pirq_msi(char *name, int *irq, int *pirq);
+#define XEN_ALLOC_PIRQ (1 << 0)
+#define XEN_ALLOC_IRQ  (1 << 1)
+void xen_allocate_pirq_msi(char *name, int *irq, int *pirq, int alloc_mask);
 int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type);
 #endif
 
@@ -89,4 +91,7 @@ int xen_vector_from_irq(unsigned pirq);
 /* Return gsi allocated to pirq */
 int xen_gsi_from_irq(unsigned pirq);
 
+/* Return irq from pirq */
+int xen_irq_from_pirq(unsigned pirq);
+
 #endif /* _XEN_EVENTS_H */
index e8cbf431c8ccfd33f76fd018e8dd64ea6dd2c8b7..75271b9a8f61bedcec5a18465b5a9ca8e84a38c7 100644 (file)
@@ -24,8 +24,15 @@ typedef unsigned int RING_IDX;
  * A ring contains as many entries as will fit, rounded down to the nearest
  * power of two (so we can mask with (size-1) to loop around).
  */
-#define __RING_SIZE(_s, _sz) \
-    (__RD32(((_sz) - (long)&(_s)->ring + (long)(_s)) / sizeof((_s)->ring[0])))
+#define __CONST_RING_SIZE(_s, _sz)                             \
+       (__RD32(((_sz) - offsetof(struct _s##_sring, ring)) /   \
+               sizeof(((struct _s##_sring *)0)->ring[0])))
+
+/*
+ * The same for passing in an actual pointer instead of a name tag.
+ */
+#define __RING_SIZE(_s, _sz)                                           \
+       (__RD32(((_sz) - (long)&(_s)->ring + (long)(_s)) / sizeof((_s)->ring[0])))
 
 /*
  * Macros to make the correct C datatypes for a new kind of ring.
index d7a6c13bde69cf505bef40027bcd555a4463d57f..eac3ce1537190228ba8dc74f0398d8e6e4795572 100644 (file)
@@ -140,6 +140,19 @@ struct xen_machphys_mfn_list {
 };
 DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mfn_list);
 
+/*
+ * Returns the location in virtual address space of the machine_to_phys
+ * mapping table. Architectures which do not have a m2p table, or which do not
+ * map it by default into guest address space, do not implement this command.
+ * arg == addr of xen_machphys_mapping_t.
+ */
+#define XENMEM_machphys_mapping     12
+struct xen_machphys_mapping {
+    unsigned long v_start, v_end; /* Start and end virtual addresses.   */
+    unsigned long max_mfn;        /* Maximum MFN that can be looked up. */
+};
+DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mapping_t);
+
 /*
  * Sets the GPFN at which a particular page appears in the specified guest's
  * pseudophysical address space.
index 2b2c66c3df0073e21535e3acdb5e54908b9ca116..534cac89a77deb20242aaf0b567c9a663c2db1d5 100644 (file)
@@ -188,6 +188,16 @@ struct physdev_nr_pirqs {
     uint32_t nr_pirqs;
 };
 
+/* type is MAP_PIRQ_TYPE_GSI or MAP_PIRQ_TYPE_MSI
+ * the hypercall returns a free pirq */
+#define PHYSDEVOP_get_free_pirq    23
+struct physdev_get_free_pirq {
+    /* IN */ 
+    int type;
+    /* OUT */
+    uint32_t pirq;
+};
+
 /*
  * Notify that some PIRQ-bound event channels have been unmasked.
  * ** This command is obsolete since interface version 0x00030202 and is **
index eaf85fab12632d45cc00d8976d9108a3eacc2850..0be36b976f4b02905034532919e7fc576eba19d7 100644 (file)
@@ -1 +1,8 @@
+#ifndef _XEN_PAGE_H
+#define _XEN_PAGE_H
+
 #include <asm/xen/page.h>
+
+extern phys_addr_t xen_extra_mem_start, xen_extra_mem_size;
+
+#endif /* _XEN_PAGE_H */
index b42cdfd92fee5becfa065aeaeec36b743b9664e8..17857fb4d5509b24a475609e2806af53c79d5317 100644 (file)
 #define __LINUX_PUBLIC_PRIVCMD_H__
 
 #include <linux/types.h>
+#include <linux/compiler.h>
 
 typedef unsigned long xen_pfn_t;
 
-#ifndef __user
-#define __user
-#endif
-
 struct privcmd_hypercall {
        __u64 op;
        __u64 arg[5];
index 88c10468db467bb862554aab55f5d4891e4b0f03..c9728992a776356e043d21df7b33aa045c2d7904 100644 (file)
@@ -613,6 +613,19 @@ config CGROUP_MEM_RES_CTLR_SWAP
          if boot option "noswapaccount" is set, swap will not be accounted.
          Now, memory usage of swap_cgroup is 2 bytes per entry. If swap page
          size is 4096bytes, 512k per 1Gbytes of swap.
+config CGROUP_MEM_RES_CTLR_SWAP_ENABLED
+       bool "Memory Resource Controller Swap Extension enabled by default"
+       depends on CGROUP_MEM_RES_CTLR_SWAP
+       default y
+       help
+         Memory Resource Controller Swap Extension comes with its price in
+         a bigger memory consumption. General purpose distribution kernels
+         which want to enable the feautre but keep it disabled by default
+         and let the user enable it by swapaccount boot command line
+         parameter should have this option unselected.
+         For those who want to have the feature enabled by default should
+         select this option (if, for some reason, they need to disable it
+         then noswapaccount does the trick).
 
 menuconfig CGROUP_SCHED
        bool "Group CPU scheduler"
index 37755d621924e5256b3494d5e94b57415be5a3f1..a6e729766821307c7440fd4d321d3decdc3182d6 100644 (file)
@@ -82,7 +82,7 @@ static kdbtab_t kdb_base_commands[50];
 #define for_each_kdbcmd(cmd, num)                                      \
        for ((cmd) = kdb_base_commands, (num) = 0;                      \
             num < kdb_max_commands;                                    \
-            num == KDB_BASE_CMD_MAX ? cmd = kdb_commands : cmd++, num++)
+            num++, num == KDB_BASE_CMD_MAX ? cmd = kdb_commands : cmd++)
 
 typedef struct _kdbmsg {
        int     km_diag;        /* kdb diagnostic */
@@ -646,7 +646,7 @@ static int kdb_defcmd2(const char *cmdstr, const char *argv0)
        }
        if (!s->usable)
                return KDB_NOTIMP;
-       s->command = kmalloc((s->count + 1) * sizeof(*(s->command)), GFP_KDB);
+       s->command = kzalloc((s->count + 1) * sizeof(*(s->command)), GFP_KDB);
        if (!s->command) {
                kdb_printf("Could not allocate new kdb_defcmd table for %s\n",
                           cmdstr);
@@ -2361,7 +2361,7 @@ static int kdb_pid(int argc, const char **argv)
  */
 static int kdb_ll(int argc, const char **argv)
 {
-       int diag;
+       int diag = 0;
        unsigned long addr;
        long offset = 0;
        unsigned long va;
@@ -2400,20 +2400,21 @@ static int kdb_ll(int argc, const char **argv)
                char buf[80];
 
                if (KDB_FLAG(CMD_INTERRUPT))
-                       return 0;
+                       goto out;
 
                sprintf(buf, "%s " kdb_machreg_fmt "\n", command, va);
                diag = kdb_parse(buf);
                if (diag)
-                       return diag;
+                       goto out;
 
                addr = va + linkoffset;
                if (kdb_getword(&va, addr, sizeof(va)))
-                       return 0;
+                       goto out;
        }
-       kfree(command);
 
-       return 0;
+out:
+       kfree(command);
+       return diag;
 }
 
 static int kdb_kgdb(int argc, const char **argv)
@@ -2739,13 +2740,13 @@ int kdb_register_repeat(char *cmd,
                }
                if (kdb_commands) {
                        memcpy(new, kdb_commands,
-                              kdb_max_commands * sizeof(*new));
+                         (kdb_max_commands - KDB_BASE_CMD_MAX) * sizeof(*new));
                        kfree(kdb_commands);
                }
                memset(new + kdb_max_commands, 0,
                       kdb_command_extend * sizeof(*new));
                kdb_commands = new;
-               kp = kdb_commands + kdb_max_commands;
+               kp = kdb_commands + kdb_max_commands - KDB_BASE_CMD_MAX;
                kdb_max_commands += kdb_command_extend;
        }
 
index 21aa7b3001fb49edce43446dd85898f62ab33d98..676149a4ac5ff497367a484e2b66c01e915ccefd 100644 (file)
@@ -914,6 +914,15 @@ NORET_TYPE void do_exit(long code)
        if (unlikely(!tsk->pid))
                panic("Attempted to kill the idle task!");
 
+       /*
+        * If do_exit is called because this processes oopsed, it's possible
+        * that get_fs() was left as KERNEL_DS, so reset it to USER_DS before
+        * continuing. Amongst other possible reasons, this is to prevent
+        * mm_release()->clear_child_tid() from writing to a user-controlled
+        * kernel address.
+        */
+       set_fs(USER_DS);
+
        tracehook_report_exit(&code);
 
        validate_creds_for_do_exit(tsk);
index 3b159c5991b7561bdba253eeb479f91622a35fb9..5447dc7defa95b8f0e13acb80b45487df7dc2e73 100644 (file)
@@ -273,6 +273,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
 
        setup_thread_stack(tsk, orig);
        clear_user_return_notifier(tsk);
+       clear_tsk_need_resched(tsk);
        stackend = end_of_stack(tsk);
        *stackend = STACK_END_MAGIC;    /* for overflow detection */
 
index 2c9120f0afca9872cc4edba57d4e5cfe9311788f..e5325825aeb6e1e4ea0514ee37cfa53412ec4e3c 100644 (file)
@@ -620,7 +620,7 @@ static struct pmu perf_breakpoint = {
        .read           = hw_breakpoint_pmu_read,
 };
 
-static int __init init_hw_breakpoint(void)
+int __init init_hw_breakpoint(void)
 {
        unsigned int **task_bp_pinned;
        int cpu, err_cpu;
@@ -655,6 +655,5 @@ static int __init init_hw_breakpoint(void)
 
        return -ENOMEM;
 }
-core_initcall(init_hw_breakpoint);
 
 
index 01b1d3a88983f92c189e0c9b27f23ffe0e73f88f..6c8a2a9f8a7bf802f72527831e0f5f32b773e964 100644 (file)
@@ -214,7 +214,7 @@ static int irq_spurious_proc_show(struct seq_file *m, void *v)
 
 static int irq_spurious_proc_open(struct inode *inode, struct file *file)
 {
-       return single_open(file, irq_spurious_proc_show, NULL);
+       return single_open(file, irq_spurious_proc_show, PDE(inode)->data);
 }
 
 static const struct file_operations irq_spurious_proc_fops = {
index f16763ff8481b727bdf0263c241ddf2e1d6ba09a..90f881904bb1202ba1566f5db2e28eaf128551b9 100644 (file)
@@ -145,7 +145,9 @@ void irq_work_run(void)
                 * Clear the BUSY bit and return to the free state if
                 * no-one else claimed it meanwhile.
                 */
-               cmpxchg(&entry->next, next_flags(NULL, IRQ_WORK_BUSY), NULL);
+               (void)cmpxchg(&entry->next,
+                             next_flags(NULL, IRQ_WORK_BUSY),
+                             NULL);
        }
 }
 EXPORT_SYMBOL_GPL(irq_work_run);
index a8db2570f99a9cb094daa2e773fc74e6e23d25bb..6f6d091b57573bf37fc98fdcb2df91c08787543d 100644 (file)
@@ -546,7 +546,7 @@ static const struct file_operations kallsyms_operations = {
 
 static int __init kallsyms_init(void)
 {
-       proc_create("kallsyms", 0400, NULL, &kallsyms_operations);
+       proc_create("kallsyms", 0444, NULL, &kallsyms_operations);
        return 0;
 }
 device_initcall(kallsyms_init);
index 437a74a7524a7f592f669dbdc91a6c90503959ae..d190664f25ff3fa10dca29f37b483f08ad07eae1 100644 (file)
@@ -2326,6 +2326,18 @@ static void find_module_sections(struct module *mod, struct load_info *info)
        kmemleak_scan_area(mod->trace_events, sizeof(*mod->trace_events) *
                           mod->num_trace_events, GFP_KERNEL);
 #endif
+#ifdef CONFIG_TRACING
+       mod->trace_bprintk_fmt_start = section_objs(info, "__trace_printk_fmt",
+                                        sizeof(*mod->trace_bprintk_fmt_start),
+                                        &mod->num_trace_bprintk_fmt);
+       /*
+        * This section contains pointers to allocated objects in the trace
+        * code and not scanning it leads to false positives.
+        */
+       kmemleak_scan_area(mod->trace_bprintk_fmt_start,
+                          sizeof(*mod->trace_bprintk_fmt_start) *
+                          mod->num_trace_bprintk_fmt, GFP_KERNEL);
+#endif
 #ifdef CONFIG_FTRACE_MCOUNT_RECORD
        /* sechdrs[0].sh_size is always zero */
        mod->ftrace_callsites = section_objs(info, "__mcount_loc",
index cb6c0d2af68f64b16bd0557f3c7fb7001151b71d..2870feee81dd7a046703645c9ec50022d4339f39 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/perf_event.h>
 #include <linux/ftrace_event.h>
+#include <linux/hw_breakpoint.h>
 
 #include <asm/irq_regs.h>
 
@@ -1286,8 +1287,6 @@ void __perf_event_task_sched_out(struct task_struct *task,
 {
        int ctxn;
 
-       perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 1, NULL, 0);
-
        for_each_task_context_nr(ctxn)
                perf_event_context_sched_out(task, ctxn, next);
 }
@@ -1621,8 +1620,12 @@ static void rotate_ctx(struct perf_event_context *ctx)
 {
        raw_spin_lock(&ctx->lock);
 
-       /* Rotate the first entry last of non-pinned groups */
-       list_rotate_left(&ctx->flexible_groups);
+       /*
+        * Rotate the first entry last of non-pinned groups. Rotation might be
+        * disabled by the inheritance code.
+        */
+       if (!ctx->rotate_disable)
+               list_rotate_left(&ctx->flexible_groups);
 
        raw_spin_unlock(&ctx->lock);
 }
@@ -2234,11 +2237,6 @@ int perf_event_release_kernel(struct perf_event *event)
        raw_spin_unlock_irq(&ctx->lock);
        mutex_unlock(&ctx->mutex);
 
-       mutex_lock(&event->owner->perf_event_mutex);
-       list_del_init(&event->owner_entry);
-       mutex_unlock(&event->owner->perf_event_mutex);
-       put_task_struct(event->owner);
-
        free_event(event);
 
        return 0;
@@ -2251,9 +2249,43 @@ EXPORT_SYMBOL_GPL(perf_event_release_kernel);
 static int perf_release(struct inode *inode, struct file *file)
 {
        struct perf_event *event = file->private_data;
+       struct task_struct *owner;
 
        file->private_data = NULL;
 
+       rcu_read_lock();
+       owner = ACCESS_ONCE(event->owner);
+       /*
+        * Matches the smp_wmb() in perf_event_exit_task(). If we observe
+        * !owner it means the list deletion is complete and we can indeed
+        * free this event, otherwise we need to serialize on
+        * owner->perf_event_mutex.
+        */
+       smp_read_barrier_depends();
+       if (owner) {
+               /*
+                * Since delayed_put_task_struct() also drops the last
+                * task reference we can safely take a new reference
+                * while holding the rcu_read_lock().
+                */
+               get_task_struct(owner);
+       }
+       rcu_read_unlock();
+
+       if (owner) {
+               mutex_lock(&owner->perf_event_mutex);
+               /*
+                * We have to re-check the event->owner field, if it is cleared
+                * we raced with perf_event_exit_task(), acquiring the mutex
+                * ensured they're done, and we can proceed with freeing the
+                * event.
+                */
+               if (event->owner)
+                       list_del_init(&event->owner_entry);
+               mutex_unlock(&owner->perf_event_mutex);
+               put_task_struct(owner);
+       }
+
        return perf_event_release_kernel(event);
 }
 
@@ -3792,6 +3824,8 @@ static void perf_event_task_event(struct perf_task_event *task_event)
        rcu_read_lock();
        list_for_each_entry_rcu(pmu, &pmus, entry) {
                cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
+               if (cpuctx->active_pmu != pmu)
+                       goto next;
                perf_event_task_ctx(&cpuctx->ctx, task_event);
 
                ctx = task_event->task_ctx;
@@ -3927,6 +3961,8 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event)
        rcu_read_lock();
        list_for_each_entry_rcu(pmu, &pmus, entry) {
                cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
+               if (cpuctx->active_pmu != pmu)
+                       goto next;
                perf_event_comm_ctx(&cpuctx->ctx, comm_event);
 
                ctxn = pmu->task_ctx_nr;
@@ -4112,6 +4148,8 @@ got_name:
        rcu_read_lock();
        list_for_each_entry_rcu(pmu, &pmus, entry) {
                cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
+               if (cpuctx->active_pmu != pmu)
+                       goto next;
                perf_event_mmap_ctx(&cpuctx->ctx, mmap_event,
                                        vma->vm_flags & VM_EXEC);
 
@@ -4681,7 +4719,7 @@ static int perf_swevent_init(struct perf_event *event)
                break;
        }
 
-       if (event_id > PERF_COUNT_SW_MAX)
+       if (event_id >= PERF_COUNT_SW_MAX)
                return -ENOENT;
 
        if (!event->parent) {
@@ -5113,20 +5151,36 @@ static void *find_pmu_context(int ctxn)
        return NULL;
 }
 
-static void free_pmu_context(void * __percpu cpu_context)
+static void update_pmu_context(struct pmu *pmu, struct pmu *old_pmu)
 {
-       struct pmu *pmu;
+       int cpu;
+
+       for_each_possible_cpu(cpu) {
+               struct perf_cpu_context *cpuctx;
+
+               cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu);
+
+               if (cpuctx->active_pmu == old_pmu)
+                       cpuctx->active_pmu = pmu;
+       }
+}
+
+static void free_pmu_context(struct pmu *pmu)
+{
+       struct pmu *i;
 
        mutex_lock(&pmus_lock);
        /*
         * Like a real lame refcount.
         */
-       list_for_each_entry(pmu, &pmus, entry) {
-               if (pmu->pmu_cpu_context == cpu_context)
+       list_for_each_entry(i, &pmus, entry) {
+               if (i->pmu_cpu_context == pmu->pmu_cpu_context) {
+                       update_pmu_context(i, pmu);
                        goto out;
+               }
        }
 
-       free_percpu(cpu_context);
+       free_percpu(pmu->pmu_cpu_context);
 out:
        mutex_unlock(&pmus_lock);
 }
@@ -5158,6 +5212,7 @@ int perf_pmu_register(struct pmu *pmu)
                cpuctx->ctx.pmu = pmu;
                cpuctx->jiffies_interval = 1;
                INIT_LIST_HEAD(&cpuctx->rotation_list);
+               cpuctx->active_pmu = pmu;
        }
 
 got_cpu_context:
@@ -5209,7 +5264,7 @@ void perf_pmu_unregister(struct pmu *pmu)
        synchronize_rcu();
 
        free_percpu(pmu->pmu_disable_count);
-       free_pmu_context(pmu->pmu_cpu_context);
+       free_pmu_context(pmu);
 }
 
 struct pmu *perf_init_event(struct perf_event *event)
@@ -5677,7 +5732,7 @@ SYSCALL_DEFINE5(perf_event_open,
        mutex_unlock(&ctx->mutex);
 
        event->owner = current;
-       get_task_struct(current);
+
        mutex_lock(&current->perf_event_mutex);
        list_add_tail(&event->owner_entry, &current->perf_event_list);
        mutex_unlock(&current->perf_event_mutex);
@@ -5745,12 +5800,6 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
        ++ctx->generation;
        mutex_unlock(&ctx->mutex);
 
-       event->owner = current;
-       get_task_struct(current);
-       mutex_lock(&current->perf_event_mutex);
-       list_add_tail(&event->owner_entry, &current->perf_event_list);
-       mutex_unlock(&current->perf_event_mutex);
-
        return event;
 
 err_free:
@@ -5901,8 +5950,24 @@ again:
  */
 void perf_event_exit_task(struct task_struct *child)
 {
+       struct perf_event *event, *tmp;
        int ctxn;
 
+       mutex_lock(&child->perf_event_mutex);
+       list_for_each_entry_safe(event, tmp, &child->perf_event_list,
+                                owner_entry) {
+               list_del_init(&event->owner_entry);
+
+               /*
+                * Ensure the list deletion is visible before we clear
+                * the owner, closes a race against perf_release() where
+                * we need to serialize on the owner->perf_event_mutex.
+                */
+               smp_wmb();
+               event->owner = NULL;
+       }
+       mutex_unlock(&child->perf_event_mutex);
+
        for_each_task_context_nr(ctxn)
                perf_event_exit_task_context(child, ctxn);
 }
@@ -6122,6 +6187,7 @@ int perf_event_init_context(struct task_struct *child, int ctxn)
        struct perf_event *event;
        struct task_struct *parent = current;
        int inherited_all = 1;
+       unsigned long flags;
        int ret = 0;
 
        child->perf_event_ctxp[ctxn] = NULL;
@@ -6162,6 +6228,15 @@ int perf_event_init_context(struct task_struct *child, int ctxn)
                        break;
        }
 
+       /*
+        * We can't hold ctx->lock when iterating the ->flexible_group list due
+        * to allocations, but we need to prevent rotation because
+        * rotate_ctx() will change the list from interrupt context.
+        */
+       raw_spin_lock_irqsave(&parent_ctx->lock, flags);
+       parent_ctx->rotate_disable = 1;
+       raw_spin_unlock_irqrestore(&parent_ctx->lock, flags);
+
        list_for_each_entry(event, &parent_ctx->flexible_groups, group_entry) {
                ret = inherit_task_group(event, parent, parent_ctx,
                                         child, ctxn, &inherited_all);
@@ -6169,6 +6244,10 @@ int perf_event_init_context(struct task_struct *child, int ctxn)
                        break;
        }
 
+       raw_spin_lock_irqsave(&parent_ctx->lock, flags);
+       parent_ctx->rotate_disable = 0;
+       raw_spin_unlock_irqrestore(&parent_ctx->lock, flags);
+
        child_ctx = child->perf_event_ctxp[ctxn];
 
        if (child_ctx && inherited_all) {
@@ -6321,6 +6400,8 @@ perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu)
 
 void __init perf_event_init(void)
 {
+       int ret;
+
        perf_event_init_all_cpus();
        init_srcu_struct(&pmus_srcu);
        perf_pmu_register(&perf_swevent);
@@ -6328,4 +6409,7 @@ void __init perf_event_init(void)
        perf_pmu_register(&perf_task_clock);
        perf_tp_register();
        perf_cpu_notifier(perf_cpu_notify);
+
+       ret = init_hw_breakpoint();
+       WARN(ret, "hw_breakpoint initialization failed with: %d", ret);
 }
index 6842eeba58798276d61b469072e50e0d6116bbac..05bb7173850e065a0899821d8e41c922d3548c07 100644 (file)
@@ -37,13 +37,13 @@ static int check_clock(const clockid_t which_clock)
        if (pid == 0)
                return 0;
 
-       read_lock(&tasklist_lock);
+       rcu_read_lock();
        p = find_task_by_vpid(pid);
        if (!p || !(CPUCLOCK_PERTHREAD(which_clock) ?
-                  same_thread_group(p, current) : thread_group_leader(p))) {
+                  same_thread_group(p, current) : has_group_leader_pid(p))) {
                error = -EINVAL;
        }
-       read_unlock(&tasklist_lock);
+       rcu_read_unlock();
 
        return error;
 }
@@ -390,7 +390,7 @@ int posix_cpu_timer_create(struct k_itimer *new_timer)
 
        INIT_LIST_HEAD(&new_timer->it.cpu.entry);
 
-       read_lock(&tasklist_lock);
+       rcu_read_lock();
        if (CPUCLOCK_PERTHREAD(new_timer->it_clock)) {
                if (pid == 0) {
                        p = current;
@@ -404,7 +404,7 @@ int posix_cpu_timer_create(struct k_itimer *new_timer)
                        p = current->group_leader;
                } else {
                        p = find_task_by_vpid(pid);
-                       if (p && !thread_group_leader(p))
+                       if (p && !has_group_leader_pid(p))
                                p = NULL;
                }
        }
@@ -414,7 +414,7 @@ int posix_cpu_timer_create(struct k_itimer *new_timer)
        } else {
                ret = -EINVAL;
        }
-       read_unlock(&tasklist_lock);
+       rcu_read_unlock();
 
        return ret;
 }
index 657272e91d0a0af648a892fd64ca2111a100dfb4..048d0b5148319db70883ee0c9963459c22048385 100644 (file)
@@ -327,7 +327,6 @@ static int create_image(int platform_mode)
 int hibernation_snapshot(int platform_mode)
 {
        int error;
-       gfp_t saved_mask;
 
        error = platform_begin(platform_mode);
        if (error)
@@ -339,7 +338,7 @@ int hibernation_snapshot(int platform_mode)
                goto Close;
 
        suspend_console();
-       saved_mask = clear_gfp_allowed_mask(GFP_IOFS);
+       pm_restrict_gfp_mask();
        error = dpm_suspend_start(PMSG_FREEZE);
        if (error)
                goto Recover_platform;
@@ -348,7 +347,10 @@ int hibernation_snapshot(int platform_mode)
                goto Recover_platform;
 
        error = create_image(platform_mode);
-       /* Control returns here after successful restore */
+       /*
+        * Control returns here (1) after the image has been created or the
+        * image creation has failed and (2) after a successful restore.
+        */
 
  Resume_devices:
        /* We may need to release the preallocated image pages here. */
@@ -357,7 +359,10 @@ int hibernation_snapshot(int platform_mode)
 
        dpm_resume_end(in_suspend ?
                (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
-       set_gfp_allowed_mask(saved_mask);
+
+       if (error || !in_suspend)
+               pm_restore_gfp_mask();
+
        resume_console();
  Close:
        platform_end(platform_mode);
@@ -452,17 +457,16 @@ static int resume_target_kernel(bool platform_mode)
 int hibernation_restore(int platform_mode)
 {
        int error;
-       gfp_t saved_mask;
 
        pm_prepare_console();
        suspend_console();
-       saved_mask = clear_gfp_allowed_mask(GFP_IOFS);
+       pm_restrict_gfp_mask();
        error = dpm_suspend_start(PMSG_QUIESCE);
        if (!error) {
                error = resume_target_kernel(platform_mode);
                dpm_resume_end(PMSG_RECOVER);
        }
-       set_gfp_allowed_mask(saved_mask);
+       pm_restore_gfp_mask();
        resume_console();
        pm_restore_console();
        return error;
@@ -476,7 +480,6 @@ int hibernation_restore(int platform_mode)
 int hibernation_platform_enter(void)
 {
        int error;
-       gfp_t saved_mask;
 
        if (!hibernation_ops)
                return -ENOSYS;
@@ -492,7 +495,6 @@ int hibernation_platform_enter(void)
 
        entering_platform_hibernation = true;
        suspend_console();
-       saved_mask = clear_gfp_allowed_mask(GFP_IOFS);
        error = dpm_suspend_start(PMSG_HIBERNATE);
        if (error) {
                if (hibernation_ops->recover)
@@ -536,7 +538,6 @@ int hibernation_platform_enter(void)
  Resume_devices:
        entering_platform_hibernation = false;
        dpm_resume_end(PMSG_RESTORE);
-       set_gfp_allowed_mask(saved_mask);
        resume_console();
 
  Close:
@@ -646,6 +647,7 @@ int hibernate(void)
                swsusp_free();
                if (!error)
                        power_down();
+               pm_restore_gfp_mask();
        } else {
                pr_debug("PM: Image restored successfully.\n");
        }
index 7335952ee473956e6a1e7b57f3d397220e6c5536..ecf770509d0d1bb9dce2381716d6e7583ee6c492 100644 (file)
@@ -197,7 +197,6 @@ static int suspend_enter(suspend_state_t state)
 int suspend_devices_and_enter(suspend_state_t state)
 {
        int error;
-       gfp_t saved_mask;
 
        if (!suspend_ops)
                return -ENOSYS;
@@ -208,7 +207,7 @@ int suspend_devices_and_enter(suspend_state_t state)
                        goto Close;
        }
        suspend_console();
-       saved_mask = clear_gfp_allowed_mask(GFP_IOFS);
+       pm_restrict_gfp_mask();
        suspend_test_start();
        error = dpm_suspend_start(PMSG_SUSPEND);
        if (error) {
@@ -225,7 +224,7 @@ int suspend_devices_and_enter(suspend_state_t state)
        suspend_test_start();
        dpm_resume_end(PMSG_RESUME);
        suspend_test_finish("resume devices");
-       set_gfp_allowed_mask(saved_mask);
+       pm_restore_gfp_mask();
        resume_console();
  Close:
        if (suspend_ops->end)
index a0e4a86ccf94887a6f64ae985db131608def8952..8c7e4832b9be0f8e031fb07645f6ad8e955c0318 100644 (file)
@@ -6,6 +6,7 @@
  *
  * Copyright (C) 1998,2001-2005 Pavel Machek <pavel@ucw.cz>
  * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
+ * Copyright (C) 2010 Bojan Smojver <bojan@rexursive.com>
  *
  * This file is released under the GPLv2.
  *
@@ -29,7 +30,7 @@
 
 #include "power.h"
 
-#define HIBERNATE_SIG  "LINHIB0001"
+#define HIBERNATE_SIG  "S1SUSPEND"
 
 /*
  *     The swap map is a data structure used for keeping track of each page
@@ -753,30 +754,43 @@ static int load_image_lzo(struct swap_map_handle *handle,
 {
        unsigned int m;
        int error = 0;
+       struct bio *bio;
        struct timeval start;
        struct timeval stop;
        unsigned nr_pages;
-       size_t off, unc_len, cmp_len;
-       unsigned char *unc, *cmp, *page;
+       size_t i, off, unc_len, cmp_len;
+       unsigned char *unc, *cmp, *page[LZO_CMP_PAGES];
 
-       page = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
-       if (!page) {
-               printk(KERN_ERR "PM: Failed to allocate LZO page\n");
-               return -ENOMEM;
+       for (i = 0; i < LZO_CMP_PAGES; i++) {
+               page[i] = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
+               if (!page[i]) {
+                       printk(KERN_ERR "PM: Failed to allocate LZO page\n");
+
+                       while (i)
+                               free_page((unsigned long)page[--i]);
+
+                       return -ENOMEM;
+               }
        }
 
        unc = vmalloc(LZO_UNC_SIZE);
        if (!unc) {
                printk(KERN_ERR "PM: Failed to allocate LZO uncompressed\n");
-               free_page((unsigned long)page);
+
+               for (i = 0; i < LZO_CMP_PAGES; i++)
+                       free_page((unsigned long)page[i]);
+
                return -ENOMEM;
        }
 
        cmp = vmalloc(LZO_CMP_SIZE);
        if (!cmp) {
                printk(KERN_ERR "PM: Failed to allocate LZO compressed\n");
+
                vfree(unc);
-               free_page((unsigned long)page);
+               for (i = 0; i < LZO_CMP_PAGES; i++)
+                       free_page((unsigned long)page[i]);
+
                return -ENOMEM;
        }
 
@@ -787,6 +801,7 @@ static int load_image_lzo(struct swap_map_handle *handle,
        if (!m)
                m = 1;
        nr_pages = 0;
+       bio = NULL;
        do_gettimeofday(&start);
 
        error = snapshot_write_next(snapshot);
@@ -794,11 +809,11 @@ static int load_image_lzo(struct swap_map_handle *handle,
                goto out_finish;
 
        for (;;) {
-               error = swap_read_page(handle, page, NULL); /* sync */
+               error = swap_read_page(handle, page[0], NULL); /* sync */
                if (error)
                        break;
 
-               cmp_len = *(size_t *)page;
+               cmp_len = *(size_t *)page[0];
                if (unlikely(!cmp_len ||
                             cmp_len > lzo1x_worst_compress(LZO_UNC_SIZE))) {
                        printk(KERN_ERR "PM: Invalid LZO compressed length\n");
@@ -806,13 +821,20 @@ static int load_image_lzo(struct swap_map_handle *handle,
                        break;
                }
 
-               memcpy(cmp, page, PAGE_SIZE);
-               for (off = PAGE_SIZE; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
-                       error = swap_read_page(handle, page, NULL); /* sync */
+               for (off = PAGE_SIZE, i = 1;
+                    off < LZO_HEADER + cmp_len; off += PAGE_SIZE, i++) {
+                       error = swap_read_page(handle, page[i], &bio);
                        if (error)
                                goto out_finish;
+               }
 
-                       memcpy(cmp + off, page, PAGE_SIZE);
+               error = hib_wait_on_bio_chain(&bio); /* need all data now */
+               if (error)
+                       goto out_finish;
+
+               for (off = 0, i = 0;
+                    off < LZO_HEADER + cmp_len; off += PAGE_SIZE, i++) {
+                       memcpy(cmp + off, page[i], PAGE_SIZE);
                }
 
                unc_len = LZO_UNC_SIZE;
@@ -857,7 +879,8 @@ out_finish:
 
        vfree(cmp);
        vfree(unc);
-       free_page((unsigned long)page);
+       for (i = 0; i < LZO_CMP_PAGES; i++)
+               free_page((unsigned long)page[i]);
 
        return error;
 }
index e819e17877ca9cd2540440a67919b2b019222976..c36c3b9e8a84f59ad5894a1e2d04c7252b656ebe 100644 (file)
@@ -137,7 +137,7 @@ static int snapshot_release(struct inode *inode, struct file *filp)
        free_all_swap_pages(data->swap);
        if (data->frozen)
                thaw_processes();
-       pm_notifier_call_chain(data->mode == O_WRONLY ?
+       pm_notifier_call_chain(data->mode == O_RDONLY ?
                        PM_POST_HIBERNATION : PM_POST_RESTORE);
        atomic_inc(&snapshot_device_available);
 
@@ -263,6 +263,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
        case SNAPSHOT_UNFREEZE:
                if (!data->frozen || data->ready)
                        break;
+               pm_restore_gfp_mask();
                thaw_processes();
                usermodehelper_enable();
                data->frozen = 0;
@@ -275,6 +276,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
                        error = -EPERM;
                        break;
                }
+               pm_restore_gfp_mask();
                error = hibernation_snapshot(data->platform_support);
                if (!error)
                        error = put_user(in_suspend, (int __user *)arg);
index 9a2264fc42cafac30d9264d569e4e673e9617f19..a23315dc4498844c113cecc9792eabd063e1d87b 100644 (file)
@@ -1082,13 +1082,15 @@ void printk_tick(void)
 
 int printk_needs_cpu(int cpu)
 {
+       if (unlikely(cpu_is_offline(cpu)))
+               printk_tick();
        return per_cpu(printk_pending, cpu);
 }
 
 void wake_up_klogd(void)
 {
        if (waitqueue_active(&log_wait))
-               __raw_get_cpu_var(printk_pending) = 1;
+               this_cpu_write(printk_pending, 1);
 }
 
 /**
index 9fad33efd0db50b3269572f598a1ce418731153c..798e2fae2a069645c13853f4b658dada92af8f66 100644 (file)
@@ -40,23 +40,6 @@ EXPORT_SYMBOL(iomem_resource);
 
 static DEFINE_RWLOCK(resource_lock);
 
-/*
- * By default, we allocate free space bottom-up.  The architecture can request
- * top-down by clearing this flag.  The user can override the architecture's
- * choice with the "resource_alloc_from_bottom" kernel boot option, but that
- * should only be a debugging tool.
- */
-int resource_alloc_from_bottom = 1;
-
-static __init int setup_alloc_from_bottom(char *s)
-{
-       printk(KERN_INFO
-              "resource: allocating from bottom-up; please report a bug\n");
-       resource_alloc_from_bottom = 1;
-       return 0;
-}
-early_param("resource_alloc_from_bottom", setup_alloc_from_bottom);
-
 static void *r_next(struct seq_file *m, void *v, loff_t *pos)
 {
        struct resource *p = v;
@@ -374,6 +357,10 @@ int __weak page_is_ram(unsigned long pfn)
        return walk_system_ram_range(pfn, 1, NULL, __is_ram) == 1;
 }
 
+void __weak arch_remove_reservations(struct resource *avail)
+{
+}
+
 static resource_size_t simple_align_resource(void *data,
                                             const struct resource *avail,
                                             resource_size_t size,
@@ -396,75 +383,8 @@ static bool resource_contains(struct resource *res1, struct resource *res2)
        return res1->start <= res2->start && res1->end >= res2->end;
 }
 
-/*
- * Find the resource before "child" in the sibling list of "root" children.
- */
-static struct resource *find_sibling_prev(struct resource *root, struct resource *child)
-{
-       struct resource *this;
-
-       for (this = root->child; this; this = this->sibling)
-               if (this->sibling == child)
-                       return this;
-
-       return NULL;
-}
-
 /*
  * Find empty slot in the resource tree given range and alignment.
- * This version allocates from the end of the root resource first.
- */
-static int find_resource_from_top(struct resource *root, struct resource *new,
-                                 resource_size_t size, resource_size_t min,
-                                 resource_size_t max, resource_size_t align,
-                                 resource_size_t (*alignf)(void *,
-                                                  const struct resource *,
-                                                  resource_size_t,
-                                                  resource_size_t),
-                                 void *alignf_data)
-{
-       struct resource *this;
-       struct resource tmp, avail, alloc;
-
-       tmp.start = root->end;
-       tmp.end = root->end;
-
-       this = find_sibling_prev(root, NULL);
-       for (;;) {
-               if (this) {
-                       if (this->end < root->end)
-                               tmp.start = this->end + 1;
-               } else
-                       tmp.start = root->start;
-
-               resource_clip(&tmp, min, max);
-
-               /* Check for overflow after ALIGN() */
-               avail = *new;
-               avail.start = ALIGN(tmp.start, align);
-               avail.end = tmp.end;
-               if (avail.start >= tmp.start) {
-                       alloc.start = alignf(alignf_data, &avail, size, align);
-                       alloc.end = alloc.start + size - 1;
-                       if (resource_contains(&avail, &alloc)) {
-                               new->start = alloc.start;
-                               new->end = alloc.end;
-                               return 0;
-                       }
-               }
-
-               if (!this || this->start == root->start)
-                       break;
-
-               tmp.end = this->start - 1;
-               this = find_sibling_prev(root, this);
-       }
-       return -EBUSY;
-}
-
-/*
- * Find empty slot in the resource tree given range and alignment.
- * This version allocates from the beginning of the root resource first.
  */
 static int find_resource(struct resource *root, struct resource *new,
                         resource_size_t size, resource_size_t min,
@@ -478,23 +398,24 @@ static int find_resource(struct resource *root, struct resource *new,
        struct resource *this = root->child;
        struct resource tmp = *new, avail, alloc;
 
+       tmp.flags = new->flags;
        tmp.start = root->start;
        /*
-        * Skip past an allocated resource that starts at 0, since the
-        * assignment of this->start - 1 to tmp->end below would cause an
-        * underflow.
+        * Skip past an allocated resource that starts at 0, since the assignment
+        * of this->start - 1 to tmp->end below would cause an underflow.
         */
        if (this && this->start == 0) {
                tmp.start = this->end + 1;
                this = this->sibling;
        }
-       for (;;) {
+       for(;;) {
                if (this)
                        tmp.end = this->start - 1;
                else
                        tmp.end = root->end;
 
                resource_clip(&tmp, min, max);
+               arch_remove_reservations(&tmp);
 
                /* Check for overflow after ALIGN() */
                avail = *new;
@@ -509,10 +430,8 @@ static int find_resource(struct resource *root, struct resource *new,
                                return 0;
                        }
                }
-
                if (!this)
                        break;
-
                tmp.start = this->end + 1;
                this = this->sibling;
        }
@@ -545,10 +464,7 @@ int allocate_resource(struct resource *root, struct resource *new,
                alignf = simple_align_resource;
 
        write_lock(&resource_lock);
-       if (resource_alloc_from_bottom)
-               err = find_resource(root, new, size, min, max, align, alignf, alignf_data);
-       else
-               err = find_resource_from_top(root, new, size, min, max, align, alignf, alignf_data);
+       err = find_resource(root, new, size, min, max, align, alignf, alignf_data);
        if (err >= 0 && __request_resource(root, new))
                err = -EBUSY;
        write_unlock(&resource_lock);
index dc91a4d09ac3b71a3c347187ff2a1691c952cebd..297d1a0eedb0e68d8b9327f530ba477c93b1222e 100644 (file)
@@ -636,22 +636,18 @@ static inline struct task_group *task_group(struct task_struct *p)
 
 #endif /* CONFIG_CGROUP_SCHED */
 
-static u64 irq_time_cpu(int cpu);
-static void sched_irq_time_avg_update(struct rq *rq, u64 irq_time);
+static void update_rq_clock_task(struct rq *rq, s64 delta);
 
-inline void update_rq_clock(struct rq *rq)
+static void update_rq_clock(struct rq *rq)
 {
-       if (!rq->skip_clock_update) {
-               int cpu = cpu_of(rq);
-               u64 irq_time;
+       s64 delta;
 
-               rq->clock = sched_clock_cpu(cpu);
-               irq_time = irq_time_cpu(cpu);
-               if (rq->clock - irq_time > rq->clock_task)
-                       rq->clock_task = rq->clock - irq_time;
+       if (rq->skip_clock_update)
+               return;
 
-               sched_irq_time_avg_update(rq, irq_time);
-       }
+       delta = sched_clock_cpu(cpu_of(rq)) - rq->clock;
+       rq->clock += delta;
+       update_rq_clock_task(rq, delta);
 }
 
 /*
@@ -1924,10 +1920,9 @@ static void deactivate_task(struct rq *rq, struct task_struct *p, int flags)
  * They are read and saved off onto struct rq in update_rq_clock().
  * This may result in other CPU reading this CPU's irq time and can
  * race with irq/account_system_vtime on this CPU. We would either get old
- * or new value (or semi updated value on 32 bit) with a side effect of
- * accounting a slice of irq time to wrong task when irq is in progress
- * while we read rq->clock. That is a worthy compromise in place of having
- * locks on each irq in account_system_time.
+ * or new value with a side effect of accounting a slice of irq time to wrong
+ * task when irq is in progress while we read rq->clock. That is a worthy
+ * compromise in place of having locks on each irq in account_system_time.
  */
 static DEFINE_PER_CPU(u64, cpu_hardirq_time);
 static DEFINE_PER_CPU(u64, cpu_softirq_time);
@@ -1945,19 +1940,58 @@ void disable_sched_clock_irqtime(void)
        sched_clock_irqtime = 0;
 }
 
-static u64 irq_time_cpu(int cpu)
+#ifndef CONFIG_64BIT
+static DEFINE_PER_CPU(seqcount_t, irq_time_seq);
+
+static inline void irq_time_write_begin(void)
 {
-       if (!sched_clock_irqtime)
-               return 0;
+       __this_cpu_inc(irq_time_seq.sequence);
+       smp_wmb();
+}
+
+static inline void irq_time_write_end(void)
+{
+       smp_wmb();
+       __this_cpu_inc(irq_time_seq.sequence);
+}
+
+static inline u64 irq_time_read(int cpu)
+{
+       u64 irq_time;
+       unsigned seq;
 
+       do {
+               seq = read_seqcount_begin(&per_cpu(irq_time_seq, cpu));
+               irq_time = per_cpu(cpu_softirq_time, cpu) +
+                          per_cpu(cpu_hardirq_time, cpu);
+       } while (read_seqcount_retry(&per_cpu(irq_time_seq, cpu), seq));
+
+       return irq_time;
+}
+#else /* CONFIG_64BIT */
+static inline void irq_time_write_begin(void)
+{
+}
+
+static inline void irq_time_write_end(void)
+{
+}
+
+static inline u64 irq_time_read(int cpu)
+{
        return per_cpu(cpu_softirq_time, cpu) + per_cpu(cpu_hardirq_time, cpu);
 }
+#endif /* CONFIG_64BIT */
 
+/*
+ * Called before incrementing preempt_count on {soft,}irq_enter
+ * and before decrementing preempt_count on {soft,}irq_exit.
+ */
 void account_system_vtime(struct task_struct *curr)
 {
        unsigned long flags;
+       s64 delta;
        int cpu;
-       u64 now, delta;
 
        if (!sched_clock_irqtime)
                return;
@@ -1965,9 +1999,10 @@ void account_system_vtime(struct task_struct *curr)
        local_irq_save(flags);
 
        cpu = smp_processor_id();
-       now = sched_clock_cpu(cpu);
-       delta = now - per_cpu(irq_start_time, cpu);
-       per_cpu(irq_start_time, cpu) = now;
+       delta = sched_clock_cpu(cpu) - __this_cpu_read(irq_start_time);
+       __this_cpu_add(irq_start_time, delta);
+
+       irq_time_write_begin();
        /*
         * We do not account for softirq time from ksoftirqd here.
         * We want to continue accounting softirq time to ksoftirqd thread
@@ -1975,33 +2010,55 @@ void account_system_vtime(struct task_struct *curr)
         * that do not consume any time, but still wants to run.
         */
        if (hardirq_count())
-               per_cpu(cpu_hardirq_time, cpu) += delta;
+               __this_cpu_add(cpu_hardirq_time, delta);
        else if (in_serving_softirq() && !(curr->flags & PF_KSOFTIRQD))
-               per_cpu(cpu_softirq_time, cpu) += delta;
+               __this_cpu_add(cpu_softirq_time, delta);
 
+       irq_time_write_end();
        local_irq_restore(flags);
 }
 EXPORT_SYMBOL_GPL(account_system_vtime);
 
-static void sched_irq_time_avg_update(struct rq *rq, u64 curr_irq_time)
+static void update_rq_clock_task(struct rq *rq, s64 delta)
 {
-       if (sched_clock_irqtime && sched_feat(NONIRQ_POWER)) {
-               u64 delta_irq = curr_irq_time - rq->prev_irq_time;
-               rq->prev_irq_time = curr_irq_time;
-               sched_rt_avg_update(rq, delta_irq);
-       }
+       s64 irq_delta;
+
+       irq_delta = irq_time_read(cpu_of(rq)) - rq->prev_irq_time;
+
+       /*
+        * Since irq_time is only updated on {soft,}irq_exit, we might run into
+        * this case when a previous update_rq_clock() happened inside a
+        * {soft,}irq region.
+        *
+        * When this happens, we stop ->clock_task and only update the
+        * prev_irq_time stamp to account for the part that fit, so that a next
+        * update will consume the rest. This ensures ->clock_task is
+        * monotonic.
+        *
+        * It does however cause some slight miss-attribution of {soft,}irq
+        * time, a more accurate solution would be to update the irq_time using
+        * the current rq->clock timestamp, except that would require using
+        * atomic ops.
+        */
+       if (irq_delta > delta)
+               irq_delta = delta;
+
+       rq->prev_irq_time += irq_delta;
+       delta -= irq_delta;
+       rq->clock_task += delta;
+
+       if (irq_delta && sched_feat(NONIRQ_POWER))
+               sched_rt_avg_update(rq, irq_delta);
 }
 
-#else
+#else /* CONFIG_IRQ_TIME_ACCOUNTING */
 
-static u64 irq_time_cpu(int cpu)
+static void update_rq_clock_task(struct rq *rq, s64 delta)
 {
-       return 0;
+       rq->clock_task += delta;
 }
 
-static void sched_irq_time_avg_update(struct rq *rq, u64 curr_irq_time) { }
-
-#endif
+#endif /* CONFIG_IRQ_TIME_ACCOUNTING */
 
 #include "sched_idletask.c"
 #include "sched_fair.c"
@@ -2129,7 +2186,7 @@ static void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags)
         * A queue event has occurred, and we're going to schedule.  In
         * this case, we can save a useless back to back clock update.
         */
-       if (test_tsk_need_resched(rq->curr))
+       if (rq->curr->se.on_rq && test_tsk_need_resched(rq->curr))
                rq->skip_clock_update = 1;
 }
 
@@ -3119,6 +3176,15 @@ static long calc_load_fold_active(struct rq *this_rq)
        return delta;
 }
 
+static unsigned long
+calc_load(unsigned long load, unsigned long exp, unsigned long active)
+{
+       load *= exp;
+       load += active * (FIXED_1 - exp);
+       load += 1UL << (FSHIFT - 1);
+       return load >> FSHIFT;
+}
+
 #ifdef CONFIG_NO_HZ
 /*
  * For NO_HZ we delay the active fold to the next LOAD_FREQ update.
@@ -3148,6 +3214,128 @@ static long calc_load_fold_idle(void)
 
        return delta;
 }
+
+/**
+ * fixed_power_int - compute: x^n, in O(log n) time
+ *
+ * @x:         base of the power
+ * @frac_bits: fractional bits of @x
+ * @n:         power to raise @x to.
+ *
+ * By exploiting the relation between the definition of the natural power
+ * function: x^n := x*x*...*x (x multiplied by itself for n times), and
+ * the binary encoding of numbers used by computers: n := \Sum n_i * 2^i,
+ * (where: n_i \elem {0, 1}, the binary vector representing n),
+ * we find: x^n := x^(\Sum n_i * 2^i) := \Prod x^(n_i * 2^i), which is
+ * of course trivially computable in O(log_2 n), the length of our binary
+ * vector.
+ */
+static unsigned long
+fixed_power_int(unsigned long x, unsigned int frac_bits, unsigned int n)
+{
+       unsigned long result = 1UL << frac_bits;
+
+       if (n) for (;;) {
+               if (n & 1) {
+                       result *= x;
+                       result += 1UL << (frac_bits - 1);
+                       result >>= frac_bits;
+               }
+               n >>= 1;
+               if (!n)
+                       break;
+               x *= x;
+               x += 1UL << (frac_bits - 1);
+               x >>= frac_bits;
+       }
+
+       return result;
+}
+
+/*
+ * a1 = a0 * e + a * (1 - e)
+ *
+ * a2 = a1 * e + a * (1 - e)
+ *    = (a0 * e + a * (1 - e)) * e + a * (1 - e)
+ *    = a0 * e^2 + a * (1 - e) * (1 + e)
+ *
+ * a3 = a2 * e + a * (1 - e)
+ *    = (a0 * e^2 + a * (1 - e) * (1 + e)) * e + a * (1 - e)
+ *    = a0 * e^3 + a * (1 - e) * (1 + e + e^2)
+ *
+ *  ...
+ *
+ * an = a0 * e^n + a * (1 - e) * (1 + e + ... + e^n-1) [1]
+ *    = a0 * e^n + a * (1 - e) * (1 - e^n)/(1 - e)
+ *    = a0 * e^n + a * (1 - e^n)
+ *
+ * [1] application of the geometric series:
+ *
+ *              n         1 - x^(n+1)
+ *     S_n := \Sum x^i = -------------
+ *             i=0          1 - x
+ */
+static unsigned long
+calc_load_n(unsigned long load, unsigned long exp,
+           unsigned long active, unsigned int n)
+{
+
+       return calc_load(load, fixed_power_int(exp, FSHIFT, n), active);
+}
+
+/*
+ * NO_HZ can leave us missing all per-cpu ticks calling
+ * calc_load_account_active(), but since an idle CPU folds its delta into
+ * calc_load_tasks_idle per calc_load_account_idle(), all we need to do is fold
+ * in the pending idle delta if our idle period crossed a load cycle boundary.
+ *
+ * Once we've updated the global active value, we need to apply the exponential
+ * weights adjusted to the number of cycles missed.
+ */
+static void calc_global_nohz(unsigned long ticks)
+{
+       long delta, active, n;
+
+       if (time_before(jiffies, calc_load_update))
+               return;
+
+       /*
+        * If we crossed a calc_load_update boundary, make sure to fold
+        * any pending idle changes, the respective CPUs might have
+        * missed the tick driven calc_load_account_active() update
+        * due to NO_HZ.
+        */
+       delta = calc_load_fold_idle();
+       if (delta)
+               atomic_long_add(delta, &calc_load_tasks);
+
+       /*
+        * If we were idle for multiple load cycles, apply them.
+        */
+       if (ticks >= LOAD_FREQ) {
+               n = ticks / LOAD_FREQ;
+
+               active = atomic_long_read(&calc_load_tasks);
+               active = active > 0 ? active * FIXED_1 : 0;
+
+               avenrun[0] = calc_load_n(avenrun[0], EXP_1, active, n);
+               avenrun[1] = calc_load_n(avenrun[1], EXP_5, active, n);
+               avenrun[2] = calc_load_n(avenrun[2], EXP_15, active, n);
+
+               calc_load_update += n * LOAD_FREQ;
+       }
+
+       /*
+        * Its possible the remainder of the above division also crosses
+        * a LOAD_FREQ period, the regular check in calc_global_load()
+        * which comes after this will take care of that.
+        *
+        * Consider us being 11 ticks before a cycle completion, and us
+        * sleeping for 4*LOAD_FREQ + 22 ticks, then the above code will
+        * age us 4 cycles, and the test in calc_global_load() will
+        * pick up the final one.
+        */
+}
 #else
 static void calc_load_account_idle(struct rq *this_rq)
 {
@@ -3157,6 +3345,10 @@ static inline long calc_load_fold_idle(void)
 {
        return 0;
 }
+
+static void calc_global_nohz(unsigned long ticks)
+{
+}
 #endif
 
 /**
@@ -3174,24 +3366,17 @@ void get_avenrun(unsigned long *loads, unsigned long offset, int shift)
        loads[2] = (avenrun[2] + offset) << shift;
 }
 
-static unsigned long
-calc_load(unsigned long load, unsigned long exp, unsigned long active)
-{
-       load *= exp;
-       load += active * (FIXED_1 - exp);
-       return load >> FSHIFT;
-}
-
 /*
  * calc_load - update the avenrun load estimates 10 ticks after the
  * CPUs have updated calc_load_tasks.
  */
-void calc_global_load(void)
+void calc_global_load(unsigned long ticks)
 {
-       unsigned long upd = calc_load_update + 10;
        long active;
 
-       if (time_before(jiffies, upd))
+       calc_global_nohz(ticks);
+
+       if (time_before(jiffies, calc_load_update + 10))
                return;
 
        active = atomic_long_read(&calc_load_tasks);
@@ -3845,7 +4030,6 @@ static void put_prev_task(struct rq *rq, struct task_struct *prev)
 {
        if (prev->se.on_rq)
                update_rq_clock(rq);
-       rq->skip_clock_update = 0;
        prev->sched_class->put_prev_task(rq, prev);
 }
 
@@ -3903,7 +4087,6 @@ need_resched_nonpreemptible:
                hrtick_clear(rq);
 
        raw_spin_lock_irq(&rq->lock);
-       clear_tsk_need_resched(prev);
 
        switch_count = &prev->nivcsw;
        if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
@@ -3935,6 +4118,8 @@ need_resched_nonpreemptible:
 
        put_prev_task(rq, prev);
        next = pick_next_task(rq);
+       clear_tsk_need_resched(prev);
+       rq->skip_clock_update = 0;
 
        if (likely(prev != next)) {
                sched_info_switch(prev, next);
index 52ab113d8bb95ee8e08299b9bad6b0df5691ea89..00ebd7686676bd87a6e5b3be513d27028e518796 100644 (file)
@@ -1758,10 +1758,6 @@ static void pull_task(struct rq *src_rq, struct task_struct *p,
        set_task_cpu(p, this_cpu);
        activate_task(this_rq, p, 0);
        check_preempt_curr(this_rq, p, 0);
-
-       /* re-arm NEWIDLE balancing when moving tasks */
-       src_rq->avg_idle = this_rq->avg_idle = 2*sysctl_sched_migration_cost;
-       this_rq->idle_stamp = 0;
 }
 
 /*
@@ -3219,8 +3215,10 @@ static void idle_balance(int this_cpu, struct rq *this_rq)
                interval = msecs_to_jiffies(sd->balance_interval);
                if (time_after(next_balance, sd->last_balance + interval))
                        next_balance = sd->last_balance + interval;
-               if (pulled_task)
+               if (pulled_task) {
+                       this_rq->idle_stamp = 0;
                        break;
+               }
        }
 
        raw_spin_lock(&this_rq->lock);
index 68a9ae7679b717f6eb4782ce5114ad405dec5a4c..353b9227c2ecfe11793a17b0a41f534ebdbd14f8 100644 (file)
@@ -1252,6 +1252,12 @@ unsigned long get_next_timer_interrupt(unsigned long now)
        struct tvec_base *base = __get_cpu_var(tvec_bases);
        unsigned long expires;
 
+       /*
+        * Pretend that there is no timer pending if the cpu is offline.
+        * Possible pending timers will be migrated later to an active cpu.
+        */
+       if (cpu_is_offline(smp_processor_id()))
+               return now + NEXT_TIMER_MAX_DELTA;
        spin_lock(&base->lock);
        if (time_before_eq(base->next_timer, base->timer_jiffies))
                base->next_timer = __next_timer_interrupt(base);
@@ -1319,7 +1325,7 @@ void do_timer(unsigned long ticks)
 {
        jiffies_64 += ticks;
        update_wall_time();
-       calc_global_load();
+       calc_global_load(ticks);
 }
 
 #ifdef __ARCH_WANT_SYS_ALARM
index 0420841579806ce14b3fc86b9fe13df649dac711..f8cf959bad456dead3a5dec2fdd1a21e384f22bb 100644 (file)
@@ -1283,6 +1283,8 @@ void trace_dump_stack(void)
        __ftrace_trace_stack(global_trace.buffer, flags, 3, preempt_count());
 }
 
+static DEFINE_PER_CPU(int, user_stack_count);
+
 void
 ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc)
 {
@@ -1301,6 +1303,18 @@ ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc)
        if (unlikely(in_nmi()))
                return;
 
+       /*
+        * prevent recursion, since the user stack tracing may
+        * trigger other kernel events.
+        */
+       preempt_disable();
+       if (__this_cpu_read(user_stack_count))
+               goto out;
+
+       __this_cpu_inc(user_stack_count);
+
+
+
        event = trace_buffer_lock_reserve(buffer, TRACE_USER_STACK,
                                          sizeof(*entry), flags, pc);
        if (!event)
@@ -1318,6 +1332,11 @@ ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc)
        save_stack_trace_user(&trace);
        if (!filter_check_discard(call, entry, buffer, event))
                ring_buffer_unlock_commit(buffer, event);
+
+       __this_cpu_dec(user_stack_count);
+
+ out:
+       preempt_enable();
 }
 
 #ifdef UNUSED
@@ -2319,11 +2338,19 @@ tracing_write_stub(struct file *filp, const char __user *ubuf,
        return count;
 }
 
+static loff_t tracing_seek(struct file *file, loff_t offset, int origin)
+{
+       if (file->f_mode & FMODE_READ)
+               return seq_lseek(file, offset, origin);
+       else
+               return 0;
+}
+
 static const struct file_operations tracing_fops = {
        .open           = tracing_open,
        .read           = seq_read,
        .write          = tracing_write_stub,
-       .llseek         = seq_lseek,
+       .llseek         = tracing_seek,
        .release        = tracing_release,
 };
 
index 90db1bd1a97852e4c547c43d840b2ca624c9a773..e785b0f2aea57f362f9528fb979f15716f7f2aa4 100644 (file)
@@ -661,7 +661,7 @@ void wq_worker_waking_up(struct task_struct *task, unsigned int cpu)
 {
        struct worker *worker = kthread_data(task);
 
-       if (likely(!(worker->flags & WORKER_NOT_RUNNING)))
+       if (!(worker->flags & WORKER_NOT_RUNNING))
                atomic_inc(get_gcwq_nr_running(cpu));
 }
 
@@ -687,7 +687,7 @@ struct task_struct *wq_worker_sleeping(struct task_struct *task,
        struct global_cwq *gcwq = get_gcwq(cpu);
        atomic_t *nr_running = get_gcwq_nr_running(cpu);
 
-       if (unlikely(worker->flags & WORKER_NOT_RUNNING))
+       if (worker->flags & WORKER_NOT_RUNNING)
                return NULL;
 
        /* this can only happen on the local cpu */
@@ -3692,7 +3692,8 @@ static int __init init_workqueues(void)
        system_nrt_wq = alloc_workqueue("events_nrt", WQ_NON_REENTRANT, 0);
        system_unbound_wq = alloc_workqueue("events_unbound", WQ_UNBOUND,
                                            WQ_UNBOUND_MAX_ACTIVE);
-       BUG_ON(!system_wq || !system_long_wq || !system_nrt_wq);
+       BUG_ON(!system_wq || !system_long_wq || !system_nrt_wq ||
+              !system_unbound_wq);
        return 0;
 }
 early_initcall(init_workqueues);
index 5bf0020b9248801236d1a1ca7a3233e1bf2b2bb7..b1c17730767745f81d9990effd5078cdc769dc08 100644 (file)
@@ -8,7 +8,6 @@
  *
  *  Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
  */
-#include <linux/kernel.h>
 #include <linux/rwsem.h>
 #include <linux/mutex.h>
 #include <linux/module.h>
@@ -39,7 +38,6 @@ int debug_locks_off(void)
 {
        if (__debug_locks_off()) {
                if (!debug_locks_silent) {
-                       oops_in_progress = 1;
                        console_verbose();
                        return 1;
                }
index ea89840fc65fa2b499ce3c19c657e9e8a680b240..6b9aee20f2426b88024a25749402fc5ca1ff7a0a 100644 (file)
@@ -143,13 +143,18 @@ void __remove_from_page_cache(struct page *page)
 void remove_from_page_cache(struct page *page)
 {
        struct address_space *mapping = page->mapping;
+       void (*freepage)(struct page *);
 
        BUG_ON(!PageLocked(page));
 
+       freepage = mapping->a_ops->freepage;
        spin_lock_irq(&mapping->tree_lock);
        __remove_from_page_cache(page);
        spin_unlock_irq(&mapping->tree_lock);
        mem_cgroup_uncharge_cache_page(page);
+
+       if (freepage)
+               freepage(page);
 }
 EXPORT_SYMBOL(remove_from_page_cache);
 
index c4a3558589ab15de3ac9abb135ee499d17544142..85855240933d7cf195ce1548faa75d8120c21478 100644 (file)
@@ -2738,7 +2738,8 @@ out_page_table_lock:
                unlock_page(pagecache_page);
                put_page(pagecache_page);
        }
-       unlock_page(page);
+       if (page != pagecache_page)
+               unlock_page(page);
 
 out_mutex:
        mutex_unlock(&hugetlb_instantiation_mutex);
index 65ab5c7067d994ad934c4f4bd5fd5809235a0756..43bc893470b40512e26bdd129fb2194708bfbbdc 100644 (file)
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -1724,8 +1724,13 @@ static int ksm_memory_callback(struct notifier_block *self,
                /*
                 * Keep it very simple for now: just lock out ksmd and
                 * MADV_UNMERGEABLE while any memory is going offline.
+                * mutex_lock_nested() is necessary because lockdep was alarmed
+                * that here we take ksm_thread_mutex inside notifier chain
+                * mutex, and later take notifier chain mutex inside
+                * ksm_thread_mutex to unlock it.   But that's safe because both
+                * are inside mem_hotplug_mutex.
                 */
-               mutex_lock(&ksm_thread_mutex);
+               mutex_lock_nested(&ksm_thread_mutex, SINGLE_DEPTH_NESTING);
                break;
 
        case MEM_OFFLINE:
index 2efa8ea07ff7d931577da964c190f5524088da3d..7a22b41292115f78dc039ebf5e271090dc5a8f9d 100644 (file)
@@ -61,7 +61,14 @@ struct mem_cgroup *root_mem_cgroup __read_mostly;
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP
 /* Turned on only when memory cgroup is enabled && really_do_swap_account = 1 */
 int do_swap_account __read_mostly;
-static int really_do_swap_account __initdata = 1; /* for remember boot option*/
+
+/* for remember boot option*/
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED
+static int really_do_swap_account __initdata = 1;
+#else
+static int really_do_swap_account __initdata = 0;
+#endif
+
 #else
 #define do_swap_account                (0)
 #endif
@@ -278,13 +285,14 @@ enum move_type {
 
 /* "mc" and its members are protected by cgroup_mutex */
 static struct move_charge_struct {
-       spinlock_t        lock; /* for from, to, moving_task */
+       spinlock_t        lock; /* for from, to */
        struct mem_cgroup *from;
        struct mem_cgroup *to;
        unsigned long precharge;
        unsigned long moved_charge;
        unsigned long moved_swap;
        struct task_struct *moving_task;        /* a task moving charges */
+       struct mm_struct *mm;
        wait_queue_head_t waitq;                /* a waitq for other context */
 } mc = {
        .lock = __SPIN_LOCK_UNLOCKED(mc.lock),
@@ -2152,7 +2160,7 @@ static void __mem_cgroup_move_account(struct page_cgroup *pc,
 {
        VM_BUG_ON(from == to);
        VM_BUG_ON(PageLRU(pc->page));
-       VM_BUG_ON(!PageCgroupLocked(pc));
+       VM_BUG_ON(!page_is_cgroup_locked(pc));
        VM_BUG_ON(!PageCgroupUsed(pc));
        VM_BUG_ON(pc->mem_cgroup != from);
 
@@ -4631,7 +4639,7 @@ static unsigned long mem_cgroup_count_precharge(struct mm_struct *mm)
        unsigned long precharge;
        struct vm_area_struct *vma;
 
-       down_read(&mm->mmap_sem);
+       /* We've already held the mmap_sem */
        for (vma = mm->mmap; vma; vma = vma->vm_next) {
                struct mm_walk mem_cgroup_count_precharge_walk = {
                        .pmd_entry = mem_cgroup_count_precharge_pte_range,
@@ -4643,7 +4651,6 @@ static unsigned long mem_cgroup_count_precharge(struct mm_struct *mm)
                walk_page_range(vma->vm_start, vma->vm_end,
                                        &mem_cgroup_count_precharge_walk);
        }
-       up_read(&mm->mmap_sem);
 
        precharge = mc.precharge;
        mc.precharge = 0;
@@ -4694,11 +4701,16 @@ static void mem_cgroup_clear_mc(void)
 
                mc.moved_swap = 0;
        }
+       if (mc.mm) {
+               up_read(&mc.mm->mmap_sem);
+               mmput(mc.mm);
+       }
        spin_lock(&mc.lock);
        mc.from = NULL;
        mc.to = NULL;
-       mc.moving_task = NULL;
        spin_unlock(&mc.lock);
+       mc.moving_task = NULL;
+       mc.mm = NULL;
        mem_cgroup_end_move(from);
        memcg_oom_recover(from);
        memcg_oom_recover(to);
@@ -4724,12 +4736,21 @@ static int mem_cgroup_can_attach(struct cgroup_subsys *ss,
                        return 0;
                /* We move charges only when we move a owner of the mm */
                if (mm->owner == p) {
+                       /*
+                        * We do all the move charge works under one mmap_sem to
+                        * avoid deadlock with down_write(&mmap_sem)
+                        * -> try_charge() -> if (mc.moving_task) -> sleep.
+                        */
+                       down_read(&mm->mmap_sem);
+
                        VM_BUG_ON(mc.from);
                        VM_BUG_ON(mc.to);
                        VM_BUG_ON(mc.precharge);
                        VM_BUG_ON(mc.moved_charge);
                        VM_BUG_ON(mc.moved_swap);
                        VM_BUG_ON(mc.moving_task);
+                       VM_BUG_ON(mc.mm);
+
                        mem_cgroup_start_move(from);
                        spin_lock(&mc.lock);
                        mc.from = from;
@@ -4737,14 +4758,16 @@ static int mem_cgroup_can_attach(struct cgroup_subsys *ss,
                        mc.precharge = 0;
                        mc.moved_charge = 0;
                        mc.moved_swap = 0;
-                       mc.moving_task = current;
                        spin_unlock(&mc.lock);
+                       mc.moving_task = current;
+                       mc.mm = mm;
 
                        ret = mem_cgroup_precharge_mc(mm);
                        if (ret)
                                mem_cgroup_clear_mc();
-               }
-               mmput(mm);
+                       /* We call up_read() and mmput() in clear_mc(). */
+               } else
+                       mmput(mm);
        }
        return ret;
 }
@@ -4832,7 +4855,7 @@ static void mem_cgroup_move_charge(struct mm_struct *mm)
        struct vm_area_struct *vma;
 
        lru_add_drain_all();
-       down_read(&mm->mmap_sem);
+       /* We've already held the mmap_sem */
        for (vma = mm->mmap; vma; vma = vma->vm_next) {
                int ret;
                struct mm_walk mem_cgroup_move_charge_walk = {
@@ -4851,7 +4874,6 @@ static void mem_cgroup_move_charge(struct mm_struct *mm)
                         */
                        break;
        }
-       up_read(&mm->mmap_sem);
 }
 
 static void mem_cgroup_move_task(struct cgroup_subsys *ss,
@@ -4860,17 +4882,11 @@ static void mem_cgroup_move_task(struct cgroup_subsys *ss,
                                struct task_struct *p,
                                bool threadgroup)
 {
-       struct mm_struct *mm;
-
-       if (!mc.to)
+       if (!mc.mm)
                /* no need to move charge */
                return;
 
-       mm = get_task_mm(p);
-       if (mm) {
-               mem_cgroup_move_charge(mm);
-               mmput(mm);
-       }
+       mem_cgroup_move_charge(mc.mm);
        mem_cgroup_clear_mc();
 }
 #else  /* !CONFIG_MMU */
@@ -4911,10 +4927,20 @@ struct cgroup_subsys mem_cgroup_subsys = {
 };
 
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP
+static int __init enable_swap_account(char *s)
+{
+       /* consider enabled if no parameter or 1 is given */
+       if (!s || !strcmp(s, "1"))
+               really_do_swap_account = 1;
+       else if (!strcmp(s, "0"))
+               really_do_swap_account = 0;
+       return 1;
+}
+__setup("swapaccount", enable_swap_account);
 
 static int __init disable_swap_account(char *s)
 {
-       really_do_swap_account = 0;
+       enable_swap_account("0");
        return 1;
 }
 __setup("noswapaccount", disable_swap_account);
index 124324134ff67b3c4a0bc06661b4f70f2406840f..46ab2c044b0e657ad1844dd291a3b537c97d58b6 100644 (file)
@@ -51,6 +51,7 @@
 #include <linux/slab.h>
 #include <linux/swapops.h>
 #include <linux/hugetlb.h>
+#include <linux/memory_hotplug.h>
 #include "internal.h"
 
 int sysctl_memory_failure_early_kill __read_mostly = 0;
@@ -1230,11 +1231,10 @@ static int get_any_page(struct page *p, unsigned long pfn, int flags)
                return 1;
 
        /*
-        * The lock_system_sleep prevents a race with memory hotplug,
-        * because the isolation assumes there's only a single user.
+        * The lock_memory_hotplug prevents a race with memory hotplug.
         * This is a big hammer, a better would be nicer.
         */
-       lock_system_sleep();
+       lock_memory_hotplug();
 
        /*
         * Isolate the page, so that it doesn't get reallocated if it
@@ -1264,7 +1264,7 @@ static int get_any_page(struct page *p, unsigned long pfn, int flags)
                ret = 1;
        }
        unset_migratetype_isolate(p);
-       unlock_system_sleep();
+       unlock_memory_hotplug();
        return ret;
 }
 
index 9260314a221e0720d5cc3ecf5f00325c7ec3fba6..2c6523af54738faba3dd37eef938315503275de4 100644 (file)
 
 #include "internal.h"
 
+DEFINE_MUTEX(mem_hotplug_mutex);
+
+void lock_memory_hotplug(void)
+{
+       mutex_lock(&mem_hotplug_mutex);
+
+       /* for exclusive hibernation if CONFIG_HIBERNATION=y */
+       lock_system_sleep();
+}
+
+void unlock_memory_hotplug(void)
+{
+       unlock_system_sleep();
+       mutex_unlock(&mem_hotplug_mutex);
+}
+
+
 /* add this memory to iomem resource */
 static struct resource *register_memory_resource(u64 start, u64 size)
 {
@@ -493,7 +510,7 @@ int mem_online_node(int nid)
        pg_data_t       *pgdat;
        int     ret;
 
-       lock_system_sleep();
+       lock_memory_hotplug();
        pgdat = hotadd_new_pgdat(nid, 0);
        if (pgdat) {
                ret = -ENOMEM;
@@ -504,7 +521,7 @@ int mem_online_node(int nid)
        BUG_ON(ret);
 
 out:
-       unlock_system_sleep();
+       unlock_memory_hotplug();
        return ret;
 }
 
@@ -516,7 +533,7 @@ int __ref add_memory(int nid, u64 start, u64 size)
        struct resource *res;
        int ret;
 
-       lock_system_sleep();
+       lock_memory_hotplug();
 
        res = register_memory_resource(start, size);
        ret = -EEXIST;
@@ -563,7 +580,7 @@ error:
                release_memory_resource(res);
 
 out:
-       unlock_system_sleep();
+       unlock_memory_hotplug();
        return ret;
 }
 EXPORT_SYMBOL_GPL(add_memory);
@@ -791,7 +808,7 @@ static int offline_pages(unsigned long start_pfn,
        if (!test_pages_in_a_zone(start_pfn, end_pfn))
                return -EINVAL;
 
-       lock_system_sleep();
+       lock_memory_hotplug();
 
        zone = page_zone(pfn_to_page(start_pfn));
        node = zone_to_nid(zone);
@@ -880,7 +897,7 @@ repeat:
        writeback_set_ratelimit();
 
        memory_notify(MEM_OFFLINE, &arg);
-       unlock_system_sleep();
+       unlock_memory_hotplug();
        return 0;
 
 failed_removal:
@@ -891,7 +908,7 @@ failed_removal:
        undo_isolate_page_range(start_pfn, end_pfn);
 
 out:
-       unlock_system_sleep();
+       unlock_memory_hotplug();
        return ret;
 }
 
index 4a57f135b76e74741e7c7d285642067a3e18efe6..11ff260fb282b778657a872aec0947d5f15616c6 100644 (file)
@@ -1307,15 +1307,18 @@ SYSCALL_DEFINE4(migrate_pages, pid_t, pid, unsigned long, maxnode,
                goto out;
 
        /* Find the mm_struct */
+       rcu_read_lock();
        read_lock(&tasklist_lock);
        task = pid ? find_task_by_vpid(pid) : current;
        if (!task) {
                read_unlock(&tasklist_lock);
+               rcu_read_unlock();
                err = -ESRCH;
                goto out;
        }
        mm = get_task_mm(task);
        read_unlock(&tasklist_lock);
+       rcu_read_unlock();
 
        err = -EINVAL;
        if (!mm)
index b179abb1474ae41bff47060b5241045d3b1b12ad..50a4aa0255a0703f83c8667028afe8545d78e09a 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2462,6 +2462,7 @@ int install_special_mapping(struct mm_struct *mm,
                            unsigned long addr, unsigned long len,
                            unsigned long vm_flags, struct page **pages)
 {
+       int ret;
        struct vm_area_struct *vma;
 
        vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
@@ -2479,16 +2480,23 @@ int install_special_mapping(struct mm_struct *mm,
        vma->vm_ops = &special_mapping_vmops;
        vma->vm_private_data = pages;
 
-       if (unlikely(insert_vm_struct(mm, vma))) {
-               kmem_cache_free(vm_area_cachep, vma);
-               return -ENOMEM;
-       }
+       ret = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1);
+       if (ret)
+               goto out;
+
+       ret = insert_vm_struct(mm, vma);
+       if (ret)
+               goto out;
 
        mm->total_vm += len >> PAGE_SHIFT;
 
        perf_event_mmap(vma);
 
        return 0;
+
+out:
+       kmem_cache_free(vm_area_cachep, vma);
+       return ret;
 }
 
 static DEFINE_MUTEX(mm_all_locks_mutex);
index 3613517c75929b17e1b3d93a650e5d9957c2315a..27a9ac58851678d30c7c477d00a857cf2f63bc35 100644 (file)
@@ -1717,6 +1717,7 @@ void exit_mmap(struct mm_struct *mm)
                mm->mmap = vma->vm_next;
                delete_vma_from_mm(vma);
                delete_vma(mm, vma);
+               cond_resched();
        }
 
        kleave("");
index 07a654486f75cfdfe13035f7bf501e2d2dbf0a4a..ff7e158723987d4355ec84a2c090716ec8accbe9 100644 (file)
@@ -104,19 +104,24 @@ gfp_t gfp_allowed_mask __read_mostly = GFP_BOOT_MASK;
  * only be modified with pm_mutex held, unless the suspend/hibernate code is
  * guaranteed not to run in parallel with that modification).
  */
-void set_gfp_allowed_mask(gfp_t mask)
+
+static gfp_t saved_gfp_mask;
+
+void pm_restore_gfp_mask(void)
 {
        WARN_ON(!mutex_is_locked(&pm_mutex));
-       gfp_allowed_mask = mask;
+       if (saved_gfp_mask) {
+               gfp_allowed_mask = saved_gfp_mask;
+               saved_gfp_mask = 0;
+       }
 }
 
-gfp_t clear_gfp_allowed_mask(gfp_t mask)
+void pm_restrict_gfp_mask(void)
 {
-       gfp_t ret = gfp_allowed_mask;
-
        WARN_ON(!mutex_is_locked(&pm_mutex));
-       gfp_allowed_mask &= ~mask;
-       return ret;
+       WARN_ON(saved_gfp_mask);
+       saved_gfp_mask = gfp_allowed_mask;
+       gfp_allowed_mask &= ~GFP_IOFS;
 }
 #endif /* CONFIG_PM_SLEEP */
 
@@ -3008,14 +3013,6 @@ static __init_refok int __build_all_zonelists(void *data)
                build_zonelist_cache(pgdat);
        }
 
-#ifdef CONFIG_MEMORY_HOTPLUG
-       /* Setup real pagesets for the new zone */
-       if (data) {
-               struct zone *zone = data;
-               setup_zone_pageset(zone);
-       }
-#endif
-
        /*
         * Initialize the boot_pagesets that are going to be used
         * for bootstrapping processors. The real pagesets for
@@ -3064,7 +3061,11 @@ void build_all_zonelists(void *data)
        } else {
                /* we have to stop all cpus to guarantee there is no user
                   of zonelist */
-               stop_machine(__build_all_zonelists, data, NULL);
+#ifdef CONFIG_MEMORY_HOTPLUG
+               if (data)
+                       setup_zone_pageset((struct zone *)data);
+#endif
+               stop_machine(__build_all_zonelists, NULL, NULL);
                /* cpuset refresh routine should be here */
        }
        vm_total_pages = nr_free_pagecache_pages();
index 8b1a2ce21ee53f3a6ea598759faf02c21c4c5dd2..38cc58b8b2b0d37340f6e327c56c796bd7c24516 100644 (file)
@@ -139,7 +139,6 @@ int walk_page_range(unsigned long addr, unsigned long end,
        pgd_t *pgd;
        unsigned long next;
        int err = 0;
-       struct vm_area_struct *vma;
 
        if (addr >= end)
                return err;
@@ -149,15 +148,17 @@ int walk_page_range(unsigned long addr, unsigned long end,
 
        pgd = pgd_offset(walk->mm, addr);
        do {
+               struct vm_area_struct *uninitialized_var(vma);
+
                next = pgd_addr_end(addr, end);
 
+#ifdef CONFIG_HUGETLB_PAGE
                /*
                 * handle hugetlb vma individually because pagetable walk for
                 * the hugetlb page is dependent on the architecture and
                 * we can't handled it in the same manner as non-huge pages.
                 */
                vma = find_vma(walk->mm, addr);
-#ifdef CONFIG_HUGETLB_PAGE
                if (vma && is_vm_hugetlb_page(vma)) {
                        if (vma->vm_end < next)
                                next = vma->vm_end;
index 981fb730aa04d82ef7b739497beb22d10fe9f98c..bec0e355fbadfda52fe317d053f191c178df478b 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -3401,13 +3401,13 @@ static int validate_slab(struct kmem_cache *s, struct page *page,
 
        for_each_free_object(p, s, page->freelist) {
                set_bit(slab_index(p, s, addr), map);
-               if (!check_object(s, page, p, 0))
+               if (!check_object(s, page, p, SLUB_RED_INACTIVE))
                        return 0;
        }
 
        for_each_object(p, s, addr, page->objects)
                if (!test_bit(slab_index(p, s, addr), map))
-                       if (!check_object(s, page, p, 1))
+                       if (!check_object(s, page, p, SLUB_RED_ACTIVE))
                                return 0;
        return 1;
 }
index ba887bff48c5a263c315a6ef098284df4df5bb44..3c2d5ddfa0d49f3cf31449e214d8fbd50e92ad08 100644 (file)
@@ -390,6 +390,10 @@ invalidate_complete_page2(struct address_space *mapping, struct page *page)
        __remove_from_page_cache(page);
        spin_unlock_irq(&mapping->tree_lock);
        mem_cgroup_uncharge_cache_page(page);
+
+       if (mapping->a_ops->freepage)
+               mapping->a_ops->freepage(page);
+
        page_cache_release(page);       /* pagecache ref */
        return 1;
 failed:
index a3d66b3dc5cb0c9136b13764958d6aedf5b10526..eb5cc7d00c5a7c0443f9ff663317cf229ab74353 100644 (file)
@@ -31,8 +31,6 @@
 #include <asm/tlbflush.h>
 #include <asm/shmparam.h>
 
-bool vmap_lazy_unmap __read_mostly = true;
-
 /*** Page table manipulation functions ***/
 
 static void vunmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end)
@@ -503,9 +501,6 @@ static unsigned long lazy_max_pages(void)
 {
        unsigned int log;
 
-       if (!vmap_lazy_unmap)
-               return 0;
-
        log = fls(num_online_cpus());
 
        return log * (32UL * 1024 * 1024 / PAGE_SIZE);
@@ -566,7 +561,6 @@ static void __purge_vmap_area_lazy(unsigned long *start, unsigned long *end,
                        if (va->va_end > *end)
                                *end = va->va_end;
                        nr += (va->va_end - va->va_start) >> PAGE_SHIFT;
-                       unmap_vmap_area(va);
                        list_add_tail(&va->purge_list, &valist);
                        va->flags |= VM_LAZY_FREEING;
                        va->flags &= ~VM_LAZY_FREE;
@@ -611,10 +605,11 @@ static void purge_vmap_area_lazy(void)
 }
 
 /*
- * Free and unmap a vmap area, caller ensuring flush_cache_vunmap had been
- * called for the correct range previously.
+ * Free a vmap area, caller ensuring that the area has been unmapped
+ * and flush_cache_vunmap had been called for the correct range
+ * previously.
  */
-static void free_unmap_vmap_area_noflush(struct vmap_area *va)
+static void free_vmap_area_noflush(struct vmap_area *va)
 {
        va->flags |= VM_LAZY_FREE;
        atomic_add((va->va_end - va->va_start) >> PAGE_SHIFT, &vmap_lazy_nr);
@@ -622,6 +617,16 @@ static void free_unmap_vmap_area_noflush(struct vmap_area *va)
                try_purge_vmap_area_lazy();
 }
 
+/*
+ * Free and unmap a vmap area, caller ensuring flush_cache_vunmap had been
+ * called for the correct range previously.
+ */
+static void free_unmap_vmap_area_noflush(struct vmap_area *va)
+{
+       unmap_vmap_area(va);
+       free_vmap_area_noflush(va);
+}
+
 /*
  * Free and unmap a vmap area
  */
@@ -798,7 +803,7 @@ static void free_vmap_block(struct vmap_block *vb)
        spin_unlock(&vmap_block_tree_lock);
        BUG_ON(tmp != vb);
 
-       free_unmap_vmap_area_noflush(vb->va);
+       free_vmap_area_noflush(vb->va);
        call_rcu(&vb->rcu_head, rcu_free_vb);
 }
 
@@ -936,6 +941,8 @@ static void vb_free(const void *addr, unsigned long size)
        rcu_read_unlock();
        BUG_ON(!vb);
 
+       vunmap_page_range((unsigned long)addr, (unsigned long)addr + size);
+
        spin_lock(&vb->lock);
        BUG_ON(bitmap_allocate_region(vb->dirty_map, offset >> PAGE_SHIFT, order));
 
@@ -988,7 +995,6 @@ void vm_unmap_aliases(void)
 
                                s = vb->va->va_start + (i << PAGE_SHIFT);
                                e = vb->va->va_start + (j << PAGE_SHIFT);
-                               vunmap_page_range(s, e);
                                flush = 1;
 
                                if (s < start)
index d31d7ce52c0ea2dbbf85b26019c9fdd70fab624a..9ca587c692748adbc715b440ff5aa8c89357c511 100644 (file)
@@ -494,9 +494,16 @@ static int __remove_mapping(struct address_space *mapping, struct page *page)
                spin_unlock_irq(&mapping->tree_lock);
                swapcache_free(swap, page);
        } else {
+               void (*freepage)(struct page *);
+
+               freepage = mapping->a_ops->freepage;
+
                __remove_from_page_cache(page);
                spin_unlock_irq(&mapping->tree_lock);
                mem_cgroup_uncharge_cache_page(page);
+
+               if (freepage != NULL)
+                       freepage(page);
        }
 
        return 1;
index 42eac4d33216b81c307a87016e821051bc86146e..8f62f17ee1c726fec7fc683082b0807a15b848aa 100644 (file)
@@ -750,8 +750,6 @@ static const char * const vmstat_text[] = {
        "nr_shmem",
        "nr_dirtied",
        "nr_written",
-       "nr_dirty_threshold",
-       "nr_dirty_background_threshold",
 
 #ifdef CONFIG_NUMA
        "numa_hit",
@@ -761,6 +759,8 @@ static const char * const vmstat_text[] = {
        "numa_local",
        "numa_other",
 #endif
+       "nr_dirty_threshold",
+       "nr_dirty_background_threshold",
 
 #ifdef CONFIG_VM_EVENT_COUNTERS
        "pgpgin",
index 799c631f0fed0c1e8210d2d61e3fdf3afd27aea9..f7fa67c78766f59c0b107ece600348f401a40d57 100644 (file)
@@ -143,12 +143,13 @@ static struct class atm_class = {
        .dev_uevent             = atm_uevent,
 };
 
-int atm_register_sysfs(struct atm_dev *adev)
+int atm_register_sysfs(struct atm_dev *adev, struct device *parent)
 {
        struct device *cdev = &adev->class_dev;
        int i, j, err;
 
        cdev->class = &atm_class;
+       cdev->parent = parent;
        dev_set_drvdata(cdev, adev);
 
        dev_set_name(cdev, "%s%d", adev->type, adev->number);
index d29e582615116a68e1f476091c6475d589401878..23f45ce6f3510fb1e9b30b58b7e52fac6a456961 100644 (file)
@@ -74,8 +74,9 @@ struct atm_dev *atm_dev_lookup(int number)
 }
 EXPORT_SYMBOL(atm_dev_lookup);
 
-struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
-                                int number, unsigned long *flags)
+struct atm_dev *atm_dev_register(const char *type, struct device *parent,
+                                const struct atmdev_ops *ops, int number,
+                                unsigned long *flags)
 {
        struct atm_dev *dev, *inuse;
 
@@ -115,7 +116,7 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
                goto out_fail;
        }
 
-       if (atm_register_sysfs(dev) < 0) {
+       if (atm_register_sysfs(dev, parent) < 0) {
                pr_err("atm_register_sysfs failed for dev %s\n", type);
                atm_proc_dev_deregister(dev);
                goto out_fail;
index 126fb1840dfbb2ddd853602892e1a5e740bd90ac..521431e305073acc8c418c56317c09bb13b4731d 100644 (file)
@@ -42,6 +42,6 @@ static inline void atm_proc_dev_deregister(struct atm_dev *dev)
 
 #endif /* CONFIG_PROC_FS */
 
-int atm_register_sysfs(struct atm_dev *adev);
+int atm_register_sysfs(struct atm_dev *adev, struct device *parent);
 void atm_unregister_sysfs(struct atm_dev *adev);
 #endif
index d0927d1fdadaba4887dbac40064c4328541b9b00..66b9e5c0523a2211450cece91d5cf217fbd4722b 100644 (file)
@@ -882,7 +882,7 @@ static int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
        int lm = 0;
 
        if (type != SCO_LINK && type != ESCO_LINK)
-               return 0;
+               return -EINVAL;
 
        BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
 
@@ -908,7 +908,7 @@ static int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
        BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
 
        if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
-               return 0;
+               return -EINVAL;
 
        if (!status) {
                struct sco_conn *conn;
@@ -927,7 +927,7 @@ static int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
        BT_DBG("hcon %p reason %d", hcon, reason);
 
        if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
-               return 0;
+               return -EINVAL;
 
        sco_conn_del(hcon, bt_err(reason));
 
index aab1cabb803598f82893676e991e2743a74f5bf4..5f19415ec9c0dfb893d6f03b94ad03cdbca3307d 100644 (file)
@@ -1,9 +1,6 @@
 #
 # Makefile for CEPH filesystem.
 #
-
-ifneq ($(KERNELRELEASE),)
-
 obj-$(CONFIG_CEPH_LIB) += libceph.o
 
 libceph-objs := ceph_common.o messenger.o msgpool.o buffer.o pagelist.o \
@@ -16,22 +13,3 @@ libceph-objs := ceph_common.o messenger.o msgpool.o buffer.o pagelist.o \
        ceph_fs.o ceph_strings.o ceph_hash.o \
        pagevec.o
 
-else
-#Otherwise we were called directly from the command
-# line; invoke the kernel build system.
-
-KERNELDIR ?= /lib/modules/$(shell uname -r)/build
-PWD := $(shell pwd)
-
-default: all
-
-all:
-       $(MAKE) -C $(KERNELDIR) M=$(PWD) CONFIG_CEPH_LIB=m modules
-
-modules_install:
-       $(MAKE) -C $(KERNELDIR) M=$(PWD) CONFIG_CEPH_LIB=m modules_install
-
-clean:
-       $(MAKE) -C $(KERNELDIR) M=$(PWD) clean
-
-endif
index 53d8abfa25d5ede4b487c88a5341b376c4921c26..bf3e6a13c215cd61cd7372e85ba19e7fc7974e9a 100644 (file)
@@ -19,7 +19,7 @@ struct ceph_buffer *ceph_buffer_new(size_t len, gfp_t gfp)
        if (b->vec.iov_base) {
                b->is_vmalloc = false;
        } else {
-               b->vec.iov_base = __vmalloc(len, gfp, PAGE_KERNEL);
+               b->vec.iov_base = __vmalloc(len, gfp | __GFP_HIGHMEM, PAGE_KERNEL);
                if (!b->vec.iov_base) {
                        kfree(b);
                        return NULL;
index 0e8157ee5d4382a32992f34c2b1cf0d78f2868b4..b6ff4a1519ab664c43d9bff871dc95d8efb52daa 100644 (file)
@@ -97,11 +97,9 @@ struct workqueue_struct *ceph_msgr_wq;
 int ceph_msgr_init(void)
 {
        ceph_msgr_wq = create_workqueue("ceph-msgr");
-       if (IS_ERR(ceph_msgr_wq)) {
-               int ret = PTR_ERR(ceph_msgr_wq);
-               pr_err("msgr_init failed to create workqueue: %d\n", ret);
-               ceph_msgr_wq = NULL;
-               return ret;
+       if (!ceph_msgr_wq) {
+               pr_err("msgr_init failed to create workqueue\n");
+               return -ENOMEM;
        }
        return 0;
 }
@@ -540,8 +538,7 @@ static void prepare_write_message(struct ceph_connection *con)
                /* initialize page iterator */
                con->out_msg_pos.page = 0;
                if (m->pages)
-                       con->out_msg_pos.page_pos =
-                               le16_to_cpu(m->hdr.data_off) & ~PAGE_MASK;
+                       con->out_msg_pos.page_pos = m->page_alignment;
                else
                        con->out_msg_pos.page_pos = 0;
                con->out_msg_pos.data_pos = 0;
@@ -1491,7 +1488,7 @@ static int read_partial_message(struct ceph_connection *con)
        struct ceph_msg *m = con->in_msg;
        int ret;
        int to, left;
-       unsigned front_len, middle_len, data_len, data_off;
+       unsigned front_len, middle_len, data_len;
        int datacrc = con->msgr->nocrc;
        int skip;
        u64 seq;
@@ -1527,19 +1524,17 @@ static int read_partial_message(struct ceph_connection *con)
        data_len = le32_to_cpu(con->in_hdr.data_len);
        if (data_len > CEPH_MSG_MAX_DATA_LEN)
                return -EIO;
-       data_off = le16_to_cpu(con->in_hdr.data_off);
 
        /* verify seq# */
        seq = le64_to_cpu(con->in_hdr.seq);
        if ((s64)seq - (s64)con->in_seq < 1) {
-               pr_info("skipping %s%lld %s seq %lld, expected %lld\n",
+               pr_info("skipping %s%lld %s seq %lld expected %lld\n",
                        ENTITY_NAME(con->peer_name),
                        ceph_pr_addr(&con->peer_addr.in_addr),
                        seq, con->in_seq + 1);
                con->in_base_pos = -front_len - middle_len - data_len -
                        sizeof(m->footer);
                con->in_tag = CEPH_MSGR_TAG_READY;
-               con->in_seq++;
                return 0;
        } else if ((s64)seq - (s64)con->in_seq > 1) {
                pr_err("read_partial_message bad seq %lld expected %lld\n",
@@ -1576,7 +1571,7 @@ static int read_partial_message(struct ceph_connection *con)
 
                con->in_msg_pos.page = 0;
                if (m->pages)
-                       con->in_msg_pos.page_pos = data_off & ~PAGE_MASK;
+                       con->in_msg_pos.page_pos = m->page_alignment;
                else
                        con->in_msg_pos.page_pos = 0;
                con->in_msg_pos.data_pos = 0;
@@ -2301,6 +2296,7 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags)
 
        /* data */
        m->nr_pages = 0;
+       m->page_alignment = 0;
        m->pages = NULL;
        m->pagelist = NULL;
        m->bio = NULL;
@@ -2370,6 +2366,7 @@ static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con,
                               type, front_len);
                        return NULL;
                }
+               msg->page_alignment = le16_to_cpu(hdr->data_off);
        }
        memcpy(&msg->hdr, &con->in_hdr, sizeof(con->in_hdr));
 
index 79391994b3edee7d531b823c0720262090db6618..3e20a122ffa2f2bf40a91596fe12bb93e6874b64 100644 (file)
@@ -71,6 +71,7 @@ void ceph_calc_raw_layout(struct ceph_osd_client *osdc,
                op->extent.length = objlen;
        }
        req->r_num_pages = calc_pages_for(off, *plen);
+       req->r_page_alignment = off & ~PAGE_MASK;
        if (op->op == CEPH_OSD_OP_WRITE)
                op->payload_len = *plen;
 
@@ -390,6 +391,8 @@ void ceph_osdc_build_request(struct ceph_osd_request *req,
                req->r_request->hdr.data_len = cpu_to_le32(data_len);
        }
 
+       req->r_request->page_alignment = req->r_page_alignment;
+
        BUG_ON(p > msg->front.iov_base + msg->front.iov_len);
        msg_size = p - msg->front.iov_base;
        msg->front.iov_len = msg_size;
@@ -419,7 +422,8 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
                                               u32 truncate_seq,
                                               u64 truncate_size,
                                               struct timespec *mtime,
-                                              bool use_mempool, int num_reply)
+                                              bool use_mempool, int num_reply,
+                                              int page_align)
 {
        struct ceph_osd_req_op ops[3];
        struct ceph_osd_request *req;
@@ -447,6 +451,10 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
        calc_layout(osdc, vino, layout, off, plen, req, ops);
        req->r_file_layout = *layout;  /* keep a copy */
 
+       /* in case it differs from natural alignment that calc_layout
+          filled in for us */
+       req->r_page_alignment = page_align;
+
        ceph_osdc_build_request(req, off, plen, ops,
                                snapc,
                                mtime,
@@ -1489,7 +1497,7 @@ int ceph_osdc_readpages(struct ceph_osd_client *osdc,
                        struct ceph_vino vino, struct ceph_file_layout *layout,
                        u64 off, u64 *plen,
                        u32 truncate_seq, u64 truncate_size,
-                       struct page **pages, int num_pages)
+                       struct page **pages, int num_pages, int page_align)
 {
        struct ceph_osd_request *req;
        int rc = 0;
@@ -1499,15 +1507,15 @@ int ceph_osdc_readpages(struct ceph_osd_client *osdc,
        req = ceph_osdc_new_request(osdc, layout, vino, off, plen,
                                    CEPH_OSD_OP_READ, CEPH_OSD_FLAG_READ,
                                    NULL, 0, truncate_seq, truncate_size, NULL,
-                                   false, 1);
+                                   false, 1, page_align);
        if (!req)
                return -ENOMEM;
 
        /* it may be a short read due to an object boundary */
        req->r_pages = pages;
 
-       dout("readpages  final extent is %llu~%llu (%d pages)\n",
-            off, *plen, req->r_num_pages);
+       dout("readpages  final extent is %llu~%llu (%d pages align %d)\n",
+            off, *plen, req->r_num_pages, page_align);
 
        rc = ceph_osdc_start_request(osdc, req, false);
        if (!rc)
@@ -1533,6 +1541,7 @@ int ceph_osdc_writepages(struct ceph_osd_client *osdc, struct ceph_vino vino,
 {
        struct ceph_osd_request *req;
        int rc = 0;
+       int page_align = off & ~PAGE_MASK;
 
        BUG_ON(vino.snap != CEPH_NOSNAP);
        req = ceph_osdc_new_request(osdc, layout, vino, off, &len,
@@ -1541,7 +1550,7 @@ int ceph_osdc_writepages(struct ceph_osd_client *osdc, struct ceph_vino vino,
                                            CEPH_OSD_FLAG_WRITE,
                                    snapc, do_sync,
                                    truncate_seq, truncate_size, mtime,
-                                   nofail, 1);
+                                   nofail, 1, page_align);
        if (!req)
                return -ENOMEM;
 
@@ -1638,8 +1647,7 @@ static struct ceph_msg *get_reply(struct ceph_connection *con,
        m = ceph_msg_get(req->r_reply);
 
        if (data_len > 0) {
-               unsigned data_off = le16_to_cpu(hdr->data_off);
-               int want = calc_pages_for(data_off & ~PAGE_MASK, data_len);
+               int want = calc_pages_for(req->r_page_alignment, data_len);
 
                if (unlikely(req->r_num_pages < want)) {
                        pr_warning("tid %lld reply %d > expected %d pages\n",
@@ -1651,6 +1659,7 @@ static struct ceph_msg *get_reply(struct ceph_connection *con,
                }
                m->pages = req->r_pages;
                m->nr_pages = req->r_num_pages;
+               m->page_alignment = req->r_page_alignment;
 #ifdef CONFIG_BLOCK
                m->bio = req->r_bio;
 #endif
index 54caf06871559adb490018023cea7163f2451706..1a040e64c69f23545f98e282bae934b3ed33baa9 100644 (file)
@@ -13,8 +13,7 @@
  * build a vector of user pages
  */
 struct page **ceph_get_direct_page_vector(const char __user *data,
-                                                int num_pages,
-                                                loff_t off, size_t len)
+                                         int num_pages, bool write_page)
 {
        struct page **pages;
        int rc;
@@ -25,24 +24,27 @@ struct page **ceph_get_direct_page_vector(const char __user *data,
 
        down_read(&current->mm->mmap_sem);
        rc = get_user_pages(current, current->mm, (unsigned long)data,
-                           num_pages, 0, 0, pages, NULL);
+                           num_pages, write_page, 0, pages, NULL);
        up_read(&current->mm->mmap_sem);
-       if (rc < 0)
+       if (rc < num_pages)
                goto fail;
        return pages;
 
 fail:
-       kfree(pages);
+       ceph_put_page_vector(pages, rc > 0 ? rc : 0, false);
        return ERR_PTR(rc);
 }
 EXPORT_SYMBOL(ceph_get_direct_page_vector);
 
-void ceph_put_page_vector(struct page **pages, int num_pages)
+void ceph_put_page_vector(struct page **pages, int num_pages, bool dirty)
 {
        int i;
 
-       for (i = 0; i < num_pages; i++)
+       for (i = 0; i < num_pages; i++) {
+               if (dirty)
+                       set_page_dirty_lock(pages[i]);
                put_page(pages[i]);
+       }
        kfree(pages);
 }
 EXPORT_SYMBOL(ceph_put_page_vector);
index 23e9b2a6b4c8ade67fff929c78cea57483b49964..ae21a0d3c4a2a4566c3792476e07ce0d2d2ece38 100644 (file)
@@ -589,23 +589,16 @@ int sk_chk_filter(struct sock_filter *filter, int flen)
 EXPORT_SYMBOL(sk_chk_filter);
 
 /**
- *     sk_filter_rcu_release: Release a socket filter by rcu_head
+ *     sk_filter_release_rcu - Release a socket filter by rcu_head
  *     @rcu: rcu_head that contains the sk_filter to free
  */
-static void sk_filter_rcu_release(struct rcu_head *rcu)
+void sk_filter_release_rcu(struct rcu_head *rcu)
 {
        struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu);
 
-       sk_filter_release(fp);
-}
-
-static void sk_filter_delayed_uncharge(struct sock *sk, struct sk_filter *fp)
-{
-       unsigned int size = sk_filter_len(fp);
-
-       atomic_sub(size, &sk->sk_omem_alloc);
-       call_rcu_bh(&fp->rcu, sk_filter_rcu_release);
+       kfree(fp);
 }
+EXPORT_SYMBOL(sk_filter_release_rcu);
 
 /**
  *     sk_attach_filter - attach a socket filter
@@ -649,7 +642,7 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
        rcu_assign_pointer(sk->sk_filter, fp);
 
        if (old_fp)
-               sk_filter_delayed_uncharge(sk, old_fp);
+               sk_filter_uncharge(sk, old_fp);
        return 0;
 }
 EXPORT_SYMBOL_GPL(sk_attach_filter);
@@ -663,7 +656,7 @@ int sk_detach_filter(struct sock *sk)
                                           sock_owned_by_user(sk));
        if (filter) {
                rcu_assign_pointer(sk->sk_filter, NULL);
-               sk_filter_delayed_uncharge(sk, filter);
+               sk_filter_uncharge(sk, filter);
                ret = 0;
        }
        return ret;
index a5ff5a89f376bb1299dec78fa34abe9480ae01f1..7f902cad10f8b13d7096f53905e3a47bb3c12d25 100644 (file)
@@ -712,15 +712,21 @@ static void rx_queue_release(struct kobject *kobj)
 
 
        map = rcu_dereference_raw(queue->rps_map);
-       if (map)
+       if (map) {
+               RCU_INIT_POINTER(queue->rps_map, NULL);
                call_rcu(&map->rcu, rps_map_release);
+       }
 
        flow_table = rcu_dereference_raw(queue->rps_flow_table);
-       if (flow_table)
+       if (flow_table) {
+               RCU_INIT_POINTER(queue->rps_flow_table, NULL);
                call_rcu(&flow_table->rcu, rps_dev_flow_table_release);
+       }
 
        if (atomic_dec_and_test(&first->count))
                kfree(first);
+       else
+               memset(kobj, 0, sizeof(*kobj));
 }
 
 static struct kobj_type rx_queue_ktype = {
index 7552495aff7aef090d99654312d5365afa421e95..fceeb37d7161697922dd46e00d62e3c1cd89eb4b 100644 (file)
@@ -45,9 +45,7 @@ int reqsk_queue_alloc(struct request_sock_queue *queue,
        nr_table_entries = roundup_pow_of_two(nr_table_entries + 1);
        lopt_size += nr_table_entries * sizeof(struct request_sock *);
        if (lopt_size > PAGE_SIZE)
-               lopt = __vmalloc(lopt_size,
-                       GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO,
-                       PAGE_KERNEL);
+               lopt = vzalloc(lopt_size);
        else
                lopt = kzalloc(lopt_size, GFP_KERNEL);
        if (lopt == NULL)
index 0ae6c22da85b2a3516980691c8fbcf2f7228e3d6..c19bb4ee405ede196271ac9af5452dd21525fe2e 100644 (file)
@@ -96,11 +96,13 @@ bool skb_defer_rx_timestamp(struct sk_buff *skb)
        struct phy_device *phydev;
        unsigned int type;
 
-       skb_push(skb, ETH_HLEN);
+       if (skb_headroom(skb) < ETH_HLEN)
+               return false;
+       __skb_push(skb, ETH_HLEN);
 
        type = classify(skb);
 
-       skb_pull(skb, ETH_HLEN);
+       __skb_pull(skb, ETH_HLEN);
 
        switch (type) {
        case PTP_CLASS_V1_IPV4:
index 265985370fa1de664b1b7f3de427cb043fc74665..e424a09e83f61e6410607c01a2623ee5f8dea854 100644 (file)
@@ -239,7 +239,8 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb)
                dccp_update_gsr(sk, seqno);
 
                if (dh->dccph_type != DCCP_PKT_SYNC &&
-                   (ackno != DCCP_PKT_WITHOUT_ACK_SEQ))
+                   ackno != DCCP_PKT_WITHOUT_ACK_SEQ &&
+                   after48(ackno, dp->dccps_gar))
                        dp->dccps_gar = ackno;
        } else {
                unsigned long now = jiffies;
index a76b78de679fa7e928cfae7b62c0a7e73c2256dd..6f97268ed85fe5de5b5d3318a038f49d0f65629e 100644 (file)
@@ -1556,6 +1556,8 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char __us
                        if (r_len > sizeof(struct linkinfo_dn))
                                r_len = sizeof(struct linkinfo_dn);
 
+                       memset(&link, 0, sizeof(link));
+
                        switch(sock->state) {
                                case SS_CONNECTING:
                                        link.idn_linkstate = LL_CONNECTING;
index f8c1ae4b41f03641f7bb7db11feb88893df65519..15dcc1a586b4a312ee877e78b4e72f1a5e9631e2 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/skbuff.h>
 #include <linux/udp.h>
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 #include <net/sock.h>
 #include <net/inet_common.h>
 #include <linux/stat.h>
@@ -276,12 +277,12 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
 #endif
 #ifdef CONFIG_ECONET_AUNUDP
        struct msghdr udpmsg;
-       struct iovec iov[msg->msg_iovlen+1];
+       struct iovec iov[2];
        struct aunhdr ah;
        struct sockaddr_in udpdest;
        __kernel_size_t size;
-       int i;
        mm_segment_t oldfs;
+       char *userbuf;
 #endif
 
        /*
@@ -297,23 +298,14 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
 
        mutex_lock(&econet_mutex);
 
-       if (saddr == NULL) {
-               struct econet_sock *eo = ec_sk(sk);
-
-               addr.station = eo->station;
-               addr.net     = eo->net;
-               port         = eo->port;
-               cb           = eo->cb;
-       } else {
-               if (msg->msg_namelen < sizeof(struct sockaddr_ec)) {
-                       mutex_unlock(&econet_mutex);
-                       return -EINVAL;
-               }
-               addr.station = saddr->addr.station;
-               addr.net = saddr->addr.net;
-               port = saddr->port;
-               cb = saddr->cb;
-       }
+        if (saddr == NULL || msg->msg_namelen < sizeof(struct sockaddr_ec)) {
+                mutex_unlock(&econet_mutex);
+                return -EINVAL;
+        }
+        addr.station = saddr->addr.station;
+        addr.net = saddr->addr.net;
+        port = saddr->port;
+        cb = saddr->cb;
 
        /* Look for a device with the right network number. */
        dev = net2dev_map[addr.net];
@@ -328,17 +320,17 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
                }
        }
 
-       if (len + 15 > dev->mtu) {
-               mutex_unlock(&econet_mutex);
-               return -EMSGSIZE;
-       }
-
        if (dev->type == ARPHRD_ECONET) {
                /* Real hardware Econet.  We're not worthy etc. */
 #ifdef CONFIG_ECONET_NATIVE
                unsigned short proto = 0;
                int res;
 
+               if (len + 15 > dev->mtu) {
+                       mutex_unlock(&econet_mutex);
+                       return -EMSGSIZE;
+               }
+
                dev_hold(dev);
 
                skb = sock_alloc_send_skb(sk, len+LL_ALLOCATED_SPACE(dev),
@@ -351,7 +343,6 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
 
                eb = (struct ec_cb *)&skb->cb;
 
-               /* BUG: saddr may be NULL */
                eb->cookie = saddr->cookie;
                eb->sec = *saddr;
                eb->sent = ec_tx_done;
@@ -415,6 +406,11 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
                return -ENETDOWN;               /* No socket - can't send */
        }
 
+       if (len > 32768) {
+               err = -E2BIG;
+               goto error;
+       }
+
        /* Make up a UDP datagram and hand it off to some higher intellect. */
 
        memset(&udpdest, 0, sizeof(udpdest));
@@ -446,36 +442,26 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
 
        /* tack our header on the front of the iovec */
        size = sizeof(struct aunhdr);
-       /*
-        * XXX: that is b0rken.  We can't mix userland and kernel pointers
-        * in iovec, since on a lot of platforms copy_from_user() will
-        * *not* work with the kernel and userland ones at the same time,
-        * regardless of what we do with set_fs().  And we are talking about
-        * econet-over-ethernet here, so "it's only ARM anyway" doesn't
-        * apply.  Any suggestions on fixing that code?         -- AV
-        */
        iov[0].iov_base = (void *)&ah;
        iov[0].iov_len = size;
-       for (i = 0; i < msg->msg_iovlen; i++) {
-               void __user *base = msg->msg_iov[i].iov_base;
-               size_t iov_len = msg->msg_iov[i].iov_len;
-               /* Check it now since we switch to KERNEL_DS later. */
-               if (!access_ok(VERIFY_READ, base, iov_len)) {
-                       mutex_unlock(&econet_mutex);
-                       return -EFAULT;
-               }
-               iov[i+1].iov_base = base;
-               iov[i+1].iov_len = iov_len;
-               size += iov_len;
+
+       userbuf = vmalloc(len);
+       if (userbuf == NULL) {
+               err = -ENOMEM;
+               goto error;
        }
 
+       iov[1].iov_base = userbuf;
+       iov[1].iov_len = len;
+       err = memcpy_fromiovec(userbuf, msg->msg_iov, len);
+       if (err)
+               goto error_free_buf;
+
        /* Get a skbuff (no data, just holds our cb information) */
        if ((skb = sock_alloc_send_skb(sk, 0,
                                       msg->msg_flags & MSG_DONTWAIT,
-                                      &err)) == NULL) {
-               mutex_unlock(&econet_mutex);
-               return err;
-       }
+                                      &err)) == NULL)
+               goto error_free_buf;
 
        eb = (struct ec_cb *)&skb->cb;
 
@@ -491,7 +477,7 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
        udpmsg.msg_name = (void *)&udpdest;
        udpmsg.msg_namelen = sizeof(udpdest);
        udpmsg.msg_iov = &iov[0];
-       udpmsg.msg_iovlen = msg->msg_iovlen + 1;
+       udpmsg.msg_iovlen = 2;
        udpmsg.msg_control = NULL;
        udpmsg.msg_controllen = 0;
        udpmsg.msg_flags=0;
@@ -499,9 +485,13 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
        oldfs = get_fs(); set_fs(KERNEL_DS);    /* More privs :-) */
        err = sock_sendmsg(udpsock, &udpmsg, size);
        set_fs(oldfs);
+
+error_free_buf:
+       vfree(userbuf);
 #else
        err = -EPROTOTYPE;
 #endif
+       error:
        mutex_unlock(&econet_mutex);
 
        return err;
@@ -671,6 +661,11 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg)
        err = 0;
        switch (cmd) {
        case SIOCSIFADDR:
+               if (!capable(CAP_NET_ADMIN)) {
+                       err = -EPERM;
+                       break;
+               }
+
                edev = dev->ec_ptr;
                if (edev == NULL) {
                        /* Magic up a new one. */
@@ -856,9 +851,13 @@ static void aun_incoming(struct sk_buff *skb, struct aunhdr *ah, size_t len)
 {
        struct iphdr *ip = ip_hdr(skb);
        unsigned char stn = ntohl(ip->saddr) & 0xff;
+       struct dst_entry *dst = skb_dst(skb);
+       struct ec_device *edev = NULL;
        struct sock *sk = NULL;
        struct sk_buff *newskb;
-       struct ec_device *edev = skb->dev->ec_ptr;
+
+       if (dst)
+               edev = dst->dev->ec_ptr;
 
        if (! edev)
                goto bad;
index 200eb538fbb3f77101fe9646893dddbd9e83117b..0f280348e0fdad70adb37f3b33bdbe6fedd99025 100644 (file)
@@ -365,7 +365,7 @@ static struct tnode *tnode_alloc(size_t size)
        if (size <= PAGE_SIZE)
                return kzalloc(size, GFP_KERNEL);
        else
-               return __vmalloc(size, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
+               return vzalloc(size);
 }
 
 static void __tnode_vfree(struct work_struct *arg)
index 96bc7f9475a3f2f0124685cc1b7afb7b58c23d8d..e5d1a44bcbdf04b851d441ea5ebd8fbe44514704 100644 (file)
@@ -569,6 +569,9 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
                /* No need to clone since we're just using its address. */
                rt2 = rt;
 
+               if (!fl.nl_u.ip4_u.saddr)
+                       fl.nl_u.ip4_u.saddr = rt->rt_src;
+
                err = xfrm_lookup(net, (struct dst_entry **)&rt, &fl, NULL, 0);
                switch (err) {
                case 0:
index 1b344f30b463fab9ed70a8f19a19d348d7c626f7..3c0369a3a663693ac24e6acdd2730909ae5ddf4a 100644 (file)
@@ -133,8 +133,7 @@ int __inet_inherit_port(struct sock *sk, struct sock *child)
                        }
                }
        }
-       sk_add_bind_node(child, &tb->owners);
-       inet_csk(child)->icsk_bind_hash = tb;
+       inet_bind_hash(child, tb, port);
        spin_unlock(&head->lock);
 
        return 0;
index 1b48eb1ed4531d3fd037e7ee9aa6367b6cb575f3..b14ec7d03b6e70b9a5a1823261ac18cb40462035 100644 (file)
@@ -253,6 +253,7 @@ static const struct snmp_mib snmp4_net_list[] = {
        SNMP_MIB_ITEM("TCPMinTTLDrop", LINUX_MIB_TCPMINTTLDROP),
        SNMP_MIB_ITEM("TCPDeferAcceptDrop", LINUX_MIB_TCPDEFERACCEPTDROP),
        SNMP_MIB_ITEM("IPReversePathFilter", LINUX_MIB_IPRPFILTER),
+       SNMP_MIB_ITEM("TCPTimeWaitOverflow", LINUX_MIB_TCPTIMEWAITOVERFLOW),
        SNMP_MIB_SENTINEL
 };
 
index e91911d7aae26656f940a747a6d0ccb91739f39a..1b4ec21497a49756025965e4e17e4bc9466f4f5c 100644 (file)
@@ -26,6 +26,8 @@ static int zero;
 static int tcp_retr1_max = 255;
 static int ip_local_port_range_min[] = { 1, 1 };
 static int ip_local_port_range_max[] = { 65535, 65535 };
+static int tcp_adv_win_scale_min = -31;
+static int tcp_adv_win_scale_max = 31;
 
 /* Update system visible IP port range */
 static void set_local_port_range(int range[2])
@@ -426,7 +428,9 @@ static struct ctl_table ipv4_table[] = {
                .data           = &sysctl_tcp_adv_win_scale,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &tcp_adv_win_scale_min,
+               .extra2         = &tcp_adv_win_scale_max,
        },
        {
                .procname       = "tcp_tw_reuse",
index 0814199694854e534eb4ff12671e02313dced8e9..f15c36a706ecb07385d46a7d8eeb1233cfbb2daa 100644 (file)
@@ -2246,7 +2246,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
                /* Values greater than interface MTU won't take effect. However
                 * at the point when this call is done we typically don't yet
                 * know which interface is going to be used */
-               if (val < 64 || val > MAX_TCP_WINDOW) {
+               if (val < TCP_MIN_MSS || val > MAX_TCP_WINDOW) {
                        err = -EINVAL;
                        break;
                }
index 69ccbc1dde9cdfed2719e243fd6091cc9781a876..e13da6de1fc79e26dc6d03b671e1becf9e6c8754 100644 (file)
@@ -2043,7 +2043,9 @@ get_req:
        }
 get_sk:
        sk_nulls_for_each_from(sk, node) {
-               if (sk->sk_family == st->family && net_eq(sock_net(sk), net)) {
+               if (!net_eq(sock_net(sk), net))
+                       continue;
+               if (sk->sk_family == st->family) {
                        cur = sk;
                        goto out;
                }
index 43cf901d765970b6a1a80f167a80ec285a8397b6..a66735f75963582ebc2243e37fd12ca4604be678 100644 (file)
@@ -347,7 +347,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
                 * socket up.  We've got bigger problems than
                 * non-graceful socket closings.
                 */
-               LIMIT_NETDEBUG(KERN_INFO "TCP: time wait bucket table overflow\n");
+               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPTIMEWAITOVERFLOW);
        }
 
        tcp_update_metrics(sk);
index 05b1ecf367632763cbdb1f3bfe0e74c9c4d20c0c..61c2463e2753f809c12f31967e7fa189e41e1f54 100644 (file)
@@ -231,11 +231,10 @@ void tcp_select_initial_window(int __space, __u32 mss,
                /* when initializing use the value from init_rcv_wnd
                 * rather than the default from above
                 */
-               if (init_rcv_wnd &&
-                   (*rcv_wnd > init_rcv_wnd * mss))
-                       *rcv_wnd = init_rcv_wnd * mss;
-               else if (*rcv_wnd > init_cwnd * mss)
-                       *rcv_wnd = init_cwnd * mss;
+               if (init_rcv_wnd)
+                       *rcv_wnd = min(*rcv_wnd, init_rcv_wnd * mss);
+               else
+                       *rcv_wnd = min(*rcv_wnd, init_cwnd * mss);
        }
 
        /* Set the clamp no higher than max representable value */
@@ -386,27 +385,30 @@ struct tcp_out_options {
  */
 static u8 tcp_cookie_size_check(u8 desired)
 {
-       if (desired > 0) {
+       int cookie_size;
+
+       if (desired > 0)
                /* previously specified */
                return desired;
-       }
-       if (sysctl_tcp_cookie_size <= 0) {
+
+       cookie_size = ACCESS_ONCE(sysctl_tcp_cookie_size);
+       if (cookie_size <= 0)
                /* no default specified */
                return 0;
-       }
-       if (sysctl_tcp_cookie_size <= TCP_COOKIE_MIN) {
+
+       if (cookie_size <= TCP_COOKIE_MIN)
                /* value too small, specify minimum */
                return TCP_COOKIE_MIN;
-       }
-       if (sysctl_tcp_cookie_size >= TCP_COOKIE_MAX) {
+
+       if (cookie_size >= TCP_COOKIE_MAX)
                /* value too large, specify maximum */
                return TCP_COOKIE_MAX;
-       }
-       if (0x1 & sysctl_tcp_cookie_size) {
+
+       if (cookie_size & 1)
                /* 8-bit multiple, illegal, fix it */
-               return (u8)(sysctl_tcp_cookie_size + 0x1);
-       }
-       return (u8)sysctl_tcp_cookie_size;
+               cookie_size++;
+
+       return (u8)cookie_size;
 }
 
 /* Write previously computed TCP options to the packet.
@@ -1513,6 +1515,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb)
        struct tcp_sock *tp = tcp_sk(sk);
        const struct inet_connection_sock *icsk = inet_csk(sk);
        u32 send_win, cong_win, limit, in_flight;
+       int win_divisor;
 
        if (TCP_SKB_CB(skb)->flags & TCPHDR_FIN)
                goto send_now;
@@ -1544,13 +1547,14 @@ static int tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb)
        if ((skb != tcp_write_queue_tail(sk)) && (limit >= skb->len))
                goto send_now;
 
-       if (sysctl_tcp_tso_win_divisor) {
+       win_divisor = ACCESS_ONCE(sysctl_tcp_tso_win_divisor);
+       if (win_divisor) {
                u32 chunk = min(tp->snd_wnd, tp->snd_cwnd * tp->mss_cache);
 
                /* If at least some fraction of a window is available,
                 * just use it.
                 */
-               chunk /= sysctl_tcp_tso_win_divisor;
+               chunk /= win_divisor;
                if (limit >= chunk)
                        goto send_now;
        } else {
index b41ce0f0d514154597753d549b5a29a3bc7e7ae0..93b7a933a7758254ed70ed849d333ad4d19114a7 100644 (file)
 #endif
 
 #define        INFINITY_LIFE_TIME      0xFFFFFFFF
-#define TIME_DELTA(a, b) ((unsigned long)((long)(a) - (long)(b)))
+
+static inline u32 cstamp_delta(unsigned long cstamp)
+{
+       return (cstamp - INITIAL_JIFFIES) * 100UL / HZ;
+}
 
 #define ADDRCONF_TIMER_FUZZ_MINUS      (HZ > 50 ? HZ/50 : 1)
 #define ADDRCONF_TIMER_FUZZ            (HZ / 4)
@@ -2754,13 +2758,13 @@ static int addrconf_ifdown(struct net_device *dev, int how)
                        ifa->state = INET6_IFADDR_STATE_DEAD;
                        spin_unlock_bh(&ifa->state_lock);
 
-                       if (state == INET6_IFADDR_STATE_DEAD) {
-                               in6_ifa_put(ifa);
-                       } else {
+                       if (state != INET6_IFADDR_STATE_DEAD) {
                                __ipv6_ifa_notify(RTM_DELADDR, ifa);
                                atomic_notifier_call_chain(&inet6addr_chain,
                                                           NETDEV_DOWN, ifa);
                        }
+
+                       in6_ifa_put(ifa);
                        write_lock_bh(&idev->lock);
                }
        }
@@ -3444,10 +3448,8 @@ static int put_cacheinfo(struct sk_buff *skb, unsigned long cstamp,
 {
        struct ifa_cacheinfo ci;
 
-       ci.cstamp = (u32)(TIME_DELTA(cstamp, INITIAL_JIFFIES) / HZ * 100
-                       + TIME_DELTA(cstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
-       ci.tstamp = (u32)(TIME_DELTA(tstamp, INITIAL_JIFFIES) / HZ * 100
-                       + TIME_DELTA(tstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
+       ci.cstamp = cstamp_delta(cstamp);
+       ci.tstamp = cstamp_delta(tstamp);
        ci.ifa_prefered = preferred;
        ci.ifa_valid = valid;
 
@@ -3798,8 +3800,10 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
        array[DEVCONF_AUTOCONF] = cnf->autoconf;
        array[DEVCONF_DAD_TRANSMITS] = cnf->dad_transmits;
        array[DEVCONF_RTR_SOLICITS] = cnf->rtr_solicits;
-       array[DEVCONF_RTR_SOLICIT_INTERVAL] = cnf->rtr_solicit_interval;
-       array[DEVCONF_RTR_SOLICIT_DELAY] = cnf->rtr_solicit_delay;
+       array[DEVCONF_RTR_SOLICIT_INTERVAL] =
+               jiffies_to_msecs(cnf->rtr_solicit_interval);
+       array[DEVCONF_RTR_SOLICIT_DELAY] =
+               jiffies_to_msecs(cnf->rtr_solicit_delay);
        array[DEVCONF_FORCE_MLD_VERSION] = cnf->force_mld_version;
 #ifdef CONFIG_IPV6_PRIVACY
        array[DEVCONF_USE_TEMPADDR] = cnf->use_tempaddr;
@@ -3813,7 +3817,8 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
        array[DEVCONF_ACCEPT_RA_PINFO] = cnf->accept_ra_pinfo;
 #ifdef CONFIG_IPV6_ROUTER_PREF
        array[DEVCONF_ACCEPT_RA_RTR_PREF] = cnf->accept_ra_rtr_pref;
-       array[DEVCONF_RTR_PROBE_INTERVAL] = cnf->rtr_probe_interval;
+       array[DEVCONF_RTR_PROBE_INTERVAL] =
+               jiffies_to_msecs(cnf->rtr_probe_interval);
 #ifdef CONFIG_IPV6_ROUTE_INFO
        array[DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN] = cnf->accept_ra_rt_info_max_plen;
 #endif
@@ -3929,10 +3934,9 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
        NLA_PUT_U32(skb, IFLA_INET6_FLAGS, idev->if_flags);
 
        ci.max_reasm_len = IPV6_MAXPLEN;
-       ci.tstamp = (__u32)(TIME_DELTA(idev->tstamp, INITIAL_JIFFIES) / HZ * 100
-                   + TIME_DELTA(idev->tstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
-       ci.reachable_time = idev->nd_parms->reachable_time;
-       ci.retrans_time = idev->nd_parms->retrans_time;
+       ci.tstamp = cstamp_delta(idev->tstamp);
+       ci.reachable_time = jiffies_to_msecs(idev->nd_parms->reachable_time);
+       ci.retrans_time = jiffies_to_msecs(idev->nd_parms->retrans_time);
        NLA_PUT(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci);
 
        nla = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32));
@@ -4017,11 +4021,11 @@ void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
                kfree_skb(skb);
                goto errout;
        }
-       rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
+       rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFINFO, NULL, GFP_ATOMIC);
        return;
 errout:
        if (err < 0)
-               rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err);
+               rtnl_set_sk_err(net, RTNLGRP_IPV6_IFINFO, err);
 }
 
 static inline size_t inet6_prefix_nlmsg_size(void)
index 2a59610c2a582ed885ae756729b58da00e6f324f..70e891a20fb9258686b9d9914e6694a3837d0acb 100644 (file)
@@ -1175,6 +1175,8 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
                                sizeof (struct ipv6hdr);
 
                        dev->mtu = rt->rt6i_dev->mtu - sizeof (struct ipv6hdr);
+                       if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
+                               dev->mtu-=8;
 
                        if (dev->mtu < IPV6_MIN_MTU)
                                dev->mtu = IPV6_MIN_MTU;
@@ -1363,12 +1365,17 @@ static const struct net_device_ops ip6_tnl_netdev_ops = {
 
 static void ip6_tnl_dev_setup(struct net_device *dev)
 {
+       struct ip6_tnl *t;
+
        dev->netdev_ops = &ip6_tnl_netdev_ops;
        dev->destructor = ip6_dev_free;
 
        dev->type = ARPHRD_TUNNEL6;
        dev->hard_header_len = LL_MAX_HEADER + sizeof (struct ipv6hdr);
        dev->mtu = ETH_DATA_LEN - sizeof (struct ipv6hdr);
+       t = netdev_priv(dev);
+       if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
+               dev->mtu-=8;
        dev->flags |= IFF_NOARP;
        dev->addr_len = sizeof(struct in6_addr);
        dev->features |= NETIF_F_NETNS_LOCAL;
index d6bfaec3bbbf1a91701fd31616757af1a565bb41..8c4d00c7cd2bb030c194c19e00b5455d2cddf3df 100644 (file)
@@ -606,8 +606,9 @@ static int ipip6_rcv(struct sk_buff *skb)
                return 0;
        }
 
-       icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
+       /* no tunnel matched,  let upstream know, ipsec may handle it */
        rcu_read_unlock();
+       return 1;
 out:
        kfree_skb(skb);
        return 0;
index 285761e77d90f98ee15c6b47b34c8ead10692e33..f6054f9ccbe33c2fbd9aef8c88551c84bb5fbf62 100644 (file)
@@ -550,22 +550,30 @@ EXPORT_SYMBOL(irttp_close_tsap);
  */
 int irttp_udata_request(struct tsap_cb *self, struct sk_buff *skb)
 {
+       int ret;
+
        IRDA_ASSERT(self != NULL, return -1;);
        IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
        IRDA_ASSERT(skb != NULL, return -1;);
 
        IRDA_DEBUG(4, "%s()\n", __func__);
 
+       /* Take shortcut on zero byte packets */
+       if (skb->len == 0) {
+               ret = 0;
+               goto err;
+       }
+
        /* Check that nothing bad happens */
-       if ((skb->len == 0) || (!self->connected)) {
-               IRDA_DEBUG(1, "%s(), No data, or not connected\n",
-                          __func__);
+       if (!self->connected) {
+               IRDA_WARNING("%s(), Not connected\n", __func__);
+               ret = -ENOTCONN;
                goto err;
        }
 
        if (skb->len > self->max_seg_size) {
-               IRDA_DEBUG(1, "%s(), UData is too large for IrLAP!\n",
-                          __func__);
+               IRDA_ERROR("%s(), UData is too large for IrLAP!\n", __func__);
+               ret = -EMSGSIZE;
                goto err;
        }
 
@@ -576,7 +584,7 @@ int irttp_udata_request(struct tsap_cb *self, struct sk_buff *skb)
 
 err:
        dev_kfree_skb(skb);
-       return -1;
+       return ret;
 }
 EXPORT_SYMBOL(irttp_udata_request);
 
@@ -599,9 +607,15 @@ int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb)
        IRDA_DEBUG(2, "%s() : queue len = %d\n", __func__,
                   skb_queue_len(&self->tx_queue));
 
+       /* Take shortcut on zero byte packets */
+       if (skb->len == 0) {
+               ret = 0;
+               goto err;
+       }
+
        /* Check that nothing bad happens */
-       if ((skb->len == 0) || (!self->connected)) {
-               IRDA_WARNING("%s: No data, or not connected\n", __func__);
+       if (!self->connected) {
+               IRDA_WARNING("%s: Not connected\n", __func__);
                ret = -ENOTCONN;
                goto err;
        }
index 0bf6a59545ab9439f3ab7126539cd9aef419b752..522e219f3558a3e0e3ad70f27e2de3d09ed8f543 100644 (file)
@@ -674,4 +674,8 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
 MODULE_DESCRIPTION("L2TP over IP");
 MODULE_VERSION("1.0");
-MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, SOCK_DGRAM, IPPROTO_L2TP);
+
+/* Use the value of SOCK_DGRAM (2) directory, because __stringify does't like
+ * enums
+ */
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 2, IPPROTO_L2TP);
index 582612998211d24aa8d4aea919eed1ba1e994db3..e35dbe55f5201c7a8b4b61ffe382766e4abadcb8 100644 (file)
@@ -317,8 +317,9 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
                goto out;
        rc = -ENODEV;
        rtnl_lock();
+       rcu_read_lock();
        if (sk->sk_bound_dev_if) {
-               llc->dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if);
+               llc->dev = dev_get_by_index_rcu(&init_net, sk->sk_bound_dev_if);
                if (llc->dev) {
                        if (!addr->sllc_arphrd)
                                addr->sllc_arphrd = llc->dev->type;
@@ -329,13 +330,13 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
                            !llc_mac_match(addr->sllc_mac,
                                           llc->dev->dev_addr)) {
                                rc = -EINVAL;
-                               dev_put(llc->dev);
                                llc->dev = NULL;
                        }
                }
        } else
                llc->dev = dev_getbyhwaddr(&init_net, addr->sllc_arphrd,
                                           addr->sllc_mac);
+       rcu_read_unlock();
        rtnl_unlock();
        if (!llc->dev)
                goto out;
index 4d6f8653ec8819a7e69cdb9cb447b77c1e7e7047..8e8ea9cb7093185b4645a6bf7d23467e15ee518b 100644 (file)
@@ -92,7 +92,7 @@ config MAC80211_MESH
 config MAC80211_LEDS
        bool "Enable LED triggers"
        depends on MAC80211
-       select NEW_LEDS
+       depends on LEDS_CLASS
        select LEDS_TRIGGERS
        ---help---
          This option enables a few LED triggers for different
index 902b03ee8f60789bab002691e2db69d1f8c12cf4..54fb4a0e76f03d835c6038cffeabf18874cb2d59 100644 (file)
@@ -2247,6 +2247,10 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
                break;
        case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
        case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
+               if (is_multicast_ether_addr(mgmt->da) &&
+                   !is_broadcast_ether_addr(mgmt->da))
+                       return RX_DROP_MONITOR;
+
                /* process only for station */
                if (sdata->vif.type != NL80211_IFTYPE_STATION)
                        return RX_DROP_MONITOR;
@@ -2741,6 +2745,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
 
                        if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
                                return;
+                       goto out;
                }
        }
 
@@ -2780,6 +2785,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
                        return;
        }
 
+ out:
        dev_kfree_skb(skb);
 }
 
index 96c594309506432b897b4ab8c749aed4cb3c1349..7a637b80a62ef7a8d00d49285d9d6995b4083d9e 100644 (file)
@@ -1587,7 +1587,12 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
                                                list) {
                                if (!ieee80211_sdata_running(tmp_sdata))
                                        continue;
-                               if (tmp_sdata->vif.type != NL80211_IFTYPE_AP)
+                               if (tmp_sdata->vif.type ==
+                                   NL80211_IFTYPE_MONITOR ||
+                                   tmp_sdata->vif.type ==
+                                   NL80211_IFTYPE_AP_VLAN ||
+                                       tmp_sdata->vif.type ==
+                                   NL80211_IFTYPE_WDS)
                                        continue;
                                if (compare_ether_addr(tmp_sdata->vif.addr,
                                                       hdr->addr2) == 0) {
@@ -1732,15 +1737,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
        int nh_pos, h_pos;
        struct sta_info *sta = NULL;
        u32 sta_flags = 0;
+       struct sk_buff *tmp_skb;
 
        if (unlikely(skb->len < ETH_HLEN)) {
                ret = NETDEV_TX_OK;
                goto fail;
        }
 
-       nh_pos = skb_network_header(skb) - skb->data;
-       h_pos = skb_transport_header(skb) - skb->data;
-
        /* convert Ethernet header to proper 802.11 header (based on
         * operation mode) */
        ethertype = (skb->data[12] << 8) | skb->data[13];
@@ -1913,6 +1916,20 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                goto fail;
        }
 
+       /*
+        * If the skb is shared we need to obtain our own copy.
+        */
+       if (skb_shared(skb)) {
+               tmp_skb = skb;
+               skb = skb_copy(skb, GFP_ATOMIC);
+               kfree_skb(tmp_skb);
+
+               if (!skb) {
+                       ret = NETDEV_TX_OK;
+                       goto fail;
+               }
+       }
+
        hdr.frame_control = fc;
        hdr.duration_id = 0;
        hdr.seq_ctrl = 0;
@@ -1931,6 +1948,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                encaps_len = 0;
        }
 
+       nh_pos = skb_network_header(skb) - skb->data;
+       h_pos = skb_transport_header(skb) - skb->data;
+
        skb_pull(skb, skip_header_bytes);
        nh_pos -= skip_header_bytes;
        h_pos -= skip_header_bytes;
index a22dac227055e7499bfd9d8dd509ee5fba3e1c9b..70bd1d0774c6bdb6b1f9d4d1f07284cfe43500dd 100644 (file)
@@ -4,6 +4,7 @@
 menuconfig IP_VS
        tristate "IP virtual server support"
        depends on NET && INET && NETFILTER
+       depends on (NF_CONNTRACK || NF_CONNTRACK=n)
        ---help---
          IP Virtual Server support will let you build a high-performance
          virtual server based on cluster of two or more real servers. This
index 8920f2a83327a42f10d20acdfb651f9c1b9620a3..4e37c1cbe8b2faf5928af6be551f3f5551684411 100644 (file)
@@ -567,7 +567,7 @@ int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
                goto out;
        }
 
-       if (args->nr_local > (u64)UINT_MAX) {
+       if (args->nr_local > UIO_MAXIOV) {
                ret = -EMSGSIZE;
                goto out;
        }
index 6bd554323a342d4db49be267766b87492bd2e584..0b9ee34ad35ceb31ff764baf9cec73fba010f55b 100644 (file)
@@ -2932,6 +2932,7 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optva
        struct sctp_association *asoc = NULL;
        struct sctp_setpeerprim prim;
        struct sctp_chunk       *chunk;
+       struct sctp_af          *af;
        int                     err;
 
        sp = sctp_sk(sk);
@@ -2959,6 +2960,13 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optva
        if (!sctp_state(asoc, ESTABLISHED))
                return -ENOTCONN;
 
+       af = sctp_get_af_specific(prim.sspp_addr.ss_family);
+       if (!af)
+               return -EINVAL;
+
+       if (!af->addr_valid((union sctp_addr *)&prim.sspp_addr, sp, NULL))
+               return -EADDRNOTAVAIL;
+
        if (!sctp_assoc_lookup_laddr(asoc, (union sctp_addr *)&prim.sspp_addr))
                return -EADDRNOTAVAIL;
 
index 3ca2fd9e37200e3e12f6606065acb8c982f25528..088fb3fd45e00f3fa5d55e3e374c8751e60d225b 100644 (file)
@@ -732,6 +732,21 @@ static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
        return ret;
 }
 
+/**
+ * kernel_recvmsg - Receive a message from a socket (kernel space)
+ * @sock:       The socket to receive the message from
+ * @msg:        Received message
+ * @vec:        Input s/g array for message data
+ * @num:        Size of input s/g array
+ * @size:       Number of bytes to read
+ * @flags:      Message flags (MSG_DONTWAIT, etc...)
+ *
+ * On return the msg structure contains the scatter/gather array passed in the
+ * vec argument. The array is modified so that it consists of the unfilled
+ * portion of the original array.
+ *
+ * The returned value is the total number of bytes received, or an error.
+ */
 int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
                   struct kvec *vec, size_t num, size_t size, int flags)
 {
index 9dab9573be4146feafd1fb2db584faa3b61b0b0b..92ce94f5146b3cfb924d0103d62a2f0d51fdf84e 100644 (file)
@@ -989,20 +989,26 @@ call_refreshresult(struct rpc_task *task)
        dprint_status(task);
 
        task->tk_status = 0;
-       task->tk_action = call_allocate;
-       if (status >= 0 && rpcauth_uptodatecred(task))
-               return;
+       task->tk_action = call_refresh;
        switch (status) {
-       case -EACCES:
-               rpc_exit(task, -EACCES);
-               return;
-       case -ENOMEM:
-               rpc_exit(task, -ENOMEM);
+       case 0:
+               if (rpcauth_uptodatecred(task))
+                       task->tk_action = call_allocate;
                return;
        case -ETIMEDOUT:
                rpc_delay(task, 3*HZ);
+       case -EAGAIN:
+               status = -EACCES;
+               if (!task->tk_cred_retry)
+                       break;
+               task->tk_cred_retry--;
+               dprintk("RPC: %5u %s: retry refresh creds\n",
+                               task->tk_pid, __func__);
+               return;
        }
-       task->tk_action = call_refresh;
+       dprintk("RPC: %5u %s: refresh creds failed with error %d\n",
+                               task->tk_pid, __func__, status);
+       rpc_exit(task, status);
 }
 
 /*
index ea2ff78dcf7b7ec4f2555210af82379017e6e291..3f2c5559ca1a49a496b9d531625c1e175fb029c8 100644 (file)
@@ -212,6 +212,7 @@ int svc_create_xprt(struct svc_serv *serv, const char *xprt_name,
        spin_lock(&svc_xprt_class_lock);
        list_for_each_entry(xcl, &svc_xprt_class_list, xcl_list) {
                struct svc_xprt *newxprt;
+               unsigned short newport;
 
                if (strcmp(xprt_name, xcl->xcl_name))
                        continue;
@@ -230,8 +231,9 @@ int svc_create_xprt(struct svc_serv *serv, const char *xprt_name,
                spin_lock_bh(&serv->sv_lock);
                list_add(&newxprt->xpt_list, &serv->sv_permsocks);
                spin_unlock_bh(&serv->sv_lock);
+               newport = svc_xprt_local_port(newxprt);
                clear_bit(XPT_BUSY, &newxprt->xpt_flags);
-               return svc_xprt_local_port(newxprt);
+               return newport;
        }
  err:
        spin_unlock(&svc_xprt_class_lock);
@@ -425,8 +427,13 @@ void svc_xprt_received(struct svc_xprt *xprt)
 {
        BUG_ON(!test_bit(XPT_BUSY, &xprt->xpt_flags));
        xprt->xpt_pool = NULL;
+       /* As soon as we clear busy, the xprt could be closed and
+        * 'put', so we need a reference to call svc_xprt_enqueue with:
+        */
+       svc_xprt_get(xprt);
        clear_bit(XPT_BUSY, &xprt->xpt_flags);
        svc_xprt_enqueue(xprt);
+       svc_xprt_put(xprt);
 }
 EXPORT_SYMBOL_GPL(svc_xprt_received);
 
index 3c95304a08174f550f64f36346ce031419f6a4c8..2268e6798124c9300cd4c10f5a65376898252210 100644 (file)
@@ -1343,9 +1343,25 @@ static void unix_destruct_scm(struct sk_buff *skb)
        sock_wfree(skb);
 }
 
+#define MAX_RECURSION_LEVEL 4
+
 static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
 {
        int i;
+       unsigned char max_level = 0;
+       int unix_sock_count = 0;
+
+       for (i = scm->fp->count - 1; i >= 0; i--) {
+               struct sock *sk = unix_get_socket(scm->fp->fp[i]);
+
+               if (sk) {
+                       unix_sock_count++;
+                       max_level = max(max_level,
+                                       unix_sk(sk)->recursion_level);
+               }
+       }
+       if (unlikely(max_level > MAX_RECURSION_LEVEL))
+               return -ETOOMANYREFS;
 
        /*
         * Need to duplicate file references for the sake of garbage
@@ -1356,9 +1372,11 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
        if (!UNIXCB(skb).fp)
                return -ENOMEM;
 
-       for (i = scm->fp->count-1; i >= 0; i--)
-               unix_inflight(scm->fp->fp[i]);
-       return 0;
+       if (unix_sock_count) {
+               for (i = scm->fp->count - 1; i >= 0; i--)
+                       unix_inflight(scm->fp->fp[i]);
+       }
+       return max_level;
 }
 
 static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds)
@@ -1393,6 +1411,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
        struct sk_buff *skb;
        long timeo;
        struct scm_cookie tmp_scm;
+       int max_level;
 
        if (NULL == siocb->scm)
                siocb->scm = &tmp_scm;
@@ -1431,8 +1450,9 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
                goto out;
 
        err = unix_scm_to_skb(siocb->scm, skb, true);
-       if (err)
+       if (err < 0)
                goto out_free;
+       max_level = err + 1;
        unix_get_secdata(siocb->scm, skb);
 
        skb_reset_transport_header(skb);
@@ -1514,6 +1534,8 @@ restart:
        if (sock_flag(other, SOCK_RCVTSTAMP))
                __net_timestamp(skb);
        skb_queue_tail(&other->sk_receive_queue, skb);
+       if (max_level > unix_sk(other)->recursion_level)
+               unix_sk(other)->recursion_level = max_level;
        unix_state_unlock(other);
        other->sk_data_ready(other, len);
        sock_put(other);
@@ -1544,6 +1566,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
        int sent = 0;
        struct scm_cookie tmp_scm;
        bool fds_sent = false;
+       int max_level;
 
        if (NULL == siocb->scm)
                siocb->scm = &tmp_scm;
@@ -1607,10 +1630,11 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
 
                /* Only send the fds in the first buffer */
                err = unix_scm_to_skb(siocb->scm, skb, !fds_sent);
-               if (err) {
+               if (err < 0) {
                        kfree_skb(skb);
                        goto out_err;
                }
+               max_level = err + 1;
                fds_sent = true;
 
                err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
@@ -1626,6 +1650,8 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
                        goto pipe_err_free;
 
                skb_queue_tail(&other->sk_receive_queue, skb);
+               if (max_level > unix_sk(other)->recursion_level)
+                       unix_sk(other)->recursion_level = max_level;
                unix_state_unlock(other);
                other->sk_data_ready(other, size);
                sent += size;
@@ -1845,6 +1871,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
                unix_state_lock(sk);
                skb = skb_dequeue(&sk->sk_receive_queue);
                if (skb == NULL) {
+                       unix_sk(sk)->recursion_level = 0;
                        if (copied >= target)
                                goto unlock;
 
index c8df6fda0b1fcf124b65812f600710a3b3f17069..f89f83bf828ee0e713ded75c84da22a1c1b2426e 100644 (file)
@@ -96,7 +96,7 @@ static DECLARE_WAIT_QUEUE_HEAD(unix_gc_wait);
 unsigned int unix_tot_inflight;
 
 
-static struct sock *unix_get_socket(struct file *filp)
+struct sock *unix_get_socket(struct file *filp)
 {
        struct sock *u_sock = NULL;
        struct inode *inode = filp->f_path.dentry->d_inode;
@@ -259,9 +259,16 @@ static void inc_inflight_move_tail(struct unix_sock *u)
 }
 
 static bool gc_in_progress = false;
+#define UNIX_INFLIGHT_TRIGGER_GC 16000
 
 void wait_for_unix_gc(void)
 {
+       /*
+        * If number of inflight sockets is insane,
+        * force a garbage collect right now.
+        */
+       if (unix_tot_inflight > UNIX_INFLIGHT_TRIGGER_GC && !gc_in_progress)
+               unix_gc();
        wait_event(unix_gc_wait, gc_in_progress == false);
 }
 
index d0c92dddb26bddb5b3d55a82ebf39fa8917e446c..17cd0c04d139045bbb0802a74d9628731d9428dc 100644 (file)
@@ -44,6 +44,38 @@ rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
        return chan;
 }
 
+static bool can_beacon_sec_chan(struct wiphy *wiphy,
+                               struct ieee80211_channel *chan,
+                               enum nl80211_channel_type channel_type)
+{
+       struct ieee80211_channel *sec_chan;
+       int diff;
+
+       switch (channel_type) {
+       case NL80211_CHAN_HT40PLUS:
+               diff = 20;
+               break;
+       case NL80211_CHAN_HT40MINUS:
+               diff = -20;
+               break;
+       default:
+               return false;
+       }
+
+       sec_chan = ieee80211_get_channel(wiphy, chan->center_freq + diff);
+       if (!sec_chan)
+               return false;
+
+       /* we'll need a DFS capability later */
+       if (sec_chan->flags & (IEEE80211_CHAN_DISABLED |
+                              IEEE80211_CHAN_PASSIVE_SCAN |
+                              IEEE80211_CHAN_NO_IBSS |
+                              IEEE80211_CHAN_RADAR))
+               return false;
+
+       return true;
+}
+
 int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
                      struct wireless_dev *wdev, int freq,
                      enum nl80211_channel_type channel_type)
@@ -68,6 +100,28 @@ int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
        if (!chan)
                return -EINVAL;
 
+       /* Both channels should be able to initiate communication */
+       if (wdev && (wdev->iftype == NL80211_IFTYPE_ADHOC ||
+                    wdev->iftype == NL80211_IFTYPE_AP ||
+                    wdev->iftype == NL80211_IFTYPE_AP_VLAN ||
+                    wdev->iftype == NL80211_IFTYPE_MESH_POINT ||
+                    wdev->iftype == NL80211_IFTYPE_P2P_GO)) {
+               switch (channel_type) {
+               case NL80211_CHAN_HT40PLUS:
+               case NL80211_CHAN_HT40MINUS:
+                       if (!can_beacon_sec_chan(&rdev->wiphy, chan,
+                                                channel_type)) {
+                               printk(KERN_DEBUG
+                                      "cfg80211: Secondary channel not "
+                                      "allowed to initiate communication\n");
+                               return -EINVAL;
+                       }
+                       break;
+               default:
+                       break;
+               }
+       }
+
        result = rdev->ops->set_channel(&rdev->wiphy,
                                        wdev ? wdev->netdev : NULL,
                                        chan, channel_type);
index 73e7b954ad288229df4d03bc164f07da183444cc..b25c6463c3e996cf536454603f4f0257f3b8b51c 100644 (file)
@@ -394,6 +394,7 @@ void __exit x25_link_free(void)
        list_for_each_safe(entry, tmp, &x25_neigh_list) {
                nb = list_entry(entry, struct x25_neigh, node);
                __x25_remove_neigh(nb);
+               dev_put(nb->dev);
        }
        write_unlock_bh(&x25_neigh_list_lock);
 }
index a2023ec52329ef66b95e14dc94f7086e5683e534..1e98bc0fe0a54bbca2a7fc1f94ab9344af0fbded 100644 (file)
@@ -19,7 +19,7 @@ struct hlist_head *xfrm_hash_alloc(unsigned int sz)
        if (sz <= PAGE_SIZE)
                n = kzalloc(sz, GFP_KERNEL);
        else if (hashdist)
-               n = __vmalloc(sz, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
+               n = vzalloc(sz);
        else
                n = (struct hlist_head *)
                        __get_free_pages(GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO,
index eb96ce52f1789dd881116e76a08169189b50f02c..220ebc05c7afc6b602785f6e402d44098cc0bd8d 100644 (file)
@@ -1268,7 +1268,7 @@ struct xfrm_state * xfrm_state_migrate(struct xfrm_state *x,
 
        return xc;
 error:
-       kfree(xc);
+       xfrm_state_put(xc);
        return NULL;
 }
 EXPORT_SYMBOL(xfrm_state_migrate);
index d81b968d864e5009d89f11bff18cfc3b344bdd00..c9230e158a8f60c0a9206b3db4df3dc21f372cf4 100644 (file)
@@ -63,7 +63,12 @@ fi
 
 # Extract GFP flags from the kernel source
 TMPFILE=`mktemp -t gfptranslate-XXXXXX` || exit 1
-grep "^#define __GFP" $SOURCE/include/linux/gfp.h | sed -e 's/(__force gfp_t)//' | sed -e 's/u)/)/' | grep -v GFP_BITS | sed -e 's/)\//) \//' > $TMPFILE
+grep -q ___GFP $SOURCE/include/linux/gfp.h
+if [ $? -eq 0 ]; then
+       grep "^#define ___GFP" $SOURCE/include/linux/gfp.h | sed -e 's/u$//' | grep -v GFP_BITS > $TMPFILE
+else
+       grep "^#define __GFP" $SOURCE/include/linux/gfp.h | sed -e 's/(__force gfp_t)//' | sed -e 's/u)/)/' | grep -v GFP_BITS | sed -e 's/)\//) \//' > $TMPFILE
+fi
 
 # Parse the flags
 IFS="
index 184eb6a0b505cc50e7435950b7a770923ba06cb2..e57826ced3800bb596945a708b648d3f68006dec 100644 (file)
@@ -164,6 +164,7 @@ struct menu {
        struct menu *list;
        struct symbol *sym;
        struct property *prompt;
+       struct expr *visibility;
        struct expr *dep;
        unsigned int flags;
        char *help;
index 753cdbd7b80590abf05a0c86a6eb06153b11e774..3f7240df0f3b969f63956a06cf899091c47e70cb 100644 (file)
@@ -107,6 +107,7 @@ void menu_end_menu(void);
 void menu_add_entry(struct symbol *sym);
 void menu_end_entry(void);
 void menu_add_dep(struct expr *dep);
+void menu_add_visibility(struct expr *dep);
 struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep);
 struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
 void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
index 7e83aef42c6d41c63051664b2669c922356bff3a..b9d9aa18e6d62bbaa40c34cf7062c00c8bb15e35 100644 (file)
@@ -152,6 +152,12 @@ struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr
        return menu_add_prop(type, prompt, NULL, dep);
 }
 
+void menu_add_visibility(struct expr *expr)
+{
+       current_entry->visibility = expr_alloc_and(current_entry->visibility,
+           expr);
+}
+
 void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
 {
        menu_add_prop(type, NULL, expr, dep);
@@ -410,6 +416,11 @@ bool menu_is_visible(struct menu *menu)
        if (!menu->prompt)
                return false;
 
+       if (menu->visibility) {
+               if (expr_calc_value(menu->visibility) == no)
+                       return no;
+       }
+
        sym = menu->sym;
        if (sym) {
                sym_calc_value(sym);
index d8bc7424962296f2370cba1e9a594bf9de04f6d6..c9e690eb75451fa5f87b2c7d4f4d15f71c83c33f 100644 (file)
@@ -38,6 +38,7 @@ hex,          T_TYPE,         TF_COMMAND, S_HEX
 string,                T_TYPE,         TF_COMMAND, S_STRING
 select,                T_SELECT,       TF_COMMAND
 range,         T_RANGE,        TF_COMMAND
+visible,       T_VISIBLE,      TF_COMMAND
 option,                T_OPTION,       TF_COMMAND
 on,            T_ON,           TF_PARAM
 modules,       T_OPT_MODULES,  TF_OPTION
index c1748faf46340525706f0f25f867ffa01c3f9b19..4055d5de1750261453c46d752f09ace7b17df74d 100644 (file)
@@ -32,7 +32,7 @@
 struct kconf_id;
 
 static struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len);
-/* maximum key range = 47, duplicates = 0 */
+/* maximum key range = 50, duplicates = 0 */
 
 #ifdef __GNUC__
 __inline
@@ -46,32 +46,32 @@ kconf_id_hash (register const char *str, register unsigned int len)
 {
   static unsigned char asso_values[] =
     {
-      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, 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, 49, 49, 49, 49,
-      49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
-      49, 49, 49, 49, 49, 49, 49, 49, 11,  5,
-       0,  0,  5, 49,  5, 20, 49, 49,  5, 20,
-       5,  0, 30, 49,  0, 15,  0, 10,  0, 49,
-      25, 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, 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, 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, 49, 49, 49, 49, 49,
-      49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
-      49, 49, 49, 49, 49, 49
+      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+      52, 52, 52, 52, 52, 52, 52, 52, 40,  5,
+       0,  0,  5, 52,  0, 20, 52, 52, 10, 20,
+       5,  0, 35, 52,  0, 30,  0, 15,  0, 52,
+      15, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+      52, 52, 52, 52, 52, 52
     };
   register int hval = len;
 
@@ -102,25 +102,26 @@ struct kconf_id_strings_t
     char kconf_id_strings_str12[sizeof("default")];
     char kconf_id_strings_str13[sizeof("def_bool")];
     char kconf_id_strings_str14[sizeof("help")];
-    char kconf_id_strings_str15[sizeof("bool")];
     char kconf_id_strings_str16[sizeof("config")];
     char kconf_id_strings_str17[sizeof("def_tristate")];
-    char kconf_id_strings_str18[sizeof("boolean")];
+    char kconf_id_strings_str18[sizeof("hex")];
     char kconf_id_strings_str19[sizeof("defconfig_list")];
-    char kconf_id_strings_str21[sizeof("string")];
     char kconf_id_strings_str22[sizeof("if")];
     char kconf_id_strings_str23[sizeof("int")];
-    char kconf_id_strings_str26[sizeof("select")];
     char kconf_id_strings_str27[sizeof("modules")];
     char kconf_id_strings_str28[sizeof("tristate")];
     char kconf_id_strings_str29[sizeof("menu")];
-    char kconf_id_strings_str31[sizeof("source")];
     char kconf_id_strings_str32[sizeof("comment")];
-    char kconf_id_strings_str33[sizeof("hex")];
     char kconf_id_strings_str35[sizeof("menuconfig")];
-    char kconf_id_strings_str36[sizeof("prompt")];
-    char kconf_id_strings_str37[sizeof("depends")];
+    char kconf_id_strings_str36[sizeof("string")];
+    char kconf_id_strings_str37[sizeof("visible")];
+    char kconf_id_strings_str41[sizeof("prompt")];
+    char kconf_id_strings_str42[sizeof("depends")];
+    char kconf_id_strings_str44[sizeof("bool")];
+    char kconf_id_strings_str46[sizeof("select")];
+    char kconf_id_strings_str47[sizeof("boolean")];
     char kconf_id_strings_str48[sizeof("mainmenu")];
+    char kconf_id_strings_str51[sizeof("source")];
   };
 static struct kconf_id_strings_t kconf_id_strings_contents =
   {
@@ -136,25 +137,26 @@ static struct kconf_id_strings_t kconf_id_strings_contents =
     "default",
     "def_bool",
     "help",
-    "bool",
     "config",
     "def_tristate",
-    "boolean",
+    "hex",
     "defconfig_list",
-    "string",
     "if",
     "int",
-    "select",
     "modules",
     "tristate",
     "menu",
-    "source",
     "comment",
-    "hex",
     "menuconfig",
+    "string",
+    "visible",
     "prompt",
     "depends",
-    "mainmenu"
+    "bool",
+    "select",
+    "boolean",
+    "mainmenu",
+    "source"
   };
 #define kconf_id_strings ((const char *) &kconf_id_strings_contents)
 #ifdef __GNUC__
@@ -168,11 +170,11 @@ kconf_id_lookup (register const char *str, register unsigned int len)
 {
   enum
     {
-      TOTAL_KEYWORDS = 31,
+      TOTAL_KEYWORDS = 32,
       MIN_WORD_LENGTH = 2,
       MAX_WORD_LENGTH = 14,
       MIN_HASH_VALUE = 2,
-      MAX_HASH_VALUE = 48
+      MAX_HASH_VALUE = 51
     };
 
   static struct kconf_id wordlist[] =
@@ -191,31 +193,35 @@ kconf_id_lookup (register const char *str, register unsigned int len)
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12,   T_DEFAULT,      TF_COMMAND, S_UNKNOWN},
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13,   T_DEFAULT,      TF_COMMAND, S_BOOLEAN},
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14,           T_HELP,         TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str15,           T_TYPE,         TF_COMMAND, S_BOOLEAN},
+      {-1},
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str16,           T_CONFIG,       TF_COMMAND},
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17,   T_DEFAULT,      TF_COMMAND, S_TRISTATE},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18,   T_TYPE,         TF_COMMAND, S_BOOLEAN},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18,           T_TYPE,         TF_COMMAND, S_HEX},
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str19,   T_OPT_DEFCONFIG_LIST,TF_OPTION},
-      {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21,           T_TYPE,         TF_COMMAND, S_STRING},
+      {-1}, {-1},
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22,           T_IF,           TF_COMMAND|TF_PARAM},
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23,           T_TYPE,         TF_COMMAND, S_INT},
-      {-1}, {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26,           T_SELECT,       TF_COMMAND},
+      {-1}, {-1}, {-1},
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27,   T_OPT_MODULES,  TF_OPTION},
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28,   T_TYPE,         TF_COMMAND, S_TRISTATE},
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str29,           T_MENU,         TF_COMMAND},
-      {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31,           T_SOURCE,       TF_COMMAND},
+      {-1}, {-1},
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32,   T_COMMENT,      TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33,           T_TYPE,         TF_COMMAND, S_HEX},
-      {-1},
+      {-1}, {-1},
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35,   T_MENUCONFIG,   TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36,           T_PROMPT,       TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37,   T_DEPENDS,      TF_COMMAND},
-      {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36,           T_TYPE,         TF_COMMAND, S_STRING},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37,   T_VISIBLE,      TF_COMMAND},
+      {-1}, {-1}, {-1},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41,           T_PROMPT,       TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str42,   T_DEPENDS,      TF_COMMAND},
       {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str48,   T_MAINMENU,     TF_COMMAND}
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str44,           T_TYPE,         TF_COMMAND, S_BOOLEAN},
+      {-1},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46,           T_SELECT,       TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str47,   T_TYPE,         TF_COMMAND, S_BOOLEAN},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str48,   T_MAINMENU,     TF_COMMAND},
+      {-1}, {-1},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str51,           T_SOURCE,       TF_COMMAND}
     };
 
   if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
index 699d4b2651865cdb218951e211a131cda69020fc..4c5495ea205e646ef9c4efff923dd6a678dbda4b 100644 (file)
@@ -160,18 +160,19 @@ static struct menu *current_menu, *current_entry;
      T_DEFAULT = 275,
      T_SELECT = 276,
      T_RANGE = 277,
-     T_OPTION = 278,
-     T_ON = 279,
-     T_WORD = 280,
-     T_WORD_QUOTE = 281,
-     T_UNEQUAL = 282,
-     T_CLOSE_PAREN = 283,
-     T_OPEN_PAREN = 284,
-     T_EOL = 285,
-     T_OR = 286,
-     T_AND = 287,
-     T_EQUAL = 288,
-     T_NOT = 289
+     T_VISIBLE = 278,
+     T_OPTION = 279,
+     T_ON = 280,
+     T_WORD = 281,
+     T_WORD_QUOTE = 282,
+     T_UNEQUAL = 283,
+     T_CLOSE_PAREN = 284,
+     T_OPEN_PAREN = 285,
+     T_EOL = 286,
+     T_OR = 287,
+     T_AND = 288,
+     T_EQUAL = 289,
+     T_NOT = 290
    };
 #endif
 
@@ -419,20 +420,20 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  11
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   277
+#define YYLAST   290
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  35
+#define YYNTOKENS  36
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  48
+#define YYNNTS  50
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  113
+#define YYNRULES  118
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  185
+#define YYNSTATES  191
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   289
+#define YYMAXUTOK   290
 
 #define YYTRANSLATE(YYX)                                               \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -468,7 +469,8 @@ static const yytype_uint8 yytranslate[] =
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    33,    34
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35
 };
 
 #if YYDEBUG
@@ -478,72 +480,73 @@ static const yytype_uint16 yyprhs[] =
 {
        0,     0,     3,     6,     8,    11,    13,    14,    17,    20,
       23,    26,    31,    36,    40,    42,    44,    46,    48,    50,
-      52,    54,    56,    58,    60,    62,    64,    66,    70,    73,
-      77,    80,    84,    87,    88,    91,    94,    97,   100,   103,
-     106,   110,   115,   120,   125,   131,   135,   136,   140,   141,
-     144,   148,   151,   153,   157,   158,   161,   164,   167,   170,
-     173,   178,   182,   185,   190,   191,   194,   198,   200,   204,
-     205,   208,   211,   214,   218,   222,   225,   227,   231,   232,
-     235,   238,   241,   245,   249,   252,   255,   258,   259,   262,
-     265,   268,   273,   274,   277,   279,   281,   284,   287,   290,
-     292,   295,   296,   299,   301,   305,   309,   313,   316,   320,
-     324,   326,   328,   329
+      52,    54,    56,    58,    60,    62,    64,    66,    68,    72,
+      75,    79,    82,    86,    89,    90,    93,    96,    99,   102,
+     105,   108,   112,   117,   122,   127,   133,   137,   138,   142,
+     143,   146,   150,   153,   155,   159,   160,   163,   166,   169,
+     172,   175,   180,   184,   187,   192,   193,   196,   200,   202,
+     206,   207,   210,   213,   216,   220,   224,   228,   230,   234,
+     235,   238,   241,   244,   248,   252,   255,   258,   261,   262,
+     265,   268,   271,   276,   277,   280,   283,   286,   287,   290,
+     292,   294,   297,   300,   303,   305,   308,   309,   312,   314,
+     318,   322,   326,   329,   333,   337,   339,   341,   342
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
-      36,     0,    -1,    78,    37,    -1,    37,    -1,    62,    38,
-      -1,    38,    -1,    -1,    38,    40,    -1,    38,    54,    -1,
-      38,    66,    -1,    38,    77,    -1,    38,    25,     1,    30,
-      -1,    38,    39,     1,    30,    -1,    38,     1,    30,    -1,
+      37,     0,    -1,    81,    38,    -1,    38,    -1,    63,    39,
+      -1,    39,    -1,    -1,    39,    41,    -1,    39,    55,    -1,
+      39,    67,    -1,    39,    80,    -1,    39,    26,     1,    31,
+      -1,    39,    40,     1,    31,    -1,    39,     1,    31,    -1,
       16,    -1,    18,    -1,    19,    -1,    21,    -1,    17,    -1,
-      22,    -1,    20,    -1,    30,    -1,    60,    -1,    70,    -1,
-      43,    -1,    45,    -1,    68,    -1,    25,     1,    30,    -1,
-       1,    30,    -1,    10,    25,    30,    -1,    42,    46,    -1,
-      11,    25,    30,    -1,    44,    46,    -1,    -1,    46,    47,
-      -1,    46,    48,    -1,    46,    74,    -1,    46,    72,    -1,
-      46,    41,    -1,    46,    30,    -1,    19,    75,    30,    -1,
-      18,    76,    79,    30,    -1,    20,    80,    79,    30,    -1,
-      21,    25,    79,    30,    -1,    22,    81,    81,    79,    30,
-      -1,    23,    49,    30,    -1,    -1,    49,    25,    50,    -1,
-      -1,    33,    76,    -1,     7,    82,    30,    -1,    51,    55,
-      -1,    77,    -1,    52,    57,    53,    -1,    -1,    55,    56,
-      -1,    55,    74,    -1,    55,    72,    -1,    55,    30,    -1,
-      55,    41,    -1,    18,    76,    79,    30,    -1,    19,    75,
-      30,    -1,    17,    30,    -1,    20,    25,    79,    30,    -1,
-      -1,    57,    40,    -1,    14,    80,    78,    -1,    77,    -1,
-      58,    61,    59,    -1,    -1,    61,    40,    -1,    61,    66,
-      -1,    61,    54,    -1,     3,    76,    78,    -1,     4,    76,
-      30,    -1,    63,    73,    -1,    77,    -1,    64,    67,    65,
-      -1,    -1,    67,    40,    -1,    67,    66,    -1,    67,    54,
-      -1,     6,    76,    30,    -1,     9,    76,    30,    -1,    69,
-      73,    -1,    12,    30,    -1,    71,    13,    -1,    -1,    73,
-      74,    -1,    73,    30,    -1,    73,    41,    -1,    16,    24,
-      80,    30,    -1,    -1,    76,    79,    -1,    25,    -1,    26,
-      -1,     5,    30,    -1,     8,    30,    -1,    15,    30,    -1,
-      30,    -1,    78,    30,    -1,    -1,    14,    80,    -1,    81,
-      -1,    81,    33,    81,    -1,    81,    27,    81,    -1,    29,
-      80,    28,    -1,    34,    80,    -1,    80,    31,    80,    -1,
-      80,    32,    80,    -1,    25,    -1,    26,    -1,    -1,    25,
-      -1
+      22,    -1,    20,    -1,    23,    -1,    31,    -1,    61,    -1,
+      71,    -1,    44,    -1,    46,    -1,    69,    -1,    26,     1,
+      31,    -1,     1,    31,    -1,    10,    26,    31,    -1,    43,
+      47,    -1,    11,    26,    31,    -1,    45,    47,    -1,    -1,
+      47,    48,    -1,    47,    49,    -1,    47,    75,    -1,    47,
+      73,    -1,    47,    42,    -1,    47,    31,    -1,    19,    78,
+      31,    -1,    18,    79,    82,    31,    -1,    20,    83,    82,
+      31,    -1,    21,    26,    82,    31,    -1,    22,    84,    84,
+      82,    31,    -1,    24,    50,    31,    -1,    -1,    50,    26,
+      51,    -1,    -1,    34,    79,    -1,     7,    85,    31,    -1,
+      52,    56,    -1,    80,    -1,    53,    58,    54,    -1,    -1,
+      56,    57,    -1,    56,    75,    -1,    56,    73,    -1,    56,
+      31,    -1,    56,    42,    -1,    18,    79,    82,    31,    -1,
+      19,    78,    31,    -1,    17,    31,    -1,    20,    26,    82,
+      31,    -1,    -1,    58,    41,    -1,    14,    83,    81,    -1,
+      80,    -1,    59,    62,    60,    -1,    -1,    62,    41,    -1,
+      62,    67,    -1,    62,    55,    -1,     3,    79,    81,    -1,
+       4,    79,    31,    -1,    64,    76,    74,    -1,    80,    -1,
+      65,    68,    66,    -1,    -1,    68,    41,    -1,    68,    67,
+      -1,    68,    55,    -1,     6,    79,    31,    -1,     9,    79,
+      31,    -1,    70,    74,    -1,    12,    31,    -1,    72,    13,
+      -1,    -1,    74,    75,    -1,    74,    31,    -1,    74,    42,
+      -1,    16,    25,    83,    31,    -1,    -1,    76,    77,    -1,
+      76,    31,    -1,    23,    82,    -1,    -1,    79,    82,    -1,
+      26,    -1,    27,    -1,     5,    31,    -1,     8,    31,    -1,
+      15,    31,    -1,    31,    -1,    81,    31,    -1,    -1,    14,
+      83,    -1,    84,    -1,    84,    34,    84,    -1,    84,    28,
+      84,    -1,    30,    83,    29,    -1,    35,    83,    -1,    83,
+      32,    83,    -1,    83,    33,    83,    -1,    26,    -1,    27,
+      -1,    -1,    26,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   107,   107,   107,   109,   109,   111,   113,   114,   115,
-     116,   117,   118,   122,   126,   126,   126,   126,   126,   126,
-     126,   130,   131,   132,   133,   134,   135,   139,   140,   146,
-     154,   160,   168,   178,   180,   181,   182,   183,   184,   185,
-     188,   196,   202,   212,   218,   224,   227,   229,   240,   241,
-     246,   255,   260,   268,   271,   273,   274,   275,   276,   277,
-     280,   286,   297,   303,   313,   315,   320,   328,   336,   339,
-     341,   342,   343,   348,   355,   362,   367,   375,   378,   380,
-     381,   382,   385,   393,   400,   407,   413,   420,   422,   423,
-     424,   427,   435,   437,   442,   443,   446,   447,   448,   452,
-     453,   456,   457,   460,   461,   462,   463,   464,   465,   466,
-     469,   470,   473,   474
+       0,   108,   108,   108,   110,   110,   112,   114,   115,   116,
+     117,   118,   119,   123,   127,   127,   127,   127,   127,   127,
+     127,   127,   131,   132,   133,   134,   135,   136,   140,   141,
+     147,   155,   161,   169,   179,   181,   182,   183,   184,   185,
+     186,   189,   197,   203,   213,   219,   225,   228,   230,   241,
+     242,   247,   256,   261,   269,   272,   274,   275,   276,   277,
+     278,   281,   287,   298,   304,   314,   316,   321,   329,   337,
+     340,   342,   343,   344,   349,   356,   363,   368,   376,   379,
+     381,   382,   383,   386,   394,   401,   408,   414,   421,   423,
+     424,   425,   428,   436,   438,   439,   442,   449,   451,   456,
+     457,   460,   461,   462,   466,   467,   470,   471,   474,   475,
+     476,   477,   478,   479,   480,   483,   484,   487,   488
 };
 #endif
 
@@ -556,7 +559,7 @@ static const char *const yytname[] =
   "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG",
   "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS",
   "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", "T_SELECT", "T_RANGE",
-  "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL",
+  "T_VISIBLE", "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL",
   "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", "T_EQUAL",
   "T_NOT", "$accept", "input", "start", "stmt_list", "option_name",
   "common_stmt", "option_error", "config_entry_start", "config_stmt",
@@ -567,8 +570,8 @@ static const char *const yytname[] =
   "if_entry", "if_end", "if_stmt", "if_block", "mainmenu_stmt", "menu",
   "menu_entry", "menu_end", "menu_stmt", "menu_block", "source_stmt",
   "comment", "comment_stmt", "help_start", "help", "depends_list",
-  "depends", "prompt_stmt_opt", "prompt", "end", "nl", "if_expr", "expr",
-  "symbol", "word_opt", 0
+  "depends", "visibility_list", "visible", "prompt_stmt_opt", "prompt",
+  "end", "nl", "if_expr", "expr", "symbol", "word_opt", 0
 };
 #endif
 
@@ -580,25 +583,25 @@ static const yytype_uint16 yytoknum[] =
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289
+     285,   286,   287,   288,   289,   290
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    35,    36,    36,    37,    37,    38,    38,    38,    38,
-      38,    38,    38,    38,    39,    39,    39,    39,    39,    39,
-      39,    40,    40,    40,    40,    40,    40,    41,    41,    42,
-      43,    44,    45,    46,    46,    46,    46,    46,    46,    46,
-      47,    47,    47,    47,    47,    48,    49,    49,    50,    50,
-      51,    52,    53,    54,    55,    55,    55,    55,    55,    55,
-      56,    56,    56,    56,    57,    57,    58,    59,    60,    61,
-      61,    61,    61,    62,    63,    64,    65,    66,    67,    67,
-      67,    67,    68,    69,    70,    71,    72,    73,    73,    73,
-      73,    74,    75,    75,    76,    76,    77,    77,    77,    78,
-      78,    79,    79,    80,    80,    80,    80,    80,    80,    80,
-      81,    81,    82,    82
+       0,    36,    37,    37,    38,    38,    39,    39,    39,    39,
+      39,    39,    39,    39,    40,    40,    40,    40,    40,    40,
+      40,    40,    41,    41,    41,    41,    41,    41,    42,    42,
+      43,    44,    45,    46,    47,    47,    47,    47,    47,    47,
+      47,    48,    48,    48,    48,    48,    49,    50,    50,    51,
+      51,    52,    53,    54,    55,    56,    56,    56,    56,    56,
+      56,    57,    57,    57,    57,    58,    58,    59,    60,    61,
+      62,    62,    62,    62,    63,    64,    65,    66,    67,    68,
+      68,    68,    68,    69,    70,    71,    72,    73,    74,    74,
+      74,    74,    75,    76,    76,    76,    77,    78,    78,    79,
+      79,    80,    80,    80,    81,    81,    82,    82,    83,    83,
+      83,    83,    83,    83,    83,    84,    84,    85,    85
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
@@ -606,16 +609,16 @@ static const yytype_uint8 yyr2[] =
 {
        0,     2,     2,     1,     2,     1,     0,     2,     2,     2,
        2,     4,     4,     3,     1,     1,     1,     1,     1,     1,
-       1,     1,     1,     1,     1,     1,     1,     3,     2,     3,
-       2,     3,     2,     0,     2,     2,     2,     2,     2,     2,
-       3,     4,     4,     4,     5,     3,     0,     3,     0,     2,
-       3,     2,     1,     3,     0,     2,     2,     2,     2,     2,
-       4,     3,     2,     4,     0,     2,     3,     1,     3,     0,
-       2,     2,     2,     3,     3,     2,     1,     3,     0,     2,
-       2,     2,     3,     3,     2,     2,     2,     0,     2,     2,
-       2,     4,     0,     2,     1,     1,     2,     2,     2,     1,
-       2,     0,     2,     1,     3,     3,     3,     2,     3,     3,
-       1,     1,     0,     1
+       1,     1,     1,     1,     1,     1,     1,     1,     3,     2,
+       3,     2,     3,     2,     0,     2,     2,     2,     2,     2,
+       2,     3,     4,     4,     4,     5,     3,     0,     3,     0,
+       2,     3,     2,     1,     3,     0,     2,     2,     2,     2,
+       2,     4,     3,     2,     4,     0,     2,     3,     1,     3,
+       0,     2,     2,     2,     3,     3,     3,     1,     3,     0,
+       2,     2,     2,     3,     3,     2,     2,     2,     0,     2,
+       2,     2,     4,     0,     2,     2,     2,     0,     2,     1,
+       1,     2,     2,     2,     1,     2,     0,     2,     1,     3,
+       3,     3,     2,     3,     3,     1,     1,     0,     1
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -623,165 +626,172 @@ static const yytype_uint8 yyr2[] =
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       6,     0,    99,     0,     3,     0,     6,     6,    94,    95,
-       0,     1,     0,     0,     0,     0,   112,     0,     0,     0,
+       6,     0,   104,     0,     3,     0,     6,     6,    99,   100,
+       0,     1,     0,     0,     0,     0,   117,     0,     0,     0,
        0,     0,     0,    14,    18,    15,    16,    20,    17,    19,
-       0,    21,     0,     7,    33,    24,    33,    25,    54,    64,
-       8,    69,    22,    87,    78,     9,    26,    87,    23,    10,
-       0,   100,     2,    73,    13,     0,    96,     0,   113,     0,
-      97,     0,     0,     0,   110,   111,     0,     0,     0,   103,
-      98,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,    74,    82,    50,    83,    29,    31,     0,   107,     0,
-       0,    66,     0,     0,    11,    12,     0,     0,     0,     0,
-      92,     0,     0,     0,    46,     0,    39,    38,    34,    35,
-       0,    37,    36,     0,     0,    92,     0,    58,    59,    55,
-      57,    56,    65,    53,    52,    70,    72,    68,    71,    67,
-      89,    90,    88,    79,    81,    77,    80,    76,   106,   108,
-     109,   105,   104,    28,    85,     0,   101,     0,   101,   101,
-     101,     0,     0,     0,    86,    62,   101,     0,   101,     0,
-       0,     0,    40,    93,     0,     0,   101,    48,    45,    27,
-       0,    61,     0,    91,   102,    41,    42,    43,     0,     0,
-      47,    60,    63,    44,    49
+      21,     0,    22,     0,     7,    34,    25,    34,    26,    55,
+      65,     8,    70,    23,    93,    79,     9,    27,    88,    24,
+      10,     0,   105,     2,    74,    13,     0,   101,     0,   118,
+       0,   102,     0,     0,     0,   115,   116,     0,     0,     0,
+     108,   103,     0,     0,     0,     0,     0,     0,     0,    88,
+       0,     0,    75,    83,    51,    84,    30,    32,     0,   112,
+       0,     0,    67,     0,     0,    11,    12,     0,     0,     0,
+       0,    97,     0,     0,     0,    47,     0,    40,    39,    35,
+      36,     0,    38,    37,     0,     0,    97,     0,    59,    60,
+      56,    58,    57,    66,    54,    53,    71,    73,    69,    72,
+      68,   106,    95,     0,    94,    80,    82,    78,    81,    77,
+      90,    91,    89,   111,   113,   114,   110,   109,    29,    86,
+       0,   106,     0,   106,   106,   106,     0,     0,     0,    87,
+      63,   106,     0,   106,     0,    96,     0,     0,    41,    98,
+       0,     0,   106,    49,    46,    28,     0,    62,     0,   107,
+      92,    42,    43,    44,     0,     0,    48,    61,    64,    45,
+      50
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] =
 {
-      -1,     3,     4,     5,    32,    33,   107,    34,    35,    36,
-      37,    73,   108,   109,   152,   180,    38,    39,   123,    40,
-      75,   119,    76,    41,   127,    42,    77,     6,    43,    44,
-     135,    45,    79,    46,    47,    48,   110,   111,    78,   112,
-     147,   148,    49,     7,   161,    68,    69,    59
+      -1,     3,     4,     5,    33,    34,   108,    35,    36,    37,
+      38,    74,   109,   110,   157,   186,    39,    40,   124,    41,
+      76,   120,    77,    42,   128,    43,    78,     6,    44,    45,
+     137,    46,    80,    47,    48,    49,   111,   112,    81,   113,
+      79,   134,   152,   153,    50,     7,   165,    69,    70,    60
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -89
+#define YYPACT_NINF -90
 static const yytype_int16 yypact[] =
 {
-       3,     4,   -89,    20,   -89,   100,   -89,     7,   -89,   -89,
-      -8,   -89,    17,     4,    28,     4,    37,    36,     4,    68,
-      87,   -18,    69,   -89,   -89,   -89,   -89,   -89,   -89,   -89,
-     128,   -89,   138,   -89,   -89,   -89,   -89,   -89,   -89,   -89,
-     -89,   -89,   -89,   -89,   -89,   -89,   -89,   -89,   -89,   -89,
-     127,   -89,   -89,   110,   -89,   126,   -89,   136,   -89,   137,
-     -89,   147,   150,   152,   -89,   -89,   -18,   -18,   171,   -14,
-     -89,   153,   157,    34,    67,   180,   233,   220,   207,   220,
-     154,   -89,   -89,   -89,   -89,   -89,   -89,     0,   -89,   -18,
-     -18,   110,    44,    44,   -89,   -89,   163,   174,   182,     4,
-       4,   -18,   194,    44,   -89,   219,   -89,   -89,   -89,   -89,
-     223,   -89,   -89,   203,     4,     4,   215,   -89,   -89,   -89,
-     -89,   -89,   -89,   -89,   -89,   -89,   -89,   -89,   -89,   -89,
-     -89,   -89,   -89,   -89,   -89,   -89,   -89,   -89,   -89,   213,
-     -89,   -89,   -89,   -89,   -89,   -18,   232,   227,   232,    -5,
-     232,    44,    35,   234,   -89,   -89,   232,   235,   232,   224,
-     -18,   236,   -89,   -89,   237,   238,   232,   216,   -89,   -89,
-     240,   -89,   241,   -89,    71,   -89,   -89,   -89,   242,     4,
-     -89,   -89,   -89,   -89,   -89
+       4,    42,   -90,    96,   -90,   111,   -90,    15,   -90,   -90,
+      75,   -90,    82,    42,   104,    42,   110,   107,    42,   115,
+     125,    -4,   121,   -90,   -90,   -90,   -90,   -90,   -90,   -90,
+     -90,   162,   -90,   163,   -90,   -90,   -90,   -90,   -90,   -90,
+     -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,
+     -90,   139,   -90,   -90,   138,   -90,   142,   -90,   143,   -90,
+     152,   -90,   164,   167,   168,   -90,   -90,    -4,    -4,    77,
+     -18,   -90,   177,   185,    33,    71,   195,   247,   236,    -2,
+     236,   171,   -90,   -90,   -90,   -90,   -90,   -90,    41,   -90,
+      -4,    -4,   138,    97,    97,   -90,   -90,   186,   187,   194,
+      42,    42,    -4,   196,    97,   -90,   219,   -90,   -90,   -90,
+     -90,   210,   -90,   -90,   204,    42,    42,   199,   -90,   -90,
+     -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,
+     -90,   222,   -90,   223,   -90,   -90,   -90,   -90,   -90,   -90,
+     -90,   -90,   -90,   -90,   215,   -90,   -90,   -90,   -90,   -90,
+      -4,   222,   228,   222,    -5,   222,    97,    35,   229,   -90,
+     -90,   222,   232,   222,    -4,   -90,   135,   233,   -90,   -90,
+     234,   235,   222,   240,   -90,   -90,   237,   -90,   239,   -13,
+     -90,   -90,   -90,   -90,   244,    42,   -90,   -90,   -90,   -90,
+     -90
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] =
 {
-     -89,   -89,   255,   267,   -89,    47,   -57,   -89,   -89,   -89,
-     -89,   239,   -89,   -89,   -89,   -89,   -89,   -89,   -89,   130,
-     -89,   -89,   -89,   -89,   -89,   -89,   -89,   -89,   -89,   -89,
-     -89,   181,   -89,   -89,   -89,   -89,   -89,   199,   229,    16,
-     162,    -1,    74,    -7,   103,   -65,   -88,   -89
+     -90,   -90,   269,   271,   -90,    23,   -70,   -90,   -90,   -90,
+     -90,   243,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -48,
+     -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,
+     -90,   -20,   -90,   -90,   -90,   -90,   -90,   206,   205,   -68,
+     -90,   -90,   169,    -1,    27,    -7,   118,   -66,   -89,   -90
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
    positive, shift that token.  If negative, reduce the rule which
    number is the opposite.  If zero, do what YYDEFACT says.
    If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -85
+#define YYTABLE_NINF -86
 static const yytype_int16 yytable[] =
 {
-      10,    87,    88,    53,   141,   142,     1,    64,    65,   160,
-       1,    66,    55,    92,    57,   151,    67,    61,   118,    93,
-      11,   131,     2,   131,   139,   140,    89,    90,   138,     8,
-       9,    89,    90,     2,   -30,    96,   149,    51,   -30,   -30,
-     -30,   -30,   -30,   -30,   -30,   -30,    97,    54,   -30,   -30,
-      98,   -30,    99,   100,   101,   102,   103,   104,    56,   105,
-     167,    91,    58,   166,   106,   168,    60,   -32,    96,    64,
-      65,   -32,   -32,   -32,   -32,   -32,   -32,   -32,   -32,    97,
-     159,   -32,   -32,    98,   -32,    99,   100,   101,   102,   103,
-     104,   121,   105,    62,   132,   174,   132,   106,   146,    70,
-      -5,    12,    89,    90,    13,    14,    15,    16,    17,    18,
-      19,    20,    63,   156,    21,    22,    23,    24,    25,    26,
-      27,    28,    29,   122,   125,    30,   133,    -4,    12,    71,
-      31,    13,    14,    15,    16,    17,    18,    19,    20,    72,
-      51,    21,    22,    23,    24,    25,    26,    27,    28,    29,
-     124,   129,    30,   137,   -84,    96,    81,    31,   -84,   -84,
-     -84,   -84,   -84,   -84,   -84,   -84,    82,    83,   -84,   -84,
-      98,   -84,   -84,   -84,   -84,   -84,   -84,    84,   184,   105,
-      85,    96,    86,    94,   130,   -51,   -51,    95,   -51,   -51,
-     -51,   -51,    97,   143,   -51,   -51,    98,   113,   114,   115,
-     116,     2,    89,    90,   144,   105,   145,   126,    96,   134,
-     117,   -75,   -75,   -75,   -75,   -75,   -75,   -75,   -75,   150,
-     153,   -75,   -75,    98,    13,    14,    15,    16,    17,    18,
-      19,    20,   105,   155,    21,    22,   154,   130,    14,    15,
-     158,    17,    18,    19,    20,    90,   160,    21,    22,   179,
-      31,   163,   164,   165,   173,    89,    90,   162,   128,   170,
-     136,   172,    52,    31,   169,   171,   175,   176,   177,   178,
-     181,   182,   183,    50,   120,    74,    80,   157
+      10,    88,    89,    54,   146,   147,   119,     1,   122,   164,
+      93,   141,    56,   142,    58,   156,    94,    62,     1,    90,
+      91,   131,    65,    66,   144,   145,    67,    90,    91,   132,
+     127,    68,   136,   -31,    97,     2,   154,   -31,   -31,   -31,
+     -31,   -31,   -31,   -31,   -31,    98,    52,   -31,   -31,    99,
+     -31,   100,   101,   102,   103,   104,   -31,   105,   129,   106,
+     138,   173,    92,   141,   107,   142,   174,   172,     8,     9,
+     143,   -33,    97,    90,    91,   -33,   -33,   -33,   -33,   -33,
+     -33,   -33,   -33,    98,   166,   -33,   -33,    99,   -33,   100,
+     101,   102,   103,   104,   -33,   105,    11,   106,   179,   151,
+     123,   126,   107,   135,   125,   130,     2,   139,     2,    90,
+      91,    -5,    12,    55,   161,    13,    14,    15,    16,    17,
+      18,    19,    20,    65,    66,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    57,    59,    31,    61,    -4,
+      12,    63,    32,    13,    14,    15,    16,    17,    18,    19,
+      20,    64,    71,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    72,    73,    31,   180,    90,    91,    52,
+      32,   -85,    97,    82,    83,   -85,   -85,   -85,   -85,   -85,
+     -85,   -85,   -85,    84,   190,   -85,   -85,    99,   -85,   -85,
+     -85,   -85,   -85,   -85,   -85,    85,    97,   106,    86,    87,
+     -52,   -52,   140,   -52,   -52,   -52,   -52,    98,    95,   -52,
+     -52,    99,   114,   115,   116,   117,    96,   148,   149,   150,
+     158,   106,   155,   159,    97,   163,   118,   -76,   -76,   -76,
+     -76,   -76,   -76,   -76,   -76,   160,   164,   -76,   -76,    99,
+      13,    14,    15,    16,    17,    18,    19,    20,    91,   106,
+      21,    22,    14,    15,   140,    17,    18,    19,    20,   168,
+     175,    21,    22,   177,   181,   182,   183,    32,   187,   167,
+     188,   169,   170,   171,   185,   189,    53,    51,    32,   176,
+      75,   178,   121,     0,   133,   162,     0,     0,     0,     0,
+     184
 };
 
-static const yytype_uint8 yycheck[] =
+static const yytype_int16 yycheck[] =
 {
-       1,    66,    67,    10,    92,    93,     3,    25,    26,    14,
-       3,    29,    13,    27,    15,   103,    34,    18,    75,    33,
-       0,    78,    30,    80,    89,    90,    31,    32,    28,    25,
-      26,    31,    32,    30,     0,     1,   101,    30,     4,     5,
-       6,     7,     8,     9,    10,    11,    12,    30,    14,    15,
-      16,    17,    18,    19,    20,    21,    22,    23,    30,    25,
-      25,    68,    25,   151,    30,    30,    30,     0,     1,    25,
-      26,     4,     5,     6,     7,     8,     9,    10,    11,    12,
-     145,    14,    15,    16,    17,    18,    19,    20,    21,    22,
-      23,    75,    25,    25,    78,   160,    80,    30,    99,    30,
-       0,     1,    31,    32,     4,     5,     6,     7,     8,     9,
-      10,    11,    25,   114,    14,    15,    16,    17,    18,    19,
-      20,    21,    22,    76,    77,    25,    79,     0,     1,     1,
-      30,     4,     5,     6,     7,     8,     9,    10,    11,     1,
-      30,    14,    15,    16,    17,    18,    19,    20,    21,    22,
-      76,    77,    25,    79,     0,     1,    30,    30,     4,     5,
-       6,     7,     8,     9,    10,    11,    30,    30,    14,    15,
-      16,    17,    18,    19,    20,    21,    22,    30,   179,    25,
-      30,     1,    30,    30,    30,     5,     6,    30,     8,     9,
-      10,    11,    12,    30,    14,    15,    16,    17,    18,    19,
-      20,    30,    31,    32,    30,    25,    24,    77,     1,    79,
-      30,     4,     5,     6,     7,     8,     9,    10,    11,    25,
-       1,    14,    15,    16,     4,     5,     6,     7,     8,     9,
-      10,    11,    25,    30,    14,    15,    13,    30,     5,     6,
-      25,     8,     9,    10,    11,    32,    14,    14,    15,    33,
-      30,   148,   149,   150,    30,    31,    32,    30,    77,   156,
-      79,   158,     7,    30,    30,    30,    30,    30,    30,   166,
-      30,    30,    30,     6,    75,    36,    47,   115
+       1,    67,    68,    10,    93,    94,    76,     3,    76,    14,
+      28,    81,    13,    81,    15,   104,    34,    18,     3,    32,
+      33,    23,    26,    27,    90,    91,    30,    32,    33,    31,
+      78,    35,    80,     0,     1,    31,   102,     4,     5,     6,
+       7,     8,     9,    10,    11,    12,    31,    14,    15,    16,
+      17,    18,    19,    20,    21,    22,    23,    24,    78,    26,
+      80,    26,    69,   133,    31,   133,    31,   156,    26,    27,
+      29,     0,     1,    32,    33,     4,     5,     6,     7,     8,
+       9,    10,    11,    12,   150,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    24,     0,    26,   164,   100,
+      77,    78,    31,    80,    77,    78,    31,    80,    31,    32,
+      33,     0,     1,    31,   115,     4,     5,     6,     7,     8,
+       9,    10,    11,    26,    27,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    31,    26,    26,    31,     0,
+       1,    26,    31,     4,     5,     6,     7,     8,     9,    10,
+      11,    26,    31,    14,    15,    16,    17,    18,    19,    20,
+      21,    22,    23,     1,     1,    26,    31,    32,    33,    31,
+      31,     0,     1,    31,    31,     4,     5,     6,     7,     8,
+       9,    10,    11,    31,   185,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    31,     1,    26,    31,    31,
+       5,     6,    31,     8,     9,    10,    11,    12,    31,    14,
+      15,    16,    17,    18,    19,    20,    31,    31,    31,    25,
+       1,    26,    26,    13,     1,    26,    31,     4,     5,     6,
+       7,     8,     9,    10,    11,    31,    14,    14,    15,    16,
+       4,     5,     6,     7,     8,     9,    10,    11,    33,    26,
+      14,    15,     5,     6,    31,     8,     9,    10,    11,    31,
+      31,    14,    15,    31,    31,    31,    31,    31,    31,   151,
+      31,   153,   154,   155,    34,    31,     7,     6,    31,   161,
+      37,   163,    76,    -1,    79,   116,    -1,    -1,    -1,    -1,
+     172
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,     3,    30,    36,    37,    38,    62,    78,    25,    26,
-      76,     0,     1,     4,     5,     6,     7,     8,     9,    10,
+       0,     3,    31,    37,    38,    39,    63,    81,    26,    27,
+      79,     0,     1,     4,     5,     6,     7,     8,     9,    10,
       11,    14,    15,    16,    17,    18,    19,    20,    21,    22,
-      25,    30,    39,    40,    42,    43,    44,    45,    51,    52,
-      54,    58,    60,    63,    64,    66,    68,    69,    70,    77,
-      38,    30,    37,    78,    30,    76,    30,    76,    25,    82,
-      30,    76,    25,    25,    25,    26,    29,    34,    80,    81,
-      30,     1,     1,    46,    46,    55,    57,    61,    73,    67,
-      73,    30,    30,    30,    30,    30,    30,    80,    80,    31,
-      32,    78,    27,    33,    30,    30,     1,    12,    16,    18,
-      19,    20,    21,    22,    23,    25,    30,    41,    47,    48,
-      71,    72,    74,    17,    18,    19,    20,    30,    41,    56,
-      72,    74,    40,    53,    77,    40,    54,    59,    66,    77,
-      30,    41,    74,    40,    54,    65,    66,    77,    28,    80,
-      80,    81,    81,    30,    30,    24,    76,    75,    76,    80,
-      25,    81,    49,     1,    13,    30,    76,    75,    25,    80,
-      14,    79,    30,    79,    79,    79,    81,    25,    30,    30,
-      79,    30,    79,    30,    80,    30,    30,    30,    79,    33,
-      50,    30,    30,    30,    76
+      23,    26,    31,    40,    41,    43,    44,    45,    46,    52,
+      53,    55,    59,    61,    64,    65,    67,    69,    70,    71,
+      80,    39,    31,    38,    81,    31,    79,    31,    79,    26,
+      85,    31,    79,    26,    26,    26,    27,    30,    35,    83,
+      84,    31,     1,     1,    47,    47,    56,    58,    62,    76,
+      68,    74,    31,    31,    31,    31,    31,    31,    83,    83,
+      32,    33,    81,    28,    34,    31,    31,     1,    12,    16,
+      18,    19,    20,    21,    22,    24,    26,    31,    42,    48,
+      49,    72,    73,    75,    17,    18,    19,    20,    31,    42,
+      57,    73,    75,    41,    54,    80,    41,    55,    60,    67,
+      80,    23,    31,    74,    77,    41,    55,    66,    67,    80,
+      31,    42,    75,    29,    83,    83,    84,    84,    31,    31,
+      25,    79,    78,    79,    83,    26,    84,    50,     1,    13,
+      31,    79,    78,    26,    14,    82,    83,    82,    31,    82,
+      82,    82,    84,    26,    31,    31,    82,    31,    82,    83,
+      31,    31,    31,    31,    82,    34,    51,    31,    31,    31,
+      79
 };
 
 #define yyerrok                (yyerrstatus = 0)
@@ -1292,7 +1302,7 @@ yydestruct (yymsg, yytype, yyvaluep)
 
   switch (yytype)
     {
-      case 52: /* "choice_entry" */
+      case 53: /* "choice_entry" */
 
        {
        fprintf(stderr, "%s:%d: missing end statement for this entry\n",
@@ -1302,7 +1312,7 @@ yydestruct (yymsg, yytype, yyvaluep)
 };
 
        break;
-      case 58: /* "if_entry" */
+      case 59: /* "if_entry" */
 
        {
        fprintf(stderr, "%s:%d: missing end statement for this entry\n",
@@ -1312,7 +1322,7 @@ yydestruct (yymsg, yytype, yyvaluep)
 };
 
        break;
-      case 64: /* "menu_entry" */
+      case 65: /* "menu_entry" */
 
        {
        fprintf(stderr, "%s:%d: missing end statement for this entry\n",
@@ -1644,17 +1654,17 @@ yyreduce:
     { zconf_error("invalid statement"); ;}
     break;
 
-  case 27:
+  case 28:
 
     { zconf_error("unknown option \"%s\"", (yyvsp[(1) - (3)].string)); ;}
     break;
 
-  case 28:
+  case 29:
 
     { zconf_error("invalid option"); ;}
     break;
 
-  case 29:
+  case 30:
 
     {
        struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);
@@ -1664,7 +1674,7 @@ yyreduce:
 ;}
     break;
 
-  case 30:
+  case 31:
 
     {
        menu_end_entry();
@@ -1672,7 +1682,7 @@ yyreduce:
 ;}
     break;
 
-  case 31:
+  case 32:
 
     {
        struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);
@@ -1682,7 +1692,7 @@ yyreduce:
 ;}
     break;
 
-  case 32:
+  case 33:
 
     {
        if (current_entry->prompt)
@@ -1694,7 +1704,7 @@ yyreduce:
 ;}
     break;
 
-  case 40:
+  case 41:
 
     {
        menu_set_type((yyvsp[(1) - (3)].id)->stype);
@@ -1704,7 +1714,7 @@ yyreduce:
 ;}
     break;
 
-  case 41:
+  case 42:
 
     {
        menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));
@@ -1712,7 +1722,7 @@ yyreduce:
 ;}
     break;
 
-  case 42:
+  case 43:
 
     {
        menu_add_expr(P_DEFAULT, (yyvsp[(2) - (4)].expr), (yyvsp[(3) - (4)].expr));
@@ -1724,7 +1734,7 @@ yyreduce:
 ;}
     break;
 
-  case 43:
+  case 44:
 
     {
        menu_add_symbol(P_SELECT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr));
@@ -1732,7 +1742,7 @@ yyreduce:
 ;}
     break;
 
-  case 44:
+  case 45:
 
     {
        menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[(2) - (5)].symbol), (yyvsp[(3) - (5)].symbol)), (yyvsp[(4) - (5)].expr));
@@ -1740,7 +1750,7 @@ yyreduce:
 ;}
     break;
 
-  case 47:
+  case 48:
 
     {
        struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string)));
@@ -1752,17 +1762,17 @@ yyreduce:
 ;}
     break;
 
-  case 48:
+  case 49:
 
     { (yyval.string) = NULL; ;}
     break;
 
-  case 49:
+  case 50:
 
     { (yyval.string) = (yyvsp[(2) - (2)].string); ;}
     break;
 
-  case 50:
+  case 51:
 
     {
        struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), SYMBOL_CHOICE);
@@ -1773,14 +1783,14 @@ yyreduce:
 ;}
     break;
 
-  case 51:
+  case 52:
 
     {
        (yyval.menu) = menu_add_menu();
 ;}
     break;
 
-  case 52:
+  case 53:
 
     {
        if (zconf_endtoken((yyvsp[(1) - (1)].id), T_CHOICE, T_ENDCHOICE)) {
@@ -1790,7 +1800,7 @@ yyreduce:
 ;}
     break;
 
-  case 60:
+  case 61:
 
     {
        menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));
@@ -1798,7 +1808,7 @@ yyreduce:
 ;}
     break;
 
-  case 61:
+  case 62:
 
     {
        if ((yyvsp[(1) - (3)].id)->stype == S_BOOLEAN || (yyvsp[(1) - (3)].id)->stype == S_TRISTATE) {
@@ -1811,7 +1821,7 @@ yyreduce:
 ;}
     break;
 
-  case 62:
+  case 63:
 
     {
        current_entry->sym->flags |= SYMBOL_OPTIONAL;
@@ -1819,7 +1829,7 @@ yyreduce:
 ;}
     break;
 
-  case 63:
+  case 64:
 
     {
        if ((yyvsp[(1) - (4)].id)->stype == S_UNKNOWN) {
@@ -1831,7 +1841,7 @@ yyreduce:
 ;}
     break;
 
-  case 66:
+  case 67:
 
     {
        printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
@@ -1841,7 +1851,7 @@ yyreduce:
 ;}
     break;
 
-  case 67:
+  case 68:
 
     {
        if (zconf_endtoken((yyvsp[(1) - (1)].id), T_IF, T_ENDIF)) {
@@ -1851,14 +1861,14 @@ yyreduce:
 ;}
     break;
 
-  case 73:
+  case 74:
 
     {
        menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL);
 ;}
     break;
 
-  case 74:
+  case 75:
 
     {
        menu_add_entry(NULL);
@@ -1867,14 +1877,14 @@ yyreduce:
 ;}
     break;
 
-  case 75:
+  case 76:
 
     {
        (yyval.menu) = menu_add_menu();
 ;}
     break;
 
-  case 76:
+  case 77:
 
     {
        if (zconf_endtoken((yyvsp[(1) - (1)].id), T_MENU, T_ENDMENU)) {
@@ -1884,7 +1894,7 @@ yyreduce:
 ;}
     break;
 
-  case 82:
+  case 83:
 
     {
        printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
@@ -1892,7 +1902,7 @@ yyreduce:
 ;}
     break;
 
-  case 83:
+  case 84:
 
     {
        menu_add_entry(NULL);
@@ -1901,14 +1911,14 @@ yyreduce:
 ;}
     break;
 
-  case 84:
+  case 85:
 
     {
        menu_end_entry();
 ;}
     break;
 
-  case 85:
+  case 86:
 
     {
        printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
@@ -1916,14 +1926,14 @@ yyreduce:
 ;}
     break;
 
-  case 86:
+  case 87:
 
     {
        current_entry->help = (yyvsp[(2) - (2)].string);
 ;}
     break;
 
-  case 91:
+  case 92:
 
     {
        menu_add_dep((yyvsp[(3) - (4)].expr));
@@ -1931,84 +1941,91 @@ yyreduce:
 ;}
     break;
 
-  case 93:
+  case 96:
+
+    {
+       menu_add_visibility((yyvsp[(2) - (2)].expr));
+;}
+    break;
+
+  case 98:
 
     {
        menu_add_prompt(P_PROMPT, (yyvsp[(1) - (2)].string), (yyvsp[(2) - (2)].expr));
 ;}
     break;
 
-  case 96:
+  case 101:
 
     { (yyval.id) = (yyvsp[(1) - (2)].id); ;}
     break;
 
-  case 97:
+  case 102:
 
     { (yyval.id) = (yyvsp[(1) - (2)].id); ;}
     break;
 
-  case 98:
+  case 103:
 
     { (yyval.id) = (yyvsp[(1) - (2)].id); ;}
     break;
 
-  case 101:
+  case 106:
 
     { (yyval.expr) = NULL; ;}
     break;
 
-  case 102:
+  case 107:
 
     { (yyval.expr) = (yyvsp[(2) - (2)].expr); ;}
     break;
 
-  case 103:
+  case 108:
 
     { (yyval.expr) = expr_alloc_symbol((yyvsp[(1) - (1)].symbol)); ;}
     break;
 
-  case 104:
+  case 109:
 
     { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;}
     break;
 
-  case 105:
+  case 110:
 
     { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;}
     break;
 
-  case 106:
+  case 111:
 
     { (yyval.expr) = (yyvsp[(2) - (3)].expr); ;}
     break;
 
-  case 107:
+  case 112:
 
     { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[(2) - (2)].expr)); ;}
     break;
 
-  case 108:
+  case 113:
 
     { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
     break;
 
-  case 109:
+  case 114:
 
     { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
     break;
 
-  case 110:
+  case 115:
 
     { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 0); free((yyvsp[(1) - (1)].string)); ;}
     break;
 
-  case 111:
+  case 116:
 
     { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); ;}
     break;
 
-  case 112:
+  case 117:
 
     { (yyval.string) = NULL; ;}
     break;
@@ -2278,6 +2295,7 @@ static const char *zconf_tokenname(int token)
        case T_IF:              return "if";
        case T_ENDIF:           return "endif";
        case T_DEPENDS:         return "depends";
+       case T_VISIBLE:         return "visible";
        }
        return "<token>";
 }
index 2abd3c7ff15d91d25679a4cec6f1ff21da38fb23..49fb4ab664c39b555692896f97fc8d6bfad36cd1 100644 (file)
@@ -36,7 +36,7 @@ static struct menu *current_menu, *current_entry;
 #define YYERROR_VERBOSE
 #endif
 %}
-%expect 28
+%expect 30
 
 %union
 {
@@ -68,6 +68,7 @@ static struct menu *current_menu, *current_entry;
 %token <id>T_DEFAULT
 %token <id>T_SELECT
 %token <id>T_RANGE
+%token <id>T_VISIBLE
 %token <id>T_OPTION
 %token <id>T_ON
 %token <string> T_WORD
@@ -123,7 +124,7 @@ stmt_list:
 ;
 
 option_name:
-       T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT
+       T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE
 ;
 
 common_stmt:
@@ -359,7 +360,7 @@ menu: T_MENU prompt T_EOL
        printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
 };
 
-menu_entry: menu depends_list
+menu_entry: menu visibility_list depends_list
 {
        $$ = menu_add_menu();
 };
@@ -430,6 +431,19 @@ depends: T_DEPENDS T_ON expr T_EOL
        printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
 };
 
+/* visibility option */
+
+visibility_list:
+         /* empty */
+       | visibility_list visible
+       | visibility_list T_EOL
+;
+
+visible: T_VISIBLE if_expr
+{
+       menu_add_visibility($2);
+};
+
 /* prompt statement */
 
 prompt_stmt_opt:
@@ -526,6 +540,7 @@ static const char *zconf_tokenname(int token)
        case T_IF:              return "if";
        case T_ENDIF:           return "endif";
        case T_DEPENDS:         return "depends";
+       case T_VISIBLE:         return "visible";
        }
        return "<token>";
 }
index cdb6dc1f6458ba4634c0f8584ae3da615ce10696..39580a5dc5df6083a5766ae8853c6610e417474f 100755 (executable)
@@ -5,7 +5,7 @@ use strict;
 ## Copyright (c) 1998 Michael Zucchi, All Rights Reserved        ##
 ## Copyright (C) 2000, 1  Tim Waugh <twaugh@redhat.com>          ##
 ## Copyright (C) 2001  Simon Huggins                             ##
-## Copyright (C) 2005-2009  Randy Dunlap                         ##
+## Copyright (C) 2005-2010  Randy Dunlap                         ##
 ##                                                              ##
 ## #define enhancements by Armin Kuster <akuster@mvista.com>    ##
 ## Copyright (c) 2000 MontaVista Software, Inc.                         ##
@@ -453,7 +453,7 @@ sub output_highlight {
     if ($output_mode eq "html" || $output_mode eq "xml") {
        $contents = local_unescape($contents);
        # convert data read & converted thru xml_escape() into &xyz; format:
-       $contents =~ s/\\\\\\/&/g;
+       $contents =~ s/\\\\\\/\&/g;
     }
 #   print STDERR "contents b4:$contents\n";
     eval $dohighlight;
@@ -770,7 +770,11 @@ sub output_struct_xml(%) {
     print $args{'type'} . " " . $args{'struct'} . " {\n";
     foreach $parameter (@{$args{'parameterlist'}}) {
        if ($parameter =~ /^#/) {
-           print "$parameter\n";
+           my $prm = $parameter;
+           # convert data read & converted thru xml_escape() into &xyz; format:
+           # This allows us to have #define macros interspersed in a struct.
+           $prm =~ s/\\\\\\/\&/g;
+           print "$prm\n";
            next;
        }
 
@@ -1701,6 +1705,8 @@ sub push_parameter($$$) {
        }
        }
 
+       $param = xml_escape($param);
+
        # strip spaces from $param so that it is one continous string
        # on @parameterlist;
        # this fixes a problem where check_sections() cannot find
index 58e933a20544a2cd379446661d01f3755494bf97..39667174971d1eb86105edd927aa92d39c0954bf 100644 (file)
@@ -119,7 +119,7 @@ static uint_t (*Elf_r_sym)(Elf_Rel const *rp) = fn_ELF_R_SYM;
 
 static void fn_ELF_R_INFO(Elf_Rel *const rp, unsigned sym, unsigned type)
 {
-       rp->r_info = ELF_R_INFO(sym, type);
+       rp->r_info = _w(ELF_R_INFO(sym, type));
 }
 static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_ELF_R_INFO;
 
index 8509bb51293530fae488f60594199031cd16bf07..bbbe584d44943077a41b22684b5ecdbce18f532a 100755 (executable)
@@ -125,7 +125,9 @@ exuberant()
        -I DEFINE_TRACE,EXPORT_TRACEPOINT_SYMBOL,EXPORT_TRACEPOINT_SYMBOL_GPL \
        --extra=+f --c-kinds=-px                                \
        --regex-asm='/^ENTRY\(([^)]*)\).*/\1/'                  \
-       --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/'
+       --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' \
+       --regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/'               \
+       --regex-c++='/^DEFINE_EVENT\(([^,)]*).*/trace_\1/'
 
        all_kconfigs | xargs $1 -a                              \
        --langdef=kconfig --language-force=kconfig              \
index f2f41c8542211143cc56e83328092d1bcb27a2bf..6e24091818950edc9c298241be2d28a751b39f83 100644 (file)
@@ -420,9 +420,9 @@ static int __devinit atmel_abdac_probe(struct platform_device *pdev)
                return PTR_ERR(pclk);
        }
        sample_clk = clk_get(&pdev->dev, "sample_clk");
-       if (IS_ERR(pclk)) {
+       if (IS_ERR(sample_clk)) {
                dev_dbg(&pdev->dev, "no sample clock\n");
-               retval = PTR_ERR(pclk);
+               retval = PTR_ERR(sample_clk);
                goto out_put_pclk;
        }
        clk_enable(pclk);
index 5c8c7dff8ede8a3989301ce083319e75cbffe808..b753ec661fcfd149d079f530e05729d8d0cc524b 100644 (file)
@@ -1510,16 +1510,19 @@ static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __use
 static int snd_pcm_oss_reset(struct snd_pcm_oss_file *pcm_oss_file)
 {
        struct snd_pcm_substream *substream;
+       struct snd_pcm_runtime *runtime;
+       int i;
 
-       substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
-       if (substream != NULL) {
-               snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
-               substream->runtime->oss.prepare = 1;
-       }
-       substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
-       if (substream != NULL) {
+       for (i = 0; i < 2; i++) { 
+               substream = pcm_oss_file->streams[i];
+               if (!substream)
+                       continue;
+               runtime = substream->runtime;
                snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
-               substream->runtime->oss.prepare = 1;
+               runtime->oss.prepare = 1;
+               runtime->oss.buffer_used = 0;
+               runtime->oss.prev_hw_ptr_period = 0;
+               runtime->oss.period_ptr = 0;
        }
        return 0;
 }
index a1707cca9c6635c8b4cd7e79b5cebe21bffc2d9e..b75db8e9cc0f36fff03d0ecf1884b23b3bad724b 100644 (file)
@@ -223,7 +223,7 @@ static void xrun_log(struct snd_pcm_substream *substream,
        entry->jiffies = jiffies;
        entry->pos = pos;
        entry->period_size = runtime->period_size;
-       entry->buffer_size = runtime->buffer_size;;
+       entry->buffer_size = runtime->buffer_size;
        entry->old_hw_ptr = runtime->status->hw_ptr;
        entry->hw_ptr_base = runtime->hw_ptr_base;
        log->idx = (log->idx + 1) % XRUN_LOG_CNT;
index 727bdb9ba2dc1bc9b0cc62fd8abde19403ca292d..d8cf3e58dc76aa1017ef5b9424e862e95498ee6d 100644 (file)
@@ -71,7 +71,7 @@ int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver,
        if (sound_nblocks >= MAX_MEM_BLOCKS)
                sound_nblocks = MAX_MEM_BLOCKS - 1;
 
-       op = (struct audio_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct audio_operations)));
+       op = (struct audio_operations *) (sound_mem_blocks[sound_nblocks] = vzalloc(sizeof(struct audio_operations)));
        sound_nblocks++;
        if (sound_nblocks >= MAX_MEM_BLOCKS)
                sound_nblocks = MAX_MEM_BLOCKS - 1;
@@ -81,7 +81,6 @@ int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver,
                sound_unload_audiodev(num);
                return -(ENOMEM);
        }
-       memset((char *) op, 0, sizeof(struct audio_operations));
        init_waitqueue_head(&op->in_sleeper);
        init_waitqueue_head(&op->out_sleeper);  
        init_waitqueue_head(&op->poll_sleeper);
@@ -128,7 +127,7 @@ int sound_install_mixer(int vers, char *name, struct mixer_operations *driver,
        /* FIXME: This leaks a mixer_operations struct every time its called
           until you unload sound! */
           
-       op = (struct mixer_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct mixer_operations)));
+       op = (struct mixer_operations *) (sound_mem_blocks[sound_nblocks] = vzalloc(sizeof(struct mixer_operations)));
        sound_nblocks++;
        if (sound_nblocks >= MAX_MEM_BLOCKS)
                sound_nblocks = MAX_MEM_BLOCKS - 1;
@@ -137,7 +136,6 @@ int sound_install_mixer(int vers, char *name, struct mixer_operations *driver,
                printk(KERN_ERR "Sound: Can't allocate mixer driver for (%s)\n", name);
                return -ENOMEM;
        }
-       memset((char *) op, 0, sizeof(struct mixer_operations));
        memcpy((char *) op, (char *) driver, driver_size);
 
        strlcpy(op->name, name, sizeof(op->name));
index 782b3b84dac68ccd036c52ee3533336f243ac15b..ceedb1eff203812e85049f7cdb46b92a588fc557 100644 (file)
@@ -178,7 +178,7 @@ int MIDIbuf_open(int dev, struct file *file)
                return err;
 
        parms[dev].prech_timeout = MAX_SCHEDULE_TIMEOUT;
-       midi_in_buf[dev] = (struct midi_buf *) vmalloc(sizeof(struct midi_buf));
+       midi_in_buf[dev] = vmalloc(sizeof(struct midi_buf));
 
        if (midi_in_buf[dev] == NULL)
        {
@@ -188,7 +188,7 @@ int MIDIbuf_open(int dev, struct file *file)
        }
        midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0;
 
-       midi_out_buf[dev] = (struct midi_buf *) vmalloc(sizeof(struct midi_buf));
+       midi_out_buf[dev] = vmalloc(sizeof(struct midi_buf));
 
        if (midi_out_buf[dev] == NULL)
        {
index e19dd5dcc2debd9e3b4a7fa9ec481849f8442a30..9b800ce5100ef286864234b308fb646c7d5dc9a1 100644 (file)
@@ -859,7 +859,7 @@ static int pss_coproc_ioctl(void *dev_info, unsigned int cmd, void __user *arg,
                        return 0;
 
                case SNDCTL_COPR_LOAD:
-                       buf = (copr_buffer *) vmalloc(sizeof(copr_buffer));
+                       buf = vmalloc(sizeof(copr_buffer));
                        if (buf == NULL)
                                return -ENOSPC;
                        if (copy_from_user(buf, arg, sizeof(copr_buffer))) {
@@ -871,7 +871,7 @@ static int pss_coproc_ioctl(void *dev_info, unsigned int cmd, void __user *arg,
                        return err;
                
                case SNDCTL_COPR_SENDMSG:
-                       mbuf = (copr_msg *)vmalloc(sizeof(copr_msg));
+                       mbuf = vmalloc(sizeof(copr_msg));
                        if (mbuf == NULL)
                                return -ENOSPC;
                        if (copy_from_user(mbuf, arg, sizeof(copr_msg))) {
@@ -895,7 +895,7 @@ static int pss_coproc_ioctl(void *dev_info, unsigned int cmd, void __user *arg,
 
                case SNDCTL_COPR_RCVMSG:
                        err = 0;
-                       mbuf = (copr_msg *)vmalloc(sizeof(copr_msg));
+                       mbuf = vmalloc(sizeof(copr_msg));
                        if (mbuf == NULL)
                                return -ENOSPC;
                        data = (unsigned short *)mbuf->data;
index e85789e53816640f8e7e7224fdd0199787e5f4de..5ea1098ac427a5546bdf9f211587bbe8030d1821 100644 (file)
@@ -1646,13 +1646,13 @@ void sequencer_init(void)
 {
        if (sequencer_ok)
                return;
-       queue = (unsigned char *)vmalloc(SEQ_MAX_QUEUE * EV_SZ);
+       queue = vmalloc(SEQ_MAX_QUEUE * EV_SZ);
        if (queue == NULL)
        {
                printk(KERN_ERR "sequencer: Can't allocate memory for sequencer output queue\n");
                return;
        }
-       iqueue = (unsigned char *)vmalloc(SEQ_MAX_QUEUE * IEV_SZ);
+       iqueue = vmalloc(SEQ_MAX_QUEUE * IEV_SZ);
        if (iqueue == NULL)
        {
                printk(KERN_ERR "sequencer: Can't allocate memory for sequencer input queue\n");
index 62895a719fcbcce841b05f44fce0a90813d70477..22dbd91811a4e61398a9b9077c5cbe26c0139119 100644 (file)
@@ -435,7 +435,7 @@ void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev)
        struct hpi_message hm;
        struct hpi_response hr;
        struct hpi_adapter *pa;
-       pa = (struct hpi_adapter *)pci_get_drvdata(pci_dev);
+       pa = pci_get_drvdata(pci_dev);
 
        hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
                HPI_SUBSYS_DELETE_ADAPTER);
index 4679ed83a43b8687402b7efca98ed47a0518ac98..2f3cacbd5528da80cccca5791147d6f516dcdf82 100644 (file)
@@ -1129,10 +1129,11 @@ snd_azf3328_codec_setdmaa(struct snd_azf3328 *chip,
 
                count_areas = size/2;
                addr_area2 = addr+count_areas;
-               count_areas--; /* max. index */
                snd_azf3328_dbgcodec("setdma: buffers %08lx[%u] / %08lx[%u]\n",
                                addr, count_areas, addr_area2, count_areas);
 
+               count_areas--; /* max. index */
+
                /* build combined I/O buffer length word */
                lengths = (count_areas << 16) | (count_areas);
                spin_lock_irqsave(&chip->reg_lock, flags);
@@ -1740,11 +1741,15 @@ static const struct snd_pcm_hardware snd_azf3328_hardware =
        .rate_max =             AZF_FREQ_66200,
        .channels_min =         1,
        .channels_max =         2,
-       .buffer_bytes_max =     65536,
-       .period_bytes_min =     64,
-       .period_bytes_max =     65536,
-       .periods_min =          1,
-       .periods_max =          1024,
+       .buffer_bytes_max =     (64*1024),
+       .period_bytes_min =     1024,
+       .period_bytes_max =     (32*1024),
+       /* We simply have two DMA areas (instead of a list of descriptors
+          such as other cards); I believe that this is a fixed hardware
+          attribute and there isn't much driver magic to be done to expand it.
+          Thus indicate that we have at least and at most 2 periods. */
+       .periods_min =          2,
+       .periods_max =          2,
        /* FIXME: maybe that card actually has a FIFO?
         * Hmm, it seems newer revisions do have one, but we still don't know
         * its size... */
@@ -1980,8 +1985,13 @@ snd_azf3328_timer_stop(struct snd_timer *timer)
        chip = snd_timer_chip(timer);
        spin_lock_irqsave(&chip->reg_lock, flags);
        /* disable timer countdown and interrupt */
-       /* FIXME: should we write TIMER_IRQ_ACK here? */
-       snd_azf3328_ctrl_outb(chip, IDX_IO_TIMER_VALUE + 3, 0);
+       /* Hmm, should we write TIMER_IRQ_ACK here?
+          YES indeed, otherwise a rogue timer operation - which prompts
+          ALSA(?) to call repeated stop() in vain, but NOT start() -
+          will never end (value 0x03 is kept shown in control byte).
+          Simply manually poking 0x04 _once_ immediately successfully stops
+          the hardware/ALSA interrupt activity. */
+       snd_azf3328_ctrl_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x04);
        spin_unlock_irqrestore(&chip->reg_lock, flags);
        snd_azf3328_dbgcallleave();
        return 0;
index 85ab43e89212c6724c1e70f3cad3de33e9816935..457d21189b0db1fc5b2fcd2af22e30d20089dcb1 100644 (file)
@@ -129,8 +129,6 @@ static int ct_pcm_playback_open(struct snd_pcm_substream *substream)
 
        apcm->substream = substream;
        apcm->interrupt = ct_atc_pcm_interrupt;
-       runtime->private_data = apcm;
-       runtime->private_free = ct_atc_pcm_free_substream;
        if (IEC958 == substream->pcm->device) {
                runtime->hw = ct_spdif_passthru_playback_hw;
                atc->spdif_out_passthru(atc, 1);
@@ -155,8 +153,12 @@ static int ct_pcm_playback_open(struct snd_pcm_substream *substream)
        }
 
        apcm->timer = ct_timer_instance_new(atc->timer, apcm);
-       if (!apcm->timer)
+       if (!apcm->timer) {
+               kfree(apcm);
                return -ENOMEM;
+       }
+       runtime->private_data = apcm;
+       runtime->private_free = ct_atc_pcm_free_substream;
 
        return 0;
 }
@@ -278,8 +280,6 @@ static int ct_pcm_capture_open(struct snd_pcm_substream *substream)
        apcm->started = 0;
        apcm->substream = substream;
        apcm->interrupt = ct_atc_pcm_interrupt;
-       runtime->private_data = apcm;
-       runtime->private_free = ct_atc_pcm_free_substream;
        runtime->hw = ct_pcm_capture_hw;
        runtime->hw.rate_max = atc->rsr * atc->msr;
 
@@ -298,8 +298,12 @@ static int ct_pcm_capture_open(struct snd_pcm_substream *substream)
        }
 
        apcm->timer = ct_timer_instance_new(atc->timer, apcm);
-       if (!apcm->timer)
+       if (!apcm->timer) {
+               kfree(apcm);
                return -ENOMEM;
+       }
+       runtime->private_data = apcm;
+       runtime->private_free = ct_atc_pcm_free_substream;
 
        return 0;
 }
index cb0c23a6b473e07bd9d768f9430e7cde2342639c..4a663471dadc1e1e00d712bd5656577aeba56984 100644 (file)
@@ -189,6 +189,9 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a,
        a->channels = GRAB_BITS(buf, 0, 0, 3);
        a->channels++;
 
+       a->sample_bits = 0;
+       a->max_bitrate = 0;
+
        a->format = GRAB_BITS(buf, 0, 3, 4);
        switch (a->format) {
        case AUDIO_CODING_TYPE_REF_STREAM_HEADER:
@@ -198,7 +201,6 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a,
 
        case AUDIO_CODING_TYPE_LPCM:
                val = GRAB_BITS(buf, 2, 0, 3);
-               a->sample_bits = 0;
                for (i = 0; i < 3; i++)
                        if (val & (1 << i))
                                a->sample_bits |= cea_sample_sizes[i + 1];
@@ -598,24 +600,19 @@ void hdmi_eld_update_pcm_info(struct hdmi_eld *eld, struct hda_pcm_stream *pcm,
 {
        int i;
 
-       pcm->rates = 0;
-       pcm->formats = 0;
-       pcm->maxbps = 0;
-       pcm->channels_min = -1;
-       pcm->channels_max = 0;
+       /* assume basic audio support (the basic audio flag is not in ELD;
+        * however, all audio capable sinks are required to support basic
+        * audio) */
+       pcm->rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000;
+       pcm->formats = SNDRV_PCM_FMTBIT_S16_LE;
+       pcm->maxbps = 16;
+       pcm->channels_max = 2;
        for (i = 0; i < eld->sad_count; i++) {
                struct cea_sad *a = &eld->sad[i];
                pcm->rates |= a->rates;
-               if (a->channels < pcm->channels_min)
-                       pcm->channels_min = a->channels;
                if (a->channels > pcm->channels_max)
                        pcm->channels_max = a->channels;
                if (a->format == AUDIO_CODING_TYPE_LPCM) {
-                       if (a->sample_bits & AC_SUPPCM_BITS_16) {
-                               pcm->formats |= SNDRV_PCM_FMTBIT_S16_LE;
-                               if (pcm->maxbps < 16)
-                                       pcm->maxbps = 16;
-                       }
                        if (a->sample_bits & AC_SUPPCM_BITS_20) {
                                pcm->formats |= SNDRV_PCM_FMTBIT_S32_LE;
                                if (pcm->maxbps < 20)
@@ -635,7 +632,6 @@ void hdmi_eld_update_pcm_info(struct hdmi_eld *eld, struct hda_pcm_stream *pcm,
        /* restrict the parameters by the values the codec provides */
        pcm->rates &= codec_pars->rates;
        pcm->formats &= codec_pars->formats;
-       pcm->channels_min = max(pcm->channels_min, codec_pars->channels_min);
        pcm->channels_max = min(pcm->channels_max, codec_pars->channels_max);
        pcm->maxbps = min(pcm->maxbps, codec_pars->maxbps);
 }
index 21aa9b0e28f6cb466a81a4d1e4c48622c71f89c9..b030c8eba21fdc618fe0b5bfb32cf5b156c39bba 100644 (file)
@@ -2296,6 +2296,7 @@ static int azx_dev_free(struct snd_device *device)
  */
 static struct snd_pci_quirk position_fix_list[] __devinitdata = {
        SND_PCI_QUIRK(0x1025, 0x009f, "Acer Aspire 5110", POS_FIX_LPIB),
+       SND_PCI_QUIRK(0x1025, 0x026f, "Acer Aspire 5538", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB),
index 6361f752b5f35cfddff7f8423f0d5d185a9003d8..76bd58a0e2b637e2c17a79cc94ab54e0747de227 100644 (file)
@@ -2116,8 +2116,8 @@ static void cxt5066_update_speaker(struct hda_codec *codec)
        struct conexant_spec *spec = codec->spec;
        unsigned int pinctl;
 
-       snd_printdd("CXT5066: update speaker, hp_present=%d\n",
-               spec->hp_present);
+       snd_printdd("CXT5066: update speaker, hp_present=%d, cur_eapd=%d\n",
+                   spec->hp_present, spec->cur_eapd);
 
        /* Port A (HP) */
        pinctl = ((spec->hp_present & 1) && spec->cur_eapd) ? PIN_HP : 0;
@@ -2125,11 +2125,20 @@ static void cxt5066_update_speaker(struct hda_codec *codec)
                        pinctl);
 
        /* Port D (HP/LO) */
-       pinctl = ((spec->hp_present & 2) && spec->cur_eapd)
-               ? spec->port_d_mode : 0;
-       /* Mute if Port A is connected on Thinkpad */
-       if (spec->thinkpad && (spec->hp_present & 1))
-               pinctl = 0;
+       if (spec->dell_automute) {
+               /* DELL AIO Port Rule: PortA>  PortD>  IntSpk */
+               pinctl = (!(spec->hp_present & 1) && spec->cur_eapd)
+                       ? PIN_OUT : 0;
+       } else if (spec->thinkpad) {
+               if (spec->cur_eapd)
+                       pinctl = spec->port_d_mode;
+               /* Mute dock line-out if Port A (laptop HP) is present */
+               if (spec->hp_present&  1)
+                       pinctl = 0;
+       } else {
+               pinctl = ((spec->hp_present & 2) && spec->cur_eapd)
+                       ? spec->port_d_mode : 0;
+       }
        snd_hda_codec_write(codec, 0x1c, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
                        pinctl);
 
@@ -2137,14 +2146,6 @@ static void cxt5066_update_speaker(struct hda_codec *codec)
        pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
        snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
                        pinctl);
-
-       if (spec->dell_automute) {
-               /* DELL AIO Port Rule: PortA > PortD > IntSpk */
-               pinctl = (!(spec->hp_present & 1) && spec->cur_eapd)
-                       ? PIN_OUT : 0;
-               snd_hda_codec_write(codec, 0x1c, 0,
-                       AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl);
-       }
 }
 
 /* turn on/off EAPD (+ mute HP) as a master switch */
@@ -3095,11 +3096,11 @@ static const char *cxt5066_models[CXT5066_MODELS] = {
 static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
        SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO),
-       SND_PCI_QUIRK(0x1028, 0x02f5, "Dell",
-                     CXT5066_DELL_LAPTOP),
+       SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTRO),
        SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP),
+       SND_PCI_QUIRK(0x1043, 0x13f3, "Asus A52J", CXT5066_HP_LAPTOP),
        SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5),
        SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5),
@@ -3108,8 +3109,10 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
        SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD),
+       SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x21b4, "Thinkpad Edge", CXT5066_IDEAPAD),
+       SND_PCI_QUIRK(0x17aa, 0x21c8, "Thinkpad Edge 11", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G series", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x390a, "Lenovo S10-3t", CXT5066_IDEAPAD),
index d3e49aa5b9ecd42f6db6f5892319e6602ad9b7ab..31df7747990d0be6690a520321a0498c9caba349 100644 (file)
@@ -834,7 +834,6 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
                        return -ENODEV;
        } else {
                /* fallback to the codec default */
-               hinfo->channels_min = codec_pars->channels_min;
                hinfo->channels_max = codec_pars->channels_max;
                hinfo->rates = codec_pars->rates;
                hinfo->formats = codec_pars->formats;
index 5f00589cb791aebed2d7aa1f0bd908819b9123b8..427da45d7906560f517e04de74c84ab971c0a50a 100644 (file)
@@ -1614,6 +1614,7 @@ do_sku:
                spec->init_amp = ALC_INIT_GPIO3;
                break;
        case 5:
+       default:
                spec->init_amp = ALC_INIT_DEFAULT;
                break;
        }
@@ -2013,6 +2014,36 @@ static struct hda_verb alc888_acer_aspire_6530g_verbs[] = {
        { }
 };
 
+/*
+ *ALC888 Acer Aspire 7730G model
+ */
+
+static struct hda_verb alc888_acer_aspire_7730G_verbs[] = {
+/* Bias voltage on for external mic port */
+       {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN | PIN_VREF80},
+/* Front Mic: set to PIN_IN (empty by default) */
+       {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+/* Unselect Front Mic by default in input mixer 3 */
+       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
+/* Enable unsolicited event for HP jack */
+       {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+/* Enable speaker output */
+       {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
+/* Enable headphone output */
+       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP},
+       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+       {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
+/*Enable internal subwoofer */
+       {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x17, AC_VERB_SET_CONNECT_SEL, 0x02},
+       {0x17, AC_VERB_SET_EAPD_BTLENABLE, 2},
+       { }
+};
+
 /*
  * ALC889 Acer Aspire 8930G model
  */
@@ -2200,6 +2231,16 @@ static void alc888_acer_aspire_6530g_setup(struct hda_codec *codec)
        spec->autocfg.speaker_pins[2] = 0x17;
 }
 
+static void alc888_acer_aspire_7730g_setup(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+
+       spec->autocfg.hp_pins[0] = 0x15;
+       spec->autocfg.speaker_pins[0] = 0x14;
+       spec->autocfg.speaker_pins[1] = 0x16;
+       spec->autocfg.speaker_pins[2] = 0x17;
+}
+
 static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
@@ -4554,6 +4595,7 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU),
        SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW),
        SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG),
+       SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_LG),
        SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG),
        SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_LG_LW),
        SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700),
@@ -9524,13 +9566,6 @@ static struct hda_verb alc883_acer_eapd_verbs[] = {
        { }
 };
 
-static struct hda_verb alc888_acer_aspire_7730G_verbs[] = {
-       {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-       {0x17, AC_VERB_SET_CONNECT_SEL, 0x02},
-       {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-       { } /* end */
-};
-
 static void alc888_6st_dell_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
@@ -9831,7 +9866,6 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x3bfc, "Lenovo NB0763", ALC883_LENOVO_NB0763),
        SND_PCI_QUIRK(0x17aa, 0x3bfd, "Lenovo NB0763", ALC883_LENOVO_NB0763),
        SND_PCI_QUIRK(0x17aa, 0x101d, "Lenovo Sky", ALC888_LENOVO_SKY),
-       SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2),
        SND_PCI_QUIRK(0x17c0, 0x4085, "MEDION MD96630", ALC888_LENOVO_MS7195_DIG),
        SND_PCI_QUIRK(0x17f2, 0x5000, "Albatron KI690-AM2", ALC883_6ST_DIG),
        SND_PCI_QUIRK(0x1991, 0x5625, "Haier W66", ALC883_HAIER_W66),
@@ -10328,7 +10362,7 @@ static struct alc_config_preset alc882_presets[] = {
                .const_channel_count = 6,
                .input_mux = &alc883_capture_source,
                .unsol_event = alc_automute_amp_unsol_event,
-               .setup = alc888_acer_aspire_6530g_setup,
+               .setup = alc888_acer_aspire_7730g_setup,
                .init_hook = alc_automute_amp,
        },
        [ALC883_MEDION] = {
@@ -10796,7 +10830,8 @@ static int alc_auto_add_mic_boost(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
        struct auto_pin_cfg *cfg = &spec->autocfg;
-       int i, err;
+       int i, err, type;
+       int type_idx = 0;
        hda_nid_t nid;
 
        for (i = 0; i < cfg->num_inputs; i++) {
@@ -10805,9 +10840,15 @@ static int alc_auto_add_mic_boost(struct hda_codec *codec)
                nid = cfg->inputs[i].pin;
                if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
                        char label[32];
+                       type = cfg->inputs[i].type;
+                       if (i > 0 && type == cfg->inputs[i - 1].type)
+                               type_idx++;
+                       else
+                               type_idx = 0;
                        snprintf(label, sizeof(label), "%s Boost",
                                 hda_get_autocfg_input_label(codec, cfg, i));
-                       err = add_control(spec, ALC_CTL_WIDGET_VOL, label, 0,
+                       err = add_control(spec, ALC_CTL_WIDGET_VOL, label,
+                                         type_idx,
                                  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
                        if (err < 0)
                                return err;
@@ -14623,7 +14664,10 @@ static int alc275_setup_dual_adc(struct hda_codec *codec)
 /* different alc269-variants */
 enum {
        ALC269_TYPE_NORMAL,
+       ALC269_TYPE_ALC258,
        ALC269_TYPE_ALC259,
+       ALC269_TYPE_ALC269VB,
+       ALC269_TYPE_ALC270,
        ALC269_TYPE_ALC271X,
 };
 
@@ -14763,6 +14807,8 @@ static int alc269_resume(struct hda_codec *codec)
 enum {
        ALC269_FIXUP_SONY_VAIO,
        ALC269_FIXUP_DELL_M101Z,
+       ALC269_FIXUP_LENOVO_EDGE14,
+       ALC269_FIXUP_ASUS_G73JW,
 };
 
 static const struct alc_fixup alc269_fixups[] = {
@@ -14780,11 +14826,22 @@ static const struct alc_fixup alc269_fixups[] = {
                        {}
                }
        },
+       [ALC269_FIXUP_LENOVO_EDGE14] = {
+               .sku = ALC_FIXUP_SKU_IGNORE,
+       },
+       [ALC269_FIXUP_ASUS_G73JW] = {
+               .pins = (const struct alc_pincfg[]) {
+                       { 0x17, 0x99130111 }, /* subwoofer */
+                       { }
+               }
+       },
 };
 
 static struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
        SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
+       SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_LENOVO_EDGE14),
+       SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
        {}
 };
 
@@ -15023,7 +15080,7 @@ static int alc269_fill_coef(struct hda_codec *codec)
 static int patch_alc269(struct hda_codec *codec)
 {
        struct alc_spec *spec;
-       int board_config;
+       int board_config, coef;
        int err;
 
        spec = kzalloc(sizeof(*spec), GFP_KERNEL);
@@ -15034,14 +15091,23 @@ static int patch_alc269(struct hda_codec *codec)
 
        alc_auto_parse_customize_define(codec);
 
-       if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010){
+       coef = alc_read_coef_idx(codec, 0);
+       if ((coef & 0x00f0) == 0x0010) {
                if (codec->bus->pci->subsystem_vendor == 0x1025 &&
                    spec->cdefine.platform_type == 1) {
                        alc_codec_rename(codec, "ALC271X");
                        spec->codec_variant = ALC269_TYPE_ALC271X;
-               } else {
+               } else if ((coef & 0xf000) == 0x1000) {
+                       spec->codec_variant = ALC269_TYPE_ALC270;
+               } else if ((coef & 0xf000) == 0x2000) {
                        alc_codec_rename(codec, "ALC259");
                        spec->codec_variant = ALC269_TYPE_ALC259;
+               } else if ((coef & 0xf000) == 0x3000) {
+                       alc_codec_rename(codec, "ALC258");
+                       spec->codec_variant = ALC269_TYPE_ALC258;
+               } else {
+                       alc_codec_rename(codec, "ALC269VB");
+                       spec->codec_variant = ALC269_TYPE_ALC269VB;
                }
        } else
                alc_fix_pll_init(codec, 0x20, 0x04, 15);
@@ -15104,7 +15170,7 @@ static int patch_alc269(struct hda_codec *codec)
        spec->stream_digital_capture = &alc269_pcm_digital_capture;
 
        if (!spec->adc_nids) { /* wasn't filled automatically? use default */
-               if (spec->codec_variant != ALC269_TYPE_NORMAL) {
+               if (spec->codec_variant == ALC269_TYPE_NORMAL) {
                        spec->adc_nids = alc269_adc_nids;
                        spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids);
                        spec->capsrc_nids = alc269_capsrc_nids;
@@ -16898,7 +16964,7 @@ static struct alc_config_preset alc861vd_presets[] = {
 static int alc861vd_auto_create_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
 {
-       return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x09, 0);
+       return alc_auto_create_input_ctls(codec, cfg, 0x0b, 0x22, 0);
 }
 
 
@@ -18952,6 +19018,8 @@ static inline hda_nid_t alc662_mix_to_dac(hda_nid_t nid)
                return 0x02;
        else if (nid >= 0x0c && nid <= 0x0e)
                return nid - 0x0c + 0x02;
+       else if (nid == 0x26) /* ALC887-VD has this DAC too */
+               return 0x25;
        else
                return 0;
 }
@@ -18960,7 +19028,7 @@ static inline hda_nid_t alc662_mix_to_dac(hda_nid_t nid)
 static hda_nid_t alc662_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
                                   hda_nid_t dac)
 {
-       hda_nid_t mix[4];
+       hda_nid_t mix[5];
        int i, num;
 
        num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
@@ -19298,6 +19366,7 @@ static const struct alc_fixup alc662_fixups[] = {
 
 static struct snd_pci_quirk alc662_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
+       SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
        {}
@@ -19419,7 +19488,10 @@ static int patch_alc888(struct hda_codec *codec)
 {
        if ((alc_read_coef_idx(codec, 0) & 0x00f0)==0x0030){
                kfree(codec->chip_name);
-               codec->chip_name = kstrdup("ALC888-VD", GFP_KERNEL);
+               if (codec->vendor_id == 0x10ec0887)
+                       codec->chip_name = kstrdup("ALC887-VD", GFP_KERNEL);
+               else
+                       codec->chip_name = kstrdup("ALC888-VD", GFP_KERNEL);
                if (!codec->chip_name) {
                        alc_free(codec);
                        return -ENOMEM;
@@ -19909,7 +19981,7 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = {
        { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
          .patch = patch_alc882 },
        { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
-       { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc882 },
+       { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc888 },
        { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
          .patch = patch_alc882 },
        { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc888 },
index 93fa59cc60ef9ba0f5b2315c6461d3966608994c..efa4225f5fd6c95f9f0218d38002d1ca12d88bd3 100644 (file)
@@ -389,6 +389,11 @@ static hda_nid_t stac92hd83xxx_dmic_nids[STAC92HD83XXX_NUM_DMICS + 1] = {
        0x11, 0x20, 0
 };
 
+#define STAC92HD87B_NUM_DMICS   1
+static hda_nid_t stac92hd87b_dmic_nids[STAC92HD87B_NUM_DMICS + 1] = {
+       0x11, 0
+};
+
 #define STAC92HD83XXX_NUM_CAPS 2
 static unsigned long stac92hd83xxx_capvols[] = {
        HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
@@ -1622,6 +1627,8 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {
 static struct snd_pci_quirk stac92hd73xx_codec_id_cfg_tbl[] = {
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02a1,
                      "Alienware M17x", STAC_ALIENWARE_M17X),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x043a,
+                     "Alienware M17x", STAC_ALIENWARE_M17X),
        {} /* terminator */
 };
 
@@ -3486,10 +3493,8 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
                                return err;
                }
 
-               if (snd_hda_get_bool_hint(codec, "separate_dmux") != 1) {
+               if (snd_hda_get_bool_hint(codec, "separate_dmux") != 1)
                        snd_hda_add_imux_item(imux, label, index, NULL);
-                       spec->num_analog_muxes++;
-               }
        }
 
        return 0;
@@ -5452,12 +5457,17 @@ again:
                                stac92hd83xxx_brd_tbl[spec->board_config]);
 
        switch (codec->vendor_id) {
+       case 0x111d76d1:
+       case 0x111d76d9:
+               spec->dmic_nids = stac92hd87b_dmic_nids;
+               spec->num_dmics = stac92xx_connected_ports(codec,
+                               stac92hd87b_dmic_nids,
+                               STAC92HD87B_NUM_DMICS);
+               /* Fall through */
        case 0x111d7666:
        case 0x111d7667:
        case 0x111d7668:
        case 0x111d7669:
-       case 0x111d76d1:
-       case 0x111d76d9:
                spec->num_pins = ARRAY_SIZE(stac92hd88xxx_pin_nids);
                spec->pin_nids = stac92hd88xxx_pin_nids;
                spec->mono_nid = 0;
index 400f9ebd243e84ebf595cb4cba69f6a3cb3552b7..629a5494347a021600ed6f2dbf82feb5971d10ac 100644 (file)
@@ -1864,6 +1864,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
                .name = "Dell Inspiron 8600",   /* STAC9750/51 */
                .type = AC97_TUNE_HP_ONLY
        },
+       {
+               .subvendor = 0x1028,
+               .subdevice = 0x0182,
+               .name = "Dell Latitude D610",   /* STAC9750/51 */
+               .type = AC97_TUNE_HP_ONLY
+       },
        {
                .subvendor = 0x1028,
                .subdevice = 0x0186,
index a46f5083db99229c88797895b9de5170bede8245..812e288ef2e76eb58de27118a7522700f0f21a38 100644 (file)
 
 #include <sound/hwdep.h>
 
+#ifndef readl_be
 #define readl_be(x) be32_to_cpu(__raw_readl(x))
+#endif
+
+#ifndef writel_be
 #define writel_be(data,addr) __raw_writel(cpu_to_be32(data),addr)
+#endif
 
+#ifndef readl_le
 #define readl_le(x) le32_to_cpu(__raw_readl(x))
+#endif
+
+#ifndef writel_le
 #define writel_le(data,addr) __raw_writel(cpu_to_le32(data),addr)
+#endif
 
 #define MIXART_MEM(mgr,x)      ((mgr)->mem[0].virt + (x))
 #define MIXART_REG(mgr,x)      ((mgr)->mem[1].virt + (x))
index 85081172403f25ec056a99eb58a341fbd5d57370..b47cfd45b3b98f04b2c6d89135de310fb3b264ef 100644 (file)
@@ -1228,10 +1228,8 @@ int __devinit snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return)
                                               chip->rsrc[i].start + 1,
                                               rnames[i]) == NULL) {
                                printk(KERN_ERR "snd: can't request rsrc "
-                                      " %d (%s: 0x%016llx:%016llx)\n",
-                                      i, rnames[i],
-                                      (unsigned long long)chip->rsrc[i].start,
-                                      (unsigned long long)chip->rsrc[i].end);
+                                      " %d (%s: %pR)\n",
+                                      i, rnames[i], &chip->rsrc[i]);
                                err = -ENODEV;
                                goto __error;
                        }
@@ -1256,10 +1254,8 @@ int __devinit snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return)
                                               chip->rsrc[i].start + 1,
                                               rnames[i]) == NULL) {
                                printk(KERN_ERR "snd: can't request rsrc "
-                                      " %d (%s: 0x%016llx:%016llx)\n",
-                                      i, rnames[i],
-                                      (unsigned long long)chip->rsrc[i].start,
-                                      (unsigned long long)chip->rsrc[i].end);
+                                      " %d (%s: %pR)\n",
+                                      i, rnames[i], &chip->rsrc[i]);
                                err = -ENODEV;
                                goto __error;
                        }
index e720d5e6f04cfdd135ea42e5b74ed74e75724bed..bee3c94f58b0736c57f361141e0ed32e58640317 100644 (file)
@@ -16,7 +16,8 @@ config SND_ATMEL_SOC_SSC
 
 config SND_AT91_SOC_SAM9G20_WM8731
        tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board"
-       depends on ATMEL_SSC && ARCH_AT91SAM9G20 && SND_ATMEL_SOC
+       depends on ATMEL_SSC && ARCH_AT91SAM9G20 && SND_ATMEL_SOC && \
+                   AT91_PROGRAMMABLE_CLOCKS
        select SND_ATMEL_SOC_SSC
        select SND_SOC_WM8731
        help
@@ -25,7 +26,7 @@ config SND_AT91_SOC_SAM9G20_WM8731
 
 config SND_AT32_SOC_PLAYPAQ
         tristate "SoC Audio support for PlayPaq with WM8510"
-        depends on SND_ATMEL_SOC && BOARD_PLAYPAQ
+        depends on SND_ATMEL_SOC && BOARD_PLAYPAQ && AT91_PROGRAMMABLE_CLOCKS
         select SND_ATMEL_SOC_SSC
         select SND_SOC_WM8510
         help
index 293569dfd0edec6d70551d90e610a93bba74ad7f..e521ada80542512e124822ef11db5bfbd5bddb3a 100644 (file)
@@ -222,9 +222,9 @@ static int __init at91sam9g20ek_init(void)
        }
 
        pllb = clk_get(NULL, "pllb");
-       if (IS_ERR(mclk)) {
+       if (IS_ERR(pllb)) {
                printk(KERN_ERR "ASoC: Failed to get PLLB\n");
-               ret = PTR_ERR(mclk);
+               ret = PTR_ERR(pllb);
                goto err_mclk;
        }
        ret = clk_set_parent(mclk, pllb);
@@ -240,6 +240,7 @@ static int __init at91sam9g20ek_init(void)
        if (!at91sam9g20ek_snd_device) {
                printk(KERN_ERR "ASoC: Platform device allocation failed\n");
                ret = -ENOMEM;
+               goto err_mclk;
        }
 
        platform_set_drvdata(at91sam9g20ek_snd_device,
@@ -248,11 +249,13 @@ static int __init at91sam9g20ek_init(void)
        ret = platform_device_add(at91sam9g20ek_snd_device);
        if (ret) {
                printk(KERN_ERR "ASoC: Platform device allocation failed\n");
-               platform_device_put(at91sam9g20ek_snd_device);
+               goto err_device_add;
        }
 
        return ret;
 
+err_device_add:
+       platform_device_put(at91sam9g20ek_snd_device);
 err_mclk:
        clk_put(mclk);
        mclk = NULL;
index e3d283561c196a8198e97d6bf2cc3b1b11987624..86e0f8586dc362f0f6edadf1995bb6176c436fe6 100644 (file)
@@ -167,7 +167,6 @@ static int __init afeb9260_soc_init(void)
 
        return 0;
 err1:
-       platform_device_del(afeb9260_snd_device);
        platform_device_put(afeb9260_snd_device);
        return err;
 }
index bc22ee93a75daf3c852ce65f9767df519445251c..d63e28773eb1841ac7bdd06af0d37a0d5c03013b 100644 (file)
 #include <sound/max98088.h>
 #include "max98088.h"
 
+enum max98088_type {
+       MAX98088,
+       MAX98089,
+};
+
 struct max98088_cdata {
        unsigned int rate;
        unsigned int fmt;
@@ -36,6 +41,7 @@ struct max98088_cdata {
 
 struct max98088_priv {
        u8 reg_cache[M98088_REG_CNT];
+       enum max98088_type devtype;
        void *control_data;
        struct max98088_pdata *pdata;
        unsigned int sysclk;
@@ -2013,7 +2019,10 @@ err_access:
 
 static int max98088_remove(struct snd_soc_codec *codec)
 {
+       struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+
        max98088_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       kfree(max98088->eq_texts);
 
        return 0;
 }
@@ -2040,6 +2049,8 @@ static int max98088_i2c_probe(struct i2c_client *i2c,
        if (max98088 == NULL)
                return -ENOMEM;
 
+       max98088->devtype = id->driver_data;
+
        i2c_set_clientdata(i2c, max98088);
        max98088->control_data = i2c;
        max98088->pdata = i2c->dev.platform_data;
@@ -2059,7 +2070,8 @@ static int __devexit max98088_i2c_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id max98088_i2c_id[] = {
-       { "max98088", 0 },
+       { "max98088", MAX98088 },
+       { "max98089", MAX98089 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, max98088_i2c_id);
index 00d67cc8e2062a9071dcb78ee0fb2d64b5a77166..061f9e5a497bc3280b42a7a55838709e24cbb35b 100644 (file)
@@ -383,6 +383,7 @@ static struct snd_soc_codec_driver soc_codec_dev_stac9766 = {
        .reg_cache_size = sizeof(stac9766_reg),
        .reg_word_size = sizeof(u16),
        .reg_cache_step = 2,
+       .reg_cache_default = stac9766_reg,
 };
 
 static __devinit int stac9766_probe(struct platform_device *pdev)
index fc687790188b2f1ee2b33f48f2dab0b831f3ffa9..77b8f9ae29be5fcd2a64b5d2bba0b1803f43602d 100644 (file)
@@ -1176,7 +1176,7 @@ EXPORT_SYMBOL_GPL(aic3x_set_gpio);
 int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio)
 {
        u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG;
-       u8 val, bit = gpio ? 2: 1;
+       u8 val = 0, bit = gpio ? 2 : 1;
 
        aic3x_read(codec, reg, &val);
        return (val >> bit) & 1;
@@ -1204,7 +1204,7 @@ EXPORT_SYMBOL_GPL(aic3x_set_headset_detection);
 
 int aic3x_headset_detected(struct snd_soc_codec *codec)
 {
-       u8 val;
+       u8 val = 0;
        aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val);
        return (val >> 4) & 1;
 }
@@ -1212,7 +1212,7 @@ EXPORT_SYMBOL_GPL(aic3x_headset_detected);
 
 int aic3x_button_pressed(struct snd_soc_codec *codec)
 {
-       u8 val;
+       u8 val = 0;
        aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val);
        return (val >> 5) & 1;
 }
index ee4fb201de60ca9ceb969fd00ce1292aad0a9330..d2c24309567303667dfcae14d79a6809e4ce1e7b 100644 (file)
@@ -78,8 +78,10 @@ static int tpa6130a2_i2c_write(int reg, u8 value)
 
        if (data->power_state) {
                val = i2c_smbus_write_byte_data(tpa6130a2_client, reg, value);
-               if (val < 0)
+               if (val < 0) {
                        dev_err(&tpa6130a2_client->dev, "Write failed\n");
+                       return val;
+               }
        }
 
        /* Either powered on or off, we save the context */
index 7540a509a6f58acec8c29aad5c76b65a86a5f83a..464f0cfa4c7a538b7eef3a86752d57f551952d54 100644 (file)
@@ -597,6 +597,7 @@ static struct snd_soc_codec_driver soc_codec_dev_uda134x = {
        .resume =       uda134x_soc_resume,
        .reg_cache_size = sizeof(uda134x_reg),
        .reg_word_size = sizeof(u8),
+       .reg_cache_default = uda134x_reg,
        .reg_cache_step = 1,
        .read = uda134x_read_reg_cache,
        .write = uda134x_write,
index f4f1fba38eb9458176f5bda41cc93d12c87722eb..7611add7f8c38751806684a521d891ede746197f 100644 (file)
@@ -831,7 +831,7 @@ static int wm8350_set_dai_sysclk(struct snd_soc_dai *codec_dai,
        }
 
        /* MCLK direction */
-       if (dir == WM8350_MCLK_DIR_OUT)
+       if (dir == SND_SOC_CLOCK_OUT)
                wm8350_set_bits(wm8350, WM8350_CLOCK_CONTROL_2,
                                WM8350_MCLK_DIR);
        else
@@ -1586,6 +1586,13 @@ static  int wm8350_codec_probe(struct snd_soc_codec *codec)
        wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME,
                        WM8350_OUT2_VU | WM8350_OUT2R_MUTE);
 
+       /* Make sure AIF tristating is disabled by default */
+       wm8350_clear_bits(wm8350, WM8350_AI_FORMATING, WM8350_AIF_TRI);
+
+       /* Make sure we've got a sane companding setup too */
+       wm8350_clear_bits(wm8350, WM8350_ADC_DAC_COMP,
+                         WM8350_DAC_COMP | WM8350_LOOPBACK);
+
        /* Make sure jack detect is disabled to start off with */
        wm8350_clear_bits(wm8350, WM8350_JACK_DETECT,
                          WM8350_JDL_ENA | WM8350_JDR_ENA);
index 712ef7c76f90bbde579229ea85716dd14f7acb10..9a433a5396cb781727e39a4c1c6005f1bbc9a421 100644 (file)
@@ -146,7 +146,6 @@ static int wm8523_startup(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       return 0;
        snd_pcm_hw_constraint_list(substream->runtime, 0,
                                   SNDRV_PCM_HW_PARAM_RATE,
                                   &wm8523->rate_constraint);
index a2e0ed59b3769f0b7d73024a6e4740338b1ccb81..8725d4e754310d86774935b48e1a2443fe04405c 100644 (file)
 static const u16 wm8580_reg[] = {
        0x0121, 0x017e, 0x007d, 0x0014, /*R3*/
        0x0121, 0x017e, 0x007d, 0x0194, /*R7*/
-       0x001c, 0x0002, 0x0002, 0x00c2, /*R11*/
+       0x0010, 0x0002, 0x0002, 0x00c2, /*R11*/
        0x0182, 0x0082, 0x000a, 0x0024, /*R15*/
        0x0009, 0x0000, 0x00ff, 0x0000, /*R19*/
        0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R23*/
@@ -491,16 +491,16 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
                paifa |= 0x8;
                break;
        case SNDRV_PCM_FORMAT_S20_3LE:
-               paifa |= 0x10;
+               paifa |= 0x0;
                paifb |= WM8580_AIF_LENGTH_20;
                break;
        case SNDRV_PCM_FORMAT_S24_LE:
-               paifa |= 0x10;
+               paifa |= 0x0;
                paifb |= WM8580_AIF_LENGTH_24;
                break;
        case SNDRV_PCM_FORMAT_S32_LE:
-               paifa |= 0x10;
-               paifb |= WM8580_AIF_LENGTH_24;
+               paifa |= 0x0;
+               paifb |= WM8580_AIF_LENGTH_32;
                break;
        default:
                return -EINVAL;
index 631385802eb44a587f5fe375d8f1c61e89ba9d02..e725c09a3e79bf7bafa6fda17ee6112fd629e6ee 100644 (file)
@@ -526,7 +526,7 @@ static int wm8731_probe(struct snd_soc_codec *codec)
        snd_soc_update_bits(codec, WM8731_RINVOL, 0x100, 0);
 
        /* Disable bypass path by default */
-       snd_soc_update_bits(codec, WM8731_APANA, 0x4, 0);
+       snd_soc_update_bits(codec, WM8731_APANA, 0x8, 0);
 
        snd_soc_add_controls(codec, wm8731_snd_controls,
                             ARRAY_SIZE(wm8731_snd_controls));
index 04182c464e35ffeffb069ad06242dca74da52248..0132a27140ae539c85c822b06b984b0733d84e41 100644 (file)
@@ -34,7 +34,6 @@
 /* codec private data */
 struct wm8776_priv {
        enum snd_soc_control_type control_type;
-       u16 reg_cache[WM8776_CACHEREGNUM];
        int sysclk[2];
 };
 
index 33be84e506ea7d4e2927a4e44a06e49ab648f156..9001cc48ba1371596c890ce12465e314d9022a81 100644 (file)
@@ -818,7 +818,8 @@ static int wm8904_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
 
-       return wm8904->deemph;
+       ucontrol->value.enumerated.item[0] = wm8904->deemph;
+       return 0;
 }
 
 static int wm8904_put_deemph(struct snd_kcontrol *kcontrol,
@@ -2498,6 +2499,8 @@ static int wm8904_remove(struct snd_soc_codec *codec)
 
        wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF);
        regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
+       kfree(wm8904->retune_mobile_texts);
+       kfree(wm8904->drc_texts);
 
        return 0;
 }
index f89ad6c9a80b9162e7040ea6fe76b434c9f743f1..9cbab8e1de0149cd8b2063406ecbae29ca0c78e5 100644 (file)
@@ -380,7 +380,8 @@ static int wm8955_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
 
-       return wm8955->deemph;
+       ucontrol->value.enumerated.item[0] = wm8955->deemph;
+       return 0;
 }
 
 static int wm8955_put_deemph(struct snd_kcontrol *kcontrol,
index 8d5efb333c33f260b271af07e9352b14679f0502..21986c42272f07ac693cd21d15f48cff20c43352 100644 (file)
@@ -138,7 +138,8 @@ static int wm8960_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
 
-       return wm8960->deemph;
+       ucontrol->value.enumerated.item[0] = wm8960->deemph;
+       return 0;
 }
 
 static int wm8960_put_deemph(struct snd_kcontrol *kcontrol,
index 4f326f6041042742255731ba078574b37a48a6f3..8340485c985145a2ad1614bedaf39f2377276d88 100644 (file)
@@ -711,7 +711,7 @@ static int wm8961_hw_params(struct snd_pcm_substream *substream,
        if (fs <= 24000)
                reg |= WM8961_DACSLOPE;
        else
-               reg &= WM8961_DACSLOPE;
+               reg &= ~WM8961_DACSLOPE;
        snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_2, reg);
 
        return 0;
@@ -736,7 +736,7 @@ static int wm8961_set_sysclk(struct snd_soc_dai *dai, int clk_id,
                freq /= 2;
        } else {
                dev_dbg(codec->dev, "Using MCLK/1 for %dHz MCLK\n", freq);
-               reg &= WM8961_MCLKDIV;
+               reg &= ~WM8961_MCLKDIV;
        }
 
        snd_soc_write(codec, WM8961_CLOCKING1, reg);
index 894d0cd3aa9b95896fbaff30db883b1fe39bc668..1304ca91a11c708c567f69c45052c95f1f7be17e 100644 (file)
@@ -3339,7 +3339,7 @@ static irqreturn_t wm8962_irq(int irq, void *data)
        int mask;
        int active;
 
-       mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2);
+       mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2_MASK);
 
        active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2);
        active &= ~mask;
@@ -3500,8 +3500,11 @@ static ssize_t wm8962_beep_set(struct device *dev,
 {
        struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
        long int time;
+       int ret;
 
-       strict_strtol(buf, 10, &time);
+       ret = strict_strtol(buf, 10, &time);
+       if (ret != 0)
+               return ret;
 
        input_event(wm8962->beep, EV_SND, SND_TONE, time);
 
index 0db59c3aa5d4dbb6cd2a821d29eaa75887290977..4d3e6f1ac5843f7a6f28ed0a9490bacea4ba3ad0 100644 (file)
@@ -3903,6 +3903,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
                return -ENOMEM;
        snd_soc_codec_set_drvdata(codec, wm8994);
 
+       codec->reg_cache = &wm8994->reg_cache;
+
        wm8994->pdata = dev_get_platdata(codec->dev->parent);
        wm8994->codec = codec;
 
@@ -4059,6 +4061,8 @@ static int  wm8994_codec_remove(struct snd_soc_codec *codec)
        wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994);
        wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994);
        wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994);
+       kfree(wm8994->retune_mobile_texts);
+       kfree(wm8994->drc_texts);
        kfree(wm8994);
 
        return 0;
@@ -4071,6 +4075,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8994 = {
        .resume =       wm8994_resume,
        .read = wm8994_read,
        .write = wm8994_write,
+       .readable_register = wm8994_readable,
+       .volatile_register = wm8994_volatile,
        .set_bias_level = wm8994_set_bias_level,
 };
 
index 19ca782ac970f1956243862534e5df1df12a3113..0e24092722c39522d85980a71f8a3727d01cf63f 100644 (file)
@@ -293,7 +293,7 @@ SOC_DOUBLE_R("Speaker Switch",
 SOC_DOUBLE_R("Speaker ZC Switch",
             WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT,
             7, 1, 0),
-SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 0, 3, 7, 0,
+SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 3, 0, 7, 0,
               spkboost_tlv),
 SOC_ENUM("Speaker Reference", speaker_ref),
 SOC_ENUM("Speaker Mode", speaker_mode),
index 2b07b17a6b2d68f3173380bc16de4eb07b921689..bc9e6b0b3f6fd67c4061ce364198a272d7a557d3 100644 (file)
@@ -157,12 +157,23 @@ static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd)
 }
 
 /* davinci-evm digital audio interface glue - connects codec <--> CPU */
-static struct snd_soc_dai_link evm_dai = {
+static struct snd_soc_dai_link dm6446_evm_dai = {
        .name = "TLV320AIC3X",
        .stream_name = "AIC3X",
-       .cpu_dai_name = "davinci-mcasp.0",
+       .cpu_dai_name = "davinci-mcbsp",
        .codec_dai_name = "tlv320aic3x-hifi",
-       .codec_name = "tlv320aic3x-codec.0-001a",
+       .codec_name = "tlv320aic3x-codec.1-001b",
+       .platform_name = "davinci-pcm-audio",
+       .init = evm_aic3x_init,
+       .ops = &evm_ops,
+};
+
+static struct snd_soc_dai_link dm355_evm_dai = {
+       .name = "TLV320AIC3X",
+       .stream_name = "AIC3X",
+       .cpu_dai_name = "davinci-mcbsp.1",
+       .codec_dai_name = "tlv320aic3x-hifi",
+       .codec_name = "tlv320aic3x-codec.1-001b",
        .platform_name = "davinci-pcm-audio",
        .init = evm_aic3x_init,
        .ops = &evm_ops,
@@ -172,10 +183,10 @@ static struct snd_soc_dai_link dm365_evm_dai = {
 #ifdef CONFIG_SND_DM365_AIC3X_CODEC
        .name = "TLV320AIC3X",
        .stream_name = "AIC3X",
-       .cpu_dai_name = "davinci-i2s",
+       .cpu_dai_name = "davinci-mcbsp",
        .codec_dai_name = "tlv320aic3x-hifi",
        .init = evm_aic3x_init,
-       .codec_name = "tlv320aic3x-codec.0-001a",
+       .codec_name = "tlv320aic3x-codec.1-0018",
        .ops = &evm_ops,
 #elif defined(CONFIG_SND_DM365_VOICE_CODEC)
        .name = "Voice Codec - CQ93VC",
@@ -219,10 +230,17 @@ static struct snd_soc_dai_link da8xx_evm_dai = {
        .ops = &evm_ops,
 };
 
-/* davinci dm6446, dm355 evm audio machine driver */
-static struct snd_soc_card snd_soc_card_evm = {
-       .name = "DaVinci EVM",
-       .dai_link = &evm_dai,
+/* davinci dm6446 evm audio machine driver */
+static struct snd_soc_card dm6446_snd_soc_card_evm = {
+       .name = "DaVinci DM6446 EVM",
+       .dai_link = &dm6446_evm_dai,
+       .num_links = 1,
+};
+
+/* davinci dm355 evm audio machine driver */
+static struct snd_soc_card dm355_snd_soc_card_evm = {
+       .name = "DaVinci DM355 EVM",
+       .dai_link = &dm355_evm_dai,
        .num_links = 1,
 };
 
@@ -261,10 +279,10 @@ static int __init evm_init(void)
        int ret;
 
        if (machine_is_davinci_evm()) {
-               evm_snd_dev_data = &snd_soc_card_evm;
+               evm_snd_dev_data = &dm6446_snd_soc_card_evm;
                index = 0;
        } else if (machine_is_davinci_dm355_evm()) {
-               evm_snd_dev_data = &snd_soc_card_evm;
+               evm_snd_dev_data = &dm355_snd_soc_card_evm;
                index = 1;
        } else if (machine_is_davinci_dm365_evm()) {
                evm_snd_dev_data = &dm365_snd_soc_card_evm;
index d46b545d41f432f037c58eb6c3b4b0f1b13cc2a2..9e0e565e6ed9c2e9308e74e80f2bad50d8f58b28 100644 (file)
@@ -426,9 +426,6 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
        snd_pcm_format_t fmt;
        unsigned element_cnt = 1;
 
-       dai->capture_dma_data = dev->dma_params;
-       dai->playback_dma_data = dev->dma_params;
-
        /* general line settings */
        spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
        if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
@@ -601,6 +598,15 @@ static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
        return ret;
 }
 
+static int davinci_i2s_startup(struct snd_pcm_substream *substream,
+                              struct snd_soc_dai *dai)
+{
+       struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);
+
+       snd_soc_dai_set_dma_data(dai, substream, dev->dma_params);
+       return 0;
+}
+
 static void davinci_i2s_shutdown(struct snd_pcm_substream *substream,
                struct snd_soc_dai *dai)
 {
@@ -612,6 +618,7 @@ static void davinci_i2s_shutdown(struct snd_pcm_substream *substream,
 #define DAVINCI_I2S_RATES      SNDRV_PCM_RATE_8000_96000
 
 static struct snd_soc_dai_ops davinci_i2s_dai_ops = {
+       .startup        = davinci_i2s_startup,
        .shutdown       = davinci_i2s_shutdown,
        .prepare        = davinci_i2s_prepare,
        .trigger        = davinci_i2s_trigger,
@@ -749,7 +756,7 @@ static struct platform_driver davinci_mcbsp_driver = {
        .probe          = davinci_i2s_probe,
        .remove         = davinci_i2s_remove,
        .driver         = {
-               .name   = "davinci-i2s",
+               .name   = "davinci-mcbsp",
                .owner  = THIS_MODULE,
        },
 };
index 86918ee12419e7fd3ff626bdb2ccd18a1bd09021..fb55d2c5d704ff25983fd5ef4d16dfc461e60a76 100644 (file)
@@ -715,9 +715,6 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
        int word_length;
        u8 fifo_level;
 
-       cpu_dai->capture_dma_data = dev->dma_params;
-       cpu_dai->playback_dma_data = dev->dma_params;
-
        davinci_hw_common_param(dev, substream->stream);
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                fifo_level = dev->txnumevt;
@@ -799,7 +796,17 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
        return ret;
 }
 
+static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
+                                struct snd_soc_dai *dai)
+{
+       struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);
+
+       snd_soc_dai_set_dma_data(dai, substream, dev->dma_params);
+       return 0;
+}
+
 static struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
+       .startup        = davinci_mcasp_startup,
        .trigger        = davinci_mcasp_trigger,
        .hw_params      = davinci_mcasp_hw_params,
        .set_fmt        = davinci_mcasp_set_dai_fmt,
index 009b6521a1bf9f3731e9d597f09ff3644126b967..6c6666a1f942682907cae74b6bf4aa382ad955e8 100644 (file)
@@ -84,7 +84,7 @@ static struct snd_soc_ops sffsdr_ops = {
 static struct snd_soc_dai_link sffsdr_dai = {
        .name = "PCM3008", /* Codec name */
        .stream_name = "PCM3008 HiFi",
-       .cpu_dai_name = "davinci-asp.0",
+       .cpu_dai_name = "davinci-mcbsp",
        .codec_dai_name = "pcm3008-hifi",
        .codec_name = "pcm3008-codec",
        .platform_name = "davinci-pcm-audio",
index ea232f6a2c21912e408a69ea2d1f8df28e4552dd..9d2afccc3a2d645dceb1e263ef7158f4c7667934 100644 (file)
@@ -97,9 +97,6 @@ static int davinci_vcif_hw_params(struct snd_pcm_substream *substream,
                        &davinci_vcif_dev->dma_params[substream->stream];
        u32 w;
 
-       dai->capture_dma_data = davinci_vcif_dev->dma_params;
-       dai->playback_dma_data = davinci_vcif_dev->dma_params;
-
        /* Restart the codec before setup */
        davinci_vcif_stop(substream);
        davinci_vcif_start(substream);
@@ -174,9 +171,19 @@ static int davinci_vcif_trigger(struct snd_pcm_substream *substream, int cmd,
        return ret;
 }
 
+static int davinci_vcif_startup(struct snd_pcm_substream *substream,
+                               struct snd_soc_dai *dai)
+{
+       struct davinci_vcif_dev *dev = snd_soc_dai_get_drvdata(dai);
+
+       snd_soc_dai_set_dma_data(dai, substream, dev->dma_params);
+       return 0;
+}
+
 #define DAVINCI_VCIF_RATES     SNDRV_PCM_RATE_8000_48000
 
 static struct snd_soc_dai_ops davinci_vcif_dai_ops = {
+       .startup        = davinci_vcif_startup,
        .trigger        = davinci_vcif_trigger,
        .hw_params      = davinci_vcif_hw_params,
 };
@@ -240,7 +247,10 @@ fail:
 
 static int davinci_vcif_remove(struct platform_device *pdev)
 {
+       struct davinci_vcif_dev *davinci_vcif_dev = dev_get_drvdata(&pdev->dev);
+
        snd_soc_unregister_dai(&pdev->dev);
+       kfree(davinci_vcif_dev);
 
        return 0;
 }
index 4b0d199137286c5b2ff17491e6ac501acb53ccbc..286817946c5674c6a4536d4afda7507316e99883 100644 (file)
@@ -54,24 +54,26 @@ static int __init simone_init(void)
 
        ret = platform_device_add(simone_snd_ac97_device);
        if (ret)
-               goto fail;
+               goto fail1;
 
        simone_snd_device = platform_device_alloc("soc-audio", -1);
        if (!simone_snd_device) {
                ret = -ENOMEM;
-               goto fail;
+               goto fail2;
        }
 
        platform_set_drvdata(simone_snd_device, &snd_soc_simone);
        ret = platform_device_add(simone_snd_device);
-       if (ret) {
-               platform_device_put(simone_snd_device);
-               goto fail;
-       }
+       if (ret)
+               goto fail3;
 
-       return ret;
+       return 0;
 
-fail:
+fail3:
+       platform_device_put(simone_snd_device);
+fail2:
+       platform_device_del(simone_snd_ac97_device);
+fail1:
        platform_device_put(simone_snd_ac97_device);
        return ret;
 }
index 53251e6b5bd509303dc17500e8f4d64feeea7021..108b5d8bd0e944bc2f0525c930c35df643e1a500 100644 (file)
@@ -76,6 +76,7 @@ static __init int efika_fabric_init(void)
        rc = platform_device_add(pdev);
        if (rc) {
                pr_err("efika_fabric_init: platform_device_add() failed\n");
+               platform_device_put(pdev);
                return -ENODEV;
        }
        return 0;
index dce6b551cd7816be84c5dbd77db74be4c88e8315..f92dca07cd35ffdcb46bb16e7c0a4f6db8bc29fe 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
-#include <linux/of_device.h>
 #include <linux/of_platform.h>
 
 #include <sound/soc.h>
index 74ffed41340ff00c5d9ba97dc927059731b80673..9018fa5bf0db8db93737ef946073613f20b279df 100644 (file)
@@ -160,7 +160,7 @@ static int __devinit psc_i2s_of_probe(struct platform_device *op,
        rc = snd_soc_register_dais(&op->dev, psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai));
        if (rc != 0) {
                pr_err("Failed to register DAI\n");
-               return 0;
+               return rc;
        }
 
        psc_dma = dev_get_drvdata(&op->dev);
index 0d7dcf1e4863592c439a626b7fe449b56669f45d..7d7847a1e66bbba18bf583137808b2e751e29cd9 100644 (file)
@@ -498,6 +498,7 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "platform device add failed\n");
                goto error;
        }
+       dev_set_drvdata(&pdev->dev, sound_device);
 
        of_node_put(codec_np);
 
index 63b9eaa1ebc202d68eda5d18904816f8a86a458b..026b756961e0eaa84dc995c8b3a2aaf6f1a9b3a2 100644 (file)
@@ -498,6 +498,7 @@ static int p1022_ds_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "platform device add failed\n");
                goto error;
        }
+       dev_set_drvdata(&pdev->dev, sound_device);
 
        of_node_put(codec_np);
 
index 25f27ec1dd6e4bba2590b869745d575c1d5b3545..ba4d85e317ed459907601b1df426738ddf88ee68 100644 (file)
@@ -76,6 +76,7 @@ static __init int pcm030_fabric_init(void)
        rc = platform_device_add(pdev);
        if (rc) {
                pr_err("pcm030_fabric_init: platform_device_add() failed\n");
+               platform_device_put(pdev);
                return -ENODEV;
        }
        return 0;
index b59675257ce55b61b6410f04008f12d6d705e37d..dd4fffdbd17751d496a388dd38606fcd08ec319a 100644 (file)
@@ -34,8 +34,8 @@ static int eukrea_tlv320_hw_params(struct snd_pcm_substream *substream,
                            struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
        ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
@@ -79,10 +79,10 @@ static struct snd_soc_ops eukrea_tlv320_snd_ops = {
 static struct snd_soc_dai_link eukrea_tlv320_dai = {
        .name           = "tlv320aic23",
        .stream_name    = "TLV320AIC23",
-       .codec_dai      = "tlv320aic23-hifi",
+       .codec_dai_name = "tlv320aic23-hifi",
        .platform_name  = "imx-pcm-audio.0",
        .codec_name     = "tlv320aic23-codec.0-001a",
-       .cpu_dai = "imx-ssi.0",
+       .cpu_dai_name   = "imx-ssi.0",
        .ops            = &eukrea_tlv320_snd_ops,
 };
 
index fd493ee1428e2a977ac96ba7f7acc3a88d226025..671ef8dd524cb81b7ef8fae3dd6b033bd644e143 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/dmaengine.h>
 
 #include <sound/core.h>
 #include <sound/initval.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 
-#include <mach/dma-mx1-mx2.h>
+#include <mach/dma.h>
 
 #include "imx-ssi.h"
 
 struct imx_pcm_runtime_data {
-       int sg_count;
-       struct scatterlist *sg_list;
-       int period;
+       int period_bytes;
        int periods;
-       unsigned long dma_addr;
        int dma;
-       struct snd_pcm_substream *substream;
        unsigned long offset;
        unsigned long size;
-       unsigned long period_cnt;
        void *buf;
        int period_time;
+       struct dma_async_tx_descriptor *desc;
+       struct dma_chan *dma_chan;
+       struct imx_dma_data dma_data;
 };
 
-/* Called by the DMA framework when a period has elapsed */
-static void imx_ssi_dma_progression(int channel, void *data,
-                                       struct scatterlist *sg)
+static void audio_dma_irq(void *data)
 {
-       struct snd_pcm_substream *substream = data;
+       struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data;
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct imx_pcm_runtime_data *iprtd = runtime->private_data;
 
-       if (!sg)
-               return;
-
-       runtime = iprtd->substream->runtime;
+       iprtd->offset += iprtd->period_bytes;
+       iprtd->offset %= iprtd->period_bytes * iprtd->periods;
 
-       iprtd->offset = sg->dma_address - runtime->dma_addr;
-
-       snd_pcm_period_elapsed(iprtd->substream);
+       snd_pcm_period_elapsed(substream);
 }
 
-static void imx_ssi_dma_callback(int channel, void *data)
+static bool filter(struct dma_chan *chan, void *param)
 {
-       pr_err("%s shouldn't be called\n", __func__);
-}
+       struct imx_pcm_runtime_data *iprtd = param;
 
-static void snd_imx_dma_err_callback(int channel, void *data, int err)
-{
-       struct snd_pcm_substream *substream = data;
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct imx_pcm_dma_params *dma_params = 
-               snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct imx_pcm_runtime_data *iprtd = runtime->private_data;
-       int ret;
+       if (!imx_dma_is_general_purpose(chan))
+               return false;
 
-       pr_err("DMA timeout on channel %d -%s%s%s%s\n",
-                channel,
-                err & IMX_DMA_ERR_BURST ?    " burst" : "",
-                err & IMX_DMA_ERR_REQUEST ?  " request" : "",
-                err & IMX_DMA_ERR_TRANSFER ? " transfer" : "",
-                err & IMX_DMA_ERR_BUFFER ?   " buffer" : "");
+        chan->private = &iprtd->dma_data;
 
-       imx_dma_disable(iprtd->dma);
-       ret = imx_dma_setup_sg(iprtd->dma, iprtd->sg_list, iprtd->sg_count,
-                       IMX_DMA_LENGTH_LOOP, dma_params->dma_addr,
-                       substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
-                       DMA_MODE_WRITE : DMA_MODE_READ);
-       if (!ret)
-               imx_dma_enable(iprtd->dma);
+        return true;
 }
 
-static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream)
+static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream,
+                               struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct imx_pcm_dma_params *dma_params;
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct imx_pcm_runtime_data *iprtd = runtime->private_data;
+       struct dma_slave_config slave_config;
+       dma_cap_mask_t mask;
+       enum dma_slave_buswidth buswidth;
        int ret;
 
        dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
-       iprtd->dma = imx_dma_request_by_prio(DRV_NAME, DMA_PRIO_HIGH);
-       if (iprtd->dma < 0) {
-               pr_err("Failed to claim the audio DMA\n");
-               return -ENODEV;
-       }
+       iprtd->dma_data.peripheral_type = IMX_DMATYPE_SSI;
+       iprtd->dma_data.priority = DMA_PRIO_HIGH;
+       iprtd->dma_data.dma_request = dma_params->dma;
 
-       ret = imx_dma_setup_handlers(iprtd->dma,
-                               imx_ssi_dma_callback,
-                               snd_imx_dma_err_callback, substream);
-       if (ret)
-               goto out;
+       /* Try to grab a DMA channel */
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
+       iprtd->dma_chan = dma_request_channel(mask, filter, iprtd);
+       if (!iprtd->dma_chan)
+               return -EINVAL;
 
-       ret = imx_dma_setup_progression_handler(iprtd->dma,
-                       imx_ssi_dma_progression);
-       if (ret) {
-               pr_err("Failed to setup the DMA handler\n");
-               goto out;
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+       case SNDRV_PCM_FORMAT_S24_LE:
+               buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
+               break;
+       default:
+               return 0;
        }
 
-       ret = imx_dma_config_channel(iprtd->dma,
-                       IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO,
-                       IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
-                       dma_params->dma, 1);
-       if (ret < 0) {
-               pr_err("Cannot configure DMA channel: %d\n", ret);
-               goto out;
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               slave_config.direction = DMA_TO_DEVICE;
+               slave_config.dst_addr = dma_params->dma_addr;
+               slave_config.dst_addr_width = buswidth;
+               slave_config.dst_maxburst = dma_params->burstsize;
+       } else {
+               slave_config.direction = DMA_FROM_DEVICE;
+               slave_config.src_addr = dma_params->dma_addr;
+               slave_config.src_addr_width = buswidth;
+               slave_config.src_maxburst = dma_params->burstsize;
        }
 
-       imx_dma_config_burstlen(iprtd->dma, dma_params->burstsize * 2);
+       ret = dmaengine_slave_config(iprtd->dma_chan, &slave_config);
+       if (ret)
+               return ret;
 
        return 0;
-out:
-       imx_dma_free(iprtd->dma);
-       return ret;
 }
 
 static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream,
                                struct snd_pcm_hw_params *params)
 {
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct imx_pcm_runtime_data *iprtd = runtime->private_data;
-       int i;
        unsigned long dma_addr;
+       struct dma_chan *chan;
+       struct imx_pcm_dma_params *dma_params;
+       int ret;
 
-       imx_ssi_dma_alloc(substream);
+       dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+       ret = imx_ssi_dma_alloc(substream, params);
+       if (ret)
+               return ret;
+       chan = iprtd->dma_chan;
 
        iprtd->size = params_buffer_bytes(params);
        iprtd->periods = params_periods(params);
-       iprtd->period = params_period_bytes(params);
+       iprtd->period_bytes = params_period_bytes(params);
        iprtd->offset = 0;
        iprtd->period_time = HZ / (params_rate(params) /
                        params_period_size(params));
 
        snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 
-       if (iprtd->sg_count != iprtd->periods) {
-               kfree(iprtd->sg_list);
-
-               iprtd->sg_list = kcalloc(iprtd->periods + 1,
-                               sizeof(struct scatterlist), GFP_KERNEL);
-               if (!iprtd->sg_list)
-                       return -ENOMEM;
-               iprtd->sg_count = iprtd->periods + 1;
-       }
-
-       sg_init_table(iprtd->sg_list, iprtd->sg_count);
        dma_addr = runtime->dma_addr;
 
-       for (i = 0; i < iprtd->periods; i++) {
-               iprtd->sg_list[i].page_link = 0;
-               iprtd->sg_list[i].offset = 0;
-               iprtd->sg_list[i].dma_address = dma_addr;
-               iprtd->sg_list[i].length = iprtd->period;
-               dma_addr += iprtd->period;
+       iprtd->buf = (unsigned int *)substream->dma_buffer.area;
+
+       iprtd->desc = chan->device->device_prep_dma_cyclic(chan, dma_addr,
+                       iprtd->period_bytes * iprtd->periods,
+                       iprtd->period_bytes,
+                       substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
+                       DMA_TO_DEVICE : DMA_FROM_DEVICE);
+       if (!iprtd->desc) {
+               dev_err(&chan->dev->device, "cannot prepare slave dma\n");
+               return -EINVAL;
        }
 
-       /* close the loop */
-       iprtd->sg_list[iprtd->sg_count - 1].offset = 0;
-       iprtd->sg_list[iprtd->sg_count - 1].length = 0;
-       iprtd->sg_list[iprtd->sg_count - 1].page_link =
-                       ((unsigned long) iprtd->sg_list | 0x01) & ~0x02;
+       iprtd->desc->callback = audio_dma_irq;
+       iprtd->desc->callback_param = substream;
+
        return 0;
 }
 
@@ -194,41 +176,21 @@ static int snd_imx_pcm_hw_free(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct imx_pcm_runtime_data *iprtd = runtime->private_data;
 
-       if (iprtd->dma >= 0) {
-               imx_dma_free(iprtd->dma);
-               iprtd->dma = -EINVAL;
+       if (iprtd->dma_chan) {
+               dma_release_channel(iprtd->dma_chan);
+               iprtd->dma_chan = NULL;
        }
 
-       kfree(iprtd->sg_list);
-       iprtd->sg_list = NULL;
-
        return 0;
 }
 
 static int snd_imx_pcm_prepare(struct snd_pcm_substream *substream)
 {
-       struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct imx_pcm_dma_params *dma_params;
-       struct imx_pcm_runtime_data *iprtd = runtime->private_data;
-       int err;
 
        dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
-       iprtd->substream = substream;
-       iprtd->buf = (unsigned int *)substream->dma_buffer.area;
-       iprtd->period_cnt = 0;
-
-       pr_debug("%s: buf: %p period: %d periods: %d\n",
-                       __func__, iprtd->buf, iprtd->period, iprtd->periods);
-
-       err = imx_dma_setup_sg(iprtd->dma, iprtd->sg_list, iprtd->sg_count,
-                       IMX_DMA_LENGTH_LOOP, dma_params->dma_addr,
-                       substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
-                       DMA_MODE_WRITE : DMA_MODE_READ);
-       if (err)
-               return err;
-
        return 0;
 }
 
@@ -241,14 +203,14 @@ static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               imx_dma_enable(iprtd->dma);
+               dmaengine_submit(iprtd->desc);
 
                break;
 
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               imx_dma_disable(iprtd->dma);
+               dmaengine_terminate_all(iprtd->dma_chan);
 
                break;
        default:
@@ -263,6 +225,9 @@ static snd_pcm_uframes_t snd_imx_pcm_pointer(struct snd_pcm_substream *substream
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct imx_pcm_runtime_data *iprtd = runtime->private_data;
 
+       pr_debug("%s: %ld %ld\n", __func__, iprtd->offset,
+                       bytes_to_frames(substream->runtime, iprtd->offset));
+
        return bytes_to_frames(substream->runtime, iprtd->offset);
 }
 
@@ -279,7 +244,7 @@ static struct snd_pcm_hardware snd_imx_hardware = {
        .channels_max = 2,
        .buffer_bytes_max = IMX_SSI_DMABUF_SIZE,
        .period_bytes_min = 128,
-       .period_bytes_max = 16 * 1024,
+       .period_bytes_max = 65535, /* Limited by SDMA engine */
        .periods_min = 2,
        .periods_max = 255,
        .fifo_size = 0,
@@ -304,11 +269,23 @@ static int snd_imx_open(struct snd_pcm_substream *substream)
        }
 
        snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
+
+       return 0;
+}
+
+static int snd_imx_close(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct imx_pcm_runtime_data *iprtd = runtime->private_data;
+
+       kfree(iprtd);
+
        return 0;
 }
 
 static struct snd_pcm_ops imx_pcm_ops = {
        .open           = snd_imx_open,
+       .close          = snd_imx_close,
        .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = snd_imx_pcm_hw_params,
        .hw_free        = snd_imx_pcm_hw_free,
@@ -340,7 +317,6 @@ static struct platform_driver imx_pcm_driver = {
                        .name = "imx-pcm-audio",
                        .owner = THIS_MODULE,
        },
-
        .probe = imx_soc_platform_probe,
        .remove = __devexit_p(imx_soc_platform_remove),
 };
@@ -356,4 +332,3 @@ static void __exit snd_imx_pcm_exit(void)
        platform_driver_unregister(&imx_pcm_driver);
 }
 module_exit(snd_imx_pcm_exit);
-
index d4bd345b0a8d4ba891222f5752fe6eca56aec7b4..390b6ffc26581477599b03efa08ebf9379d6d2b7 100644 (file)
@@ -439,7 +439,22 @@ void imx_pcm_free(struct snd_pcm *pcm)
 }
 EXPORT_SYMBOL_GPL(imx_pcm_free);
 
+static int imx_ssi_dai_probe(struct snd_soc_dai *dai)
+{
+       struct imx_ssi *ssi = dev_get_drvdata(dai->dev);
+       uint32_t val;
+
+       snd_soc_dai_set_drvdata(dai, ssi);
+
+       val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) |
+               SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize);
+       writel(val, ssi->base + SSI_SFCSR);
+
+       return 0;
+}
+
 static struct snd_soc_dai_driver imx_ssi_dai = {
+       .probe = imx_ssi_dai_probe,
        .playback = {
                .channels_min = 2,
                .channels_max = 2,
@@ -455,20 +470,6 @@ static struct snd_soc_dai_driver imx_ssi_dai = {
        .ops = &imx_ssi_pcm_dai_ops,
 };
 
-static int imx_ssi_dai_probe(struct snd_soc_dai *dai)
-{
-       struct imx_ssi *ssi = dev_get_drvdata(dai->dev);
-       uint32_t val;
-
-       snd_soc_dai_set_drvdata(dai, ssi);
-
-       val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) |
-               SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize);
-       writel(val, ssi->base + SSI_SFCSR);
-
-       return 0;
-}
-
 static struct snd_soc_dai_driver imx_ac97_dai = {
        .probe = imx_ssi_dai_probe,
        .ac97_control = 1,
@@ -677,9 +678,25 @@ static int imx_ssi_probe(struct platform_device *pdev)
                goto failed_register;
        }
 
-       ssi->soc_platform_pdev = platform_device_alloc("imx-fiq-pcm-audio", pdev->id);
-       if (!ssi->soc_platform_pdev)
+       ssi->soc_platform_pdev_fiq = platform_device_alloc("imx-fiq-pcm-audio", pdev->id);
+       if (!ssi->soc_platform_pdev_fiq) {
+               ret = -ENOMEM;
+               goto failed_pdev_fiq_alloc;
+       }
+
+       platform_set_drvdata(ssi->soc_platform_pdev_fiq, ssi);
+       ret = platform_device_add(ssi->soc_platform_pdev_fiq);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to add platform device\n");
+               goto failed_pdev_fiq_add;
+       }
+
+       ssi->soc_platform_pdev = platform_device_alloc("imx-pcm-audio", pdev->id);
+       if (!ssi->soc_platform_pdev) {
+               ret = -ENOMEM;
                goto failed_pdev_alloc;
+       }
+
        platform_set_drvdata(ssi->soc_platform_pdev, ssi);
        ret = platform_device_add(ssi->soc_platform_pdev);
        if (ret) {
@@ -692,6 +709,10 @@ static int imx_ssi_probe(struct platform_device *pdev)
 failed_pdev_add:
        platform_device_put(ssi->soc_platform_pdev);
 failed_pdev_alloc:
+       platform_device_del(ssi->soc_platform_pdev_fiq);
+failed_pdev_fiq_add:
+       platform_device_put(ssi->soc_platform_pdev_fiq);
+failed_pdev_fiq_alloc:
        snd_soc_unregister_dai(&pdev->dev);
 failed_register:
 failed_ac97:
@@ -712,8 +733,8 @@ static int __devexit imx_ssi_remove(struct platform_device *pdev)
        struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        struct imx_ssi *ssi = platform_get_drvdata(pdev);
 
-       platform_device_del(ssi->soc_platform_pdev);
-       platform_device_put(ssi->soc_platform_pdev);
+       platform_device_unregister(ssi->soc_platform_pdev);
+       platform_device_unregister(ssi->soc_platform_pdev_fiq);
 
        snd_soc_unregister_dai(&pdev->dev);
 
index 53b780d9b2b09375fdc7bf7f60a81af5045ab406..a4406a13489279280a1635f0dab2563475c7426f 100644 (file)
 
 #define DRV_NAME "imx-ssi"
 
+#include <linux/dmaengine.h>
+#include <mach/dma.h>
+
 struct imx_pcm_dma_params {
        int dma;
        unsigned long dma_addr;
@@ -212,6 +215,7 @@ struct imx_ssi {
        int enabled;
 
        struct platform_device *soc_platform_pdev;
+       struct platform_device *soc_platform_pdev_fiq;
 };
 
 struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev,
index 6a65dd7055199febc9a63393430461d086e2d4e8..9eabc28667e681b41d8ce800d00db7367bb56b1d 100644 (file)
@@ -20,9 +20,6 @@
 #include <sound/soc-dapm.h>
 #include <asm/mach-types.h>
 
-#include "../codecs/wm9712.h"
-#include "imx-ssi.h"
-
 static struct snd_soc_card imx_phycore;
 
 static struct snd_soc_ops imx_phycore_hifi_ops = {
@@ -41,11 +38,12 @@ static struct snd_soc_dai_link imx_phycore_dai_ac97[] = {
 };
 
 static struct snd_soc_card imx_phycore = {
-       .name           = "PhyCORE-audio",
+       .name           = "PhyCORE-ac97-audio",
        .dai_link       = imx_phycore_dai_ac97,
        .num_links      = ARRAY_SIZE(imx_phycore_dai_ac97),
 };
 
+static struct platform_device *imx_phycore_snd_ac97_device;
 static struct platform_device *imx_phycore_snd_device;
 
 static int __init imx_phycore_init(void)
@@ -56,29 +54,42 @@ static int __init imx_phycore_init(void)
                /* return happy. We might run on a totally different machine */
                return 0;
 
-       imx_phycore_snd_device = platform_device_alloc("soc-audio", -1);
-       if (!imx_phycore_snd_device)
+       imx_phycore_snd_ac97_device = platform_device_alloc("soc-audio", -1);
+       if (!imx_phycore_snd_ac97_device)
                return -ENOMEM;
 
-       platform_set_drvdata(imx_phycore_snd_device, &imx_phycore);
-       ret = platform_device_add(imx_phycore_snd_device);
+       platform_set_drvdata(imx_phycore_snd_ac97_device, &imx_phycore);
+       ret = platform_device_add(imx_phycore_snd_ac97_device);
+       if (ret)
+               goto fail1;
 
        imx_phycore_snd_device = platform_device_alloc("wm9712-codec", -1);
-       if (!imx_phycore_snd_device)
-               return -ENOMEM;
+       if (!imx_phycore_snd_device) {
+               ret = -ENOMEM;
+               goto fail2;
+       }
        ret = platform_device_add(imx_phycore_snd_device);
 
        if (ret) {
                printk(KERN_ERR "ASoC: Platform device allocation failed\n");
-               platform_device_put(imx_phycore_snd_device);
+               goto fail3;
        }
 
+       return 0;
+
+fail3:
+       platform_device_put(imx_phycore_snd_device);
+fail2:
+       platform_device_del(imx_phycore_snd_ac97_device);
+fail1:
+       platform_device_put(imx_phycore_snd_ac97_device);
        return ret;
 }
 
 static void __exit imx_phycore_exit(void)
 {
        platform_device_unregister(imx_phycore_snd_device);
+       platform_device_unregister(imx_phycore_snd_ac97_device);
 }
 
 late_initcall(imx_phycore_init);
index 293dc748797c51cf11a63b6b0afa548521ff2898..dac6732da9695dfda940e78c98a5d58961b93955 100644 (file)
@@ -49,7 +49,7 @@ static unsigned short nuc900_ac97_read(struct snd_ac97 *ac97,
        mutex_lock(&ac97_mutex);
 
        val = nuc900_checkready();
-       if (!!val) {
+       if (val) {
                dev_err(nuc900_audio->dev, "AC97 codec is not ready\n");
                goto out;
        }
@@ -102,7 +102,7 @@ static void nuc900_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
        mutex_lock(&ac97_mutex);
 
        tmp = nuc900_checkready();
-       if (!!tmp)
+       if (tmp)
                dev_err(nuc900_audio->dev, "AC97 codec is not ready\n");
 
        /* clear the R_WB bit and write register index */
@@ -149,7 +149,7 @@ static void nuc900_ac97_warm_reset(struct snd_ac97 *ac97)
        udelay(100);
 
        val = nuc900_checkready();
-       if (!!val)
+       if (val)
                dev_err(nuc900_audio->dev, "AC97 codec is not ready\n");
 
        mutex_unlock(&ac97_mutex);
@@ -263,8 +263,7 @@ static int nuc900_ac97_trigger(struct snd_pcm_substream *substream,
        return ret;
 }
 
-static int nuc900_ac97_probe(struct platform_device *pdev,
-                                       struct snd_soc_dai *dai)
+static int nuc900_ac97_probe(struct snd_soc_dai *dai)
 {
        struct nuc900_audio *nuc900_audio = nuc900_ac97_data;
        unsigned long val;
@@ -284,12 +283,12 @@ static int nuc900_ac97_probe(struct platform_device *pdev,
        return 0;
 }
 
-static void nuc900_ac97_remove(struct platform_device *pdev,
-                                               struct snd_soc_dai *dai)
+static int nuc900_ac97_remove(struct snd_soc_dai *dai)
 {
        struct nuc900_audio *nuc900_audio = nuc900_ac97_data;
 
        clk_disable(nuc900_audio->clk);
+       return 0;
 }
 
 static struct snd_soc_dai_ops nuc900_ac97_dai_ops = {
@@ -313,7 +312,7 @@ static struct snd_soc_dai_driver nuc900_ac97_dai = {
                .channels_max   = 2,
        },
        .ops = &nuc900_ac97_dai_ops,
-}
+};
 
 static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev)
 {
@@ -384,7 +383,6 @@ out0:
 
 static int __devexit nuc900_ac97_drvremove(struct platform_device *pdev)
 {
-
        snd_soc_unregister_dai(&pdev->dev);
 
        clk_put(nuc900_ac97_data->clk);
@@ -392,6 +390,7 @@ static int __devexit nuc900_ac97_drvremove(struct platform_device *pdev)
        release_mem_region(nuc900_ac97_data->res->start,
                                resource_size(nuc900_ac97_data->res));
 
+       kfree(nuc900_ac97_data);
        nuc900_ac97_data = NULL;
 
        return 0;
index aeed8ead2b2bcc42fcb5e06200a807f68cc6ce63..59f7e8ed1a6898937e3472016bce5e4bdc11e3de 100644 (file)
@@ -110,4 +110,6 @@ struct nuc900_audio {
 
 };
 
+extern struct nuc900_audio *nuc900_ac97_data;
+
 #endif /*end _NUC900_AUDIO_H */
index 195d1ac94771808c0eda8075255efff787cdfd59..8263f56dc665f4aa2dd04ecf6cba5ca7244283dd 100644 (file)
@@ -50,12 +50,12 @@ static int nuc900_dma_hw_params(struct snd_pcm_substream *substream,
        unsigned long flags;
        int ret = 0;
 
-       spin_lock_irqsave(&nuc900_audio->lock, flags);
-
        ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
        if (ret < 0)
                return ret;
 
+       spin_lock_irqsave(&nuc900_audio->lock, flags);
+
        nuc900_audio->substream = substream;
        nuc900_audio->dma_addr[substream->stream] = runtime->dma_addr;
        nuc900_audio->buffersize[substream->stream] =
@@ -169,6 +169,7 @@ static int nuc900_dma_prepare(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct nuc900_audio *nuc900_audio = runtime->private_data;
        unsigned long flags, val;
+       int ret = 0;
 
        spin_lock_irqsave(&nuc900_audio->lock, flags);
 
@@ -197,10 +198,10 @@ static int nuc900_dma_prepare(struct snd_pcm_substream *substream)
                AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val);
                break;
        default:
-               return -EINVAL;
+               ret = -EINVAL;
        }
        spin_unlock_irqrestore(&nuc900_audio->lock, flags);
-       return 0;
+       return ret;
 }
 
 static int nuc900_dma_trigger(struct snd_pcm_substream *substream, int cmd)
@@ -332,7 +333,7 @@ static struct snd_soc_platform_driver nuc900_soc_platform = {
        .ops            = &nuc900_dma_ops,
        .pcm_new        = nuc900_dma_new,
        .pcm_free       = nuc900_dma_free_dma_buffers,
-}
+};
 
 static int __devinit nuc900_soc_platform_probe(struct platform_device *pdev)
 {
index d542ea2ff6bec2e1117003a580cee7f6fe9db2e4..a088db6d50911799780838c0388cf9435d2c3a31 100644 (file)
@@ -12,8 +12,8 @@ config SND_OMAP_SOC_MCPDM
 config SND_OMAP_SOC_N810
        tristate "SoC Audio support for Nokia N810"
        depends on SND_OMAP_SOC && MACH_NOKIA_N810 && I2C
+       depends on OMAP_MUX
        select SND_OMAP_SOC_MCBSP
-       select OMAP_MUX
        select SND_SOC_TLV320AIC3X
        help
          Say Y if you want to add support for SoC audio on Nokia N810.
index d211c9fa5a914774534de29f51f40035320bfafb..7e84f24b9a88bf56ef0d000901d6c69d39f7461c 100644 (file)
@@ -644,15 +644,23 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
 
 
        case OMAP_MCBSP_CLKR_SRC_CLKR:
+               if (cpu_class_is_omap1())
+                       break;
                omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKR);
                break;
        case OMAP_MCBSP_CLKR_SRC_CLKX:
+               if (cpu_class_is_omap1())
+                       break;
                omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKX);
                break;
        case OMAP_MCBSP_FSR_SRC_FSR:
+               if (cpu_class_is_omap1())
+                       break;
                omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSR);
                break;
        case OMAP_MCBSP_FSR_SRC_FSX:
+               if (cpu_class_is_omap1())
+                       break;
                omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSX);
                break;
        default:
index dbd9d96b5f9243c3e0cd0aafd3181e08cce84a3a..4ee33ce2cb98a6135b310f0f9279d8bdf5a16cae 100644 (file)
@@ -306,6 +306,7 @@ static int __init omap3pandora_soc_init(void)
                pr_err(PREFIX "Failed to get DAC regulator from %s: %ld\n",
                        dev_name(&omap3pandora_snd_device->dev),
                        PTR_ERR(omap3pandora_dac_reg));
+               ret = PTR_ERR(omap3pandora_dac_reg);
                goto fail3;
        }
 
index f0e6625564287df0b33643395af20c1849b8a596..65ae00e976eff14eb67d3b14428bdf7ec9d8360b 100644 (file)
@@ -177,7 +177,8 @@ static int __init osk_soc_init(void)
        tlv320aic23_mclk = clk_get(dev, "mclk");
        if (IS_ERR(tlv320aic23_mclk)) {
                printk(KERN_ERR "Could not get mclk clock\n");
-               return -ENODEV;
+               err = PTR_ERR(tlv320aic23_mclk);
+               goto err2;
        }
 
        /*
@@ -188,7 +189,7 @@ static int __init osk_soc_init(void)
                if (clk_set_rate(tlv320aic23_mclk, CODEC_CLOCK)) {
                        printk(KERN_ERR "Cannot set MCLK for AIC23 CODEC\n");
                        err = -ECANCELED;
-                       goto err1;
+                       goto err3;
                }
        }
 
@@ -196,9 +197,12 @@ static int __init osk_soc_init(void)
               (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK);
 
        return 0;
-err1:
+
+err3:
        clk_put(tlv320aic23_mclk);
+err2:
        platform_device_del(osk_snd_device);
+err1:
        platform_device_put(osk_snd_device);
 
        return err;
@@ -207,6 +211,7 @@ err1:
 
 static void __exit osk_soc_exit(void)
 {
+       clk_put(tlv320aic23_mclk);
        platform_device_unregister(osk_snd_device);
 }
 
index 37f191bbfdd91edd64bb4abd7636600f4d694d0c..580f48571303a0023e65fba304080058ce11bd8d 100644 (file)
@@ -1,6 +1,7 @@
 config SND_PXA2XX_SOC
        tristate "SoC Audio for the Intel PXA2xx chip"
        depends on ARCH_PXA
+       select SND_ARM
        select SND_PXA2XX_LIB
        help
          Say Y or M if you want to add support for codecs attached to
index 97e9423615c9c84d859a2b5b5b31695d73f4ab2f..f451acd4935b81db8d04d67da8e99c4e650f4a5d 100644 (file)
@@ -100,8 +100,13 @@ static int corgi_startup(struct snd_pcm_substream *substream)
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_codec *codec = rtd->codec;
 
+       mutex_lock(&codec->mutex);
+
        /* check the jack status at stream startup */
        corgi_ext_control(codec);
+
+       mutex_unlock(&codec->mutex);
+
        return 0;
 }
 
index b8207ced40729b0b375f28566b09de404313f28a..5ef0526924b9e3b2f20d56d181d7fc3781468df3 100644 (file)
@@ -72,9 +72,13 @@ static int magician_startup(struct snd_pcm_substream *substream)
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_codec *codec = rtd->codec;
 
+       mutex_lock(&codec->mutex);
+
        /* check the jack status at stream startup */
        magician_ext_control(codec);
 
+       mutex_unlock(&codec->mutex);
+
        return 0;
 }
 
index af84ee9c5e11edde0c8a253e3a5072e5f3ac0e36..84edd0385a21fb39f3dfa7f429fa69df5c1dcdf1 100644 (file)
@@ -77,8 +77,13 @@ static int poodle_startup(struct snd_pcm_substream *substream)
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_codec *codec = rtd->codec;
 
+       mutex_lock(&codec->mutex);
+
        /* check the jack status at stream startup */
        poodle_ext_control(codec);
+
+       mutex_unlock(&codec->mutex);
+
        return 0;
 }
 
index f470f360f4dda9a3193b5f5011a7b9688cfb3b32..0b30d7de24ecc20e4adf3924257fe6a070741953 100644 (file)
@@ -108,8 +108,13 @@ static int spitz_startup(struct snd_pcm_substream *substream)
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_codec *codec = rtd->codec;
 
+       mutex_lock(&codec->mutex);
+
        /* check the jack status at stream startup */
        spitz_ext_control(codec);
+
+       mutex_unlock(&codec->mutex);
+
        return 0;
 }
 
index 73d0edd8ded9de053db82b27c60433fe1a7b8686..7b983f935454159d0a3569d6f747285231cbc6ae 100644 (file)
@@ -81,8 +81,13 @@ static int tosa_startup(struct snd_pcm_substream *substream)
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_codec *codec = rtd->codec;
 
+       mutex_lock(&codec->mutex);
+
        /* check the jack status at stream startup */
        tosa_ext_control(codec);
+
+       mutex_unlock(&codec->mutex);
+
        return 0;
 }
 
index 8a6b53ccd203e0a8dfe14dd7579325284e736591..d85bf8a0abb2935941b008ab12dfcf5831536e73 100644 (file)
@@ -2,6 +2,7 @@ config SND_S3C24XX_SOC
        tristate "SoC Audio for the Samsung S3CXXXX chips"
        depends on ARCH_S3C2410 || ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210
        select S3C64XX_DMA if ARCH_S3C64XX
+       select S3C2410_DMA if ARCH_S3C2410
        help
          Say Y or M if you want to add support for codecs attached to
          the S3C24XX AC97 or I2S interfaces. You will also need to
index ffd5cf2fb0a91c3ebbb45d7c58951e3915670a69..468cc11fdf47abf84bc7a6b2dbcc5298bd6f16ce 100644 (file)
@@ -50,7 +50,6 @@ static unsigned int rates[] = {
        16000,
        44100,
        48000,
-       88200,
 };
 
 static struct snd_pcm_hw_constraint_list hw_rates = {
@@ -130,7 +129,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
 };
 
 static struct platform_device *s3c24xx_snd_device;
-static struct clk *xtal;
 
 static int rx1950_startup(struct snd_pcm_substream *substream)
 {
@@ -179,10 +177,8 @@ static int rx1950_hw_params(struct snd_pcm_substream *substream,
        case 44100:
        case 88200:
                clk_source = S3C24XX_CLKSRC_MPLL;
-               fs_mode = S3C2410_IISMOD_256FS;
-               div = clk_get_rate(xtal) / (256 * rate);
-               if (clk_get_rate(xtal) % (256 * rate) > (128 * rate))
-                       div++;
+               fs_mode = S3C2410_IISMOD_384FS;
+               div = 1;
                break;
        default:
                printk(KERN_ERR "%s: rate %d is not supported\n",
@@ -210,7 +206,7 @@ static int rx1950_hw_params(struct snd_pcm_substream *substream,
 
        /* set MCLK division for sample rate */
        ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
-               S3C2410_IISMOD_384FS);
+               fs_mode);
        if (ret < 0)
                return ret;
 
@@ -295,17 +291,8 @@ static int __init rx1950_init(void)
                goto err_plat_add;
        }
 
-       xtal = clk_get(&s3c24xx_snd_device->dev, "xtal");
-
-       if (IS_ERR(xtal)) {
-               ret = PTR_ERR(xtal);
-               platform_device_unregister(s3c24xx_snd_device);
-               goto err_clk;
-       }
-
        return 0;
 
-err_clk:
 err_plat_add:
 err_plat_alloc:
 err_gpio_conf:
@@ -320,7 +307,6 @@ static void __exit rx1950_exit(void)
        platform_device_unregister(s3c24xx_snd_device);
        snd_soc_jack_free_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios),
                hp_jack_gpios);
-       clk_put(xtal);
        gpio_free(S3C2410_GPA(1));
 }
 
index f31d22ad7c88997dfc9c4511f62b2a5aa7652a27..c8bd90488a87385d33b168813878893bfa5b9266 100644 (file)
@@ -38,7 +38,7 @@ static int set_audio_clock_heirachy(struct platform_device *pdev)
        }
 
        mout_epll = clk_get(NULL, "mout_epll");
-       if (IS_ERR(fout_epll)) {
+       if (IS_ERR(mout_epll)) {
                printk(KERN_WARNING "%s: Cannot find mout_epll.\n",
                                __func__);
                ret = -EINVAL;
@@ -54,7 +54,7 @@ static int set_audio_clock_heirachy(struct platform_device *pdev)
        }
 
        sclk_spdif = clk_get(NULL, "sclk_spdif");
-       if (IS_ERR(fout_epll)) {
+       if (IS_ERR(sclk_spdif)) {
                printk(KERN_WARNING "%s: Cannot find sclk_spdif.\n",
                                __func__);
                ret = -EINVAL;
index 8778faa174a6cb66da33e1e81430c6aae2c59973..3052f64b2403929a62fec3c8257aedec40c8a7a2 100644 (file)
@@ -434,7 +434,7 @@ static struct snd_soc_dai_driver s6000_i2s_dai = {
                .rate_max = 1562500,
        },
        .ops = &s6000_i2s_dai_ops,
-}
+};
 
 static int __devinit s6000_i2s_probe(struct platform_device *pdev)
 {
index 271fd222bf1997f92cac08b6c8b27f8f604b5147..ab3ccaec72d2158d41270ee22df7f95db683eb4a 100644 (file)
@@ -473,7 +473,7 @@ static int s6000_pcm_new(struct snd_card *card,
        }
 
        res = request_irq(params->irq, s6000_pcm_irq, IRQF_SHARED,
-                         s6000_soc_platform.name, pcm);
+                         "s6000-audio", pcm);
        if (res) {
                printk(KERN_ERR "s6000-pcm couldn't get IRQ\n");
                return res;
index 96c05e1375386ebf6f11fd8d6ebcaa7dd118ac07..c1244c5bc730c478035756a9aab04309dcf8cc24 100644 (file)
@@ -167,7 +167,7 @@ static int s6105_aic3x_init(struct snd_soc_pcm_runtime *rtd)
 
        snd_soc_dapm_sync(codec);
 
-       snd_ctl_add(codec->snd_card, snd_ctl_new1(&audio_out_mux, codec));
+       snd_ctl_add(codec->card->snd_card, snd_ctl_new1(&audio_out_mux, codec));
 
        return 0;
 }
index 507e709f2807c52995bed6c8dfaad09981ce471d..4c2404b1b8625455358347b65ba15f9414956b1a 100644 (file)
@@ -132,6 +132,8 @@ struct fsi_priv {
        struct fsi_stream playback;
        struct fsi_stream capture;
 
+       long rate;
+
        u32 mst_ctrl;
 };
 
@@ -854,10 +856,17 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
 {
        struct fsi_priv *fsi = fsi_get_priv(substream);
        int is_play = fsi_is_play(substream);
+       struct fsi_master *master = fsi_get_master(fsi);
+       int (*set_rate)(struct device *dev, int is_porta, int rate, int enable);
 
        fsi_irq_disable(fsi, is_play);
        fsi_clk_ctrl(fsi, 0);
 
+       set_rate = master->info->set_rate;
+       if (set_rate && fsi->rate)
+               set_rate(dai->dev, fsi_is_port_a(fsi), fsi->rate, 0);
+       fsi->rate = 0;
+
        pm_runtime_put_sync(dai->dev);
 }
 
@@ -891,20 +900,20 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream,
 {
        struct fsi_priv *fsi = fsi_get_priv(substream);
        struct fsi_master *master = fsi_get_master(fsi);
-       int (*set_rate)(int is_porta, int rate) = master->info->set_rate;
+       int (*set_rate)(struct device *dev, int is_porta, int rate, int enable);
        int fsi_ver = master->core->ver;
-       int is_play = fsi_is_play(substream);
+       long rate = params_rate(params);
        int ret;
 
-       /* if slave mode, set_rate is not needed */
-       if (!fsi_is_master_mode(fsi, is_play))
+       set_rate = master->info->set_rate;
+       if (!set_rate)
                return 0;
 
-       /* it is error if no set_rate */
-       if (!set_rate)
-               return -EIO;
+       ret = set_rate(dai->dev, fsi_is_port_a(fsi), rate, 1);
+       if (ret < 0) /* error */
+               return ret;
 
-       ret = set_rate(fsi_is_port_a(fsi), params_rate(params));
+       fsi->rate = rate;
        if (ret > 0) {
                u32 data = 0;
 
index 40bbdf1591dca351631f8bdbbcc5f514e9c99139..05192d97b377f586e5eab56f0e38ec841d35378d 100644 (file)
@@ -387,7 +387,7 @@ static int __devinit sh4_soc_dai_probe(struct platform_device *pdev)
 
 static int __devexit sh4_soc_dai_remove(struct platform_device *pdev)
 {
-       snd_soc_unregister_dai(&pdev->dev, ARRAY_SIZE(sh4_ssi_dai));
+       snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sh4_ssi_dai));
        return 0;
 }
 
index 614a8b30d87bdefdb99414f06d1d74438e60cd18..85b7d548f1675f14c1a2065bbcffcf7d229a2e27 100644 (file)
@@ -1619,12 +1619,14 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
 #ifdef CONFIG_SND_SOC_AC97_BUS
        /* register any AC97 codecs */
        for (i = 0; i < card->num_rtd; i++) {
-                       ret = soc_register_ac97_dai_link(&card->rtd[i]);
-                       if (ret < 0) {
-                               printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name);
-                               goto probe_dai_err;
-                       }
+               ret = soc_register_ac97_dai_link(&card->rtd[i]);
+               if (ret < 0) {
+                       printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name);
+                       while (--i >= 0)
+                               soc_unregister_ac97_dai_link(&card->rtd[i]);
+                       goto probe_dai_err;
                }
+       }
 #endif
 
        card->instantiated = 1;
@@ -3043,8 +3045,10 @@ int snd_soc_register_dais(struct device *dev,
        for (i = 0; i < count; i++) {
 
                dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);
-               if (dai == NULL)
-                       return -ENOMEM;
+               if (dai == NULL) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
 
                /* create DAI component name */
                dai->name = fmt_multiple_name(dev, &dai_drv[i]);
@@ -3070,7 +3074,9 @@ int snd_soc_register_dais(struct device *dev,
                pr_debug("Registered DAI '%s'\n", dai->name);
        }
 
+       mutex_lock(&client_mutex);
        snd_soc_instantiate_cards();
+       mutex_unlock(&client_mutex);
        return 0;
 
 err:
@@ -3263,9 +3269,6 @@ int snd_soc_register_codec(struct device *dev,
        return 0;
 
 error:
-       for (i--; i >= 0; i--)
-               snd_soc_unregister_dai(dev);
-
        if (codec->reg_cache)
                kfree(codec->reg_cache);
        kfree(codec->name);
index 7d85c6496afa432cbd9791be5f1a9510e7cb78c7..c721502833bcbf424855c87bcf1fddf2805bbafe 100644 (file)
@@ -683,12 +683,12 @@ static int dapm_seq_compare(struct snd_soc_dapm_widget *a,
                            struct snd_soc_dapm_widget *b,
                            int sort[])
 {
-       if (a->codec != b->codec)
-               return (unsigned long)a - (unsigned long)b;
        if (sort[a->id] != sort[b->id])
                return sort[a->id] - sort[b->id];
        if (a->reg != b->reg)
                return a->reg - b->reg;
+       if (a->codec != b->codec)
+               return (unsigned long)a->codec - (unsigned long)b->codec;
 
        return 0;
 }
@@ -944,6 +944,9 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
                case SND_SOC_DAPM_STREAM_RESUME:
                        sys_power = 1;
                        break;
+               case SND_SOC_DAPM_STREAM_STOP:
+                       sys_power = !!codec->active;
+                       break;
                case SND_SOC_DAPM_STREAM_SUSPEND:
                        sys_power = 0;
                        break;
index 1bc56b2b94e29f9143baa9911f72fa962202d17a..337a00241a1f3a406506c4baad93e0f10a8ac7d8 100644 (file)
@@ -155,7 +155,7 @@ static int snd_at73c213_set_bitrate(struct snd_at73c213 *chip)
        if (max_tries < 1)
                max_tries = 1;
 
-       /* ssc_div must be a power of 2. */
+       /* ssc_div must be even. */
        ssc_div = (ssc_div + 1) & ~1UL;
 
        if ((ssc_rate / (ssc_div * 2 * 16)) < BITRATE_MIN) {
index 93bd2ff001fb113ff11159e419269942ac4e3743..564491fa18b27838dd79125954bc744f51f7fe2c 100644 (file)
@@ -197,7 +197,7 @@ static void sig_atexit(void)
        if (child_pid > 0)
                kill(child_pid, SIGTERM);
 
-       if (signr == -1)
+       if (signr == -1 || signr == SIGUSR1)
                return;
 
        signal(signr, SIG_DFL);
@@ -515,6 +515,7 @@ static int __cmd_record(int argc, const char **argv)
        atexit(sig_atexit);
        signal(SIGCHLD, sig_handler);
        signal(SIGINT, sig_handler);
+       signal(SIGUSR1, sig_handler);
 
        if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
                perror("failed to create pipes");
@@ -606,6 +607,7 @@ static int __cmd_record(int argc, const char **argv)
                        execvp(argv[0], (char **)argv);
 
                        perror(argv[0]);
+                       kill(getppid(), SIGUSR1);
                        exit(-1);
                }
 
@@ -697,17 +699,18 @@ static int __cmd_record(int argc, const char **argv)
        if (err < 0)
                err = event__synthesize_kernel_mmap(process_synthesized_event,
                                                    session, machine, "_stext");
-       if (err < 0) {
-               pr_err("Couldn't record kernel reference relocation symbol.\n");
-               return err;
-       }
+       if (err < 0)
+               pr_err("Couldn't record kernel reference relocation symbol\n"
+                      "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
+                      "Check /proc/kallsyms permission or run as root.\n");
 
        err = event__synthesize_modules(process_synthesized_event,
                                        session, machine);
-       if (err < 0) {
-               pr_err("Couldn't record kernel reference relocation symbol.\n");
-               return err;
-       }
+       if (err < 0)
+               pr_err("Couldn't record kernel module information.\n"
+                      "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
+                      "Check /proc/modules permission or run as root.\n");
+
        if (perf_guest)
                perf_session__process_machines(session, event__synthesize_guest_os);
 
@@ -761,7 +764,7 @@ static int __cmd_record(int argc, const char **argv)
                }
        }
 
-       if (quiet)
+       if (quiet || signr == SIGUSR1)
                return 0;
 
        fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
index d7e67b167ea338a28fed519260f1069dd8e92cf9..64a85bafde63a1c6f05451a32b31eec521c799d9 100644 (file)
@@ -946,11 +946,16 @@ perf_header__find_attr(u64 id, struct perf_header *header)
 
        /*
         * We set id to -1 if the data file doesn't contain sample
-        * ids. Check for this and avoid walking through the entire
-        * list of ids which may be large.
+        * ids. This can happen when the data file contains one type
+        * of event and in that case, the header can still store the
+        * event attribute information. Check for this and avoid
+        * walking through the entire list of ids which may be large.
         */
-       if (id == -1ULL)
+       if (id == -1ULL) {
+               if (header->attrs > 0)
+                       return &header->attr[0]->attr;
                return NULL;
+       }
 
        for (i = 0; i < header->attrs; i++) {
                struct perf_header_attr *attr = header->attr[i];
index b39f499e575a604198bf1bb11d11d6280a091548..d628c8d1cf5ec11111ab3b750da0d14f6d8fff7f 100644 (file)
@@ -295,7 +295,9 @@ static void symbols__insert_by_name(struct rb_root *self, struct symbol *sym)
 {
        struct rb_node **p = &self->rb_node;
        struct rb_node *parent = NULL;
-       struct symbol_name_rb_node *symn = ((void *)sym) - sizeof(*parent), *s;
+       struct symbol_name_rb_node *symn, *s;
+
+       symn = container_of(sym, struct symbol_name_rb_node, sym);
 
        while (*p != NULL) {
                parent = *p;
@@ -530,7 +532,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
        struct machine *machine = kmaps->machine;
        struct map *curr_map = map;
        struct symbol *pos;
-       int count = 0;
+       int count = 0, moved = 0;       
        struct rb_root *root = &self->symbols[map->type];
        struct rb_node *next = rb_first(root);
        int kernel_range = 0;
@@ -588,6 +590,11 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
                        char dso_name[PATH_MAX];
                        struct dso *dso;
 
+                       if (count == 0) {
+                               curr_map = map;
+                               goto filter_symbol;
+                       }
+
                        if (self->kernel == DSO_TYPE_GUEST_KERNEL)
                                snprintf(dso_name, sizeof(dso_name),
                                        "[guest.kernel].%d",
@@ -613,7 +620,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
                        map_groups__insert(kmaps, curr_map);
                        ++kernel_range;
                }
-
+filter_symbol:
                if (filter && filter(curr_map, pos)) {
 discard_symbol:                rb_erase(&pos->rb_node, root);
                        symbol__delete(pos);
@@ -621,8 +628,9 @@ discard_symbol:             rb_erase(&pos->rb_node, root);
                        if (curr_map != map) {
                                rb_erase(&pos->rb_node, root);
                                symbols__insert(&curr_map->dso->symbols[curr_map->type], pos);
-                       }
-                       count++;
+                               ++moved;
+                       } else
+                               ++count;
                }
        }
 
@@ -632,7 +640,7 @@ discard_symbol:             rb_erase(&pos->rb_node, root);
                dso__set_loaded(curr_map->dso, curr_map->type);
        }
 
-       return count;
+       return count + moved;
 }
 
 int dso__load_kallsyms(struct dso *self, const char *filename,
@@ -2123,14 +2131,55 @@ static struct dso *machine__create_kernel(struct machine *self)
        return kernel;
 }
 
+struct process_args {
+       u64 start;
+};
+
+static int symbol__in_kernel(void *arg, const char *name,
+                            char type __used, u64 start)
+{
+       struct process_args *args = arg;
+
+       if (strchr(name, '['))
+               return 0;
+
+       args->start = start;
+       return 1;
+}
+
+/* Figure out the start address of kernel map from /proc/kallsyms */
+static u64 machine__get_kernel_start_addr(struct machine *machine)
+{
+       const char *filename;
+       char path[PATH_MAX];
+       struct process_args args;
+
+       if (machine__is_host(machine)) {
+               filename = "/proc/kallsyms";
+       } else {
+               if (machine__is_default_guest(machine))
+                       filename = (char *)symbol_conf.default_guest_kallsyms;
+               else {
+                       sprintf(path, "%s/proc/kallsyms", machine->root_dir);
+                       filename = path;
+               }
+       }
+
+       if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0)
+               return 0;
+
+       return args.start;
+}
+
 int __machine__create_kernel_maps(struct machine *self, struct dso *kernel)
 {
        enum map_type type;
+       u64 start = machine__get_kernel_start_addr(self);
 
        for (type = 0; type < MAP__NR_TYPES; ++type) {
                struct kmap *kmap;
 
-               self->vmlinux_maps[type] = map__new2(0, kernel, type);
+               self->vmlinux_maps[type] = map__new2(start, kernel, type);
                if (self->vmlinux_maps[type] == NULL)
                        return -1;
 
index 792a750d9441af80cd16e4d797234159875babc4..c14322d1c0cfb9d7ad70bf70adce5f77dd8fe921 100644 (file)
 */
 
 #include <linux/stringify.h>
+#include <asm-generic/vmlinux.lds.h>
 
 .section .init.ramfs,"a"
 __irf_start:
 .incbin __stringify(INITRAMFS_IMAGE)
 __irf_end:
 .section .init.ramfs.info,"a"
-.globl __initramfs_size
-__initramfs_size:
+.globl VMLINUX_SYMBOL(__initramfs_size)
+VMLINUX_SYMBOL(__initramfs_size):
 #ifdef CONFIG_64BIT
        .quad __irf_end - __irf_start
 #else